1/*
2 * Loosely based on code bearing the following copyright:
3 *
4 *   Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
5 */
6
7/*
8 * Copyright 1992-2003 by The XFree86 Project, Inc.
9 * Copyright 1997 by Metro Link, Inc.
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
25 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
28 *
29 * Except as contained in this notice, the name of the copyright holder(s)
30 * and author(s) shall not be used in advertising or otherwise to promote
31 * the sale, use or other dealings in this Software without prior written
32 * authorization from the copyright holder(s) and author(s).
33 */
34
35/*
36 *
37 * Authors:
38 *	Dirk Hohndel <hohndel@XFree86.Org>
39 *	David Dawes <dawes@XFree86.Org>
40 *      Marc La France <tsi@XFree86.Org>
41 *      Egbert Eich <eich@XFree86.Org>
42 *      ... and others
43 */
44
45#ifdef HAVE_XORG_CONFIG_H
46#include <xorg-config.h>
47#endif
48
49#include <sys/types.h>
50#include <grp.h>
51
52#include "xf86.h"
53#include "xf86Modes.h"
54#include "xf86Parser.h"
55#include "xf86tokens.h"
56#include "xf86Config.h"
57#include "xf86Priv.h"
58#include "xf86_OSlib.h"
59#include "configProcs.h"
60#include "globals.h"
61#include "extension.h"
62#include "xf86pciBus.h"
63#include "xf86Xinput.h"
64#include "loaderProcs.h"
65
66#include "xkbsrv.h"
67#include "picture.h"
68#ifdef DPMSExtension
69#include "dpmsproc.h"
70#endif
71
72/*
73 * These paths define the way the config file search is done.  The escape
74 * sequences are documented in parser/scan.c.
75 */
76#ifndef ALL_CONFIGPATH
77#define ALL_CONFIGPATH	"%A," "%R," \
78			"/etc/X11/%R," "%P/etc/X11/%R," \
79			"%E," "%F," \
80			"/etc/X11/%F," "%P/etc/X11/%F," \
81			"/etc/X11/%X," "/etc/%X," \
82			"%P/etc/X11/%X.%H," \
83			"%P/etc/X11/%X," \
84			"%P/lib/X11/%X.%H," \
85			"%P/lib/X11/%X"
86#endif
87#ifndef RESTRICTED_CONFIGPATH
88#define RESTRICTED_CONFIGPATH	"/etc/X11/%S," "%P/etc/X11/%S," \
89			"/etc/X11/%G," "%P/etc/X11/%G," \
90			"/etc/X11/%X," "/etc/%X," \
91			"%P/etc/X11/%X.%H," \
92			"%P/etc/X11/%X," \
93			"%P/lib/X11/%X.%H," \
94			"%P/lib/X11/%X"
95#endif
96#ifndef ALL_CONFIGDIRPATH
97#define ALL_CONFIGDIRPATH	"%A," "%R," \
98				"/etc/X11/%R," "%C/X11/%R," \
99				"/etc/X11/%X," "%C/X11/%X"
100#endif
101#ifndef RESTRICTED_CONFIGDIRPATH
102#define RESTRICTED_CONFIGDIRPATH	"/etc/X11/%R," "%C/X11/%R," \
103					"/etc/X11/%X," "%C/X11/%X"
104#endif
105#ifndef SYS_CONFIGDIRPATH
106#define SYS_CONFIGDIRPATH	"%D/X11/%X"
107#endif
108#ifndef PROJECTROOT
109#define PROJECTROOT	"/usr/X11R6"
110#endif
111
112static ModuleDefault ModuleDefaults[] = {
113#ifdef GLXEXT
114    {.name = "glx",.toLoad = TRUE,.load_opt = NULL},
115#endif
116#ifdef __CYGWIN__
117    /* load DIX modules used by drivers first */
118    {.name = "fb",.toLoad = TRUE,.load_opt = NULL},
119    {.name = "shadow",.toLoad = TRUE,.load_opt = NULL},
120#endif
121    {.name = NULL,.toLoad = FALSE,.load_opt = NULL}
122};
123
124/* Forward declarations */
125static Bool configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen,
126                         int scrnum, MessageType from, Bool auto_gpu_device);
127static Bool configMonitor(MonPtr monitorp, XF86ConfMonitorPtr conf_monitor);
128static Bool configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device,
129                         Bool active, Bool gpu);
130static Bool configInput(InputInfoPtr pInfo, XF86ConfInputPtr conf_input,
131                        MessageType from);
132static Bool configDisplay(DispPtr displayp, XF86ConfDisplayPtr conf_display);
133static Bool addDefaultModes(MonPtr monitorp);
134
135static void configDRI(XF86ConfDRIPtr drip);
136static void configExtensions(XF86ConfExtensionsPtr conf_ext);
137
138/*
139 * xf86GetPathElem --
140 *	Extract a single element from the font path string starting at
141 *	pnt.  The font path element will be returned, and pnt will be
142 *	updated to point to the start of the next element, or set to
143 *	NULL if there are no more.
144 */
145static char *
146xf86GetPathElem(char **pnt)
147{
148    char *p1;
149
150    p1 = *pnt;
151    *pnt = index(*pnt, ',');
152    if (*pnt != NULL) {
153        **pnt = '\0';
154        *pnt += 1;
155    }
156    return p1;
157}
158
159/*
160 * xf86ValidateFontPath --
161 *	Validates the user-specified font path.  Each element that
162 *	begins with a '/' is checked to make sure the directory exists.
163 *	If the directory exists, the existence of a file named 'fonts.dir'
164 *	is checked.  If either check fails, an error is printed and the
165 *	element is removed from the font path.
166 */
167
168#define DIR_FILE "/fonts.dir"
169static char *
170xf86ValidateFontPath(char *path)
171{
172    char *next, *tmp_path, *out_pnt, *path_elem, *p1, *dir_elem;
173    struct stat stat_buf;
174    int flag;
175    int dirlen;
176
177    tmp_path = calloc(1, strlen(path) + 1);
178    out_pnt = tmp_path;
179    path_elem = NULL;
180    next = path;
181    while (next != NULL) {
182        path_elem = xf86GetPathElem(&next);
183        if (*path_elem == '/') {
184            dir_elem = xnfcalloc(1, strlen(path_elem) + 1);
185            if ((p1 = strchr(path_elem, ':')) != 0)
186                dirlen = p1 - path_elem;
187            else
188                dirlen = strlen(path_elem);
189            strlcpy(dir_elem, path_elem, dirlen + 1);
190            flag = stat(dir_elem, &stat_buf);
191            if (flag == 0)
192                if (!S_ISDIR(stat_buf.st_mode))
193                    flag = -1;
194            if (flag != 0) {
195                xf86Msg(X_WARNING, "The directory \"%s\" does not exist.\n",
196                        dir_elem);
197                xf86ErrorF("\tEntry deleted from font path.\n");
198                free(dir_elem);
199                continue;
200            }
201            else {
202                XNFasprintf(&p1, "%s%s", dir_elem, DIR_FILE);
203                flag = stat(p1, &stat_buf);
204                if (flag == 0)
205                    if (!S_ISREG(stat_buf.st_mode))
206                        flag = -1;
207                free(p1);
208                if (flag != 0) {
209                    xf86Msg(X_WARNING,
210                            "`fonts.dir' not found (or not valid) in \"%s\".\n",
211                            dir_elem);
212                    xf86ErrorF("\tEntry deleted from font path.\n");
213                    xf86ErrorF("\t(Run 'mkfontdir' on \"%s\").\n", dir_elem);
214                    free(dir_elem);
215                    continue;
216                }
217            }
218            free(dir_elem);
219        }
220
221        /*
222         * Either an OK directory, or a font server name.  So add it to
223         * the path.
224         */
225        if (out_pnt != tmp_path)
226            *out_pnt++ = ',';
227        strcat(out_pnt, path_elem);
228        out_pnt += strlen(path_elem);
229    }
230    return tmp_path;
231}
232
233#define FIND_SUITABLE(pointertype, listhead, ptr)                                            \
234    do {                                                                                     \
235        pointertype _l, _p;                                                                  \
236                                                                                             \
237        for (_l = (listhead), _p = NULL; !_p && _l; _l = (pointertype)_l->list.next) {       \
238            if (!_l->match_seat || (SeatId && xf86nameCompare(_l->match_seat, SeatId) == 0)) \
239                _p = _l;                                                                     \
240        }                                                                                    \
241                                                                                             \
242        (ptr) = _p;                                                                          \
243    } while(0)
244
245/*
246 * use the datastructure that the parser provides and pick out the parts
247 * that we need at this point
248 */
249const char **
250xf86ModulelistFromConfig(void ***optlist)
251{
252    int count = 0, i = 0;
253    const char **modulearray;
254
255    const char *ignore[] = { "GLcore", "speedo", "bitmap", "drm",
256        "freetype", "type1",
257        NULL
258    };
259    void **optarray;
260    XF86LoadPtr modp;
261    Bool found;
262
263    /*
264     * make sure the config file has been parsed and that we have a
265     * ModulePath set; if no ModulePath was given, use the default
266     * ModulePath
267     */
268    if (xf86configptr == NULL) {
269        xf86Msg(X_ERROR, "Cannot access global config data structure\n");
270        return NULL;
271    }
272
273    if (xf86configptr->conf_modules) {
274        /* Walk the disable list and let people know what we've parsed to
275         * not be loaded
276         */
277        modp = xf86configptr->conf_modules->mod_disable_lst;
278        while (modp) {
279            xf86Msg(X_WARNING,
280                    "\"%s\" will not be loaded unless you've specified it to be loaded elsewhere.\n",
281                    modp->load_name);
282            modp = (XF86LoadPtr) modp->list.next;
283        }
284        /*
285         * Walk the default settings table. For each module listed to be
286         * loaded, make sure it's in the mod_load_lst. If it's not, make
287         * sure it's not in the mod_no_load_lst. If it's not disabled,
288         * append it to mod_load_lst
289         */
290        for (i = 0; ModuleDefaults[i].name != NULL; i++) {
291            if (ModuleDefaults[i].toLoad == FALSE) {
292                xf86Msg(X_WARNING,
293                        "\"%s\" is not to be loaded by default. Skipping.\n",
294                        ModuleDefaults[i].name);
295                continue;
296            }
297            found = FALSE;
298            modp = xf86configptr->conf_modules->mod_load_lst;
299            while (modp) {
300                if (strcmp(modp->load_name, ModuleDefaults[i].name) == 0) {
301                    xf86Msg(X_INFO,
302                            "\"%s\" will be loaded. This was enabled by default and also specified in the config file.\n",
303                            ModuleDefaults[i].name);
304                    found = TRUE;
305                    break;
306                }
307                modp = (XF86LoadPtr) modp->list.next;
308            }
309            if (found == FALSE) {
310                modp = xf86configptr->conf_modules->mod_disable_lst;
311                while (modp) {
312                    if (strcmp(modp->load_name, ModuleDefaults[i].name) == 0) {
313                        xf86Msg(X_INFO,
314                                "\"%s\" will be loaded even though the default is to disable it.\n",
315                                ModuleDefaults[i].name);
316                        found = TRUE;
317                        break;
318                    }
319                    modp = (XF86LoadPtr) modp->list.next;
320                }
321            }
322            if (found == FALSE) {
323                XF86LoadPtr ptr = (XF86LoadPtr) xf86configptr->conf_modules;
324
325                xf86addNewLoadDirective(ptr, ModuleDefaults[i].name,
326                                        XF86_LOAD_MODULE,
327                                        ModuleDefaults[i].load_opt);
328                xf86Msg(X_INFO, "\"%s\" will be loaded by default.\n",
329                        ModuleDefaults[i].name);
330            }
331        }
332    }
333    else {
334        xf86configptr->conf_modules = xnfcalloc(1, sizeof(XF86ConfModuleRec));
335        for (i = 0; ModuleDefaults[i].name != NULL; i++) {
336            if (ModuleDefaults[i].toLoad == TRUE) {
337                XF86LoadPtr ptr = (XF86LoadPtr) xf86configptr->conf_modules;
338
339                xf86addNewLoadDirective(ptr, ModuleDefaults[i].name,
340                                        XF86_LOAD_MODULE,
341                                        ModuleDefaults[i].load_opt);
342            }
343        }
344    }
345
346    /*
347     * Walk the list of modules in the "Module" section to determine how
348     * many we have.
349     */
350    modp = xf86configptr->conf_modules->mod_load_lst;
351    while (modp) {
352        for (i = 0; ignore[i]; i++) {
353            if (strcmp(modp->load_name, ignore[i]) == 0)
354                modp->ignore = 1;
355        }
356        if (!modp->ignore)
357            count++;
358        modp = (XF86LoadPtr) modp->list.next;
359    }
360
361    /*
362     * allocate the memory and walk the list again to fill in the pointers
363     */
364    modulearray = xnfallocarray(count + 1, sizeof(char *));
365    optarray = xnfallocarray(count + 1, sizeof(void *));
366    count = 0;
367    if (xf86configptr->conf_modules) {
368        modp = xf86configptr->conf_modules->mod_load_lst;
369        while (modp) {
370            if (!modp->ignore) {
371                modulearray[count] = modp->load_name;
372                optarray[count] = modp->load_opt;
373                count++;
374            }
375            modp = (XF86LoadPtr) modp->list.next;
376        }
377    }
378    modulearray[count] = NULL;
379    optarray[count] = NULL;
380    if (optlist)
381        *optlist = optarray;
382    else
383        free(optarray);
384    return modulearray;
385}
386
387const char **
388xf86DriverlistFromConfig(void)
389{
390    int count = 0;
391    int j, k;
392    const char **modulearray;
393    screenLayoutPtr slp;
394
395    /*
396     * make sure the config file has been parsed and that we have a
397     * ModulePath set; if no ModulePath was given, use the default
398     * ModulePath
399     */
400    if (xf86configptr == NULL) {
401        xf86Msg(X_ERROR, "Cannot access global config data structure\n");
402        return NULL;
403    }
404
405    /*
406     * Walk the list of driver lines in active "Device" sections to
407     * determine now many implicitly loaded modules there are.
408     *
409     */
410    if (xf86ConfigLayout.screens) {
411        slp = xf86ConfigLayout.screens;
412        while (slp->screen) {
413            count++;
414            count += slp->screen->num_gpu_devices;
415            slp++;
416        }
417    }
418
419    /*
420     * Handle the set of inactive "Device" sections.
421     */
422    j = 0;
423    while (xf86ConfigLayout.inactives[j++].identifier)
424        count++;
425
426    if (count == 0)
427        return NULL;
428
429    /*
430     * allocate the memory and walk the list again to fill in the pointers
431     */
432    modulearray = xnfallocarray(count + 1, sizeof(char *));
433    count = 0;
434    slp = xf86ConfigLayout.screens;
435    while (slp->screen) {
436        modulearray[count] = slp->screen->device->driver;
437        count++;
438        for (k = 0; k < slp->screen->num_gpu_devices; k++) {
439            modulearray[count] = slp->screen->gpu_devices[k]->driver;
440            count++;
441        }
442        slp++;
443    }
444
445    j = 0;
446
447    while (xf86ConfigLayout.inactives[j].identifier)
448        modulearray[count++] = xf86ConfigLayout.inactives[j++].driver;
449
450    modulearray[count] = NULL;
451
452    /* Remove duplicates */
453    for (count = 0; modulearray[count] != NULL; count++) {
454        int i;
455
456        for (i = 0; i < count; i++)
457            if (xf86NameCmp(modulearray[i], modulearray[count]) == 0) {
458                modulearray[count] = "";
459                break;
460            }
461    }
462    return modulearray;
463}
464
465const char **
466xf86InputDriverlistFromConfig(void)
467{
468    int count = 0;
469    const char **modulearray;
470    InputInfoPtr *idp;
471
472    /*
473     * make sure the config file has been parsed and that we have a
474     * ModulePath set; if no ModulePath was given, use the default
475     * ModulePath
476     */
477    if (xf86configptr == NULL) {
478        xf86Msg(X_ERROR, "Cannot access global config data structure\n");
479        return NULL;
480    }
481
482    /*
483     * Walk the list of driver lines in active "InputDevice" sections to
484     * determine now many implicitly loaded modules there are.
485     */
486    if (xf86ConfigLayout.inputs) {
487        idp = xf86ConfigLayout.inputs;
488        while (*idp) {
489            count++;
490            idp++;
491        }
492    }
493
494    if (count == 0)
495        return NULL;
496
497    /*
498     * allocate the memory and walk the list again to fill in the pointers
499     */
500    modulearray = xnfallocarray(count + 1, sizeof(char *));
501    count = 0;
502    idp = xf86ConfigLayout.inputs;
503    while (idp && *idp) {
504        modulearray[count] = (*idp)->driver;
505        count++;
506        idp++;
507    }
508    modulearray[count] = NULL;
509
510    /* Remove duplicates */
511    for (count = 0; modulearray[count] != NULL; count++) {
512        int i;
513
514        for (i = 0; i < count; i++)
515            if (xf86NameCmp(modulearray[i], modulearray[count]) == 0) {
516                modulearray[count] = "";
517                break;
518            }
519    }
520    return modulearray;
521}
522
523static void
524configFiles(XF86ConfFilesPtr fileconf)
525{
526    MessageType pathFrom;
527    Bool must_copy;
528    int size, countDirs;
529    char *temp_path, *log_buf, *start, *end;
530
531    /* FontPath */
532    must_copy = TRUE;
533
534    temp_path = defaultFontPath ? (char *) defaultFontPath : (char *) "";
535    if (xf86fpFlag)
536        pathFrom = X_CMDLINE;
537    else if (fileconf && fileconf->file_fontpath) {
538        pathFrom = X_CONFIG;
539        if (xf86Info.useDefaultFontPath) {
540            char *new_font_path;
541            if (asprintf(&new_font_path, "%s%s%s", fileconf->file_fontpath,
542                         *temp_path ? "," : "", temp_path) == -1)
543                new_font_path = NULL;
544            else
545                must_copy = FALSE;
546            defaultFontPath = new_font_path;
547        }
548        else
549            defaultFontPath = fileconf->file_fontpath;
550    }
551    else
552        pathFrom = X_DEFAULT;
553    temp_path = defaultFontPath ? (char *) defaultFontPath : (char *) "";
554
555    /* xf86ValidateFontPath modifies its argument, but returns a copy of it. */
556    temp_path = must_copy ? xnfstrdup(defaultFontPath) : (char *) defaultFontPath;
557    defaultFontPath = xf86ValidateFontPath(temp_path);
558    free(temp_path);
559
560    /* make fontpath more readable in the logfiles */
561    countDirs = 1;
562    temp_path = (char *) defaultFontPath;
563    while ((temp_path = index(temp_path, ',')) != NULL) {
564        countDirs++;
565        temp_path++;
566    }
567
568    log_buf = xnfalloc(strlen(defaultFontPath) + (2 * countDirs) + 1);
569    temp_path = log_buf;
570    start = (char *) defaultFontPath;
571    while ((end = index(start, ',')) != NULL) {
572        size = (end - start) + 1;
573        *(temp_path++) = '\t';
574        strncpy(temp_path, start, size);
575        temp_path += size;
576        *(temp_path++) = '\n';
577        start += size;
578    }
579    /* copy last entry */
580    *(temp_path++) = '\t';
581    strcpy(temp_path, start);
582    xf86Msg(pathFrom, "FontPath set to:\n%s\n", log_buf);
583    free(log_buf);
584
585    /* ModulePath */
586
587    if (fileconf) {
588        if (xf86ModPathFrom != X_CMDLINE && fileconf->file_modulepath) {
589            xf86ModulePath = fileconf->file_modulepath;
590            xf86ModPathFrom = X_CONFIG;
591        }
592    }
593
594    xf86Msg(xf86ModPathFrom, "ModulePath set to \"%s\"\n", xf86ModulePath);
595
596    if (!xf86xkbdirFlag && fileconf && fileconf->file_xkbdir) {
597        XkbBaseDirectory = fileconf->file_xkbdir;
598        xf86Msg(X_CONFIG, "XKB base directory set to \"%s\"\n",
599                XkbBaseDirectory);
600    }
601#if 0
602    /* LogFile */
603    /*
604     * XXX The problem with this is that the log file is already open.
605     * One option might be to copy the exiting contents to the new location.
606     * and re-open it.  The down side is that the default location would
607     * already have been overwritten.  Another option would be to start with
608     * unique temporary location, then copy it once the correct name is known.
609     * A problem with this is what happens if the server exits before that
610     * happens.
611     */
612    if (xf86LogFileFrom == X_DEFAULT && fileconf->file_logfile) {
613        xf86LogFile = fileconf->file_logfile;
614        xf86LogFileFrom = X_CONFIG;
615    }
616#endif
617
618    return;
619}
620
621typedef enum {
622    FLAG_DONTVTSWITCH,
623    FLAG_DONTZAP,
624    FLAG_DONTZOOM,
625    FLAG_DISABLEVIDMODE,
626    FLAG_ALLOWNONLOCAL,
627    FLAG_ALLOWMOUSEOPENFAIL,
628    FLAG_SAVER_BLANKTIME,
629    FLAG_DPMS_STANDBYTIME,
630    FLAG_DPMS_SUSPENDTIME,
631    FLAG_DPMS_OFFTIME,
632    FLAG_NOPM,
633    FLAG_XINERAMA,
634    FLAG_LOG,
635    FLAG_RENDER_COLORMAP_MODE,
636    FLAG_IGNORE_ABI,
637    FLAG_ALLOW_EMPTY_INPUT,
638    FLAG_USE_DEFAULT_FONT_PATH,
639    FLAG_AUTO_ADD_DEVICES,
640    FLAG_AUTO_ENABLE_DEVICES,
641    FLAG_GLX_VISUALS,
642    FLAG_DRI2,
643    FLAG_USE_SIGIO,
644    FLAG_AUTO_ADD_GPU,
645    FLAG_AUTO_BIND_GPU,
646    FLAG_MAX_CLIENTS,
647    FLAG_IGLX,
648    FLAG_DEBUG,
649    FLAG_ALLOW_BYTE_SWAPPED_CLIENTS,
650} FlagValues;
651
652/**
653 * NOTE: the last value for each entry is NOT the default. It is set to TRUE
654 * if the parser found the option in the config file.
655 */
656static OptionInfoRec FlagOptions[] = {
657    {FLAG_DONTVTSWITCH, "DontVTSwitch", OPTV_BOOLEAN,
658     {0}, FALSE},
659    {FLAG_DONTZAP, "DontZap", OPTV_BOOLEAN,
660     {0}, FALSE},
661    {FLAG_DONTZOOM, "DontZoom", OPTV_BOOLEAN,
662     {0}, FALSE},
663    {FLAG_DISABLEVIDMODE, "DisableVidModeExtension", OPTV_BOOLEAN,
664     {0}, FALSE},
665    {FLAG_ALLOWNONLOCAL, "AllowNonLocalXvidtune", OPTV_BOOLEAN,
666     {0}, FALSE},
667    {FLAG_ALLOWMOUSEOPENFAIL, "AllowMouseOpenFail", OPTV_BOOLEAN,
668     {0}, FALSE},
669    {FLAG_SAVER_BLANKTIME, "BlankTime", OPTV_INTEGER,
670     {0}, FALSE},
671    {FLAG_DPMS_STANDBYTIME, "StandbyTime", OPTV_INTEGER,
672     {0}, FALSE},
673    {FLAG_DPMS_SUSPENDTIME, "SuspendTime", OPTV_INTEGER,
674     {0}, FALSE},
675    {FLAG_DPMS_OFFTIME, "OffTime", OPTV_INTEGER,
676     {0}, FALSE},
677    {FLAG_NOPM, "NoPM", OPTV_BOOLEAN,
678     {0}, FALSE},
679    {FLAG_XINERAMA, "Xinerama", OPTV_BOOLEAN,
680     {0}, FALSE},
681    {FLAG_LOG, "Log", OPTV_STRING,
682     {0}, FALSE},
683    {FLAG_RENDER_COLORMAP_MODE, "RenderColormapMode", OPTV_STRING,
684     {0}, FALSE},
685    {FLAG_IGNORE_ABI, "IgnoreABI", OPTV_BOOLEAN,
686     {0}, FALSE},
687    {FLAG_USE_DEFAULT_FONT_PATH, "UseDefaultFontPath", OPTV_BOOLEAN,
688     {0}, FALSE},
689    {FLAG_AUTO_ADD_DEVICES, "AutoAddDevices", OPTV_BOOLEAN,
690     {0}, FALSE},
691    {FLAG_AUTO_ENABLE_DEVICES, "AutoEnableDevices", OPTV_BOOLEAN,
692     {0}, FALSE},
693    {FLAG_GLX_VISUALS, "GlxVisuals", OPTV_STRING,
694     {0}, FALSE},
695    {FLAG_DRI2, "DRI2", OPTV_BOOLEAN,
696     {0}, FALSE},
697    {FLAG_USE_SIGIO, "UseSIGIO", OPTV_BOOLEAN,
698     {0}, FALSE},
699    {FLAG_AUTO_ADD_GPU, "AutoAddGPU", OPTV_BOOLEAN,
700     {0}, FALSE},
701    {FLAG_AUTO_BIND_GPU, "AutoBindGPU", OPTV_BOOLEAN,
702     {0}, FALSE},
703    {FLAG_MAX_CLIENTS, "MaxClients", OPTV_INTEGER,
704     {0}, FALSE },
705    {FLAG_IGLX, "IndirectGLX", OPTV_BOOLEAN,
706     {0}, FALSE},
707    {FLAG_DEBUG, "Debug", OPTV_STRING,
708     {0}, FALSE},
709    {FLAG_ALLOW_BYTE_SWAPPED_CLIENTS, "AllowByteSwappedClients", OPTV_BOOLEAN,
710     {0}, FALSE},
711    {-1, NULL, OPTV_NONE,
712     {0}, FALSE},
713};
714
715static void
716configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts)
717{
718    XF86OptionPtr optp, tmp;
719    int i;
720    Bool value;
721    MessageType from;
722    const char *s;
723    XkbRMLVOSet set;
724    const char *rules;
725
726    /*
727     * Merge the ServerLayout and ServerFlags options.  The former have
728     * precedence over the latter.
729     */
730    optp = NULL;
731    if (flagsconf && flagsconf->flg_option_lst)
732        optp = xf86optionListDup(flagsconf->flg_option_lst);
733    if (layoutopts) {
734        tmp = xf86optionListDup(layoutopts);
735        if (optp)
736            optp = xf86optionListMerge(optp, tmp);
737        else
738            optp = tmp;
739    }
740
741    xf86ProcessOptions(-1, optp, FlagOptions);
742
743    xf86GetOptValBool(FlagOptions, FLAG_DONTVTSWITCH, &xf86Info.dontVTSwitch);
744    xf86GetOptValBool(FlagOptions, FLAG_DONTZAP, &xf86Info.dontZap);
745    xf86GetOptValBool(FlagOptions, FLAG_DONTZOOM, &xf86Info.dontZoom);
746
747    xf86GetOptValBool(FlagOptions, FLAG_IGNORE_ABI, &xf86Info.ignoreABI);
748    if (xf86Info.ignoreABI) {
749        xf86Msg(X_CONFIG, "Ignoring ABI Version\n");
750    }
751
752    xf86GetOptValBool(FlagOptions, FLAG_ALLOW_BYTE_SWAPPED_CLIENTS, &AllowByteSwappedClients);
753    if (AllowByteSwappedClients) {
754        xf86Msg(X_CONFIG, "Allowing byte-swapped clients\n");
755    }
756    else {
757        xf86Msg(X_CONFIG, "Prohibiting byte-swapped clients\n");
758    }
759
760    if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_ADD_DEVICES)) {
761        xf86GetOptValBool(FlagOptions, FLAG_AUTO_ADD_DEVICES,
762                          &xf86Info.autoAddDevices);
763        from = X_CONFIG;
764    }
765    else {
766        from = X_DEFAULT;
767    }
768    xf86Msg(from, "%sutomatically adding devices\n",
769            xf86Info.autoAddDevices ? "A" : "Not a");
770
771    if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_ENABLE_DEVICES)) {
772        xf86GetOptValBool(FlagOptions, FLAG_AUTO_ENABLE_DEVICES,
773                          &xf86Info.autoEnableDevices);
774        from = X_CONFIG;
775    }
776    else {
777        from = X_DEFAULT;
778    }
779    xf86Msg(from, "%sutomatically enabling devices\n",
780            xf86Info.autoEnableDevices ? "A" : "Not a");
781
782    if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_ADD_GPU)) {
783        xf86GetOptValBool(FlagOptions, FLAG_AUTO_ADD_GPU,
784                          &xf86Info.autoAddGPU);
785        from = X_CONFIG;
786    }
787    else {
788        from = X_DEFAULT;
789    }
790    xf86Msg(from, "%sutomatically adding GPU devices\n",
791            xf86Info.autoAddGPU ? "A" : "Not a");
792
793    if (xf86AutoBindGPUDisabled) {
794        xf86Info.autoBindGPU = FALSE;
795        from = X_CMDLINE;
796    }
797    else if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_BIND_GPU)) {
798        xf86GetOptValBool(FlagOptions, FLAG_AUTO_BIND_GPU,
799                          &xf86Info.autoBindGPU);
800        from = X_CONFIG;
801    }
802    else {
803        from = X_DEFAULT;
804    }
805    xf86Msg(from, "%sutomatically binding GPU devices\n",
806            xf86Info.autoBindGPU ? "A" : "Not a");
807
808    /*
809     * Set things up based on the config file information.  Some of these
810     * settings may be overridden later when the command line options are
811     * checked.
812     */
813#ifdef XF86VIDMODE
814    if (xf86GetOptValBool(FlagOptions, FLAG_DISABLEVIDMODE, &value))
815        xf86Info.vidModeEnabled = !value;
816    if (xf86GetOptValBool(FlagOptions, FLAG_ALLOWNONLOCAL, &value))
817        xf86Info.vidModeAllowNonLocal = value;
818#endif
819
820    if (xf86GetOptValBool(FlagOptions, FLAG_ALLOWMOUSEOPENFAIL, &value))
821        xf86Info.allowMouseOpenFail = value;
822
823    xf86Info.pmFlag = TRUE;
824    if (xf86GetOptValBool(FlagOptions, FLAG_NOPM, &value))
825        xf86Info.pmFlag = !value;
826    {
827        if ((s = xf86GetOptValString(FlagOptions, FLAG_LOG))) {
828            if (!xf86NameCmp(s, "flush")) {
829                xf86Msg(X_CONFIG, "Flushing logfile enabled\n");
830                LogSetParameter(XLOG_FLUSH, TRUE);
831            }
832            else if (!xf86NameCmp(s, "sync")) {
833                xf86Msg(X_CONFIG, "Syncing logfile enabled\n");
834                LogSetParameter(XLOG_FLUSH, TRUE);
835                LogSetParameter(XLOG_SYNC, TRUE);
836            }
837            else {
838                xf86Msg(X_WARNING, "Unknown Log option\n");
839            }
840        }
841    }
842
843    {
844        if ((s = xf86GetOptValString(FlagOptions, FLAG_RENDER_COLORMAP_MODE))) {
845            int policy = PictureParseCmapPolicy(s);
846
847            if (policy == PictureCmapPolicyInvalid)
848                xf86Msg(X_WARNING, "Unknown colormap policy \"%s\"\n", s);
849            else {
850                xf86Msg(X_CONFIG, "Render colormap policy set to %s\n", s);
851                PictureCmapPolicy = policy;
852            }
853        }
854    }
855
856#ifdef GLXEXT
857    xf86Info.glxVisuals = XF86_GlxVisualsTypical;
858    xf86Info.glxVisualsFrom = X_DEFAULT;
859    if ((s = xf86GetOptValString(FlagOptions, FLAG_GLX_VISUALS))) {
860        if (!xf86NameCmp(s, "minimal")) {
861            xf86Info.glxVisuals = XF86_GlxVisualsMinimal;
862        }
863        else if (!xf86NameCmp(s, "typical")) {
864            xf86Info.glxVisuals = XF86_GlxVisualsTypical;
865        }
866        else if (!xf86NameCmp(s, "all")) {
867            xf86Info.glxVisuals = XF86_GlxVisualsAll;
868        }
869        else {
870            xf86Msg(X_WARNING, "Unknown GlxVisuals option\n");
871        }
872    }
873
874    if (xf86Info.iglxFrom != X_CMDLINE) {
875        if (xf86GetOptValBool(FlagOptions, FLAG_IGLX, &value)) {
876            enableIndirectGLX = value;
877            xf86Info.iglxFrom = X_CONFIG;
878        }
879    }
880#endif
881
882    xf86Info.debug = xf86GetOptValString(FlagOptions, FLAG_DEBUG);
883
884    /* if we're not hotplugging, force some input devices to exist */
885    xf86Info.forceInputDevices = !(xf86Info.autoAddDevices &&
886                                   xf86Info.autoEnableDevices);
887
888    /* when forcing input devices, we use kbd. otherwise evdev, so use the
889     * evdev rules set. */
890#if defined(__linux__)
891    if (!xf86Info.forceInputDevices)
892        rules = "evdev";
893    else
894#endif
895        rules = "base";
896
897    /* Xkb default options. */
898    XkbInitRules(&set, rules, "pc105", "us", NULL, NULL);
899    XkbSetRulesDflts(&set);
900    XkbFreeRMLVOSet(&set, FALSE);
901
902    xf86Info.useDefaultFontPath = TRUE;
903    if (xf86GetOptValBool(FlagOptions, FLAG_USE_DEFAULT_FONT_PATH, &value)) {
904        xf86Info.useDefaultFontPath = value;
905    }
906
907/* Make sure that timers don't overflow CARD32's after multiplying */
908#define MAX_TIME_IN_MIN (0x7fffffff / MILLI_PER_MIN)
909
910    i = -1;
911    xf86GetOptValInteger(FlagOptions, FLAG_SAVER_BLANKTIME, &i);
912    if ((i >= 0) && (i < MAX_TIME_IN_MIN))
913        ScreenSaverTime = defaultScreenSaverTime = i * MILLI_PER_MIN;
914    else if (i != -1)
915        ErrorF("BlankTime value %d outside legal range of 0 - %d minutes\n",
916               i, MAX_TIME_IN_MIN);
917
918#ifdef DPMSExtension
919    i = -1;
920    xf86GetOptValInteger(FlagOptions, FLAG_DPMS_STANDBYTIME, &i);
921    if ((i >= 0) && (i < MAX_TIME_IN_MIN))
922        DPMSStandbyTime = i * MILLI_PER_MIN;
923    else if (i != -1)
924        ErrorF("StandbyTime value %d outside legal range of 0 - %d minutes\n",
925               i, MAX_TIME_IN_MIN);
926    i = -1;
927    xf86GetOptValInteger(FlagOptions, FLAG_DPMS_SUSPENDTIME, &i);
928    if ((i >= 0) && (i < MAX_TIME_IN_MIN))
929        DPMSSuspendTime = i * MILLI_PER_MIN;
930    else if (i != -1)
931        ErrorF("SuspendTime value %d outside legal range of 0 - %d minutes\n",
932               i, MAX_TIME_IN_MIN);
933    i = -1;
934    xf86GetOptValInteger(FlagOptions, FLAG_DPMS_OFFTIME, &i);
935    if ((i >= 0) && (i < MAX_TIME_IN_MIN))
936        DPMSOffTime = i * MILLI_PER_MIN;
937    else if (i != -1)
938        ErrorF("OffTime value %d outside legal range of 0 - %d minutes\n",
939               i, MAX_TIME_IN_MIN);
940#endif
941
942#ifdef PANORAMIX
943    from = X_DEFAULT;
944    if (!noPanoramiXExtension)
945        from = X_CMDLINE;
946    else if (xf86GetOptValBool(FlagOptions, FLAG_XINERAMA, &value)) {
947        noPanoramiXExtension = !value;
948        from = X_CONFIG;
949    }
950    if (!noPanoramiXExtension)
951        xf86Msg(from, "Xinerama: enabled\n");
952#endif
953
954#ifdef DRI2
955    xf86Info.dri2 = FALSE;
956    xf86Info.dri2From = X_DEFAULT;
957    if (xf86GetOptValBool(FlagOptions, FLAG_DRI2, &value)) {
958        xf86Info.dri2 = value;
959        xf86Info.dri2From = X_CONFIG;
960    }
961#endif
962
963    from = X_DEFAULT;
964    if (LimitClients != LIMITCLIENTS)
965	from = X_CMDLINE;
966    i = -1;
967    if (xf86GetOptValInteger(FlagOptions, FLAG_MAX_CLIENTS, &i)) {
968        if (Ones(i) != 1 || i < 64 || i > 2048) {
969	    ErrorF("MaxClients must be one of 64, 128, 256, 512, 1024, or 2048\n");
970        } else {
971            from = X_CONFIG;
972            LimitClients = i;
973        }
974    }
975    xf86Msg(from, "Max clients allowed: %i, resource mask: 0x%x\n",
976	    LimitClients, RESOURCE_ID_MASK);
977}
978
979Bool
980xf86DRI2Enabled(void)
981{
982    return xf86Info.dri2;
983}
984
985/**
986 * Search for the pInfo in the null-terminated list given and remove (and
987 * free) it if present. All other devices are moved forward.
988 */
989static void
990freeDevice(InputInfoPtr * list, InputInfoPtr pInfo)
991{
992    InputInfoPtr *devs;
993
994    for (devs = list; devs && *devs; devs++) {
995        if (*devs == pInfo) {
996            free(*devs);
997            for (; devs && *devs; devs++)
998                devs[0] = devs[1];
999            break;
1000        }
1001    }
1002}
1003
1004/**
1005 * Append pInfo to the null-terminated list, allocating space as necessary.
1006 * pInfo is used as the last element.
1007 */
1008static InputInfoPtr *
1009addDevice(InputInfoPtr * list, InputInfoPtr pInfo)
1010{
1011    InputInfoPtr *devs;
1012    int count = 1;
1013
1014    for (devs = list; devs && *devs; devs++)
1015        count++;
1016
1017    list = xnfreallocarray(list, count + 1, sizeof(InputInfoPtr));
1018    list[count] = NULL;
1019
1020    list[count - 1] = pInfo;
1021    return list;
1022}
1023
1024/*
1025 * Locate the core input devices.  These can be specified/located in
1026 * the following ways, in order of priority:
1027 *
1028 *  1. The InputDevices named by the -pointer and -keyboard command line
1029 *     options.
1030 *  2. The "CorePointer" and "CoreKeyboard" InputDevices referred to by
1031 *     the active ServerLayout.
1032 *  3. The first InputDevices marked as "CorePointer" and "CoreKeyboard".
1033 *  4. The first InputDevices that use 'keyboard' or 'kbd' and a valid mouse
1034 *     driver (mouse, synaptics, evdev, vmmouse, void)
1035 *  5. Default devices with an empty (default) configuration.  These defaults
1036 *     will reference the 'mouse' and 'keyboard' drivers.
1037 */
1038
1039static Bool
1040checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
1041{
1042    InputInfoPtr corePointer = NULL, coreKeyboard = NULL;
1043    Bool foundPointer = FALSE, foundKeyboard = FALSE;
1044    const char *pointerMsg = NULL, *keyboardMsg = NULL;
1045    InputInfoPtr *devs,         /* iterator */
1046     indp;
1047    InputInfoPtr Pointer, Keyboard;
1048    XF86ConfInputPtr confInput;
1049    XF86ConfInputRec defPtr, defKbd;
1050    MessageType from = X_DEFAULT;
1051
1052    const char *mousedrivers[] = { "mouse", "synaptics", "evdev", "vmmouse",
1053        "void", NULL
1054    };
1055
1056    /*
1057     * First check if a core pointer or core keyboard have been specified
1058     * in the active ServerLayout.  If more than one is specified for either,
1059     * remove the core attribute from the later ones.
1060     */
1061    for (devs = servlayoutp->inputs; devs && *devs; devs++) {
1062        indp = *devs;
1063        if (indp->options &&
1064            xf86CheckBoolOption(indp->options, "CorePointer", FALSE)) {
1065            if (!corePointer) {
1066                corePointer = indp;
1067            }
1068        }
1069        if (indp->options &&
1070            xf86CheckBoolOption(indp->options, "CoreKeyboard", FALSE)) {
1071            if (!coreKeyboard) {
1072                coreKeyboard = indp;
1073            }
1074        }
1075    }
1076
1077    confInput = NULL;
1078
1079    /* 1. Check for the -pointer command line option. */
1080    if (xf86PointerName) {
1081        confInput = xf86findInput(xf86PointerName,
1082                                  xf86configptr->conf_input_lst);
1083        if (!confInput) {
1084            xf86Msg(X_ERROR, "No InputDevice section called \"%s\"\n",
1085                    xf86PointerName);
1086            return FALSE;
1087        }
1088        from = X_CMDLINE;
1089        /*
1090         * If one was already specified in the ServerLayout, it needs to be
1091         * removed.
1092         */
1093        if (corePointer) {
1094            freeDevice(servlayoutp->inputs, corePointer);
1095            corePointer = NULL;
1096        }
1097        foundPointer = TRUE;
1098    }
1099
1100    /* 2. ServerLayout-specified core pointer. */
1101    if (corePointer) {
1102        foundPointer = TRUE;
1103        from = X_CONFIG;
1104    }
1105
1106    /* 3. First core pointer device. */
1107    if (!foundPointer && (xf86Info.forceInputDevices || implicitLayout)) {
1108        XF86ConfInputPtr p;
1109
1110        for (p = xf86configptr->conf_input_lst; p; p = p->list.next) {
1111            if (p->inp_option_lst &&
1112                xf86CheckBoolOption(p->inp_option_lst, "CorePointer", FALSE)) {
1113                confInput = p;
1114                foundPointer = TRUE;
1115                from = X_DEFAULT;
1116                pointerMsg = "first core pointer device";
1117                break;
1118            }
1119        }
1120    }
1121
1122    /* 4. First pointer with an allowed mouse driver. */
1123    if (!foundPointer && xf86Info.forceInputDevices) {
1124        const char **driver = mousedrivers;
1125
1126        confInput = xf86findInput(CONF_IMPLICIT_POINTER,
1127                                  xf86configptr->conf_input_lst);
1128        while (*driver && !confInput) {
1129            confInput = xf86findInputByDriver(*driver,
1130                                              xf86configptr->conf_input_lst);
1131            driver++;
1132        }
1133        if (confInput) {
1134            foundPointer = TRUE;
1135            from = X_DEFAULT;
1136            pointerMsg = "first mouse device";
1137        }
1138    }
1139
1140    /* 5. Built-in default. */
1141    if (!foundPointer && xf86Info.forceInputDevices) {
1142        memset(&defPtr, 0, sizeof(defPtr));
1143        defPtr.inp_identifier = strdup("<default pointer>");
1144#if defined(__NetBSD__) && (defined(__i386__) || defined(__amd64__))
1145	if (xf86findDeviceByDriver("vmware", xf86configptr->conf_device_lst) ||
1146	    xf86findDeviceByDriver("vmwlegacy", xf86configptr->conf_device_lst)) {
1147		defPtr.inp_driver = strdup("vmmouse");
1148		defPtr.inp_option_lst = xf86addNewOption(defPtr.inp_option_lst, strdup("Protocol"), "wsmouse");
1149		defPtr.inp_option_lst = xf86addNewOption(defPtr.inp_option_lst, strdup("Device"), "/dev/wsmouse");
1150	} else {
1151#endif
1152        defPtr.inp_driver = strdup("mouse");
1153#if defined(__NetBSD__) && (defined(__i386__) || defined(__amd64__))
1154        }
1155#endif
1156        confInput = &defPtr;
1157        foundPointer = TRUE;
1158        from = X_DEFAULT;
1159        pointerMsg = "default mouse configuration";
1160    }
1161
1162    /* Add the core pointer device to the layout, and set it to Core. */
1163    if (foundPointer && confInput) {
1164        Pointer = xf86AllocateInput();
1165        if (Pointer)
1166            foundPointer = configInput(Pointer, confInput, from);
1167        if (foundPointer) {
1168            Pointer->options = xf86AddNewOption(Pointer->options,
1169                                                "CorePointer", "on");
1170            Pointer->options = xf86AddNewOption(Pointer->options,
1171                                                "driver",
1172                                                confInput->inp_driver);
1173            Pointer->options =
1174                xf86AddNewOption(Pointer->options, "identifier",
1175                                 confInput->inp_identifier);
1176            servlayoutp->inputs = addDevice(servlayoutp->inputs, Pointer);
1177        }
1178    }
1179
1180    if (!foundPointer && xf86Info.forceInputDevices) {
1181        /* This shouldn't happen. */
1182        xf86Msg(X_ERROR, "Cannot locate a core pointer device.\n");
1183        xf86DeleteInput(Pointer, 0);
1184        return FALSE;
1185    }
1186
1187    confInput = NULL;
1188
1189    /* 1. Check for the -keyboard command line option. */
1190    if (xf86KeyboardName) {
1191        confInput = xf86findInput(xf86KeyboardName,
1192                                  xf86configptr->conf_input_lst);
1193        if (!confInput) {
1194            xf86Msg(X_ERROR, "No InputDevice section called \"%s\"\n",
1195                    xf86KeyboardName);
1196            return FALSE;
1197        }
1198        from = X_CMDLINE;
1199        /*
1200         * If one was already specified in the ServerLayout, it needs to be
1201         * removed.
1202         */
1203        if (coreKeyboard) {
1204            freeDevice(servlayoutp->inputs, coreKeyboard);
1205            coreKeyboard = NULL;
1206        }
1207        foundKeyboard = TRUE;
1208    }
1209
1210    /* 2. ServerLayout-specified core keyboard. */
1211    if (coreKeyboard) {
1212        foundKeyboard = TRUE;
1213        from = X_CONFIG;
1214    }
1215
1216    /* 3. First core keyboard device. */
1217    if (!foundKeyboard && (xf86Info.forceInputDevices || implicitLayout)) {
1218        XF86ConfInputPtr p;
1219
1220        for (p = xf86configptr->conf_input_lst; p; p = p->list.next) {
1221            if (p->inp_option_lst &&
1222                xf86CheckBoolOption(p->inp_option_lst, "CoreKeyboard", FALSE)) {
1223                confInput = p;
1224                foundKeyboard = TRUE;
1225                from = X_DEFAULT;
1226                keyboardMsg = "first core keyboard device";
1227                break;
1228            }
1229        }
1230    }
1231
1232    /* 4. First keyboard with 'keyboard' or 'kbd' as the driver. */
1233    if (!foundKeyboard && xf86Info.forceInputDevices) {
1234        confInput = xf86findInput(CONF_IMPLICIT_KEYBOARD,
1235                                  xf86configptr->conf_input_lst);
1236        if (!confInput) {
1237            confInput = xf86findInputByDriver("kbd",
1238                                              xf86configptr->conf_input_lst);
1239        }
1240        if (confInput) {
1241            foundKeyboard = TRUE;
1242            from = X_DEFAULT;
1243            keyboardMsg = "first keyboard device";
1244        }
1245    }
1246
1247    /* 5. Built-in default. */
1248    if (!foundKeyboard && xf86Info.forceInputDevices) {
1249        memset(&defKbd, 0, sizeof(defKbd));
1250        defKbd.inp_identifier = strdup("<default keyboard>");
1251        defKbd.inp_driver = strdup("kbd");
1252        confInput = &defKbd;
1253        foundKeyboard = TRUE;
1254        keyboardMsg = "default keyboard configuration";
1255        from = X_DEFAULT;
1256    }
1257
1258    /* Add the core keyboard device to the layout, and set it to Core. */
1259    if (foundKeyboard && confInput) {
1260        Keyboard = xf86AllocateInput();
1261        if (Keyboard)
1262            foundKeyboard = configInput(Keyboard, confInput, from);
1263        if (foundKeyboard) {
1264            Keyboard->options = xf86AddNewOption(Keyboard->options,
1265                                                 "CoreKeyboard", "on");
1266            Keyboard->options = xf86AddNewOption(Keyboard->options,
1267                                                 "driver",
1268                                                 confInput->inp_driver);
1269            Keyboard->options =
1270                xf86AddNewOption(Keyboard->options, "identifier",
1271                                 confInput->inp_identifier);
1272            servlayoutp->inputs = addDevice(servlayoutp->inputs, Keyboard);
1273        }
1274    }
1275
1276    if (!foundKeyboard && xf86Info.forceInputDevices) {
1277        /* This shouldn't happen. */
1278        xf86Msg(X_ERROR, "Cannot locate a core keyboard device.\n");
1279        xf86DeleteInput(Keyboard, 0);
1280        return FALSE;
1281    }
1282
1283    if (pointerMsg) {
1284        if (implicitLayout)
1285            xf86Msg(X_DEFAULT, "No Layout section. Using the %s.\n",
1286                    pointerMsg);
1287        else
1288            xf86Msg(X_DEFAULT, "The core pointer device wasn't specified "
1289                    "explicitly in the layout.\n"
1290                    "\tUsing the %s.\n", pointerMsg);
1291    }
1292
1293    if (keyboardMsg) {
1294        if (implicitLayout)
1295            xf86Msg(X_DEFAULT, "No Layout section. Using the %s.\n",
1296                    keyboardMsg);
1297        else
1298            xf86Msg(X_DEFAULT, "The core keyboard device wasn't specified "
1299                    "explicitly in the layout.\n"
1300                    "\tUsing the %s.\n", keyboardMsg);
1301    }
1302
1303    if (!xf86Info.forceInputDevices && !(foundPointer && foundKeyboard)) {
1304#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) || defined(CONFIG_WSCONS)
1305        const char *config_backend;
1306
1307#if defined(CONFIG_HAL)
1308        config_backend = "HAL";
1309#elif defined(CONFIG_UDEV)
1310        config_backend = "udev";
1311#else
1312        config_backend = "wscons";
1313#endif
1314        xf86Msg(X_INFO, "The server relies on %s to provide the list of "
1315                "input devices.\n\tIf no devices become available, "
1316                "reconfigure %s or disable AutoAddDevices.\n",
1317                config_backend, config_backend);
1318#else
1319        xf86Msg(X_WARNING, "Hotplugging requested but the server was "
1320                "compiled without a config backend. "
1321                "No input devices were configured, the server "
1322                "will start without any input devices.\n");
1323#endif
1324    }
1325
1326    return TRUE;
1327}
1328
1329typedef enum {
1330    LAYOUT_ISOLATEDEVICE,
1331    LAYOUT_SINGLECARD
1332} LayoutValues;
1333
1334static OptionInfoRec LayoutOptions[] = {
1335    {LAYOUT_ISOLATEDEVICE, "IsolateDevice", OPTV_STRING,
1336     {0}, FALSE},
1337    {LAYOUT_SINGLECARD, "SingleCard", OPTV_BOOLEAN,
1338     {0}, FALSE},
1339    {-1, NULL, OPTV_NONE,
1340     {0}, FALSE},
1341};
1342
1343static Bool
1344configInputDevices(XF86ConfLayoutPtr layout, serverLayoutPtr servlayoutp)
1345{
1346    XF86ConfInputrefPtr irp;
1347    InputInfoPtr *indp;
1348    int count = 0;
1349
1350    /*
1351     * Count the number of input devices.
1352     */
1353    irp = layout->lay_input_lst;
1354    while (irp) {
1355        count++;
1356        irp = (XF86ConfInputrefPtr) irp->list.next;
1357    }
1358    DebugF("Found %d input devices in the layout section %s\n",
1359           count, layout->lay_identifier);
1360    indp = xnfcalloc((count + 1), sizeof(InputInfoPtr));
1361    indp[count] = NULL;
1362    irp = layout->lay_input_lst;
1363    count = 0;
1364    while (irp) {
1365        indp[count] = xf86AllocateInput();
1366        if (!configInput(indp[count], irp->iref_inputdev, X_CONFIG)) {
1367            do {
1368                free(indp[count]);
1369            } while (count--);
1370            free(indp);
1371            return FALSE;
1372        }
1373        indp[count]->options = xf86OptionListMerge(indp[count]->options,
1374                                                   irp->iref_option_lst);
1375        count++;
1376        irp = (XF86ConfInputrefPtr) irp->list.next;
1377    }
1378    servlayoutp->inputs = indp;
1379
1380    return TRUE;
1381}
1382
1383/*
1384 * figure out which layout is active, which screens are used in that layout,
1385 * which drivers and monitors are used in these screens
1386 */
1387static Bool
1388configLayout(serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout,
1389             char *default_layout)
1390{
1391    XF86ConfAdjacencyPtr adjp;
1392    XF86ConfInactivePtr idp;
1393    int saved_count, count = 0;
1394    int scrnum;
1395    XF86ConfLayoutPtr l;
1396    MessageType from;
1397    screenLayoutPtr slp;
1398    GDevPtr gdp;
1399    int i = 0, j;
1400
1401    if (!servlayoutp)
1402        return FALSE;
1403
1404    /*
1405     * which layout section is the active one?
1406     *
1407     * If there is a -layout command line option, use that one, otherwise
1408     * pick the first one.
1409     */
1410    from = X_DEFAULT;
1411    if (xf86LayoutName != NULL)
1412        from = X_CMDLINE;
1413    else if (default_layout) {
1414        xf86LayoutName = default_layout;
1415        from = X_CONFIG;
1416    }
1417    if (xf86LayoutName != NULL) {
1418        if ((l = xf86findLayout(xf86LayoutName, conf_layout)) == NULL) {
1419            xf86Msg(X_ERROR, "No ServerLayout section called \"%s\"\n",
1420                    xf86LayoutName);
1421            return FALSE;
1422        }
1423        conf_layout = l;
1424    }
1425    xf86Msg(from, "ServerLayout \"%s\"\n", conf_layout->lay_identifier);
1426    adjp = conf_layout->lay_adjacency_lst;
1427
1428    /*
1429     * we know that each screen is referenced exactly once on the left side
1430     * of a layout statement in the Layout section. So to allocate the right
1431     * size for the array we do a quick walk of the list to figure out how
1432     * many sections we have
1433     */
1434    while (adjp) {
1435        count++;
1436        adjp = (XF86ConfAdjacencyPtr) adjp->list.next;
1437    }
1438
1439    DebugF("Found %d screens in the layout section %s",
1440           count, conf_layout->lay_identifier);
1441    if (!count)                 /* alloc enough storage even if no screen is specified */
1442        count = 1;
1443
1444    slp = xnfcalloc((count + 1), sizeof(screenLayoutRec));
1445    slp[count].screen = NULL;
1446    /*
1447     * now that we have storage, loop over the list again and fill in our
1448     * data structure; at this point we do not fill in the adjacency
1449     * information as it is not clear if we need it at all
1450     */
1451    adjp = conf_layout->lay_adjacency_lst;
1452    count = 0;
1453    while (adjp) {
1454        slp[count].screen = xnfcalloc(1, sizeof(confScreenRec));
1455        if (adjp->adj_scrnum < 0)
1456            scrnum = count;
1457        else
1458            scrnum = adjp->adj_scrnum;
1459        if (!configScreen(slp[count].screen, adjp->adj_screen, scrnum,
1460                          X_CONFIG, (scrnum == 0 && !adjp->list.next))) {
1461            do {
1462                free(slp[count].screen);
1463            } while (count--);
1464            free(slp);
1465            return FALSE;
1466        }
1467        slp[count].x = adjp->adj_x;
1468        slp[count].y = adjp->adj_y;
1469        slp[count].refname = adjp->adj_refscreen;
1470        switch (adjp->adj_where) {
1471        case CONF_ADJ_OBSOLETE:
1472            slp[count].where = PosObsolete;
1473            slp[count].topname = adjp->adj_top_str;
1474            slp[count].bottomname = adjp->adj_bottom_str;
1475            slp[count].leftname = adjp->adj_left_str;
1476            slp[count].rightname = adjp->adj_right_str;
1477            break;
1478        case CONF_ADJ_ABSOLUTE:
1479            slp[count].where = PosAbsolute;
1480            break;
1481        case CONF_ADJ_RIGHTOF:
1482            slp[count].where = PosRightOf;
1483            break;
1484        case CONF_ADJ_LEFTOF:
1485            slp[count].where = PosLeftOf;
1486            break;
1487        case CONF_ADJ_ABOVE:
1488            slp[count].where = PosAbove;
1489            break;
1490        case CONF_ADJ_BELOW:
1491            slp[count].where = PosBelow;
1492            break;
1493        case CONF_ADJ_RELATIVE:
1494            slp[count].where = PosRelative;
1495            break;
1496        }
1497        count++;
1498        adjp = (XF86ConfAdjacencyPtr) adjp->list.next;
1499    }
1500
1501    /* No screen was specified in the layout. take the first one from the
1502     * config file, or - if it is NULL - configScreen autogenerates one for
1503     * us */
1504    if (!count) {
1505        XF86ConfScreenPtr screen;
1506
1507        FIND_SUITABLE (XF86ConfScreenPtr, xf86configptr->conf_screen_lst, screen);
1508        slp[0].screen = xnfcalloc(1, sizeof(confScreenRec));
1509        if (!configScreen(slp[0].screen, screen,
1510                          0, X_CONFIG, TRUE)) {
1511            free(slp[0].screen);
1512            free(slp);
1513            return FALSE;
1514        }
1515    }
1516
1517    /* XXX Need to tie down the upper left screen. */
1518
1519    /* Fill in the refscreen and top/bottom/left/right values */
1520    for (i = 0; i < count; i++) {
1521        for (j = 0; j < count; j++) {
1522            if (slp[i].refname &&
1523                strcmp(slp[i].refname, slp[j].screen->id) == 0) {
1524                slp[i].refscreen = slp[j].screen;
1525            }
1526            if (slp[i].topname &&
1527                strcmp(slp[i].topname, slp[j].screen->id) == 0) {
1528                slp[i].top = slp[j].screen;
1529            }
1530            if (slp[i].bottomname &&
1531                strcmp(slp[i].bottomname, slp[j].screen->id) == 0) {
1532                slp[i].bottom = slp[j].screen;
1533            }
1534            if (slp[i].leftname &&
1535                strcmp(slp[i].leftname, slp[j].screen->id) == 0) {
1536                slp[i].left = slp[j].screen;
1537            }
1538            if (slp[i].rightname &&
1539                strcmp(slp[i].rightname, slp[j].screen->id) == 0) {
1540                slp[i].right = slp[j].screen;
1541            }
1542        }
1543        if (slp[i].where != PosObsolete
1544            && slp[i].where != PosAbsolute && !slp[i].refscreen) {
1545            xf86Msg(X_ERROR, "Screen %s doesn't exist: deleting placement\n",
1546                    slp[i].refname);
1547            slp[i].where = PosAbsolute;
1548            slp[i].x = 0;
1549            slp[i].y = 0;
1550        }
1551    }
1552
1553    if (!count)
1554        saved_count = 1;
1555    else
1556        saved_count = count;
1557    /*
1558     * Count the number of inactive devices.
1559     */
1560    count = 0;
1561    idp = conf_layout->lay_inactive_lst;
1562    while (idp) {
1563        count++;
1564        idp = (XF86ConfInactivePtr) idp->list.next;
1565    }
1566    DebugF("Found %d inactive devices in the layout section %s\n",
1567           count, conf_layout->lay_identifier);
1568    gdp = xnfallocarray(count + 1, sizeof(GDevRec));
1569    gdp[count].identifier = NULL;
1570    idp = conf_layout->lay_inactive_lst;
1571    count = 0;
1572    while (idp) {
1573        if (!configDevice(&gdp[count], idp->inactive_device, FALSE, FALSE))
1574            goto bail;
1575        count++;
1576        idp = (XF86ConfInactivePtr) idp->list.next;
1577    }
1578
1579    if (!configInputDevices(conf_layout, servlayoutp))
1580        goto bail;
1581
1582    servlayoutp->id = conf_layout->lay_identifier;
1583    servlayoutp->screens = slp;
1584    servlayoutp->inactives = gdp;
1585    servlayoutp->options = conf_layout->lay_option_lst;
1586    from = X_DEFAULT;
1587
1588    return TRUE;
1589
1590 bail:
1591    do {
1592        free(slp[saved_count].screen);
1593    } while (saved_count--);
1594    free(slp);
1595    free(gdp);
1596    return FALSE;
1597}
1598
1599/*
1600 * No layout section, so find the first Screen section and set that up as
1601 * the only active screen.
1602 */
1603static Bool
1604configImpliedLayout(serverLayoutPtr servlayoutp, XF86ConfScreenPtr conf_screen,
1605                    XF86ConfigPtr conf_ptr)
1606{
1607    MessageType from;
1608    XF86ConfScreenPtr s;
1609    screenLayoutPtr slp;
1610    InputInfoPtr *indp;
1611    XF86ConfLayoutRec layout;
1612
1613    if (!servlayoutp)
1614        return FALSE;
1615
1616    /*
1617     * which screen section is the active one?
1618     *
1619     * If there is a -screen option, use that one, otherwise use the first
1620     * one.
1621     */
1622
1623    from = X_CONFIG;
1624    if (xf86ScreenName != NULL) {
1625        if ((s = xf86findScreen(xf86ScreenName, conf_screen)) == NULL) {
1626            xf86Msg(X_ERROR, "No Screen section called \"%s\"\n",
1627                    xf86ScreenName);
1628            return FALSE;
1629        }
1630        conf_screen = s;
1631        from = X_CMDLINE;
1632    }
1633
1634    /* We have exactly one screen */
1635
1636    slp = xnfcalloc(1, 2 * sizeof(screenLayoutRec));
1637    slp[0].screen = xnfcalloc(1, sizeof(confScreenRec));
1638    slp[1].screen = NULL;
1639    if (!configScreen(slp[0].screen, conf_screen, 0, from, TRUE)) {
1640        free(slp);
1641        return FALSE;
1642    }
1643    servlayoutp->id = "(implicit)";
1644    servlayoutp->screens = slp;
1645    servlayoutp->inactives = xnfcalloc(1, sizeof(GDevRec));
1646    servlayoutp->options = NULL;
1647
1648    memset(&layout, 0, sizeof(layout));
1649    layout.lay_identifier = servlayoutp->id;
1650    if (xf86layoutAddInputDevices(conf_ptr, &layout) > 0) {
1651        if (!configInputDevices(&layout, servlayoutp))
1652            return FALSE;
1653        from = X_DEFAULT;
1654    }
1655    else {
1656        /* Set up an empty input device list, then look for some core devices. */
1657        indp = xnfalloc(sizeof(InputInfoPtr));
1658        *indp = NULL;
1659        servlayoutp->inputs = indp;
1660    }
1661
1662    return TRUE;
1663}
1664
1665static Bool
1666configXvAdaptor(confXvAdaptorPtr adaptor, XF86ConfVideoAdaptorPtr conf_adaptor)
1667{
1668    int count = 0;
1669    XF86ConfVideoPortPtr conf_port;
1670
1671    xf86Msg(X_CONFIG, "|   |-->VideoAdaptor \"%s\"\n",
1672            conf_adaptor->va_identifier);
1673    adaptor->identifier = conf_adaptor->va_identifier;
1674    adaptor->options = conf_adaptor->va_option_lst;
1675    if (conf_adaptor->va_busid || conf_adaptor->va_driver) {
1676        xf86Msg(X_CONFIG, "|   | Unsupported device type, skipping entry\n");
1677        return FALSE;
1678    }
1679
1680    /*
1681     * figure out how many videoport subsections there are and fill them in
1682     */
1683    conf_port = conf_adaptor->va_port_lst;
1684    while (conf_port) {
1685        count++;
1686        conf_port = (XF86ConfVideoPortPtr) conf_port->list.next;
1687    }
1688    adaptor->ports = xnfallocarray(count, sizeof(confXvPortRec));
1689    adaptor->numports = count;
1690    count = 0;
1691    conf_port = conf_adaptor->va_port_lst;
1692    while (conf_port) {
1693        adaptor->ports[count].identifier = conf_port->vp_identifier;
1694        adaptor->ports[count].options = conf_port->vp_option_lst;
1695        count++;
1696        conf_port = (XF86ConfVideoPortPtr) conf_port->list.next;
1697    }
1698
1699    return TRUE;
1700}
1701
1702static Bool
1703configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, int scrnum,
1704             MessageType from, Bool auto_gpu_device)
1705{
1706    int count = 0;
1707    XF86ConfDisplayPtr dispptr;
1708    XF86ConfAdaptorLinkPtr conf_adaptor;
1709    Bool defaultMonitor = FALSE;
1710    XF86ConfScreenRec local_conf_screen;
1711    int i;
1712
1713    if (!conf_screen) {
1714        memset(&local_conf_screen, 0, sizeof(local_conf_screen));
1715        conf_screen = &local_conf_screen;
1716        conf_screen->scrn_identifier = "Default Screen Section";
1717        xf86Msg(X_DEFAULT, "No screen section available. Using defaults.\n");
1718    }
1719
1720    xf86Msg(from, "|-->Screen \"%s\" (%d)\n", conf_screen->scrn_identifier,
1721            scrnum);
1722    /*
1723     * now we fill in the elements of the screen
1724     */
1725    screenp->id = conf_screen->scrn_identifier;
1726    screenp->screennum = scrnum;
1727    screenp->defaultdepth = conf_screen->scrn_defaultdepth;
1728    screenp->defaultbpp = conf_screen->scrn_defaultbpp;
1729    screenp->defaultfbbpp = conf_screen->scrn_defaultfbbpp;
1730    screenp->monitor = xnfcalloc(1, sizeof(MonRec));
1731    /* If no monitor is specified, create a default one. */
1732    if (!conf_screen->scrn_monitor) {
1733        XF86ConfMonitorRec defMon;
1734
1735        memset(&defMon, 0, sizeof(defMon));
1736        defMon.mon_identifier = "<default monitor>";
1737        if (!configMonitor(screenp->monitor, &defMon))
1738            return FALSE;
1739        defaultMonitor = TRUE;
1740    }
1741    else {
1742        if (!configMonitor(screenp->monitor, conf_screen->scrn_monitor))
1743            return FALSE;
1744    }
1745    /* Configure the device. If there isn't one configured, attach to the
1746     * first inactive one that we can configure. If there's none that work,
1747     * set it to NULL so that the section can be autoconfigured later */
1748    screenp->device = xnfcalloc(1, sizeof(GDevRec));
1749    if ((!conf_screen->scrn_device) && (xf86configptr->conf_device_lst)) {
1750        FIND_SUITABLE (XF86ConfDevicePtr, xf86configptr->conf_device_lst, conf_screen->scrn_device);
1751        xf86Msg(X_DEFAULT, "No device specified for screen \"%s\".\n"
1752                "\tUsing the first device section listed.\n", screenp->id);
1753    }
1754    if (configDevice(screenp->device, conf_screen->scrn_device, TRUE, FALSE)) {
1755        screenp->device->myScreenSection = screenp;
1756    }
1757    else {
1758        screenp->device = NULL;
1759    }
1760
1761    if (auto_gpu_device && conf_screen->num_gpu_devices == 0 &&
1762        xf86configptr->conf_device_lst) {
1763        /* Loop through the entire device list and skip the primary device
1764         * assigned to the screen. This is important because there are two
1765         * cases where the assigned primary device is not the first device in
1766         * the device list. Firstly, if the first device in the list is assigned
1767         * to a different seat than this X server, it will not have been picked
1768         * by the previous FIND_SUITABLE. Secondly, if the device was explicitly
1769         * assigned in the config but there is still only one screen, this code
1770         * path is executed but the explicitly assigned device may not be the
1771         * first device in the list. */
1772        XF86ConfDevicePtr ptmp, sdevice = xf86configptr->conf_device_lst;
1773
1774        for (i = 0; i < MAX_GPUDEVICES; i++) {
1775            if (!sdevice)
1776                break;
1777
1778            FIND_SUITABLE (XF86ConfDevicePtr, sdevice, ptmp);
1779            if (!ptmp)
1780                break;
1781
1782            /* skip the primary device on the screen */
1783            if (ptmp != conf_screen->scrn_device) {
1784                conf_screen->scrn_gpu_devices[i] = ptmp;
1785            } else {
1786                sdevice = ptmp->list.next;
1787                i--; /* run the next iteration with the same index */
1788                continue;
1789            }
1790
1791            screenp->gpu_devices[i] = xnfcalloc(1, sizeof(GDevRec));
1792            if (configDevice(screenp->gpu_devices[i], conf_screen->scrn_gpu_devices[i], TRUE, TRUE)) {
1793                screenp->gpu_devices[i]->myScreenSection = screenp;
1794            }
1795            sdevice = conf_screen->scrn_gpu_devices[i]->list.next;
1796        }
1797        screenp->num_gpu_devices = i;
1798
1799    } else {
1800        for (i = 0; i < conf_screen->num_gpu_devices; i++) {
1801            screenp->gpu_devices[i] = xnfcalloc(1, sizeof(GDevRec));
1802            if (configDevice(screenp->gpu_devices[i], conf_screen->scrn_gpu_devices[i], TRUE, TRUE)) {
1803                screenp->gpu_devices[i]->myScreenSection = screenp;
1804            }
1805        }
1806        screenp->num_gpu_devices = conf_screen->num_gpu_devices;
1807    }
1808
1809    screenp->options = conf_screen->scrn_option_lst;
1810
1811    /*
1812     * figure out how many display subsections there are and fill them in
1813     */
1814    dispptr = conf_screen->scrn_display_lst;
1815    while (dispptr) {
1816        count++;
1817        dispptr = (XF86ConfDisplayPtr) dispptr->list.next;
1818    }
1819    screenp->displays = xnfallocarray(count, sizeof(DispPtr));
1820    screenp->numdisplays = count;
1821
1822    for (count = 0, dispptr = conf_screen->scrn_display_lst;
1823         dispptr;
1824         dispptr = (XF86ConfDisplayPtr) dispptr->list.next, count++) {
1825
1826        /* Allocate individual Display records */
1827        screenp->displays[count] = xnfcalloc(1, sizeof(DispRec));
1828
1829        /* Fill in the default Virtual size, if any */
1830        if (conf_screen->scrn_virtualX && conf_screen->scrn_virtualY) {
1831            screenp->displays[count]->virtualX = conf_screen->scrn_virtualX;
1832            screenp->displays[count]->virtualY = conf_screen->scrn_virtualY;
1833        }
1834
1835        /* Now do the per-Display Virtual sizes */
1836        configDisplay(screenp->displays[count], dispptr);
1837    }
1838
1839    /*
1840     * figure out how many videoadaptor references there are and fill them in
1841     */
1842    count = 0;
1843    conf_adaptor = conf_screen->scrn_adaptor_lst;
1844    while (conf_adaptor) {
1845        count++;
1846        conf_adaptor = (XF86ConfAdaptorLinkPtr) conf_adaptor->list.next;
1847    }
1848    screenp->xvadaptors = xnfallocarray(count, sizeof(confXvAdaptorRec));
1849    screenp->numxvadaptors = 0;
1850    conf_adaptor = conf_screen->scrn_adaptor_lst;
1851    while (conf_adaptor) {
1852        if (configXvAdaptor(&(screenp->xvadaptors[screenp->numxvadaptors]),
1853                            conf_adaptor->al_adaptor))
1854            screenp->numxvadaptors++;
1855        conf_adaptor = (XF86ConfAdaptorLinkPtr) conf_adaptor->list.next;
1856    }
1857
1858    if (defaultMonitor) {
1859        xf86Msg(X_DEFAULT, "No monitor specified for screen \"%s\".\n"
1860                "\tUsing a default monitor configuration.\n", screenp->id);
1861    }
1862    return TRUE;
1863}
1864
1865typedef enum {
1866    MON_REDUCEDBLANKING,
1867    MON_MAX_PIX_CLOCK,
1868} MonitorValues;
1869
1870static OptionInfoRec MonitorOptions[] = {
1871    {MON_REDUCEDBLANKING, "ReducedBlanking", OPTV_BOOLEAN,
1872     {0}, FALSE},
1873    {MON_MAX_PIX_CLOCK, "MaxPixClock", OPTV_FREQ,
1874     {0}, FALSE},
1875    {-1, NULL, OPTV_NONE,
1876     {0}, FALSE},
1877};
1878
1879static Bool
1880configMonitor(MonPtr monitorp, XF86ConfMonitorPtr conf_monitor)
1881{
1882    int count;
1883    DisplayModePtr mode, last = NULL;
1884    XF86ConfModeLinePtr cmodep;
1885    XF86ConfModesPtr modes;
1886    XF86ConfModesLinkPtr modeslnk = conf_monitor->mon_modes_sect_lst;
1887    Gamma zeros = { 0.0, 0.0, 0.0 };
1888    float badgamma = 0.0;
1889    double maxPixClock;
1890
1891    xf86Msg(X_CONFIG, "|   |-->Monitor \"%s\"\n", conf_monitor->mon_identifier);
1892    monitorp->id = conf_monitor->mon_identifier;
1893    monitorp->vendor = conf_monitor->mon_vendor;
1894    monitorp->model = conf_monitor->mon_modelname;
1895    monitorp->Modes = NULL;
1896    monitorp->Last = NULL;
1897    monitorp->gamma = zeros;
1898    monitorp->widthmm = conf_monitor->mon_width;
1899    monitorp->heightmm = conf_monitor->mon_height;
1900    monitorp->reducedblanking = FALSE;
1901    monitorp->maxPixClock = 0;
1902    monitorp->options = conf_monitor->mon_option_lst;
1903
1904    /*
1905     * fill in the monitor structure
1906     */
1907    for (count = 0;
1908         count < conf_monitor->mon_n_hsync && count < MAX_HSYNC; count++) {
1909        monitorp->hsync[count].hi = conf_monitor->mon_hsync[count].hi;
1910        monitorp->hsync[count].lo = conf_monitor->mon_hsync[count].lo;
1911    }
1912    monitorp->nHsync = count;
1913    for (count = 0;
1914         count < conf_monitor->mon_n_vrefresh && count < MAX_VREFRESH;
1915         count++) {
1916        monitorp->vrefresh[count].hi = conf_monitor->mon_vrefresh[count].hi;
1917        monitorp->vrefresh[count].lo = conf_monitor->mon_vrefresh[count].lo;
1918    }
1919    monitorp->nVrefresh = count;
1920
1921    /*
1922     * first we collect the mode lines from the UseModes directive
1923     */
1924    while (modeslnk) {
1925        modes = xf86findModes(modeslnk->ml_modes_str,
1926                              xf86configptr->conf_modes_lst);
1927        modeslnk->ml_modes = modes;
1928
1929        /* now add the modes found in the modes
1930           section to the list of modes for this
1931           monitor unless it has been added before
1932           because we are reusing the same section
1933           for another screen */
1934        if (xf86itemNotSublist((GenericListPtr) conf_monitor->mon_modeline_lst,
1935                               (GenericListPtr) modes->mon_modeline_lst)) {
1936            conf_monitor->mon_modeline_lst = (XF86ConfModeLinePtr)
1937                xf86addListItem((GenericListPtr) conf_monitor->mon_modeline_lst,
1938                                (GenericListPtr) modes->mon_modeline_lst);
1939        }
1940        modeslnk = modeslnk->list.next;
1941    }
1942
1943    /*
1944     * we need to hook in the mode lines now
1945     * here both data structures use lists, only our internal one
1946     * is double linked
1947     */
1948    cmodep = conf_monitor->mon_modeline_lst;
1949    while (cmodep) {
1950        mode = xnfcalloc(1, sizeof(DisplayModeRec));
1951        mode->type = 0;
1952        mode->Clock = cmodep->ml_clock;
1953        mode->HDisplay = cmodep->ml_hdisplay;
1954        mode->HSyncStart = cmodep->ml_hsyncstart;
1955        mode->HSyncEnd = cmodep->ml_hsyncend;
1956        mode->HTotal = cmodep->ml_htotal;
1957        mode->VDisplay = cmodep->ml_vdisplay;
1958        mode->VSyncStart = cmodep->ml_vsyncstart;
1959        mode->VSyncEnd = cmodep->ml_vsyncend;
1960        mode->VTotal = cmodep->ml_vtotal;
1961        mode->Flags = cmodep->ml_flags;
1962        mode->HSkew = cmodep->ml_hskew;
1963        mode->VScan = cmodep->ml_vscan;
1964        mode->name = xnfstrdup(cmodep->ml_identifier);
1965        if (last) {
1966            mode->prev = last;
1967            last->next = mode;
1968        }
1969        else {
1970            /*
1971             * this is the first mode
1972             */
1973            monitorp->Modes = mode;
1974            mode->prev = NULL;
1975        }
1976        last = mode;
1977        cmodep = (XF86ConfModeLinePtr) cmodep->list.next;
1978    }
1979    if (last) {
1980        last->next = NULL;
1981    }
1982    monitorp->Last = last;
1983
1984    /* add the (VESA) default modes */
1985    if (!addDefaultModes(monitorp))
1986        return FALSE;
1987
1988    if (conf_monitor->mon_gamma_red > GAMMA_ZERO)
1989        monitorp->gamma.red = conf_monitor->mon_gamma_red;
1990    if (conf_monitor->mon_gamma_green > GAMMA_ZERO)
1991        monitorp->gamma.green = conf_monitor->mon_gamma_green;
1992    if (conf_monitor->mon_gamma_blue > GAMMA_ZERO)
1993        monitorp->gamma.blue = conf_monitor->mon_gamma_blue;
1994
1995    /* Check that the gamma values are within range */
1996    if (monitorp->gamma.red > GAMMA_ZERO &&
1997        (monitorp->gamma.red < GAMMA_MIN || monitorp->gamma.red > GAMMA_MAX)) {
1998        badgamma = monitorp->gamma.red;
1999    }
2000    else if (monitorp->gamma.green > GAMMA_ZERO &&
2001             (monitorp->gamma.green < GAMMA_MIN ||
2002              monitorp->gamma.green > GAMMA_MAX)) {
2003        badgamma = monitorp->gamma.green;
2004    }
2005    else if (monitorp->gamma.blue > GAMMA_ZERO &&
2006             (monitorp->gamma.blue < GAMMA_MIN ||
2007              monitorp->gamma.blue > GAMMA_MAX)) {
2008        badgamma = monitorp->gamma.blue;
2009    }
2010    if (badgamma > GAMMA_ZERO) {
2011        ErrorF("Gamma value %.f is out of range (%.2f - %.1f)\n", badgamma,
2012               GAMMA_MIN, GAMMA_MAX);
2013        return FALSE;
2014    }
2015
2016    xf86ProcessOptions(-1, monitorp->options, MonitorOptions);
2017    xf86GetOptValBool(MonitorOptions, MON_REDUCEDBLANKING,
2018                      &monitorp->reducedblanking);
2019    if (xf86GetOptValFreq(MonitorOptions, MON_MAX_PIX_CLOCK, OPTUNITS_KHZ,
2020                          &maxPixClock) == TRUE) {
2021        monitorp->maxPixClock = (int) maxPixClock;
2022    }
2023
2024    return TRUE;
2025}
2026
2027static int
2028lookupVisual(const char *visname)
2029{
2030    int i;
2031
2032    if (!visname || !*visname)
2033        return -1;
2034
2035    for (i = 0; i <= DirectColor; i++) {
2036        if (!xf86nameCompare(visname, xf86VisualNames[i]))
2037            break;
2038    }
2039
2040    if (i <= DirectColor)
2041        return i;
2042
2043    return -1;
2044}
2045
2046static Bool
2047configDisplay(DispPtr displayp, XF86ConfDisplayPtr conf_display)
2048{
2049    int count = 0;
2050    XF86ModePtr modep;
2051
2052    displayp->frameX0 = conf_display->disp_frameX0;
2053    displayp->frameY0 = conf_display->disp_frameY0;
2054    displayp->virtualX = conf_display->disp_virtualX;
2055    displayp->virtualY = conf_display->disp_virtualY;
2056    displayp->depth = conf_display->disp_depth;
2057    displayp->fbbpp = conf_display->disp_bpp;
2058    displayp->weight.red = conf_display->disp_weight.red;
2059    displayp->weight.green = conf_display->disp_weight.green;
2060    displayp->weight.blue = conf_display->disp_weight.blue;
2061    displayp->blackColour.red = conf_display->disp_black.red;
2062    displayp->blackColour.green = conf_display->disp_black.green;
2063    displayp->blackColour.blue = conf_display->disp_black.blue;
2064    displayp->whiteColour.red = conf_display->disp_white.red;
2065    displayp->whiteColour.green = conf_display->disp_white.green;
2066    displayp->whiteColour.blue = conf_display->disp_white.blue;
2067    displayp->options = conf_display->disp_option_lst;
2068    if (conf_display->disp_visual) {
2069        displayp->defaultVisual = lookupVisual(conf_display->disp_visual);
2070        if (displayp->defaultVisual == -1) {
2071            ErrorF("Invalid visual name: \"%s\"\n", conf_display->disp_visual);
2072            return FALSE;
2073        }
2074    }
2075    else {
2076        displayp->defaultVisual = -1;
2077    }
2078
2079    /*
2080     * now hook in the modes
2081     */
2082    modep = conf_display->disp_mode_lst;
2083    while (modep) {
2084        count++;
2085        modep = (XF86ModePtr) modep->list.next;
2086    }
2087    displayp->modes = xnfallocarray(count + 1, sizeof(char *));
2088    modep = conf_display->disp_mode_lst;
2089    count = 0;
2090    while (modep) {
2091        displayp->modes[count] = modep->mode_name;
2092        count++;
2093        modep = (XF86ModePtr) modep->list.next;
2094    }
2095    displayp->modes[count] = NULL;
2096
2097    return TRUE;
2098}
2099
2100static Bool
2101configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device, Bool active, Bool gpu)
2102{
2103    int i;
2104
2105    if (!conf_device) {
2106        return FALSE;
2107    }
2108
2109    if (active) {
2110        if (gpu)
2111            xf86Msg(X_CONFIG, "|   |-->GPUDevice \"%s\"\n",
2112                    conf_device->dev_identifier);
2113        else
2114            xf86Msg(X_CONFIG, "|   |-->Device \"%s\"\n",
2115                    conf_device->dev_identifier);
2116    } else
2117        xf86Msg(X_CONFIG, "|-->Inactive Device \"%s\"\n",
2118                conf_device->dev_identifier);
2119
2120    devicep->identifier = conf_device->dev_identifier;
2121    devicep->vendor = conf_device->dev_vendor;
2122    devicep->board = conf_device->dev_board;
2123    devicep->chipset = conf_device->dev_chipset;
2124    devicep->ramdac = conf_device->dev_ramdac;
2125    devicep->driver = conf_device->dev_driver;
2126    devicep->active = active;
2127    devicep->videoRam = conf_device->dev_videoram;
2128    devicep->MemBase = conf_device->dev_mem_base;
2129    devicep->IOBase = conf_device->dev_io_base;
2130    devicep->clockchip = conf_device->dev_clockchip;
2131    devicep->busID = conf_device->dev_busid;
2132    devicep->chipID = conf_device->dev_chipid;
2133    devicep->chipRev = conf_device->dev_chiprev;
2134    devicep->options = conf_device->dev_option_lst;
2135    devicep->irq = conf_device->dev_irq;
2136    devicep->screen = conf_device->dev_screen;
2137
2138    for (i = 0; i < MAXDACSPEEDS; i++) {
2139        if (i < CONF_MAXDACSPEEDS)
2140            devicep->dacSpeeds[i] = conf_device->dev_dacSpeeds[i];
2141        else
2142            devicep->dacSpeeds[i] = 0;
2143    }
2144    devicep->numclocks = conf_device->dev_clocks;
2145    if (devicep->numclocks > MAXCLOCKS)
2146        devicep->numclocks = MAXCLOCKS;
2147    for (i = 0; i < devicep->numclocks; i++) {
2148        devicep->clock[i] = conf_device->dev_clock[i];
2149    }
2150    devicep->claimed = FALSE;
2151
2152    return TRUE;
2153}
2154
2155static void
2156configDRI(XF86ConfDRIPtr drip)
2157{
2158    struct group *grp;
2159
2160    xf86ConfigDRI.group = -1;
2161    xf86ConfigDRI.mode = 0;
2162
2163    if (drip) {
2164        if (drip->dri_group_name) {
2165            if ((grp = getgrnam(drip->dri_group_name)))
2166                xf86ConfigDRI.group = grp->gr_gid;
2167        }
2168        else {
2169            if (drip->dri_group >= 0)
2170                xf86ConfigDRI.group = drip->dri_group;
2171        }
2172        xf86ConfigDRI.mode = drip->dri_mode;
2173    }
2174}
2175
2176static void
2177configExtensions(XF86ConfExtensionsPtr conf_ext)
2178{
2179    XF86OptionPtr o;
2180
2181    if (conf_ext && conf_ext->ext_option_lst) {
2182        for (o = conf_ext->ext_option_lst; o; o = xf86NextOption(o)) {
2183            char *name = xf86OptionName(o);
2184            char *val = xf86OptionValue(o);
2185            char *n;
2186            Bool enable = TRUE;
2187
2188            /* Handle "No<ExtensionName>" */
2189            n = xf86NormalizeName(name);
2190            if (strncmp(n, "no", 2) == 0) {
2191                name += 2;
2192                enable = FALSE;
2193            }
2194
2195            if (!val ||
2196                xf86NameCmp(val, "enable") == 0 ||
2197                xf86NameCmp(val, "enabled") == 0 ||
2198                xf86NameCmp(val, "on") == 0 ||
2199                xf86NameCmp(val, "1") == 0 ||
2200                xf86NameCmp(val, "yes") == 0 || xf86NameCmp(val, "true") == 0) {
2201                /* NOTHING NEEDED -- enabling is handled below */
2202            }
2203            else if (xf86NameCmp(val, "disable") == 0 ||
2204                     xf86NameCmp(val, "disabled") == 0 ||
2205                     xf86NameCmp(val, "off") == 0 ||
2206                     xf86NameCmp(val, "0") == 0 ||
2207                     xf86NameCmp(val, "no") == 0 ||
2208                     xf86NameCmp(val, "false") == 0) {
2209                enable = !enable;
2210            }
2211            else {
2212                xf86Msg(X_WARNING, "Ignoring unrecognized value \"%s\"\n", val);
2213                free(n);
2214                continue;
2215            }
2216
2217            if (EnableDisableExtension(name, enable)) {
2218                xf86Msg(X_CONFIG, "Extension \"%s\" is %s\n",
2219                        name, enable ? "enabled" : "disabled");
2220            }
2221            else {
2222                xf86Msg(X_WARNING, "Ignoring unrecognized extension \"%s\"\n",
2223                        name);
2224            }
2225            free(n);
2226        }
2227    }
2228}
2229
2230static Bool
2231configInput(InputInfoPtr inputp, XF86ConfInputPtr conf_input, MessageType from)
2232{
2233    xf86Msg(from, "|-->Input Device \"%s\"\n", conf_input->inp_identifier);
2234    inputp->name = conf_input->inp_identifier;
2235    inputp->driver = conf_input->inp_driver;
2236    inputp->options = conf_input->inp_option_lst;
2237    inputp->attrs = NULL;
2238
2239    return TRUE;
2240}
2241
2242static Bool
2243modeIsPresent(DisplayModePtr mode, MonPtr monitorp)
2244{
2245    DisplayModePtr knownmodes = monitorp->Modes;
2246
2247    /* all I can think of is a linear search... */
2248    while (knownmodes != NULL) {
2249        if (!strcmp(mode->name, knownmodes->name) &&
2250            !(knownmodes->type & M_T_DEFAULT))
2251            return TRUE;
2252        knownmodes = knownmodes->next;
2253    }
2254    return FALSE;
2255}
2256
2257static Bool
2258addDefaultModes(MonPtr monitorp)
2259{
2260    DisplayModePtr mode;
2261    DisplayModePtr last = monitorp->Last;
2262    int i = 0;
2263
2264    for (i = 0; i < xf86NumDefaultModes; i++) {
2265        mode = xf86DuplicateMode(&xf86DefaultModes[i]);
2266        if (!modeIsPresent(mode, monitorp)) {
2267            monitorp->Modes = xf86ModesAdd(monitorp->Modes, mode);
2268            last = mode;
2269        }
2270        else {
2271            free(mode);
2272        }
2273    }
2274    monitorp->Last = last;
2275
2276    return TRUE;
2277}
2278
2279static void
2280checkInput(serverLayoutPtr layout, Bool implicit_layout)
2281{
2282    checkCoreInputDevices(layout, implicit_layout);
2283
2284    /* Unless we're forcing input devices, disable mouse/kbd devices in the
2285     * config. Otherwise the same physical device is added multiple times,
2286     * leading to duplicate events.
2287     */
2288    if (!xf86Info.forceInputDevices && layout->inputs) {
2289        InputInfoPtr *dev = layout->inputs;
2290        BOOL warned = FALSE;
2291
2292        while (*dev) {
2293            if (strcmp((*dev)->driver, "kbd") == 0 ||
2294                strcmp((*dev)->driver, "mouse") == 0 ||
2295                strcmp((*dev)->driver, "vmmouse") == 0) {
2296                InputInfoPtr *current;
2297
2298                if (!warned) {
2299                    xf86Msg(X_WARNING, "Hotplugging is on, devices using "
2300                            "drivers 'kbd', 'mouse' or 'vmmouse' will be disabled.\n");
2301                    warned = TRUE;
2302                }
2303
2304                xf86Msg(X_WARNING, "Disabling %s\n", (*dev)->name);
2305
2306                current = dev;
2307                free(*dev);
2308                *dev = NULL;
2309
2310                do {
2311                    *current = *(current + 1);
2312                    current++;
2313                } while (*current);
2314            }
2315            else
2316                dev++;
2317        }
2318    }
2319}
2320
2321/*
2322 * load the config file and fill the global data structure
2323 */
2324ConfigStatus
2325xf86HandleConfigFile(Bool autoconfig)
2326{
2327#ifdef XSERVER_LIBPCIACCESS
2328    const char *scanptr;
2329    Bool singlecard = 0;
2330#endif
2331    Bool implicit_layout = FALSE;
2332    XF86ConfLayoutPtr layout;
2333
2334    if (!autoconfig) {
2335        char *filename, *dirname, *sysdirname;
2336        const char *filesearch, *dirsearch;
2337        MessageType filefrom = X_DEFAULT;
2338        MessageType dirfrom = X_DEFAULT;
2339
2340        if (!PrivsElevated()) {
2341            filesearch = ALL_CONFIGPATH;
2342            dirsearch = ALL_CONFIGDIRPATH;
2343        }
2344        else {
2345            filesearch = RESTRICTED_CONFIGPATH;
2346            dirsearch = RESTRICTED_CONFIGDIRPATH;
2347        }
2348
2349        if (xf86ConfigFile)
2350            filefrom = X_CMDLINE;
2351        if (xf86ConfigDir)
2352            dirfrom = X_CMDLINE;
2353
2354        xf86initConfigFiles();
2355        sysdirname = xf86openConfigDirFiles(SYS_CONFIGDIRPATH, NULL,
2356                                            PROJECTROOT);
2357        dirname = xf86openConfigDirFiles(dirsearch, xf86ConfigDir, PROJECTROOT);
2358        filename = xf86openConfigFile(filesearch, xf86ConfigFile, PROJECTROOT);
2359        if (filename) {
2360            xf86MsgVerb(filefrom, 0, "Using config file: \"%s\"\n", filename);
2361            xf86ConfigFile = xnfstrdup(filename);
2362        }
2363        else {
2364            if (xf86ConfigFile)
2365                xf86Msg(X_ERROR, "Unable to locate/open config file: \"%s\"\n",
2366                        xf86ConfigFile);
2367        }
2368        if (dirname) {
2369            xf86MsgVerb(dirfrom, 0, "Using config directory: \"%s\"\n",
2370                        dirname);
2371            xf86ConfigDir = xnfstrdup(dirname);
2372        }
2373        else {
2374            if (xf86ConfigDir)
2375                xf86Msg(X_ERROR,
2376                        "Unable to locate/open config directory: \"%s\"\n",
2377                        xf86ConfigDir);
2378        }
2379        if (sysdirname)
2380            xf86MsgVerb(X_DEFAULT, 0, "Using system config directory \"%s\"\n",
2381                        sysdirname);
2382        if (!filename && !dirname && !sysdirname)
2383            return CONFIG_NOFILE;
2384
2385        free(filename);
2386        free(dirname);
2387        free(sysdirname);
2388    }
2389
2390    if ((xf86configptr = xf86readConfigFile()) == NULL) {
2391        xf86Msg(X_ERROR, "Problem parsing the config file\n");
2392        return CONFIG_PARSE_ERROR;
2393    }
2394    xf86closeConfigFile();
2395
2396    /* Initialise a few things. */
2397
2398    /*
2399     * now we convert part of the information contained in the parser
2400     * structures into our own structures.
2401     * The important part here is to figure out which Screen Sections
2402     * in the XF86Config file are active so that we can piece together
2403     * the modes that we need later down the road.
2404     * And while we are at it, we'll decode the rest of the stuff as well
2405     */
2406
2407    /* First check if a layout section is present, and if it is valid. */
2408    FIND_SUITABLE(XF86ConfLayoutPtr, xf86configptr->conf_layout_lst, layout);
2409    if (layout == NULL || xf86ScreenName != NULL) {
2410        XF86ConfScreenPtr screen;
2411
2412        if (xf86ScreenName == NULL) {
2413            xf86Msg(X_DEFAULT,
2414                    "No Layout section.  Using the first Screen section.\n");
2415        }
2416        FIND_SUITABLE (XF86ConfScreenPtr, xf86configptr->conf_screen_lst, screen);
2417        if (!configImpliedLayout(&xf86ConfigLayout,
2418                                 screen,
2419                                 xf86configptr)) {
2420            xf86Msg(X_ERROR, "Unable to determine the screen layout\n");
2421            return CONFIG_PARSE_ERROR;
2422        }
2423        implicit_layout = TRUE;
2424    }
2425    else {
2426        if (xf86configptr->conf_flags != NULL) {
2427            char *dfltlayout = NULL;
2428            void *optlist = xf86configptr->conf_flags->flg_option_lst;
2429
2430            if (optlist && xf86FindOption(optlist, "defaultserverlayout"))
2431                dfltlayout =
2432                    xf86SetStrOption(optlist, "defaultserverlayout", NULL);
2433            if (!configLayout(&xf86ConfigLayout, layout, dfltlayout)) {
2434                xf86Msg(X_ERROR, "Unable to determine the screen layout\n");
2435                return CONFIG_PARSE_ERROR;
2436            }
2437        }
2438        else {
2439            if (!configLayout(&xf86ConfigLayout, layout, NULL)) {
2440                xf86Msg(X_ERROR, "Unable to determine the screen layout\n");
2441                return CONFIG_PARSE_ERROR;
2442            }
2443        }
2444    }
2445
2446    xf86ProcessOptions(-1, xf86ConfigLayout.options, LayoutOptions);
2447#ifdef XSERVER_LIBPCIACCESS
2448    if ((scanptr = xf86GetOptValString(LayoutOptions, LAYOUT_ISOLATEDEVICE))) {
2449        ;                       /* IsolateDevice specified; overrides SingleCard */
2450    }
2451    else {
2452        xf86GetOptValBool(LayoutOptions, LAYOUT_SINGLECARD, &singlecard);
2453        if (singlecard)
2454            scanptr = xf86ConfigLayout.screens->screen->device->busID;
2455    }
2456    if (scanptr) {
2457        if (strncmp(scanptr, "PCI:", 4) != 0) {
2458            xf86Msg(X_WARNING, "Bus types other than PCI not yet isolable.\n"
2459                    "\tIgnoring IsolateDevice option.\n");
2460        }
2461        else
2462            xf86PciIsolateDevice(scanptr);
2463    }
2464#endif
2465    /* Now process everything else */
2466    configServerFlags(xf86configptr->conf_flags, xf86ConfigLayout.options);
2467    configFiles(xf86configptr->conf_files);
2468    configExtensions(xf86configptr->conf_extensions);
2469    configDRI(xf86configptr->conf_dri);
2470
2471    checkInput(&xf86ConfigLayout, implicit_layout);
2472
2473    /*
2474     * Handle some command line options that can override some of the
2475     * ServerFlags settings.
2476     */
2477#ifdef XF86VIDMODE
2478    if (xf86VidModeDisabled)
2479        xf86Info.vidModeEnabled = FALSE;
2480    if (xf86VidModeAllowNonLocal)
2481        xf86Info.vidModeAllowNonLocal = TRUE;
2482#endif
2483
2484    if (xf86AllowMouseOpenFail)
2485        xf86Info.allowMouseOpenFail = TRUE;
2486
2487    return CONFIG_OK;
2488}
2489
2490Bool
2491xf86PathIsSafe(const char *path)
2492{
2493    return (xf86pathIsSafe(path) != 0);
2494}
2495