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