105b261ecSmrg/*
205b261ecSmrg * Copyright 2000-2002 by Alan Hourihane, Flint Mountain, North Wales.
305b261ecSmrg *
405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its
505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that
605b261ecSmrg * the above copyright notice appear in all copies and that both that
705b261ecSmrg * copyright notice and this permission notice appear in supporting
805b261ecSmrg * documentation, and that the name of Alan Hourihane not be used in
905b261ecSmrg * advertising or publicity pertaining to distribution of the software without
1005b261ecSmrg * specific, written prior permission.  Alan Hourihane makes no representations
1105b261ecSmrg * about the suitability of this software for any purpose.  It is provided
1205b261ecSmrg * "as is" without express or implied warranty.
1305b261ecSmrg *
1405b261ecSmrg * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1605b261ecSmrg * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2005b261ecSmrg * PERFORMANCE OF THIS SOFTWARE.
2105b261ecSmrg *
2205b261ecSmrg * Author:  Alan Hourihane, alanh@fairlite.demon.co.uk
2305b261ecSmrg *
2405b261ecSmrg */
2505b261ecSmrg
2605b261ecSmrg#ifdef HAVE_XORG_CONFIG_H
2705b261ecSmrg#include <xorg-config.h>
2805b261ecSmrg#endif
2905b261ecSmrg
3005b261ecSmrg#include "xf86.h"
3105b261ecSmrg#include "xf86Config.h"
3205b261ecSmrg#include "xf86_OSlib.h"
3305b261ecSmrg#include "xf86Priv.h"
3405b261ecSmrg#define IN_XSERVER
3505b261ecSmrg#include "Configint.h"
3605b261ecSmrg#include "xf86DDC.h"
3765b04b38Smrg#include "xf86pciBus.h"
3805b261ecSmrg#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
3905b261ecSmrg#include "xf86Bus.h"
4005b261ecSmrg#include "xf86Sbus.h"
4105b261ecSmrg#endif
42f7df2e56Smrg#include "misc.h"
437e31ba66Smrg#include "loaderProcs.h"
4405b261ecSmrg
4505b261ecSmrgtypedef struct _DevToConfig {
4605b261ecSmrg    GDevRec GDev;
47f7df2e56Smrg    struct pci_device *pVideo;
4805b261ecSmrg#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
4905b261ecSmrg    sbusDevicePtr sVideo;
5005b261ecSmrg#endif
5105b261ecSmrg    int iDriver;
5205b261ecSmrg} DevToConfigRec, *DevToConfigPtr;
5305b261ecSmrg
5405b261ecSmrgstatic DevToConfigPtr DevToConfig = NULL;
5505b261ecSmrgstatic int nDevToConfig = 0, CurrentDriver;
5605b261ecSmrg
574202a189Smrgxf86MonPtr ConfiguredMonitor;
5805b261ecSmrgBool xf86DoConfigurePass1 = TRUE;
5905b261ecSmrgstatic Bool foundMouse = FALSE;
6005b261ecSmrg
6165b04b38Smrg#if   defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
62f7df2e56Smrgstatic const char *DFLT_MOUSE_DEV = "/dev/sysmouse";
63f7df2e56Smrgstatic const char *DFLT_MOUSE_PROTO = "auto";
647e31ba66Smrg#elif defined(__linux__)
65f7df2e56Smrgstatic const char *DFLT_MOUSE_DEV = "/dev/input/mice";
66f7df2e56Smrgstatic const char *DFLT_MOUSE_PROTO = "auto";
67f7df2e56Smrg#elif defined(WSCONS_SUPPORT)
68f7df2e56Smrgstatic const char *DFLT_MOUSE_DEV = "/dev/wsmouse";
69f7df2e56Smrgstatic const char *DFLT_MOUSE_PROTO = "wsmouse";
7005b261ecSmrg#else
71f7df2e56Smrgstatic const char *DFLT_MOUSE_DEV = "/dev/mouse";
72f7df2e56Smrgstatic const char *DFLT_MOUSE_PROTO = "auto";
7305b261ecSmrg#endif
7405b261ecSmrg
754202a189Smrg/*
764202a189Smrg * This is called by the driver, either through xf86Match???Instances() or
774202a189Smrg * directly.  We allocate a GDevRec and fill it in as much as we can, letting
784202a189Smrg * the caller fill in the rest and/or change it as it sees fit.
794202a189Smrg */
804202a189SmrgGDevPtr
81f7df2e56Smrgxf86AddBusDeviceToConfigure(const char *driver, BusType bus, void *busData,
82f7df2e56Smrg                            int chipset)
834202a189Smrg{
844202a189Smrg    int ret, i, j;
85f7df2e56Smrg    char *lower_driver;
864202a189Smrg
874202a189Smrg    if (!xf86DoConfigure || !xf86DoConfigurePass1)
88f7df2e56Smrg        return NULL;
894202a189Smrg
904202a189Smrg    /* Check for duplicates */
91f7df2e56Smrg    for (i = 0; i < nDevToConfig; i++) {
9265b04b38Smrg        switch (bus) {
93f7df2e56Smrg#ifdef XSERVER_LIBPCIACCESS
94f7df2e56Smrg        case BUS_PCI:
95f7df2e56Smrg            ret = xf86PciConfigure(busData, DevToConfig[i].pVideo);
96f7df2e56Smrg            break;
97f7df2e56Smrg#endif
9865b04b38Smrg#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
99f7df2e56Smrg        case BUS_SBUS:
100f7df2e56Smrg            ret = xf86SbusConfigure(busData, DevToConfig[i].sVideo);
101f7df2e56Smrg            break;
10265b04b38Smrg#endif
1030623337fSmrg#if defined(__arm32__) || defined(__arm__)
104f7df2e56Smrg        case BUS_ISA:
105f7df2e56Smrg            break;
106eec908bbSmrg#endif
107f7df2e56Smrg        default:
108f7df2e56Smrg            return NULL;
10965b04b38Smrg        }
11065b04b38Smrg        if (ret == 0)
11165b04b38Smrg            goto out;
112fcca736fSmacallan    }
1134202a189Smrg
1144202a189Smrg    /* Allocate new structure occurrence */
1154202a189Smrg    i = nDevToConfig++;
1164202a189Smrg    DevToConfig =
117f7df2e56Smrg        xnfreallocarray(DevToConfig, nDevToConfig, sizeof(DevToConfigRec));
1184202a189Smrg    memset(DevToConfig + i, 0, sizeof(DevToConfigRec));
1194202a189Smrg
1204202a189Smrg    DevToConfig[i].GDev.chipID =
121f7df2e56Smrg        DevToConfig[i].GDev.chipRev = DevToConfig[i].GDev.irq = -1;
1224202a189Smrg
1234202a189Smrg    DevToConfig[i].iDriver = CurrentDriver;
1244202a189Smrg
1254202a189Smrg    /* Fill in what we know, converting the driver name to lower case */
126f7df2e56Smrg    lower_driver = xnfalloc(strlen(driver) + 1);
127f7df2e56Smrg    for (j = 0; (lower_driver[j] = tolower(driver[j])); j++);
128f7df2e56Smrg    DevToConfig[i].GDev.driver = lower_driver;
1294202a189Smrg
1304202a189Smrg    switch (bus) {
131f7df2e56Smrg#ifdef XSERVER_LIBPCIACCESS
132f7df2e56Smrg    case BUS_PCI:
133f7df2e56Smrg	DevToConfig[i].pVideo = busData;
134f7df2e56Smrg        xf86PciConfigureNewDev(busData, DevToConfig[i].pVideo,
135f7df2e56Smrg                               &DevToConfig[i].GDev, &chipset);
136f7df2e56Smrg        break;
137f7df2e56Smrg#endif
13865b04b38Smrg#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
139f7df2e56Smrg    case BUS_SBUS:
140f7df2e56Smrg	DevToConfig[i].sVideo = busData;
141f7df2e56Smrg        xf86SbusConfigureNewDev(busData, DevToConfig[i].sVideo,
142f7df2e56Smrg                                &DevToConfig[i].GDev);
143f7df2e56Smrg        break;
14465b04b38Smrg#endif
1450623337fSmrg#if defined(__arm32__) || defined(__arm__)
146f7df2e56Smrg    case BUS_ISA:
147f7df2e56Smrg	DevToConfig[i].GDev.busID = xnfalloc(6);
1480d6c9d2dSjoerg	strcpy((char *)DevToConfig[i].GDev.busID, "ISA");
149f7df2e56Smrg	break;
150eec908bbSmrg#endif
151f7df2e56Smrg    default:
152f7df2e56Smrg        break;
15305b261ecSmrg    }
15405b261ecSmrg
15505b261ecSmrg    /* Get driver's available options */
15605b261ecSmrg    if (xf86DriverList[CurrentDriver]->AvailableOptions)
157f7df2e56Smrg        DevToConfig[i].GDev.options = (OptionInfoPtr)
158f7df2e56Smrg            (*xf86DriverList[CurrentDriver]->AvailableOptions) (chipset, bus);
15905b261ecSmrg
1604202a189Smrg    return &DevToConfig[i].GDev;
16105b261ecSmrg
162f7df2e56Smrg out:
1634202a189Smrg    return NULL;
16405b261ecSmrg}
16505b261ecSmrg
16605b261ecSmrgstatic XF86ConfInputPtr
167f7df2e56SmrgconfigureInputSection(void)
16805b261ecSmrg{
16905b261ecSmrg    XF86ConfInputPtr mouse = NULL;
17005b261ecSmrg
1717e31ba66Smrg    parsePrologue(XF86ConfInputPtr, XF86ConfInputRec);
172f7df2e56Smrg
173f7df2e56Smrg    ptr->inp_identifier = xnfstrdup("Keyboard0");
174f7df2e56Smrg    ptr->inp_driver = xnfstrdup("kbd");
17505b261ecSmrg    ptr->list.next = NULL;
1769cf0a3efSmacallan#if defined(WSCONS_SUPPORT) && !defined(__i386__) && !defined(__amd64__)
1779cf0a3efSmacallan    ptr->inp_option_lst = xf86addNewOption(ptr->inp_option_lst,
1789cf0a3efSmacallan        xstrdup("Protocol"), "wskbd");
1799cf0a3efSmacallan    ptr->inp_option_lst = xf86addNewOption(ptr->inp_option_lst,
1809cf0a3efSmacallan        xstrdup("Device"), "/dev/wskbd");
1819cf0a3efSmacallan#endif
18205b261ecSmrg
18305b261ecSmrg    /* Crude mechanism to auto-detect mouse (os dependent) */
184f7df2e56Smrg    {
185f7df2e56Smrg        int fd;
18605b261ecSmrg
187f7df2e56Smrg        fd = open(DFLT_MOUSE_DEV, 0);
188f7df2e56Smrg        if (fd != -1) {
189f7df2e56Smrg            foundMouse = TRUE;
190f7df2e56Smrg            close(fd);
191f7df2e56Smrg        }
19205b261ecSmrg    }
19305b261ecSmrg
1944202a189Smrg    mouse = calloc(1, sizeof(XF86ConfInputRec));
195f7df2e56Smrg    mouse->inp_identifier = xnfstrdup("Mouse0");
196f7df2e56Smrg    mouse->inp_driver = xnfstrdup("mouse");
197f7df2e56Smrg    mouse->inp_option_lst =
198f7df2e56Smrg        xf86addNewOption(mouse->inp_option_lst, xnfstrdup("Protocol"),
199f7df2e56Smrg                         xnfstrdup(DFLT_MOUSE_PROTO));
200f7df2e56Smrg    mouse->inp_option_lst =
201f7df2e56Smrg        xf86addNewOption(mouse->inp_option_lst, xnfstrdup("Device"),
202f7df2e56Smrg                         xnfstrdup(DFLT_MOUSE_DEV));
203f7df2e56Smrg    mouse->inp_option_lst =
204f7df2e56Smrg        xf86addNewOption(mouse->inp_option_lst, xnfstrdup("ZAxisMapping"),
205f7df2e56Smrg                         xnfstrdup("4 5 6 7"));
206f7df2e56Smrg    ptr = (XF86ConfInputPtr) xf86addListItem((glp) ptr, (glp) mouse);
20705b261ecSmrg    return ptr;
20805b261ecSmrg}
20905b261ecSmrg
21005b261ecSmrgstatic XF86ConfScreenPtr
211f7df2e56SmrgconfigureScreenSection(int screennum)
21205b261ecSmrg{
21305b261ecSmrg    int i;
214f7df2e56Smrg    int depths[] = { 1, 4, 8, 15, 16, 24 /*, 32 */  };
215f7df2e56Smrg    char *tmp;
2167e31ba66Smrg    parsePrologue(XF86ConfScreenPtr, XF86ConfScreenRec);
217f7df2e56Smrg
218f7df2e56Smrg    XNFasprintf(&tmp, "Screen%d", screennum);
219f7df2e56Smrg    ptr->scrn_identifier = tmp;
220f7df2e56Smrg    XNFasprintf(&tmp, "Monitor%d", screennum);
221f7df2e56Smrg    ptr->scrn_monitor_str = tmp;
222f7df2e56Smrg    XNFasprintf(&tmp, "Card%d", screennum);
223f7df2e56Smrg    ptr->scrn_device_str = tmp;
224f7df2e56Smrg
2257e31ba66Smrg    for (i = 0; i < ARRAY_SIZE(depths); i++) {
226f7df2e56Smrg        XF86ConfDisplayPtr conf_display;
227f7df2e56Smrg
228f7df2e56Smrg        conf_display = calloc(1, sizeof(XF86ConfDisplayRec));
229f7df2e56Smrg        conf_display->disp_depth = depths[i];
230f7df2e56Smrg        conf_display->disp_black.red = conf_display->disp_white.red = -1;
231f7df2e56Smrg        conf_display->disp_black.green = conf_display->disp_white.green = -1;
232f7df2e56Smrg        conf_display->disp_black.blue = conf_display->disp_white.blue = -1;
233f7df2e56Smrg        ptr->scrn_display_lst = (XF86ConfDisplayPtr) xf86addListItem((glp) ptr->
234f7df2e56Smrg                                                                     scrn_display_lst,
235f7df2e56Smrg                                                                     (glp)
236f7df2e56Smrg                                                                     conf_display);
23705b261ecSmrg    }
23805b261ecSmrg
23905b261ecSmrg    return ptr;
24005b261ecSmrg}
24105b261ecSmrg
242f7df2e56Smrgstatic const char *
2434202a189SmrgoptionTypeToString(OptionValueType type)
24405b261ecSmrg{
24505b261ecSmrg    switch (type) {
24605b261ecSmrg    case OPTV_NONE:
24705b261ecSmrg        return "";
24805b261ecSmrg    case OPTV_INTEGER:
24905b261ecSmrg        return "<i>";
25005b261ecSmrg    case OPTV_STRING:
25105b261ecSmrg        return "<str>";
25205b261ecSmrg    case OPTV_ANYSTR:
253f7df2e56Smrg        return "[<str>]";
25405b261ecSmrg    case OPTV_REAL:
25505b261ecSmrg        return "<f>";
25605b261ecSmrg    case OPTV_BOOLEAN:
25705b261ecSmrg        return "[<bool>]";
25805b261ecSmrg    case OPTV_FREQ:
25905b261ecSmrg        return "<freq>";
2604202a189Smrg    case OPTV_PERCENT:
2614202a189Smrg        return "<percent>";
26205b261ecSmrg    default:
26305b261ecSmrg        return "";
26405b261ecSmrg    }
26505b261ecSmrg}
26605b261ecSmrg
26705b261ecSmrgstatic XF86ConfDevicePtr
268f7df2e56SmrgconfigureDeviceSection(int screennum)
26905b261ecSmrg{
27005b261ecSmrg    OptionInfoPtr p;
27105b261ecSmrg    int i = 0;
272f7df2e56Smrg    char *identifier;
273f7df2e56Smrg
2747e31ba66Smrg    parsePrologue(XF86ConfDevicePtr, XF86ConfDeviceRec);
27505b261ecSmrg
2767e31ba66Smrg    /* Move device info to parser structure */
277f7df2e56Smrg   if (asprintf(&identifier, "Card%d", screennum) == -1)
278f7df2e56Smrg        identifier = NULL;
279f7df2e56Smrg    ptr->dev_identifier = identifier;
28005b261ecSmrg    ptr->dev_chipset = DevToConfig[screennum].GDev.chipset;
28105b261ecSmrg    ptr->dev_busid = DevToConfig[screennum].GDev.busID;
28205b261ecSmrg    ptr->dev_driver = DevToConfig[screennum].GDev.driver;
28305b261ecSmrg    ptr->dev_ramdac = DevToConfig[screennum].GDev.ramdac;
284f7df2e56Smrg    for (i = 0; i < MAXDACSPEEDS; i++)
28505b261ecSmrg        ptr->dev_dacSpeeds[i] = DevToConfig[screennum].GDev.dacSpeeds[i];
28605b261ecSmrg    ptr->dev_videoram = DevToConfig[screennum].GDev.videoRam;
28705b261ecSmrg    ptr->dev_mem_base = DevToConfig[screennum].GDev.MemBase;
28805b261ecSmrg    ptr->dev_io_base = DevToConfig[screennum].GDev.IOBase;
28905b261ecSmrg    ptr->dev_clockchip = DevToConfig[screennum].GDev.clockchip;
290f7df2e56Smrg    for (i = 0; (i < MAXCLOCKS) && (i < DevToConfig[screennum].GDev.numclocks);
291f7df2e56Smrg         i++)
29205b261ecSmrg        ptr->dev_clock[i] = DevToConfig[screennum].GDev.clock[i];
29305b261ecSmrg    ptr->dev_clocks = i;
29405b261ecSmrg    ptr->dev_chipid = DevToConfig[screennum].GDev.chipID;
29505b261ecSmrg    ptr->dev_chiprev = DevToConfig[screennum].GDev.chipRev;
29605b261ecSmrg    ptr->dev_irq = DevToConfig[screennum].GDev.irq;
29705b261ecSmrg
29805b261ecSmrg    /* Make sure older drivers don't segv */
29905b261ecSmrg    if (DevToConfig[screennum].GDev.options) {
300f7df2e56Smrg        /* Fill in the available driver options for people to use */
301f7df2e56Smrg        const char *descrip =
302f7df2e56Smrg            "        ### Available Driver options are:-\n"
303f7df2e56Smrg            "        ### Values: <i>: integer, <f>: float, "
304f7df2e56Smrg            "<bool>: \"True\"/\"False\",\n"
305f7df2e56Smrg            "        ### <string>: \"String\", <freq>: \"<f> Hz/kHz/MHz\",\n"
306f7df2e56Smrg            "        ### <percent>: \"<f>%\"\n"
307f7df2e56Smrg            "        ### [arg]: arg optional\n";
308f7df2e56Smrg        ptr->dev_comment = xnfstrdup(descrip);
309f7df2e56Smrg        if (ptr->dev_comment) {
310f7df2e56Smrg            for (p = DevToConfig[screennum].GDev.options; p->name != NULL; p++) {
311f7df2e56Smrg                char *p_e;
312f7df2e56Smrg                const char *prefix = "        #Option     ";
313f7df2e56Smrg                const char *middle = " \t# ";
314f7df2e56Smrg                const char *suffix = "\n";
315f7df2e56Smrg                const char *opttype = optionTypeToString(p->type);
316f7df2e56Smrg                char *optname;
317f7df2e56Smrg                int len = strlen(ptr->dev_comment) + strlen(prefix) +
318f7df2e56Smrg                    strlen(middle) + strlen(suffix) + 1;
319f7df2e56Smrg
320f7df2e56Smrg                if (asprintf(&optname, "\"%s\"", p->name) == -1)
321f7df2e56Smrg                    break;
322f7df2e56Smrg
323f7df2e56Smrg                len += max(20, strlen(optname));
324f7df2e56Smrg                len += strlen(opttype);
325f7df2e56Smrg
326f7df2e56Smrg                ptr->dev_comment = realloc(ptr->dev_comment, len);
327d566a54bSmrg                if (!ptr->dev_comment) {
328d566a54bSmrg                    free(optname);
329f7df2e56Smrg                    break;
330d566a54bSmrg                }
331f7df2e56Smrg                p_e = ptr->dev_comment + strlen(ptr->dev_comment);
332f7df2e56Smrg                sprintf(p_e, "%s%-20s%s%s%s", prefix, optname, middle,
333f7df2e56Smrg                        opttype, suffix);
334f7df2e56Smrg                free(optname);
335f7df2e56Smrg            }
336f7df2e56Smrg        }
33705b261ecSmrg    }
33805b261ecSmrg
33905b261ecSmrg    return ptr;
34005b261ecSmrg}
34105b261ecSmrg
34205b261ecSmrgstatic XF86ConfLayoutPtr
343f7df2e56SmrgconfigureLayoutSection(void)
34405b261ecSmrg{
34505b261ecSmrg    int scrnum = 0;
34605b261ecSmrg
3477e31ba66Smrg    parsePrologue(XF86ConfLayoutPtr, XF86ConfLayoutRec);
348f7df2e56Smrg
3497e31ba66Smrg    ptr->lay_identifier = "X.org Configured";
35005b261ecSmrg
35105b261ecSmrg    {
352f7df2e56Smrg        XF86ConfInputrefPtr iptr;
353f7df2e56Smrg
354f7df2e56Smrg        iptr = malloc(sizeof(XF86ConfInputrefRec));
355f7df2e56Smrg        iptr->list.next = NULL;
356f7df2e56Smrg        iptr->iref_option_lst = NULL;
357f7df2e56Smrg        iptr->iref_inputdev_str = xnfstrdup("Mouse0");
358f7df2e56Smrg        iptr->iref_option_lst =
359f7df2e56Smrg            xf86addNewOption(iptr->iref_option_lst, xnfstrdup("CorePointer"),
360f7df2e56Smrg                             NULL);
361f7df2e56Smrg        ptr->lay_input_lst = (XF86ConfInputrefPtr)
362f7df2e56Smrg            xf86addListItem((glp) ptr->lay_input_lst, (glp) iptr);
36305b261ecSmrg    }
36405b261ecSmrg
36505b261ecSmrg    {
366f7df2e56Smrg        XF86ConfInputrefPtr iptr;
367f7df2e56Smrg
368f7df2e56Smrg        iptr = malloc(sizeof(XF86ConfInputrefRec));
369f7df2e56Smrg        iptr->list.next = NULL;
370f7df2e56Smrg        iptr->iref_option_lst = NULL;
371f7df2e56Smrg        iptr->iref_inputdev_str = xnfstrdup("Keyboard0");
372f7df2e56Smrg        iptr->iref_option_lst =
373f7df2e56Smrg            xf86addNewOption(iptr->iref_option_lst, xnfstrdup("CoreKeyboard"),
374f7df2e56Smrg                             NULL);
375f7df2e56Smrg        ptr->lay_input_lst = (XF86ConfInputrefPtr)
376f7df2e56Smrg            xf86addListItem((glp) ptr->lay_input_lst, (glp) iptr);
37705b261ecSmrg    }
37805b261ecSmrg
379f7df2e56Smrg    for (scrnum = 0; scrnum < nDevToConfig; scrnum++) {
380f7df2e56Smrg        XF86ConfAdjacencyPtr aptr;
381f7df2e56Smrg        char *tmp;
382f7df2e56Smrg
383f7df2e56Smrg        aptr = malloc(sizeof(XF86ConfAdjacencyRec));
384f7df2e56Smrg        aptr->list.next = NULL;
385f7df2e56Smrg        aptr->adj_x = 0;
386f7df2e56Smrg        aptr->adj_y = 0;
387f7df2e56Smrg        aptr->adj_scrnum = scrnum;
388f7df2e56Smrg        XNFasprintf(&tmp, "Screen%d", scrnum);
389f7df2e56Smrg        aptr->adj_screen_str = tmp;
390f7df2e56Smrg        if (scrnum == 0) {
391f7df2e56Smrg            aptr->adj_where = CONF_ADJ_ABSOLUTE;
392f7df2e56Smrg            aptr->adj_refscreen = NULL;
393f7df2e56Smrg        }
394f7df2e56Smrg        else {
395f7df2e56Smrg            aptr->adj_where = CONF_ADJ_RIGHTOF;
396f7df2e56Smrg            XNFasprintf(&tmp, "Screen%d", scrnum - 1);
397f7df2e56Smrg            aptr->adj_refscreen = tmp;
398f7df2e56Smrg        }
399f7df2e56Smrg        ptr->lay_adjacency_lst =
400f7df2e56Smrg            (XF86ConfAdjacencyPtr) xf86addListItem((glp) ptr->lay_adjacency_lst,
401f7df2e56Smrg                                                   (glp) aptr);
40205b261ecSmrg    }
40305b261ecSmrg
40405b261ecSmrg    return ptr;
40505b261ecSmrg}
40605b261ecSmrg
40705b261ecSmrgstatic XF86ConfFlagsPtr
408f7df2e56SmrgconfigureFlagsSection(void)
40905b261ecSmrg{
4107e31ba66Smrg    parsePrologue(XF86ConfFlagsPtr, XF86ConfFlagsRec);
41105b261ecSmrg
4127e31ba66Smrg    return ptr;
41305b261ecSmrg}
41405b261ecSmrg
41505b261ecSmrgstatic XF86ConfModulePtr
416f7df2e56SmrgconfigureModuleSection(void)
41705b261ecSmrg{
418f7df2e56Smrg    const char **elist, **el;
419f7df2e56Smrg
4207e31ba66Smrg    parsePrologue(XF86ConfModulePtr, XF86ConfModuleRec);
42105b261ecSmrg
4227e31ba66Smrg    elist = LoaderListDir("extensions", NULL);
42305b261ecSmrg    if (elist) {
424f7df2e56Smrg        for (el = elist; *el; el++) {
425f7df2e56Smrg            XF86LoadPtr module;
426f7df2e56Smrg
427f7df2e56Smrg            module = calloc(1, sizeof(XF86LoadRec));
428f7df2e56Smrg            module->load_name = *el;
429f7df2e56Smrg            ptr->mod_load_lst = (XF86LoadPtr) xf86addListItem((glp) ptr->
430f7df2e56Smrg                                                              mod_load_lst,
431f7df2e56Smrg                                                              (glp) module);
432f7df2e56Smrg        }
433f7df2e56Smrg        free(elist);
43405b261ecSmrg    }
43505b261ecSmrg
43605b261ecSmrg    return ptr;
43705b261ecSmrg}
43805b261ecSmrg
43905b261ecSmrgstatic XF86ConfFilesPtr
440f7df2e56SmrgconfigureFilesSection(void)
44105b261ecSmrg{
4427e31ba66Smrg    parsePrologue(XF86ConfFilesPtr, XF86ConfFilesRec);
443f7df2e56Smrg
4447e31ba66Smrg    if (xf86ModulePath)
445f7df2e56Smrg        ptr->file_modulepath = xnfstrdup(xf86ModulePath);
446f7df2e56Smrg    if (defaultFontPath)
447f7df2e56Smrg        ptr->file_fontpath = xnfstrdup(defaultFontPath);
44805b261ecSmrg
44905b261ecSmrg    return ptr;
45005b261ecSmrg}
45105b261ecSmrg
45205b261ecSmrgstatic XF86ConfMonitorPtr
453f7df2e56SmrgconfigureMonitorSection(int screennum)
45405b261ecSmrg{
455f7df2e56Smrg    char *tmp;
4567e31ba66Smrg    parsePrologue(XF86ConfMonitorPtr, XF86ConfMonitorRec);
45705b261ecSmrg
458f7df2e56Smrg    XNFasprintf(&tmp, "Monitor%d", screennum);
459f7df2e56Smrg    ptr->mon_identifier = tmp;
460f7df2e56Smrg    ptr->mon_vendor = xnfstrdup("Monitor Vendor");
461f7df2e56Smrg    ptr->mon_modelname = xnfstrdup("Monitor Model");
46205b261ecSmrg
46305b261ecSmrg    return ptr;
46405b261ecSmrg}
46505b261ecSmrg
4664202a189Smrg/* Initialize Configure Monitor from Detailed Timing Block */
467f7df2e56Smrgstatic void
468f7df2e56Smrghandle_detailed_input(struct detailed_monitor_section *det_mon, void *data)
4694202a189Smrg{
4704202a189Smrg    XF86ConfMonitorPtr ptr = (XF86ConfMonitorPtr) data;
4714202a189Smrg
4724202a189Smrg    switch (det_mon->type) {
4734202a189Smrg    case DS_NAME:
4744202a189Smrg        ptr->mon_modelname = realloc(ptr->mon_modelname,
475f7df2e56Smrg                                     strlen((char *) (det_mon->section.name)) +
4764202a189Smrg                                     1);
477f7df2e56Smrg        strcpy(ptr->mon_modelname, (char *) (det_mon->section.name));
4784202a189Smrg        break;
4794202a189Smrg    case DS_RANGES:
480f7df2e56Smrg        ptr->mon_hsync[ptr->mon_n_hsync].lo = det_mon->section.ranges.min_h;
481f7df2e56Smrg        ptr->mon_hsync[ptr->mon_n_hsync].hi = det_mon->section.ranges.max_h;
4824202a189Smrg        ptr->mon_n_vrefresh = 1;
483f7df2e56Smrg        ptr->mon_vrefresh[ptr->mon_n_hsync].lo = det_mon->section.ranges.min_v;
484f7df2e56Smrg        ptr->mon_vrefresh[ptr->mon_n_hsync].hi = det_mon->section.ranges.max_v;
4854202a189Smrg        ptr->mon_n_hsync++;
4864202a189Smrg    default:
4874202a189Smrg        break;
4884202a189Smrg    }
4894202a189Smrg}
4904202a189Smrg
49105b261ecSmrgstatic XF86ConfMonitorPtr
492f7df2e56SmrgconfigureDDCMonitorSection(int screennum)
49305b261ecSmrg{
49405b261ecSmrg    int len, mon_width, mon_height;
495f7df2e56Smrg
49605b261ecSmrg#define displaySizeMaxLen 80
49705b261ecSmrg    char displaySize_string[displaySizeMaxLen];
49805b261ecSmrg    int displaySizeLen;
499f7df2e56Smrg    char *tmp;
50005b261ecSmrg
5017e31ba66Smrg    parsePrologue(XF86ConfMonitorPtr, XF86ConfMonitorRec);
50205b261ecSmrg
503f7df2e56Smrg    XNFasprintf(&tmp, "Monitor%d", screennum);
504f7df2e56Smrg    ptr->mon_identifier = tmp;
505f7df2e56Smrg    ptr->mon_vendor = xnfstrdup(ConfiguredMonitor->vendor.name);
50665b04b38Smrg    XNFasprintf(&ptr->mon_modelname, "%x", ConfiguredMonitor->vendor.prod_id);
50705b261ecSmrg
50805b261ecSmrg    /* features in centimetres, we want millimetres */
509f7df2e56Smrg    mon_width = 10 * ConfiguredMonitor->features.hsize;
510f7df2e56Smrg    mon_height = 10 * ConfiguredMonitor->features.vsize;
51105b261ecSmrg
51205b261ecSmrg#ifdef CONFIGURE_DISPLAYSIZE
513f7df2e56Smrg    ptr->mon_width = mon_width;
51405b261ecSmrg    ptr->mon_height = mon_height;
51505b261ecSmrg#else
51605b261ecSmrg    if (mon_width && mon_height) {
517f7df2e56Smrg        /* when values available add DisplaySize option AS A COMMENT */
518f7df2e56Smrg
519f7df2e56Smrg        displaySizeLen = snprintf(displaySize_string, displaySizeMaxLen,
520f7df2e56Smrg                                  "\t#DisplaySize\t%5d %5d\t# mm\n",
521f7df2e56Smrg                                  mon_width, mon_height);
522f7df2e56Smrg
523f7df2e56Smrg        if (displaySizeLen > 0 && displaySizeLen < displaySizeMaxLen) {
524f7df2e56Smrg            if (ptr->mon_comment) {
525f7df2e56Smrg                len = strlen(ptr->mon_comment);
526f7df2e56Smrg            }
527f7df2e56Smrg            else {
528f7df2e56Smrg                len = 0;
529f7df2e56Smrg            }
530f7df2e56Smrg            if ((ptr->mon_comment =
531f7df2e56Smrg                 realloc(ptr->mon_comment,
532f7df2e56Smrg                         len + strlen(displaySize_string) + 1))) {
533f7df2e56Smrg                strcpy(ptr->mon_comment + len, displaySize_string);
534f7df2e56Smrg            }
535f7df2e56Smrg        }
53605b261ecSmrg    }
537f7df2e56Smrg#endif                          /* def CONFIGURE_DISPLAYSIZE */
53805b261ecSmrg
539f7df2e56Smrg    xf86ForEachDetailedBlock(ConfiguredMonitor, handle_detailed_input, ptr);
54005b261ecSmrg
54105b261ecSmrg    if (ConfiguredMonitor->features.dpms) {
542f7df2e56Smrg        ptr->mon_option_lst =
543f7df2e56Smrg            xf86addNewOption(ptr->mon_option_lst, xnfstrdup("DPMS"), NULL);
54405b261ecSmrg    }
54505b261ecSmrg
54605b261ecSmrg    return ptr;
54705b261ecSmrg}
54805b261ecSmrg
5497e31ba66Smrgstatic int
5507e31ba66Smrgis_fallback(const char *s)
5517e31ba66Smrg{
5527e31ba66Smrg    /* later entries are less preferred */
5537e31ba66Smrg    const char *fallback[5] = { "modesetting", "fbdev", "vesa",  "wsfb", NULL };
5547e31ba66Smrg    int i;
5557e31ba66Smrg
5567e31ba66Smrg    for (i = 0; fallback[i]; i++)
5577e31ba66Smrg	if (strstr(s, fallback[i]))
5587e31ba66Smrg	    return i;
5597e31ba66Smrg
5607e31ba66Smrg    return -1;
5617e31ba66Smrg}
5627e31ba66Smrg
5637e31ba66Smrgstatic int
5647e31ba66Smrgdriver_sort(const void *_l, const void *_r)
5657e31ba66Smrg{
5667e31ba66Smrg    const char *l = *(const char **)_l;
5677e31ba66Smrg    const char *r = *(const char **)_r;
5687e31ba66Smrg    int left = is_fallback(l);
5697e31ba66Smrg    int right = is_fallback(r);
5707e31ba66Smrg
5717e31ba66Smrg    /* neither is a fallback, asciibetize */
5727e31ba66Smrg    if (left == -1 && right == -1)
5737e31ba66Smrg	return strcmp(l, r);
5747e31ba66Smrg
5757e31ba66Smrg    /* left is a fallback, right is not */
5767e31ba66Smrg    if (left >= 0 && right == -1)
5777e31ba66Smrg	return 1;
5787e31ba66Smrg
5797e31ba66Smrg    /* right is a fallback, left is not */
5807e31ba66Smrg    if (right >= 0 && left == -1)
5817e31ba66Smrg	return -1;
5827e31ba66Smrg
5837e31ba66Smrg    /* both are fallbacks, decide which is worse */
5847e31ba66Smrg    return left - right;
5857e31ba66Smrg}
5867e31ba66Smrg
5877e31ba66Smrgstatic void
5887e31ba66Smrgfixup_video_driver_list(const char **drivers)
5897e31ba66Smrg{
5907e31ba66Smrg    const char **end;
5917e31ba66Smrg
5927e31ba66Smrg    /* walk to the end of the list */
5937e31ba66Smrg    for (end = drivers; *end && **end; end++);
5947e31ba66Smrg
5957e31ba66Smrg    qsort(drivers, end - drivers, sizeof(const char *), driver_sort);
5967e31ba66Smrg}
5977e31ba66Smrg
5987e31ba66Smrgstatic const char **
5997e31ba66SmrgGenerateDriverList(void)
6007e31ba66Smrg{
6017e31ba66Smrg    const char **ret;
6027e31ba66Smrg    static const char *patlist[] = { "(.*)_drv\\.so", NULL };
6037e31ba66Smrg    ret = LoaderListDir("drivers", patlist);
6047e31ba66Smrg
6057e31ba66Smrg    /* fix up the probe order for video drivers */
6067e31ba66Smrg    if (ret != NULL)
6077e31ba66Smrg        fixup_video_driver_list(ret);
6087e31ba66Smrg
6097e31ba66Smrg    return ret;
6107e31ba66Smrg}
6117e31ba66Smrg
61205b261ecSmrgvoid
6134642e01fSmrgDoConfigure(void)
61405b261ecSmrg{
615f7df2e56Smrg    int i, j, screennum = -1;
616f7df2e56Smrg    const char *home = NULL;
6174642e01fSmrg    char filename[PATH_MAX];
618f7df2e56Smrg    const char *addslash = "";
61905b261ecSmrg    XF86ConfigPtr xf86config = NULL;
620f7df2e56Smrg    const char **vlist, **vl;
62105b261ecSmrg    int *dev2screen;
62205b261ecSmrg
6237e31ba66Smrg    vlist = GenerateDriverList();
62405b261ecSmrg
62505b261ecSmrg    if (!vlist) {
626f7df2e56Smrg        ErrorF("Missing output drivers.  Configuration failed.\n");
627f7df2e56Smrg        goto bail;
62805b261ecSmrg    }
62905b261ecSmrg
63005b261ecSmrg    ErrorF("List of video drivers:\n");
63105b261ecSmrg    for (vl = vlist; *vl; vl++)
632f7df2e56Smrg        ErrorF("\t%s\n", *vl);
63305b261ecSmrg
63405b261ecSmrg    /* Load all the drivers that were found. */
63505b261ecSmrg    xf86LoadModules(vlist, NULL);
63605b261ecSmrg
6374202a189Smrg    free(vlist);
63805b261ecSmrg
639f7df2e56Smrg    xorgHWAccess = xf86EnableIO();
64005b261ecSmrg
64105b261ecSmrg    /* Create XF86Config file structure */
6424642e01fSmrg    xf86config = calloc(1, sizeof(XF86ConfigRec));
64305b261ecSmrg
64405b261ecSmrg    /* Call all of the probe functions, reporting the results. */
645f7df2e56Smrg    for (CurrentDriver = 0; CurrentDriver < xf86NumDrivers; CurrentDriver++) {
646f7df2e56Smrg        Bool found_screen;
647f7df2e56Smrg        DriverRec *const drv = xf86DriverList[CurrentDriver];
648f7df2e56Smrg
649f7df2e56Smrg        found_screen = xf86CallDriverProbe(drv, TRUE);
650f7df2e56Smrg        if (found_screen && drv->Identify) {
651f7df2e56Smrg            (*drv->Identify) (0);
652f7df2e56Smrg        }
65305b261ecSmrg    }
65405b261ecSmrg
65505b261ecSmrg    if (nDevToConfig <= 0) {
656f7df2e56Smrg        ErrorF("No devices to configure.  Configuration failed.\n");
657f7df2e56Smrg        goto bail;
65805b261ecSmrg    }
65905b261ecSmrg
66005b261ecSmrg    /* Add device, monitor and screen sections for detected devices */
661f7df2e56Smrg    for (screennum = 0; screennum < nDevToConfig; screennum++) {
662f7df2e56Smrg        XF86ConfDevicePtr device_ptr;
663f7df2e56Smrg        XF86ConfMonitorPtr monitor_ptr;
664f7df2e56Smrg        XF86ConfScreenPtr screen_ptr;
665f7df2e56Smrg
666f7df2e56Smrg        device_ptr = configureDeviceSection(screennum);
667f7df2e56Smrg        xf86config->conf_device_lst = (XF86ConfDevicePtr) xf86addListItem((glp)
668f7df2e56Smrg                                                                          xf86config->
669f7df2e56Smrg                                                                          conf_device_lst,
670f7df2e56Smrg                                                                          (glp)
671f7df2e56Smrg                                                                          device_ptr);
672f7df2e56Smrg        monitor_ptr = configureMonitorSection(screennum);
673f7df2e56Smrg        xf86config->conf_monitor_lst = (XF86ConfMonitorPtr) xf86addListItem((glp) xf86config->conf_monitor_lst, (glp) monitor_ptr);
674f7df2e56Smrg        screen_ptr = configureScreenSection(screennum);
675f7df2e56Smrg        xf86config->conf_screen_lst = (XF86ConfScreenPtr) xf86addListItem((glp)
676f7df2e56Smrg                                                                          xf86config->
677f7df2e56Smrg                                                                          conf_screen_lst,
678f7df2e56Smrg                                                                          (glp)
679f7df2e56Smrg                                                                          screen_ptr);
68005b261ecSmrg    }
68105b261ecSmrg
68205b261ecSmrg    xf86config->conf_files = configureFilesSection();
68305b261ecSmrg    xf86config->conf_modules = configureModuleSection();
68405b261ecSmrg    xf86config->conf_flags = configureFlagsSection();
68505b261ecSmrg    xf86config->conf_videoadaptor_lst = NULL;
68605b261ecSmrg    xf86config->conf_modes_lst = NULL;
68705b261ecSmrg    xf86config->conf_vendor_lst = NULL;
68805b261ecSmrg    xf86config->conf_dri = NULL;
68905b261ecSmrg    xf86config->conf_input_lst = configureInputSection();
69005b261ecSmrg    xf86config->conf_layout_lst = configureLayoutSection();
69105b261ecSmrg
6924642e01fSmrg    home = getenv("HOME");
6934642e01fSmrg    if ((home == NULL) || (home[0] == '\0')) {
694f7df2e56Smrg        home = "/";
695f7df2e56Smrg    }
696f7df2e56Smrg    else {
697f7df2e56Smrg        /* Determine if trailing slash is present or needed */
698f7df2e56Smrg        int l = strlen(home);
699f7df2e56Smrg
700f7df2e56Smrg        if (home[l - 1] != '/') {
701f7df2e56Smrg            addslash = "/";
702f7df2e56Smrg        }
70305b261ecSmrg    }
70405b261ecSmrg
7054642e01fSmrg    snprintf(filename, sizeof(filename), "%s%s" XF86CONFIGFILE ".new",
706f7df2e56Smrg             home, addslash);
7074642e01fSmrg
7084642e01fSmrg    if (xf86writeConfigFile(filename, xf86config) == 0) {
709f7df2e56Smrg        xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n",
710f7df2e56Smrg                filename, strerror(errno));
711f7df2e56Smrg        goto bail;
7124642e01fSmrg    }
71305b261ecSmrg
71405b261ecSmrg    xf86DoConfigurePass1 = FALSE;
71505b261ecSmrg    /* Try to get DDC information filled in */
71605b261ecSmrg    xf86ConfigFile = filename;
71705b261ecSmrg    if (xf86HandleConfigFile(FALSE) != CONFIG_OK) {
718f7df2e56Smrg        goto bail;
71905b261ecSmrg    }
72005b261ecSmrg
72105b261ecSmrg    xf86DoConfigurePass1 = FALSE;
722f7df2e56Smrg
7237e31ba66Smrg    dev2screen = xnfcalloc(nDevToConfig, sizeof(int));
72405b261ecSmrg
72505b261ecSmrg    {
726f7df2e56Smrg        Bool *driverProbed = xnfcalloc(xf86NumDrivers, sizeof(Bool));
727f7df2e56Smrg
728f7df2e56Smrg        for (screennum = 0; screennum < nDevToConfig; screennum++) {
729f7df2e56Smrg            int k, l, n, oldNumScreens;
730f7df2e56Smrg
731f7df2e56Smrg            i = DevToConfig[screennum].iDriver;
732f7df2e56Smrg
733f7df2e56Smrg            if (driverProbed[i])
734f7df2e56Smrg                continue;
735f7df2e56Smrg            driverProbed[i] = TRUE;
736f7df2e56Smrg
737f7df2e56Smrg            oldNumScreens = xf86NumScreens;
738f7df2e56Smrg
739f7df2e56Smrg            xf86CallDriverProbe(xf86DriverList[i], FALSE);
740f7df2e56Smrg
741f7df2e56Smrg            /* reorder */
742f7df2e56Smrg            k = screennum > 0 ? screennum : 1;
743f7df2e56Smrg            for (l = oldNumScreens; l < xf86NumScreens; l++) {
744f7df2e56Smrg                /* is screen primary? */
745f7df2e56Smrg                Bool primary = FALSE;
746f7df2e56Smrg
747f7df2e56Smrg                for (n = 0; n < xf86Screens[l]->numEntities; n++) {
748f7df2e56Smrg                    if (xf86IsEntityPrimary(xf86Screens[l]->entityList[n])) {
749f7df2e56Smrg                        dev2screen[0] = l;
750f7df2e56Smrg                        primary = TRUE;
751f7df2e56Smrg                        break;
752f7df2e56Smrg                    }
753f7df2e56Smrg                }
754f7df2e56Smrg                if (primary)
755f7df2e56Smrg                    continue;
756f7df2e56Smrg                /* not primary: assign it to next device of same driver */
757f7df2e56Smrg                /*
758f7df2e56Smrg                 * NOTE: we assume that devices in DevToConfig
759f7df2e56Smrg                 * and xf86Screens[] have the same order except
760f7df2e56Smrg                 * for the primary device which always comes first.
761f7df2e56Smrg                 */
762f7df2e56Smrg                for (; k < nDevToConfig; k++) {
763f7df2e56Smrg                    if (DevToConfig[k].iDriver == i) {
764f7df2e56Smrg                        dev2screen[k++] = l;
765f7df2e56Smrg                        break;
766f7df2e56Smrg                    }
767f7df2e56Smrg                }
768f7df2e56Smrg            }
769f7df2e56Smrg        }
770f7df2e56Smrg        free(driverProbed);
77105b261ecSmrg    }
77205b261ecSmrg
77305b261ecSmrg    if (nDevToConfig != xf86NumScreens) {
774f7df2e56Smrg        ErrorF("Number of created screens does not match number of detected"
775f7df2e56Smrg               " devices.\n  Configuration failed.\n");
776f7df2e56Smrg        goto bail;
77705b261ecSmrg    }
77805b261ecSmrg
77905b261ecSmrg    xf86PostProbe();
78005b261ecSmrg
78105b261ecSmrg    for (j = 0; j < xf86NumScreens; j++) {
782f7df2e56Smrg        xf86Screens[j]->scrnIndex = j;
78305b261ecSmrg    }
78405b261ecSmrg
78505b261ecSmrg    xf86freeMonitorList(xf86config->conf_monitor_lst);
78605b261ecSmrg    xf86config->conf_monitor_lst = NULL;
78705b261ecSmrg    xf86freeScreenList(xf86config->conf_screen_lst);
78805b261ecSmrg    xf86config->conf_screen_lst = NULL;
78905b261ecSmrg    for (j = 0; j < xf86NumScreens; j++) {
790f7df2e56Smrg        XF86ConfMonitorPtr monitor_ptr;
791f7df2e56Smrg        XF86ConfScreenPtr screen_ptr;
792f7df2e56Smrg
793f7df2e56Smrg        ConfiguredMonitor = NULL;
794f7df2e56Smrg
7957e31ba66Smrg        if ((*xf86Screens[dev2screen[j]]->PreInit) &&
7967e31ba66Smrg            (*xf86Screens[dev2screen[j]]->PreInit) (xf86Screens[dev2screen[j]],
797f7df2e56Smrg                                                    PROBE_DETECT) &&
798f7df2e56Smrg            ConfiguredMonitor) {
799f7df2e56Smrg            monitor_ptr = configureDDCMonitorSection(j);
800f7df2e56Smrg        }
801f7df2e56Smrg        else {
802f7df2e56Smrg            monitor_ptr = configureMonitorSection(j);
803f7df2e56Smrg        }
804f7df2e56Smrg        screen_ptr = configureScreenSection(j);
805f7df2e56Smrg
806f7df2e56Smrg        xf86config->conf_monitor_lst = (XF86ConfMonitorPtr) xf86addListItem((glp) xf86config->conf_monitor_lst, (glp) monitor_ptr);
807f7df2e56Smrg        xf86config->conf_screen_lst = (XF86ConfScreenPtr) xf86addListItem((glp)
808f7df2e56Smrg                                                                          xf86config->
809f7df2e56Smrg                                                                          conf_screen_lst,
810f7df2e56Smrg                                                                          (glp)
811f7df2e56Smrg                                                                          screen_ptr);
81205b261ecSmrg    }
81305b261ecSmrg
8144642e01fSmrg    if (xf86writeConfigFile(filename, xf86config) == 0) {
815f7df2e56Smrg        xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n",
816f7df2e56Smrg                filename, strerror(errno));
817f7df2e56Smrg        goto bail;
8184642e01fSmrg    }
81905b261ecSmrg
82005b261ecSmrg    ErrorF("\n");
82105b261ecSmrg
82205b261ecSmrg    if (!foundMouse) {
823f7df2e56Smrg        ErrorF("\n" __XSERVERNAME__ " is not able to detect your mouse.\n"
824f7df2e56Smrg               "Edit the file and correct the Device.\n");
825f7df2e56Smrg    }
826f7df2e56Smrg    else {
827f7df2e56Smrg        ErrorF("\n" __XSERVERNAME__ " detected your mouse at device %s.\n"
828f7df2e56Smrg               "Please check your config if the mouse is still not\n"
829f7df2e56Smrg               "operational, as by default " __XSERVERNAME__
830f7df2e56Smrg               " tries to autodetect\n" "the protocol.\n", DFLT_MOUSE_DEV);
83105b261ecSmrg    }
83205b261ecSmrg
83305b261ecSmrg    if (xf86NumScreens > 1) {
834f7df2e56Smrg        ErrorF("\n" __XSERVERNAME__
835f7df2e56Smrg               " has configured a multihead system, please check your config.\n");
83605b261ecSmrg    }
83705b261ecSmrg
838f7df2e56Smrg    ErrorF("\nYour %s file is %s\n\n", XF86CONFIGFILE, filename);
83905b261ecSmrg    ErrorF("To test the server, run 'X -config %s'\n\n", filename);
84005b261ecSmrg
841f7df2e56Smrg bail:
842f7df2e56Smrg    OsCleanup(TRUE);
8435a112b11Smrg    ddxGiveUp(EXIT_ERR_CONFIGURE);
844f7df2e56Smrg    fflush(stderr);
845f7df2e56Smrg    exit(0);
846f7df2e56Smrg}
847f7df2e56Smrg
848f7df2e56Smrg/* Xorg -showopts:
849f7df2e56Smrg *   For each driver module installed, print out the list
850f7df2e56Smrg *   of options and their argument types, then exit
851f7df2e56Smrg *
852f7df2e56Smrg * Author:  Marcus Schaefer, ms@suse.de
853f7df2e56Smrg */
854f7df2e56Smrg
855f7df2e56Smrgvoid
856f7df2e56SmrgDoShowOptions(void)
857f7df2e56Smrg{
858f7df2e56Smrg    int i = 0;
859f7df2e56Smrg    const char **vlist = NULL;
860f7df2e56Smrg    char *pSymbol = 0;
861f7df2e56Smrg    XF86ModuleData *initData = 0;
862f7df2e56Smrg
8637e31ba66Smrg    if (!(vlist = GenerateDriverList())) {
864f7df2e56Smrg        ErrorF("Missing output drivers\n");
865f7df2e56Smrg        goto bail;
866f7df2e56Smrg    }
867f7df2e56Smrg    xf86LoadModules(vlist, 0);
868f7df2e56Smrg    free(vlist);
869f7df2e56Smrg    for (i = 0; i < xf86NumDrivers; i++) {
870f7df2e56Smrg        if (xf86DriverList[i]->AvailableOptions) {
871f7df2e56Smrg            const OptionInfoRec *pOption =
872f7df2e56Smrg                (*xf86DriverList[i]->AvailableOptions) (0, 0);
873f7df2e56Smrg            if (!pOption) {
874f7df2e56Smrg                ErrorF("(EE) Couldn't read option table for %s driver\n",
875f7df2e56Smrg                       xf86DriverList[i]->driverName);
876f7df2e56Smrg                continue;
877f7df2e56Smrg            }
878f7df2e56Smrg            XNFasprintf(&pSymbol, "%sModuleData",
879f7df2e56Smrg                        xf86DriverList[i]->driverName);
880f7df2e56Smrg            initData = LoaderSymbol(pSymbol);
881f7df2e56Smrg            if (initData) {
882f7df2e56Smrg                XF86ModuleVersionInfo *vers = initData->vers;
883f7df2e56Smrg                const OptionInfoRec *p;
884f7df2e56Smrg
885f7df2e56Smrg                ErrorF("Driver[%d]:%s[%s] {\n",
886f7df2e56Smrg                       i, xf86DriverList[i]->driverName, vers->vendor);
887f7df2e56Smrg                for (p = pOption; p->name != NULL; p++) {
888f7df2e56Smrg                    ErrorF("\t%s:%s\n", p->name, optionTypeToString(p->type));
889f7df2e56Smrg                }
890f7df2e56Smrg                ErrorF("}\n");
891f7df2e56Smrg            }
892f7df2e56Smrg        }
893f7df2e56Smrg    }
894f7df2e56Smrg bail:
89505b261ecSmrg    OsCleanup(TRUE);
8965a112b11Smrg    ddxGiveUp(EXIT_ERR_DRIVERS);
89705b261ecSmrg    fflush(stderr);
89805b261ecSmrg    exit(0);
89905b261ecSmrg}
900