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