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