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