xf86Configure.c revision 7e31ba66
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#include "loaderProcs.h"
44
45typedef struct _DevToConfig {
46    GDevRec GDev;
47    struct pci_device *pVideo;
48#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
49    sbusDevicePtr sVideo;
50#endif
51    int iDriver;
52} DevToConfigRec, *DevToConfigPtr;
53
54static DevToConfigPtr DevToConfig = NULL;
55static int nDevToConfig = 0, CurrentDriver;
56
57xf86MonPtr ConfiguredMonitor;
58Bool xf86DoConfigurePass1 = TRUE;
59static Bool foundMouse = FALSE;
60
61#if   defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
62static const char *DFLT_MOUSE_DEV = "/dev/sysmouse";
63static const char *DFLT_MOUSE_PROTO = "auto";
64#elif defined(__linux__)
65static const char *DFLT_MOUSE_DEV = "/dev/input/mice";
66static const char *DFLT_MOUSE_PROTO = "auto";
67#elif defined(WSCONS_SUPPORT)
68static const char *DFLT_MOUSE_DEV = "/dev/wsmouse";
69static const char *DFLT_MOUSE_PROTO = "wsmouse";
70#else
71static const char *DFLT_MOUSE_DEV = "/dev/mouse";
72static const char *DFLT_MOUSE_PROTO = "auto";
73#endif
74
75/*
76 * This is called by the driver, either through xf86Match???Instances() or
77 * directly.  We allocate a GDevRec and fill it in as much as we can, letting
78 * the caller fill in the rest and/or change it as it sees fit.
79 */
80GDevPtr
81xf86AddBusDeviceToConfigure(const char *driver, BusType bus, void *busData,
82                            int chipset)
83{
84    int ret, i, j;
85    char *lower_driver;
86
87    if (!xf86DoConfigure || !xf86DoConfigurePass1)
88        return NULL;
89
90    /* Check for duplicates */
91    for (i = 0; i < nDevToConfig; i++) {
92        switch (bus) {
93#ifdef XSERVER_LIBPCIACCESS
94        case BUS_PCI:
95            ret = xf86PciConfigure(busData, DevToConfig[i].pVideo);
96            break;
97#endif
98#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
99        case BUS_SBUS:
100            ret = xf86SbusConfigure(busData, DevToConfig[i].sVideo);
101            break;
102#endif
103#if defined(__arm32__) || defined(__arm__)
104        case BUS_ISA:
105            break;
106#endif
107        default:
108            return NULL;
109        }
110        if (ret == 0)
111            goto out;
112    }
113
114    /* Allocate new structure occurrence */
115    i = nDevToConfig++;
116    DevToConfig =
117        xnfreallocarray(DevToConfig, nDevToConfig, sizeof(DevToConfigRec));
118    memset(DevToConfig + i, 0, sizeof(DevToConfigRec));
119
120    DevToConfig[i].GDev.chipID =
121        DevToConfig[i].GDev.chipRev = DevToConfig[i].GDev.irq = -1;
122
123    DevToConfig[i].iDriver = CurrentDriver;
124
125    /* Fill in what we know, converting the driver name to lower case */
126    lower_driver = xnfalloc(strlen(driver) + 1);
127    for (j = 0; (lower_driver[j] = tolower(driver[j])); j++);
128    DevToConfig[i].GDev.driver = lower_driver;
129
130    switch (bus) {
131#ifdef XSERVER_LIBPCIACCESS
132    case BUS_PCI:
133	DevToConfig[i].pVideo = busData;
134        xf86PciConfigureNewDev(busData, DevToConfig[i].pVideo,
135                               &DevToConfig[i].GDev, &chipset);
136        break;
137#endif
138#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
139    case BUS_SBUS:
140	DevToConfig[i].sVideo = busData;
141        xf86SbusConfigureNewDev(busData, DevToConfig[i].sVideo,
142                                &DevToConfig[i].GDev);
143        break;
144#endif
145#if defined(__arm32__) || defined(__arm__)
146    case BUS_ISA:
147	DevToConfig[i].GDev.busID = xnfalloc(6);
148	strcpy((char *)DevToConfig[i].GDev.busID, "ISA");
149	break;
150#endif
151    default:
152        break;
153    }
154
155    /* Get driver's available options */
156    if (xf86DriverList[CurrentDriver]->AvailableOptions)
157        DevToConfig[i].GDev.options = (OptionInfoPtr)
158            (*xf86DriverList[CurrentDriver]->AvailableOptions) (chipset, bus);
159
160    return &DevToConfig[i].GDev;
161
162 out:
163    return NULL;
164}
165
166static XF86ConfInputPtr
167configureInputSection(void)
168{
169    XF86ConfInputPtr mouse = NULL;
170
171    parsePrologue(XF86ConfInputPtr, XF86ConfInputRec);
172
173    ptr->inp_identifier = xnfstrdup("Keyboard0");
174    ptr->inp_driver = xnfstrdup("kbd");
175    ptr->list.next = NULL;
176#if defined(WSCONS_SUPPORT) && !defined(__i386__) && !defined(__amd64__)
177    ptr->inp_option_lst = xf86addNewOption(ptr->inp_option_lst,
178        xstrdup("Protocol"), "wskbd");
179    ptr->inp_option_lst = xf86addNewOption(ptr->inp_option_lst,
180        xstrdup("Device"), "/dev/wskbd");
181#endif
182
183    /* Crude mechanism to auto-detect mouse (os dependent) */
184    {
185        int fd;
186
187        fd = open(DFLT_MOUSE_DEV, 0);
188        if (fd != -1) {
189            foundMouse = TRUE;
190            close(fd);
191        }
192    }
193
194    mouse = calloc(1, sizeof(XF86ConfInputRec));
195    mouse->inp_identifier = xnfstrdup("Mouse0");
196    mouse->inp_driver = xnfstrdup("mouse");
197    mouse->inp_option_lst =
198        xf86addNewOption(mouse->inp_option_lst, xnfstrdup("Protocol"),
199                         xnfstrdup(DFLT_MOUSE_PROTO));
200    mouse->inp_option_lst =
201        xf86addNewOption(mouse->inp_option_lst, xnfstrdup("Device"),
202                         xnfstrdup(DFLT_MOUSE_DEV));
203    mouse->inp_option_lst =
204        xf86addNewOption(mouse->inp_option_lst, xnfstrdup("ZAxisMapping"),
205                         xnfstrdup("4 5 6 7"));
206    ptr = (XF86ConfInputPtr) xf86addListItem((glp) ptr, (glp) mouse);
207    return ptr;
208}
209
210static XF86ConfScreenPtr
211configureScreenSection(int screennum)
212{
213    int i;
214    int depths[] = { 1, 4, 8, 15, 16, 24 /*, 32 */  };
215    char *tmp;
216    parsePrologue(XF86ConfScreenPtr, XF86ConfScreenRec);
217
218    XNFasprintf(&tmp, "Screen%d", screennum);
219    ptr->scrn_identifier = tmp;
220    XNFasprintf(&tmp, "Monitor%d", screennum);
221    ptr->scrn_monitor_str = tmp;
222    XNFasprintf(&tmp, "Card%d", screennum);
223    ptr->scrn_device_str = tmp;
224
225    for (i = 0; i < ARRAY_SIZE(depths); i++) {
226        XF86ConfDisplayPtr conf_display;
227
228        conf_display = calloc(1, sizeof(XF86ConfDisplayRec));
229        conf_display->disp_depth = depths[i];
230        conf_display->disp_black.red = conf_display->disp_white.red = -1;
231        conf_display->disp_black.green = conf_display->disp_white.green = -1;
232        conf_display->disp_black.blue = conf_display->disp_white.blue = -1;
233        ptr->scrn_display_lst = (XF86ConfDisplayPtr) xf86addListItem((glp) ptr->
234                                                                     scrn_display_lst,
235                                                                     (glp)
236                                                                     conf_display);
237    }
238
239    return ptr;
240}
241
242static const char *
243optionTypeToString(OptionValueType type)
244{
245    switch (type) {
246    case OPTV_NONE:
247        return "";
248    case OPTV_INTEGER:
249        return "<i>";
250    case OPTV_STRING:
251        return "<str>";
252    case OPTV_ANYSTR:
253        return "[<str>]";
254    case OPTV_REAL:
255        return "<f>";
256    case OPTV_BOOLEAN:
257        return "[<bool>]";
258    case OPTV_FREQ:
259        return "<freq>";
260    case OPTV_PERCENT:
261        return "<percent>";
262    default:
263        return "";
264    }
265}
266
267static XF86ConfDevicePtr
268configureDeviceSection(int screennum)
269{
270    OptionInfoPtr p;
271    int i = 0;
272    char *identifier;
273
274    parsePrologue(XF86ConfDevicePtr, XF86ConfDeviceRec);
275
276    /* Move device info to parser structure */
277   if (asprintf(&identifier, "Card%d", screennum) == -1)
278        identifier = NULL;
279    ptr->dev_identifier = identifier;
280    ptr->dev_chipset = DevToConfig[screennum].GDev.chipset;
281    ptr->dev_busid = DevToConfig[screennum].GDev.busID;
282    ptr->dev_driver = DevToConfig[screennum].GDev.driver;
283    ptr->dev_ramdac = DevToConfig[screennum].GDev.ramdac;
284    for (i = 0; i < MAXDACSPEEDS; i++)
285        ptr->dev_dacSpeeds[i] = DevToConfig[screennum].GDev.dacSpeeds[i];
286    ptr->dev_videoram = DevToConfig[screennum].GDev.videoRam;
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    parsePrologue(XF86ConfModulePtr, XF86ConfModuleRec);
419
420    elist = LoaderListDir("extensions", NULL);
421    if (elist) {
422        for (el = elist; *el; el++) {
423            XF86LoadPtr module;
424
425            module = calloc(1, sizeof(XF86LoadRec));
426            module->load_name = *el;
427            ptr->mod_load_lst = (XF86LoadPtr) xf86addListItem((glp) ptr->
428                                                              mod_load_lst,
429                                                              (glp) module);
430        }
431        free(elist);
432    }
433
434    return ptr;
435}
436
437static XF86ConfFilesPtr
438configureFilesSection(void)
439{
440    parsePrologue(XF86ConfFilesPtr, XF86ConfFilesRec);
441
442    if (xf86ModulePath)
443        ptr->file_modulepath = xnfstrdup(xf86ModulePath);
444    if (defaultFontPath)
445        ptr->file_fontpath = xnfstrdup(defaultFontPath);
446
447    return ptr;
448}
449
450static XF86ConfMonitorPtr
451configureMonitorSection(int screennum)
452{
453    char *tmp;
454    parsePrologue(XF86ConfMonitorPtr, XF86ConfMonitorRec);
455
456    XNFasprintf(&tmp, "Monitor%d", screennum);
457    ptr->mon_identifier = tmp;
458    ptr->mon_vendor = xnfstrdup("Monitor Vendor");
459    ptr->mon_modelname = xnfstrdup("Monitor Model");
460
461    return ptr;
462}
463
464/* Initialize Configure Monitor from Detailed Timing Block */
465static void
466handle_detailed_input(struct detailed_monitor_section *det_mon, void *data)
467{
468    XF86ConfMonitorPtr ptr = (XF86ConfMonitorPtr) data;
469
470    switch (det_mon->type) {
471    case DS_NAME:
472        ptr->mon_modelname = realloc(ptr->mon_modelname,
473                                     strlen((char *) (det_mon->section.name)) +
474                                     1);
475        strcpy(ptr->mon_modelname, (char *) (det_mon->section.name));
476        break;
477    case DS_RANGES:
478        ptr->mon_hsync[ptr->mon_n_hsync].lo = det_mon->section.ranges.min_h;
479        ptr->mon_hsync[ptr->mon_n_hsync].hi = det_mon->section.ranges.max_h;
480        ptr->mon_n_vrefresh = 1;
481        ptr->mon_vrefresh[ptr->mon_n_hsync].lo = det_mon->section.ranges.min_v;
482        ptr->mon_vrefresh[ptr->mon_n_hsync].hi = det_mon->section.ranges.max_v;
483        ptr->mon_n_hsync++;
484    default:
485        break;
486    }
487}
488
489static XF86ConfMonitorPtr
490configureDDCMonitorSection(int screennum)
491{
492    int len, mon_width, mon_height;
493
494#define displaySizeMaxLen 80
495    char displaySize_string[displaySizeMaxLen];
496    int displaySizeLen;
497    char *tmp;
498
499    parsePrologue(XF86ConfMonitorPtr, XF86ConfMonitorRec);
500
501    XNFasprintf(&tmp, "Monitor%d", screennum);
502    ptr->mon_identifier = tmp;
503    ptr->mon_vendor = xnfstrdup(ConfiguredMonitor->vendor.name);
504    XNFasprintf(&ptr->mon_modelname, "%x", ConfiguredMonitor->vendor.prod_id);
505
506    /* features in centimetres, we want millimetres */
507    mon_width = 10 * ConfiguredMonitor->features.hsize;
508    mon_height = 10 * ConfiguredMonitor->features.vsize;
509
510#ifdef CONFIGURE_DISPLAYSIZE
511    ptr->mon_width = mon_width;
512    ptr->mon_height = mon_height;
513#else
514    if (mon_width && mon_height) {
515        /* when values available add DisplaySize option AS A COMMENT */
516
517        displaySizeLen = snprintf(displaySize_string, displaySizeMaxLen,
518                                  "\t#DisplaySize\t%5d %5d\t# mm\n",
519                                  mon_width, mon_height);
520
521        if (displaySizeLen > 0 && displaySizeLen < displaySizeMaxLen) {
522            if (ptr->mon_comment) {
523                len = strlen(ptr->mon_comment);
524            }
525            else {
526                len = 0;
527            }
528            if ((ptr->mon_comment =
529                 realloc(ptr->mon_comment,
530                         len + strlen(displaySize_string) + 1))) {
531                strcpy(ptr->mon_comment + len, displaySize_string);
532            }
533        }
534    }
535#endif                          /* def CONFIGURE_DISPLAYSIZE */
536
537    xf86ForEachDetailedBlock(ConfiguredMonitor, handle_detailed_input, ptr);
538
539    if (ConfiguredMonitor->features.dpms) {
540        ptr->mon_option_lst =
541            xf86addNewOption(ptr->mon_option_lst, xnfstrdup("DPMS"), NULL);
542    }
543
544    return ptr;
545}
546
547static int
548is_fallback(const char *s)
549{
550    /* later entries are less preferred */
551    const char *fallback[5] = { "modesetting", "fbdev", "vesa",  "wsfb", NULL };
552    int i;
553
554    for (i = 0; fallback[i]; i++)
555	if (strstr(s, fallback[i]))
556	    return i;
557
558    return -1;
559}
560
561static int
562driver_sort(const void *_l, const void *_r)
563{
564    const char *l = *(const char **)_l;
565    const char *r = *(const char **)_r;
566    int left = is_fallback(l);
567    int right = is_fallback(r);
568
569    /* neither is a fallback, asciibetize */
570    if (left == -1 && right == -1)
571	return strcmp(l, r);
572
573    /* left is a fallback, right is not */
574    if (left >= 0 && right == -1)
575	return 1;
576
577    /* right is a fallback, left is not */
578    if (right >= 0 && left == -1)
579	return -1;
580
581    /* both are fallbacks, decide which is worse */
582    return left - right;
583}
584
585static void
586fixup_video_driver_list(const char **drivers)
587{
588    const char **end;
589
590    /* walk to the end of the list */
591    for (end = drivers; *end && **end; end++);
592
593    qsort(drivers, end - drivers, sizeof(const char *), driver_sort);
594}
595
596static const char **
597GenerateDriverList(void)
598{
599    const char **ret;
600    static const char *patlist[] = { "(.*)_drv\\.so", NULL };
601    ret = LoaderListDir("drivers", patlist);
602
603    /* fix up the probe order for video drivers */
604    if (ret != NULL)
605        fixup_video_driver_list(ret);
606
607    return ret;
608}
609
610void
611DoConfigure(void)
612{
613    int i, j, screennum = -1;
614    const char *home = NULL;
615    char filename[PATH_MAX];
616    const char *addslash = "";
617    XF86ConfigPtr xf86config = NULL;
618    const char **vlist, **vl;
619    int *dev2screen;
620
621    vlist = GenerateDriverList();
622
623    if (!vlist) {
624        ErrorF("Missing output drivers.  Configuration failed.\n");
625        goto bail;
626    }
627
628    ErrorF("List of video drivers:\n");
629    for (vl = vlist; *vl; vl++)
630        ErrorF("\t%s\n", *vl);
631
632    /* Load all the drivers that were found. */
633    xf86LoadModules(vlist, NULL);
634
635    free(vlist);
636
637    xorgHWAccess = xf86EnableIO();
638
639    /* Create XF86Config file structure */
640    xf86config = calloc(1, sizeof(XF86ConfigRec));
641
642    /* Call all of the probe functions, reporting the results. */
643    for (CurrentDriver = 0; CurrentDriver < xf86NumDrivers; CurrentDriver++) {
644        Bool found_screen;
645        DriverRec *const drv = xf86DriverList[CurrentDriver];
646
647        found_screen = xf86CallDriverProbe(drv, TRUE);
648        if (found_screen && drv->Identify) {
649            (*drv->Identify) (0);
650        }
651    }
652
653    if (nDevToConfig <= 0) {
654        ErrorF("No devices to configure.  Configuration failed.\n");
655        goto bail;
656    }
657
658    /* Add device, monitor and screen sections for detected devices */
659    for (screennum = 0; screennum < nDevToConfig; screennum++) {
660        XF86ConfDevicePtr device_ptr;
661        XF86ConfMonitorPtr monitor_ptr;
662        XF86ConfScreenPtr screen_ptr;
663
664        device_ptr = configureDeviceSection(screennum);
665        xf86config->conf_device_lst = (XF86ConfDevicePtr) xf86addListItem((glp)
666                                                                          xf86config->
667                                                                          conf_device_lst,
668                                                                          (glp)
669                                                                          device_ptr);
670        monitor_ptr = configureMonitorSection(screennum);
671        xf86config->conf_monitor_lst = (XF86ConfMonitorPtr) xf86addListItem((glp) xf86config->conf_monitor_lst, (glp) monitor_ptr);
672        screen_ptr = configureScreenSection(screennum);
673        xf86config->conf_screen_lst = (XF86ConfScreenPtr) xf86addListItem((glp)
674                                                                          xf86config->
675                                                                          conf_screen_lst,
676                                                                          (glp)
677                                                                          screen_ptr);
678    }
679
680    xf86config->conf_files = configureFilesSection();
681    xf86config->conf_modules = configureModuleSection();
682    xf86config->conf_flags = configureFlagsSection();
683    xf86config->conf_videoadaptor_lst = NULL;
684    xf86config->conf_modes_lst = NULL;
685    xf86config->conf_vendor_lst = NULL;
686    xf86config->conf_dri = NULL;
687    xf86config->conf_input_lst = configureInputSection();
688    xf86config->conf_layout_lst = configureLayoutSection();
689
690    home = getenv("HOME");
691    if ((home == NULL) || (home[0] == '\0')) {
692        home = "/";
693    }
694    else {
695        /* Determine if trailing slash is present or needed */
696        int l = strlen(home);
697
698        if (home[l - 1] != '/') {
699            addslash = "/";
700        }
701    }
702
703    snprintf(filename, sizeof(filename), "%s%s" XF86CONFIGFILE ".new",
704             home, addslash);
705
706    if (xf86writeConfigFile(filename, xf86config) == 0) {
707        xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n",
708                filename, strerror(errno));
709        goto bail;
710    }
711
712    xf86DoConfigurePass1 = FALSE;
713    /* Try to get DDC information filled in */
714    xf86ConfigFile = filename;
715    if (xf86HandleConfigFile(FALSE) != CONFIG_OK) {
716        goto bail;
717    }
718
719    xf86DoConfigurePass1 = FALSE;
720
721    dev2screen = xnfcalloc(nDevToConfig, sizeof(int));
722
723    {
724        Bool *driverProbed = xnfcalloc(xf86NumDrivers, sizeof(Bool));
725
726        for (screennum = 0; screennum < nDevToConfig; screennum++) {
727            int k, l, n, oldNumScreens;
728
729            i = DevToConfig[screennum].iDriver;
730
731            if (driverProbed[i])
732                continue;
733            driverProbed[i] = TRUE;
734
735            oldNumScreens = xf86NumScreens;
736
737            xf86CallDriverProbe(xf86DriverList[i], FALSE);
738
739            /* reorder */
740            k = screennum > 0 ? screennum : 1;
741            for (l = oldNumScreens; l < xf86NumScreens; l++) {
742                /* is screen primary? */
743                Bool primary = FALSE;
744
745                for (n = 0; n < xf86Screens[l]->numEntities; n++) {
746                    if (xf86IsEntityPrimary(xf86Screens[l]->entityList[n])) {
747                        dev2screen[0] = l;
748                        primary = TRUE;
749                        break;
750                    }
751                }
752                if (primary)
753                    continue;
754                /* not primary: assign it to next device of same driver */
755                /*
756                 * NOTE: we assume that devices in DevToConfig
757                 * and xf86Screens[] have the same order except
758                 * for the primary device which always comes first.
759                 */
760                for (; k < nDevToConfig; k++) {
761                    if (DevToConfig[k].iDriver == i) {
762                        dev2screen[k++] = l;
763                        break;
764                    }
765                }
766            }
767        }
768        free(driverProbed);
769    }
770
771    if (nDevToConfig != xf86NumScreens) {
772        ErrorF("Number of created screens does not match number of detected"
773               " devices.\n  Configuration failed.\n");
774        goto bail;
775    }
776
777    xf86PostProbe();
778
779    for (j = 0; j < xf86NumScreens; j++) {
780        xf86Screens[j]->scrnIndex = j;
781    }
782
783    xf86freeMonitorList(xf86config->conf_monitor_lst);
784    xf86config->conf_monitor_lst = NULL;
785    xf86freeScreenList(xf86config->conf_screen_lst);
786    xf86config->conf_screen_lst = NULL;
787    for (j = 0; j < xf86NumScreens; j++) {
788        XF86ConfMonitorPtr monitor_ptr;
789        XF86ConfScreenPtr screen_ptr;
790
791        ConfiguredMonitor = NULL;
792
793        if ((*xf86Screens[dev2screen[j]]->PreInit) &&
794            (*xf86Screens[dev2screen[j]]->PreInit) (xf86Screens[dev2screen[j]],
795                                                    PROBE_DETECT) &&
796            ConfiguredMonitor) {
797            monitor_ptr = configureDDCMonitorSection(j);
798        }
799        else {
800            monitor_ptr = configureMonitorSection(j);
801        }
802        screen_ptr = configureScreenSection(j);
803
804        xf86config->conf_monitor_lst = (XF86ConfMonitorPtr) xf86addListItem((glp) xf86config->conf_monitor_lst, (glp) monitor_ptr);
805        xf86config->conf_screen_lst = (XF86ConfScreenPtr) xf86addListItem((glp)
806                                                                          xf86config->
807                                                                          conf_screen_lst,
808                                                                          (glp)
809                                                                          screen_ptr);
810    }
811
812    if (xf86writeConfigFile(filename, xf86config) == 0) {
813        xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n",
814                filename, strerror(errno));
815        goto bail;
816    }
817
818    ErrorF("\n");
819
820    if (!foundMouse) {
821        ErrorF("\n" __XSERVERNAME__ " is not able to detect your mouse.\n"
822               "Edit the file and correct the Device.\n");
823    }
824    else {
825        ErrorF("\n" __XSERVERNAME__ " detected your mouse at device %s.\n"
826               "Please check your config if the mouse is still not\n"
827               "operational, as by default " __XSERVERNAME__
828               " tries to autodetect\n" "the protocol.\n", DFLT_MOUSE_DEV);
829    }
830
831    if (xf86NumScreens > 1) {
832        ErrorF("\n" __XSERVERNAME__
833               " has configured a multihead system, please check your config.\n");
834    }
835
836    ErrorF("\nYour %s file is %s\n\n", XF86CONFIGFILE, filename);
837    ErrorF("To test the server, run 'X -config %s'\n\n", filename);
838
839 bail:
840    OsCleanup(TRUE);
841    AbortDDX(EXIT_ERR_CONFIGURE);
842    fflush(stderr);
843    exit(0);
844}
845
846/* Xorg -showopts:
847 *   For each driver module installed, print out the list
848 *   of options and their argument types, then exit
849 *
850 * Author:  Marcus Schaefer, ms@suse.de
851 */
852
853void
854DoShowOptions(void)
855{
856    int i = 0;
857    const char **vlist = NULL;
858    char *pSymbol = 0;
859    XF86ModuleData *initData = 0;
860
861    if (!(vlist = GenerateDriverList())) {
862        ErrorF("Missing output drivers\n");
863        goto bail;
864    }
865    xf86LoadModules(vlist, 0);
866    free(vlist);
867    for (i = 0; i < xf86NumDrivers; i++) {
868        if (xf86DriverList[i]->AvailableOptions) {
869            const OptionInfoRec *pOption =
870                (*xf86DriverList[i]->AvailableOptions) (0, 0);
871            if (!pOption) {
872                ErrorF("(EE) Couldn't read option table for %s driver\n",
873                       xf86DriverList[i]->driverName);
874                continue;
875            }
876            XNFasprintf(&pSymbol, "%sModuleData",
877                        xf86DriverList[i]->driverName);
878            initData = LoaderSymbol(pSymbol);
879            if (initData) {
880                XF86ModuleVersionInfo *vers = initData->vers;
881                const OptionInfoRec *p;
882
883                ErrorF("Driver[%d]:%s[%s] {\n",
884                       i, xf86DriverList[i]->driverName, vers->vendor);
885                for (p = pOption; p->name != NULL; p++) {
886                    ErrorF("\t%s:%s\n", p->name, optionTypeToString(p->type));
887                }
888                ErrorF("}\n");
889            }
890        }
891    }
892 bail:
893    OsCleanup(TRUE);
894    AbortDDX(EXIT_ERR_DRIVERS);
895    fflush(stderr);
896    exit(0);
897}
898