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