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