xf86Configure.c revision f7df2e56
1/*
2 * Copyright 2000-2002 by Alan Hourihane, Flint Mountain, North Wales.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Alan Hourihane not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  Alan Hourihane makes no representations
11 * about the suitability of this software for any purpose.  It is provided
12 * "as is" without express or implied warranty.
13 *
14 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 *
22 * Author:  Alan Hourihane, alanh@fairlite.demon.co.uk
23 *
24 */
25
26#ifdef HAVE_XORG_CONFIG_H
27#include <xorg-config.h>
28#endif
29
30#include "xf86.h"
31#include "xf86Config.h"
32#include "xf86_OSlib.h"
33#include "xf86Priv.h"
34#define IN_XSERVER
35#include "Configint.h"
36#include "xf86DDC.h"
37#include "xf86pciBus.h"
38#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
39#include "xf86Bus.h"
40#include "xf86Sbus.h"
41#endif
42#include "misc.h"
43
44typedef struct _DevToConfig {
45    GDevRec GDev;
46    struct pci_device *pVideo;
47#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
48    sbusDevicePtr sVideo;
49#endif
50    int iDriver;
51} DevToConfigRec, *DevToConfigPtr;
52
53static DevToConfigPtr DevToConfig = NULL;
54static int nDevToConfig = 0, CurrentDriver;
55
56xf86MonPtr ConfiguredMonitor;
57Bool xf86DoConfigurePass1 = TRUE;
58static Bool foundMouse = FALSE;
59
60#if   defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
61static const char *DFLT_MOUSE_DEV = "/dev/sysmouse";
62static const char *DFLT_MOUSE_PROTO = "auto";
63#elif defined(linux)
64static const char *DFLT_MOUSE_DEV = "/dev/input/mice";
65static const char *DFLT_MOUSE_PROTO = "auto";
66#elif defined(WSCONS_SUPPORT)
67static const char *DFLT_MOUSE_DEV = "/dev/wsmouse";
68static const char *DFLT_MOUSE_PROTO = "wsmouse";
69#else
70static const char *DFLT_MOUSE_DEV = "/dev/mouse";
71static const char *DFLT_MOUSE_PROTO = "auto";
72#endif
73
74/*
75 * This is called by the driver, either through xf86Match???Instances() or
76 * directly.  We allocate a GDevRec and fill it in as much as we can, letting
77 * the caller fill in the rest and/or change it as it sees fit.
78 */
79GDevPtr
80xf86AddBusDeviceToConfigure(const char *driver, BusType bus, void *busData,
81                            int chipset)
82{
83    int ret, i, j;
84    char *lower_driver;
85
86    if (!xf86DoConfigure || !xf86DoConfigurePass1)
87        return NULL;
88
89    /* Check for duplicates */
90    for (i = 0; i < nDevToConfig; i++) {
91        switch (bus) {
92#ifdef XSERVER_LIBPCIACCESS
93        case BUS_PCI:
94            ret = xf86PciConfigure(busData, DevToConfig[i].pVideo);
95            break;
96#endif
97#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
98        case BUS_SBUS:
99            ret = xf86SbusConfigure(busData, DevToConfig[i].sVideo);
100            break;
101#endif
102#if defined(__arm32__)
103        case BUS_ISA:
104            break;
105#endif
106        default:
107            return NULL;
108        }
109        if (ret == 0)
110            goto out;
111    }
112
113    /* Allocate new structure occurrence */
114    i = nDevToConfig++;
115    DevToConfig =
116        xnfreallocarray(DevToConfig, nDevToConfig, sizeof(DevToConfigRec));
117    memset(DevToConfig + i, 0, sizeof(DevToConfigRec));
118
119    DevToConfig[i].GDev.chipID =
120        DevToConfig[i].GDev.chipRev = DevToConfig[i].GDev.irq = -1;
121
122    DevToConfig[i].iDriver = CurrentDriver;
123
124    /* Fill in what we know, converting the driver name to lower case */
125    lower_driver = xnfalloc(strlen(driver) + 1);
126    for (j = 0; (lower_driver[j] = tolower(driver[j])); j++);
127    DevToConfig[i].GDev.driver = lower_driver;
128
129    switch (bus) {
130#ifdef XSERVER_LIBPCIACCESS
131    case BUS_PCI:
132	DevToConfig[i].pVideo = busData;
133        xf86PciConfigureNewDev(busData, DevToConfig[i].pVideo,
134                               &DevToConfig[i].GDev, &chipset);
135        break;
136#endif
137#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
138    case BUS_SBUS:
139	DevToConfig[i].sVideo = busData;
140        xf86SbusConfigureNewDev(busData, DevToConfig[i].sVideo,
141                                &DevToConfig[i].GDev);
142        break;
143#endif
144#if defined(__arm32__)
145    case BUS_ISA:
146	DevToConfig[i].GDev.busID = xnfalloc(6);
147	strcpy(DevToConfig[i].GDev.busID, "ISA");
148	break;
149#endif
150    default:
151        break;
152    }
153
154    /* Get driver's available options */
155    if (xf86DriverList[CurrentDriver]->AvailableOptions)
156        DevToConfig[i].GDev.options = (OptionInfoPtr)
157            (*xf86DriverList[CurrentDriver]->AvailableOptions) (chipset, bus);
158
159    return &DevToConfig[i].GDev;
160
161 out:
162    return NULL;
163}
164
165static XF86ConfInputPtr
166configureInputSection(void)
167{
168    XF86ConfInputPtr mouse = NULL;
169
170    parsePrologue(XF86ConfInputPtr, XF86ConfInputRec)
171
172    ptr->inp_identifier = xnfstrdup("Keyboard0");
173    ptr->inp_driver = xnfstrdup("kbd");
174    ptr->list.next = NULL;
175#if defined(WSCONS_SUPPORT) && !defined(__i386__) && !defined(__amd64__)
176    ptr->inp_option_lst = xf86addNewOption(ptr->inp_option_lst,
177        xstrdup("Protocol"), "wskbd");
178    ptr->inp_option_lst = xf86addNewOption(ptr->inp_option_lst,
179        xstrdup("Device"), "/dev/wskbd");
180#endif
181
182    /* Crude mechanism to auto-detect mouse (os dependent) */
183    {
184        int fd;
185
186        fd = open(DFLT_MOUSE_DEV, 0);
187        if (fd != -1) {
188            foundMouse = TRUE;
189            close(fd);
190        }
191    }
192
193    mouse = calloc(1, sizeof(XF86ConfInputRec));
194    mouse->inp_identifier = xnfstrdup("Mouse0");
195    mouse->inp_driver = xnfstrdup("mouse");
196    mouse->inp_option_lst =
197        xf86addNewOption(mouse->inp_option_lst, xnfstrdup("Protocol"),
198                         xnfstrdup(DFLT_MOUSE_PROTO));
199    mouse->inp_option_lst =
200        xf86addNewOption(mouse->inp_option_lst, xnfstrdup("Device"),
201                         xnfstrdup(DFLT_MOUSE_DEV));
202    mouse->inp_option_lst =
203        xf86addNewOption(mouse->inp_option_lst, xnfstrdup("ZAxisMapping"),
204                         xnfstrdup("4 5 6 7"));
205    ptr = (XF86ConfInputPtr) xf86addListItem((glp) ptr, (glp) mouse);
206    return ptr;
207}
208
209static XF86ConfScreenPtr
210configureScreenSection(int screennum)
211{
212    int i;
213    int depths[] = { 1, 4, 8, 15, 16, 24 /*, 32 */  };
214    char *tmp;
215    parsePrologue(XF86ConfScreenPtr, XF86ConfScreenRec)
216
217    XNFasprintf(&tmp, "Screen%d", screennum);
218    ptr->scrn_identifier = tmp;
219    XNFasprintf(&tmp, "Monitor%d", screennum);
220    ptr->scrn_monitor_str = tmp;
221    XNFasprintf(&tmp, "Card%d", screennum);
222    ptr->scrn_device_str = tmp;
223
224    for (i = 0; i < sizeof(depths) / sizeof(depths[0]); i++) {
225        XF86ConfDisplayPtr conf_display;
226
227        conf_display = calloc(1, sizeof(XF86ConfDisplayRec));
228        conf_display->disp_depth = depths[i];
229        conf_display->disp_black.red = conf_display->disp_white.red = -1;
230        conf_display->disp_black.green = conf_display->disp_white.green = -1;
231        conf_display->disp_black.blue = conf_display->disp_white.blue = -1;
232        ptr->scrn_display_lst = (XF86ConfDisplayPtr) xf86addListItem((glp) ptr->
233                                                                     scrn_display_lst,
234                                                                     (glp)
235                                                                     conf_display);
236    }
237
238    return ptr;
239}
240
241static const char *
242optionTypeToString(OptionValueType type)
243{
244    switch (type) {
245    case OPTV_NONE:
246        return "";
247    case OPTV_INTEGER:
248        return "<i>";
249    case OPTV_STRING:
250        return "<str>";
251    case OPTV_ANYSTR:
252        return "[<str>]";
253    case OPTV_REAL:
254        return "<f>";
255    case OPTV_BOOLEAN:
256        return "[<bool>]";
257    case OPTV_FREQ:
258        return "<freq>";
259    case OPTV_PERCENT:
260        return "<percent>";
261    default:
262        return "";
263    }
264}
265
266static XF86ConfDevicePtr
267configureDeviceSection(int screennum)
268{
269    OptionInfoPtr p;
270    int i = 0;
271    char *identifier;
272
273    parsePrologue(XF86ConfDevicePtr, XF86ConfDeviceRec)
274
275        /* Move device info to parser structure */
276   if (asprintf(&identifier, "Card%d", screennum) == -1)
277        identifier = NULL;
278    ptr->dev_identifier = identifier;
279    ptr->dev_chipset = DevToConfig[screennum].GDev.chipset;
280    ptr->dev_busid = DevToConfig[screennum].GDev.busID;
281    ptr->dev_driver = DevToConfig[screennum].GDev.driver;
282    ptr->dev_ramdac = DevToConfig[screennum].GDev.ramdac;
283    for (i = 0; i < MAXDACSPEEDS; i++)
284        ptr->dev_dacSpeeds[i] = DevToConfig[screennum].GDev.dacSpeeds[i];
285    ptr->dev_videoram = DevToConfig[screennum].GDev.videoRam;
286    ptr->dev_bios_base = DevToConfig[screennum].GDev.BiosBase;
287    ptr->dev_mem_base = DevToConfig[screennum].GDev.MemBase;
288    ptr->dev_io_base = DevToConfig[screennum].GDev.IOBase;
289    ptr->dev_clockchip = DevToConfig[screennum].GDev.clockchip;
290    for (i = 0; (i < MAXCLOCKS) && (i < DevToConfig[screennum].GDev.numclocks);
291         i++)
292        ptr->dev_clock[i] = DevToConfig[screennum].GDev.clock[i];
293    ptr->dev_clocks = i;
294    ptr->dev_chipid = DevToConfig[screennum].GDev.chipID;
295    ptr->dev_chiprev = DevToConfig[screennum].GDev.chipRev;
296    ptr->dev_irq = DevToConfig[screennum].GDev.irq;
297
298    /* Make sure older drivers don't segv */
299    if (DevToConfig[screennum].GDev.options) {
300        /* Fill in the available driver options for people to use */
301        const char *descrip =
302            "        ### Available Driver options are:-\n"
303            "        ### Values: <i>: integer, <f>: float, "
304            "<bool>: \"True\"/\"False\",\n"
305            "        ### <string>: \"String\", <freq>: \"<f> Hz/kHz/MHz\",\n"
306            "        ### <percent>: \"<f>%\"\n"
307            "        ### [arg]: arg optional\n";
308        ptr->dev_comment = xnfstrdup(descrip);
309        if (ptr->dev_comment) {
310            for (p = DevToConfig[screennum].GDev.options; p->name != NULL; p++) {
311                char *p_e;
312                const char *prefix = "        #Option     ";
313                const char *middle = " \t# ";
314                const char *suffix = "\n";
315                const char *opttype = optionTypeToString(p->type);
316                char *optname;
317                int len = strlen(ptr->dev_comment) + strlen(prefix) +
318                    strlen(middle) + strlen(suffix) + 1;
319
320                if (asprintf(&optname, "\"%s\"", p->name) == -1)
321                    break;
322
323                len += max(20, strlen(optname));
324                len += strlen(opttype);
325
326                ptr->dev_comment = realloc(ptr->dev_comment, len);
327                if (!ptr->dev_comment)
328                    break;
329                p_e = ptr->dev_comment + strlen(ptr->dev_comment);
330                sprintf(p_e, "%s%-20s%s%s%s", prefix, optname, middle,
331                        opttype, suffix);
332                free(optname);
333            }
334        }
335    }
336
337    return ptr;
338}
339
340static XF86ConfLayoutPtr
341configureLayoutSection(void)
342{
343    int scrnum = 0;
344
345    parsePrologue(XF86ConfLayoutPtr, XF86ConfLayoutRec)
346
347        ptr->lay_identifier = "X.org Configured";
348
349    {
350        XF86ConfInputrefPtr iptr;
351
352        iptr = malloc(sizeof(XF86ConfInputrefRec));
353        iptr->list.next = NULL;
354        iptr->iref_option_lst = NULL;
355        iptr->iref_inputdev_str = xnfstrdup("Mouse0");
356        iptr->iref_option_lst =
357            xf86addNewOption(iptr->iref_option_lst, xnfstrdup("CorePointer"),
358                             NULL);
359        ptr->lay_input_lst = (XF86ConfInputrefPtr)
360            xf86addListItem((glp) ptr->lay_input_lst, (glp) iptr);
361    }
362
363    {
364        XF86ConfInputrefPtr iptr;
365
366        iptr = malloc(sizeof(XF86ConfInputrefRec));
367        iptr->list.next = NULL;
368        iptr->iref_option_lst = NULL;
369        iptr->iref_inputdev_str = xnfstrdup("Keyboard0");
370        iptr->iref_option_lst =
371            xf86addNewOption(iptr->iref_option_lst, xnfstrdup("CoreKeyboard"),
372                             NULL);
373        ptr->lay_input_lst = (XF86ConfInputrefPtr)
374            xf86addListItem((glp) ptr->lay_input_lst, (glp) iptr);
375    }
376
377    for (scrnum = 0; scrnum < nDevToConfig; scrnum++) {
378        XF86ConfAdjacencyPtr aptr;
379        char *tmp;
380
381        aptr = malloc(sizeof(XF86ConfAdjacencyRec));
382        aptr->list.next = NULL;
383        aptr->adj_x = 0;
384        aptr->adj_y = 0;
385        aptr->adj_scrnum = scrnum;
386        XNFasprintf(&tmp, "Screen%d", scrnum);
387        aptr->adj_screen_str = tmp;
388        if (scrnum == 0) {
389            aptr->adj_where = CONF_ADJ_ABSOLUTE;
390            aptr->adj_refscreen = NULL;
391        }
392        else {
393            aptr->adj_where = CONF_ADJ_RIGHTOF;
394            XNFasprintf(&tmp, "Screen%d", scrnum - 1);
395            aptr->adj_refscreen = tmp;
396        }
397        ptr->lay_adjacency_lst =
398            (XF86ConfAdjacencyPtr) xf86addListItem((glp) ptr->lay_adjacency_lst,
399                                                   (glp) aptr);
400    }
401
402    return ptr;
403}
404
405static XF86ConfFlagsPtr
406configureFlagsSection(void)
407{
408    parsePrologue(XF86ConfFlagsPtr, XF86ConfFlagsRec)
409
410        return ptr;
411}
412
413static XF86ConfModulePtr
414configureModuleSection(void)
415{
416    const char **elist, **el;
417
418    /* Find the list of extension & font modules. */
419    const char *esubdirs[] = {
420        "extensions",
421        "fonts",
422        NULL
423    };
424    parsePrologue(XF86ConfModulePtr, XF86ConfModuleRec)
425
426        elist = LoaderListDirs(esubdirs, NULL);
427    if (elist) {
428        for (el = elist; *el; el++) {
429            XF86LoadPtr module;
430
431            module = calloc(1, sizeof(XF86LoadRec));
432            module->load_name = *el;
433            ptr->mod_load_lst = (XF86LoadPtr) xf86addListItem((glp) ptr->
434                                                              mod_load_lst,
435                                                              (glp) module);
436        }
437        free(elist);
438    }
439
440    return ptr;
441}
442
443static XF86ConfFilesPtr
444configureFilesSection(void)
445{
446    parsePrologue(XF86ConfFilesPtr, XF86ConfFilesRec)
447
448        if (xf86ModulePath)
449        ptr->file_modulepath = xnfstrdup(xf86ModulePath);
450    if (defaultFontPath)
451        ptr->file_fontpath = xnfstrdup(defaultFontPath);
452
453    return ptr;
454}
455
456static XF86ConfMonitorPtr
457configureMonitorSection(int screennum)
458{
459    char *tmp;
460    parsePrologue(XF86ConfMonitorPtr, XF86ConfMonitorRec)
461
462    XNFasprintf(&tmp, "Monitor%d", screennum);
463    ptr->mon_identifier = tmp;
464    ptr->mon_vendor = xnfstrdup("Monitor Vendor");
465    ptr->mon_modelname = xnfstrdup("Monitor Model");
466
467    return ptr;
468}
469
470/* Initialize Configure Monitor from Detailed Timing Block */
471static void
472handle_detailed_input(struct detailed_monitor_section *det_mon, void *data)
473{
474    XF86ConfMonitorPtr ptr = (XF86ConfMonitorPtr) data;
475
476    switch (det_mon->type) {
477    case DS_NAME:
478        ptr->mon_modelname = realloc(ptr->mon_modelname,
479                                     strlen((char *) (det_mon->section.name)) +
480                                     1);
481        strcpy(ptr->mon_modelname, (char *) (det_mon->section.name));
482        break;
483    case DS_RANGES:
484        ptr->mon_hsync[ptr->mon_n_hsync].lo = det_mon->section.ranges.min_h;
485        ptr->mon_hsync[ptr->mon_n_hsync].hi = det_mon->section.ranges.max_h;
486        ptr->mon_n_vrefresh = 1;
487        ptr->mon_vrefresh[ptr->mon_n_hsync].lo = det_mon->section.ranges.min_v;
488        ptr->mon_vrefresh[ptr->mon_n_hsync].hi = det_mon->section.ranges.max_v;
489        ptr->mon_n_hsync++;
490    default:
491        break;
492    }
493}
494
495static XF86ConfMonitorPtr
496configureDDCMonitorSection(int screennum)
497{
498    int len, mon_width, mon_height;
499
500#define displaySizeMaxLen 80
501    char displaySize_string[displaySizeMaxLen];
502    int displaySizeLen;
503    char *tmp;
504
505    parsePrologue(XF86ConfMonitorPtr, XF86ConfMonitorRec)
506
507    XNFasprintf(&tmp, "Monitor%d", screennum);
508    ptr->mon_identifier = tmp;
509    ptr->mon_vendor = xnfstrdup(ConfiguredMonitor->vendor.name);
510    XNFasprintf(&ptr->mon_modelname, "%x", ConfiguredMonitor->vendor.prod_id);
511
512    /* features in centimetres, we want millimetres */
513    mon_width = 10 * ConfiguredMonitor->features.hsize;
514    mon_height = 10 * ConfiguredMonitor->features.vsize;
515
516#ifdef CONFIGURE_DISPLAYSIZE
517    ptr->mon_width = mon_width;
518    ptr->mon_height = mon_height;
519#else
520    if (mon_width && mon_height) {
521        /* when values available add DisplaySize option AS A COMMENT */
522
523        displaySizeLen = snprintf(displaySize_string, displaySizeMaxLen,
524                                  "\t#DisplaySize\t%5d %5d\t# mm\n",
525                                  mon_width, mon_height);
526
527        if (displaySizeLen > 0 && displaySizeLen < displaySizeMaxLen) {
528            if (ptr->mon_comment) {
529                len = strlen(ptr->mon_comment);
530            }
531            else {
532                len = 0;
533            }
534            if ((ptr->mon_comment =
535                 realloc(ptr->mon_comment,
536                         len + strlen(displaySize_string) + 1))) {
537                strcpy(ptr->mon_comment + len, displaySize_string);
538            }
539        }
540    }
541#endif                          /* def CONFIGURE_DISPLAYSIZE */
542
543    xf86ForEachDetailedBlock(ConfiguredMonitor, handle_detailed_input, ptr);
544
545    if (ConfiguredMonitor->features.dpms) {
546        ptr->mon_option_lst =
547            xf86addNewOption(ptr->mon_option_lst, xnfstrdup("DPMS"), NULL);
548    }
549
550    return ptr;
551}
552
553void
554DoConfigure(void)
555{
556    int i, j, screennum = -1;
557    const char *home = NULL;
558    char filename[PATH_MAX];
559    const char *addslash = "";
560    XF86ConfigPtr xf86config = NULL;
561    const char **vlist, **vl;
562    int *dev2screen;
563
564    vlist = xf86DriverlistFromCompile();
565
566    if (!vlist) {
567        ErrorF("Missing output drivers.  Configuration failed.\n");
568        goto bail;
569    }
570
571    ErrorF("List of video drivers:\n");
572    for (vl = vlist; *vl; vl++)
573        ErrorF("\t%s\n", *vl);
574
575    /* Load all the drivers that were found. */
576    xf86LoadModules(vlist, NULL);
577
578    free(vlist);
579
580    xorgHWAccess = xf86EnableIO();
581
582    /* Create XF86Config file structure */
583    xf86config = calloc(1, sizeof(XF86ConfigRec));
584
585    /* Call all of the probe functions, reporting the results. */
586    for (CurrentDriver = 0; CurrentDriver < xf86NumDrivers; CurrentDriver++) {
587        Bool found_screen;
588        DriverRec *const drv = xf86DriverList[CurrentDriver];
589
590        found_screen = xf86CallDriverProbe(drv, TRUE);
591        if (found_screen && drv->Identify) {
592            (*drv->Identify) (0);
593        }
594    }
595
596    if (nDevToConfig <= 0) {
597        ErrorF("No devices to configure.  Configuration failed.\n");
598        goto bail;
599    }
600
601    /* Add device, monitor and screen sections for detected devices */
602    for (screennum = 0; screennum < nDevToConfig; screennum++) {
603        XF86ConfDevicePtr device_ptr;
604        XF86ConfMonitorPtr monitor_ptr;
605        XF86ConfScreenPtr screen_ptr;
606
607        device_ptr = configureDeviceSection(screennum);
608        xf86config->conf_device_lst = (XF86ConfDevicePtr) xf86addListItem((glp)
609                                                                          xf86config->
610                                                                          conf_device_lst,
611                                                                          (glp)
612                                                                          device_ptr);
613        monitor_ptr = configureMonitorSection(screennum);
614        xf86config->conf_monitor_lst = (XF86ConfMonitorPtr) xf86addListItem((glp) xf86config->conf_monitor_lst, (glp) monitor_ptr);
615        screen_ptr = configureScreenSection(screennum);
616        xf86config->conf_screen_lst = (XF86ConfScreenPtr) xf86addListItem((glp)
617                                                                          xf86config->
618                                                                          conf_screen_lst,
619                                                                          (glp)
620                                                                          screen_ptr);
621    }
622
623    xf86config->conf_files = configureFilesSection();
624    xf86config->conf_modules = configureModuleSection();
625    xf86config->conf_flags = configureFlagsSection();
626    xf86config->conf_videoadaptor_lst = NULL;
627    xf86config->conf_modes_lst = NULL;
628    xf86config->conf_vendor_lst = NULL;
629    xf86config->conf_dri = NULL;
630    xf86config->conf_input_lst = configureInputSection();
631    xf86config->conf_layout_lst = configureLayoutSection();
632
633    home = getenv("HOME");
634    if ((home == NULL) || (home[0] == '\0')) {
635        home = "/";
636    }
637    else {
638        /* Determine if trailing slash is present or needed */
639        int l = strlen(home);
640
641        if (home[l - 1] != '/') {
642            addslash = "/";
643        }
644    }
645
646    snprintf(filename, sizeof(filename), "%s%s" XF86CONFIGFILE ".new",
647             home, addslash);
648
649    if (xf86writeConfigFile(filename, xf86config) == 0) {
650        xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n",
651                filename, strerror(errno));
652        goto bail;
653    }
654
655    xf86DoConfigurePass1 = FALSE;
656    /* Try to get DDC information filled in */
657    xf86ConfigFile = filename;
658    if (xf86HandleConfigFile(FALSE) != CONFIG_OK) {
659        goto bail;
660    }
661
662    xf86DoConfigurePass1 = FALSE;
663
664    dev2screen = xnfcalloc(xf86NumDrivers, sizeof(int));
665
666    {
667        Bool *driverProbed = xnfcalloc(xf86NumDrivers, sizeof(Bool));
668
669        for (screennum = 0; screennum < nDevToConfig; screennum++) {
670            int k, l, n, oldNumScreens;
671
672            i = DevToConfig[screennum].iDriver;
673
674            if (driverProbed[i])
675                continue;
676            driverProbed[i] = TRUE;
677
678            oldNumScreens = xf86NumScreens;
679
680            xf86CallDriverProbe(xf86DriverList[i], FALSE);
681
682            /* reorder */
683            k = screennum > 0 ? screennum : 1;
684            for (l = oldNumScreens; l < xf86NumScreens; l++) {
685                /* is screen primary? */
686                Bool primary = FALSE;
687
688                for (n = 0; n < xf86Screens[l]->numEntities; n++) {
689                    if (xf86IsEntityPrimary(xf86Screens[l]->entityList[n])) {
690                        dev2screen[0] = l;
691                        primary = TRUE;
692                        break;
693                    }
694                }
695                if (primary)
696                    continue;
697                /* not primary: assign it to next device of same driver */
698                /*
699                 * NOTE: we assume that devices in DevToConfig
700                 * and xf86Screens[] have the same order except
701                 * for the primary device which always comes first.
702                 */
703                for (; k < nDevToConfig; k++) {
704                    if (DevToConfig[k].iDriver == i) {
705                        dev2screen[k++] = l;
706                        break;
707                    }
708                }
709            }
710        }
711        free(driverProbed);
712    }
713
714    if (nDevToConfig != xf86NumScreens) {
715        ErrorF("Number of created screens does not match number of detected"
716               " devices.\n  Configuration failed.\n");
717        goto bail;
718    }
719
720    xf86PostProbe();
721
722    for (j = 0; j < xf86NumScreens; j++) {
723        xf86Screens[j]->scrnIndex = j;
724    }
725
726    xf86freeMonitorList(xf86config->conf_monitor_lst);
727    xf86config->conf_monitor_lst = NULL;
728    xf86freeScreenList(xf86config->conf_screen_lst);
729    xf86config->conf_screen_lst = NULL;
730    for (j = 0; j < xf86NumScreens; j++) {
731        XF86ConfMonitorPtr monitor_ptr;
732        XF86ConfScreenPtr screen_ptr;
733
734        ConfiguredMonitor = NULL;
735
736        if ((*xf86Screens[dev2screen[j]]->PreInit) (xf86Screens[dev2screen[j]],
737                                                    PROBE_DETECT) &&
738            ConfiguredMonitor) {
739            monitor_ptr = configureDDCMonitorSection(j);
740        }
741        else {
742            monitor_ptr = configureMonitorSection(j);
743        }
744        screen_ptr = configureScreenSection(j);
745
746        xf86config->conf_monitor_lst = (XF86ConfMonitorPtr) xf86addListItem((glp) xf86config->conf_monitor_lst, (glp) monitor_ptr);
747        xf86config->conf_screen_lst = (XF86ConfScreenPtr) xf86addListItem((glp)
748                                                                          xf86config->
749                                                                          conf_screen_lst,
750                                                                          (glp)
751                                                                          screen_ptr);
752    }
753
754    if (xf86writeConfigFile(filename, xf86config) == 0) {
755        xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n",
756                filename, strerror(errno));
757        goto bail;
758    }
759
760    ErrorF("\n");
761
762    if (!foundMouse) {
763        ErrorF("\n" __XSERVERNAME__ " is not able to detect your mouse.\n"
764               "Edit the file and correct the Device.\n");
765    }
766    else {
767        ErrorF("\n" __XSERVERNAME__ " detected your mouse at device %s.\n"
768               "Please check your config if the mouse is still not\n"
769               "operational, as by default " __XSERVERNAME__
770               " tries to autodetect\n" "the protocol.\n", DFLT_MOUSE_DEV);
771    }
772
773    if (xf86NumScreens > 1) {
774        ErrorF("\n" __XSERVERNAME__
775               " has configured a multihead system, please check your config.\n");
776    }
777
778    ErrorF("\nYour %s file is %s\n\n", XF86CONFIGFILE, filename);
779    ErrorF("To test the server, run 'X -config %s'\n\n", filename);
780
781 bail:
782    OsCleanup(TRUE);
783    AbortDDX(EXIT_ERR_CONFIGURE);
784    fflush(stderr);
785    exit(0);
786}
787
788/* Xorg -showopts:
789 *   For each driver module installed, print out the list
790 *   of options and their argument types, then exit
791 *
792 * Author:  Marcus Schaefer, ms@suse.de
793 */
794
795void
796DoShowOptions(void)
797{
798    int i = 0;
799    const char **vlist = NULL;
800    char *pSymbol = 0;
801    XF86ModuleData *initData = 0;
802
803    if (!(vlist = xf86DriverlistFromCompile())) {
804        ErrorF("Missing output drivers\n");
805        goto bail;
806    }
807    xf86LoadModules(vlist, 0);
808    free(vlist);
809    for (i = 0; i < xf86NumDrivers; i++) {
810        if (xf86DriverList[i]->AvailableOptions) {
811            const OptionInfoRec *pOption =
812                (*xf86DriverList[i]->AvailableOptions) (0, 0);
813            if (!pOption) {
814                ErrorF("(EE) Couldn't read option table for %s driver\n",
815                       xf86DriverList[i]->driverName);
816                continue;
817            }
818            XNFasprintf(&pSymbol, "%sModuleData",
819                        xf86DriverList[i]->driverName);
820            initData = LoaderSymbol(pSymbol);
821            if (initData) {
822                XF86ModuleVersionInfo *vers = initData->vers;
823                const OptionInfoRec *p;
824
825                ErrorF("Driver[%d]:%s[%s] {\n",
826                       i, xf86DriverList[i]->driverName, vers->vendor);
827                for (p = pOption; p->name != NULL; p++) {
828                    ErrorF("\t%s:%s\n", p->name, optionTypeToString(p->type));
829                }
830                ErrorF("}\n");
831            }
832        }
833    }
834 bail:
835    OsCleanup(TRUE);
836    AbortDDX(EXIT_ERR_DRIVERS);
837    fflush(stderr);
838    exit(0);
839}
840