1706f2543Smrg/*
2706f2543Smrg * Copyright 2000-2002 by Alan Hourihane, Flint Mountain, North Wales.
3706f2543Smrg *
4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its
5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that
6706f2543Smrg * the above copyright notice appear in all copies and that both that
7706f2543Smrg * copyright notice and this permission notice appear in supporting
8706f2543Smrg * documentation, and that the name of Alan Hourihane not be used in
9706f2543Smrg * advertising or publicity pertaining to distribution of the software without
10706f2543Smrg * specific, written prior permission.  Alan Hourihane makes no representations
11706f2543Smrg * about the suitability of this software for any purpose.  It is provided
12706f2543Smrg * "as is" without express or implied warranty.
13706f2543Smrg *
14706f2543Smrg * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16706f2543Smrg * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20706f2543Smrg * PERFORMANCE OF THIS SOFTWARE.
21706f2543Smrg *
22706f2543Smrg * Author:  Alan Hourihane, alanh@fairlite.demon.co.uk
23706f2543Smrg *
24706f2543Smrg */
25706f2543Smrg
26706f2543Smrg#ifdef HAVE_XORG_CONFIG_H
27706f2543Smrg#include <xorg-config.h>
28706f2543Smrg#endif
29706f2543Smrg
30706f2543Smrg#include "xf86.h"
31706f2543Smrg#include "xf86Config.h"
32706f2543Smrg#include "xf86_OSlib.h"
33706f2543Smrg#include "xf86Priv.h"
34706f2543Smrg#define IN_XSERVER
35706f2543Smrg#include "Configint.h"
36706f2543Smrg#include "xf86DDC.h"
37706f2543Smrg#include "xf86pciBus.h"
38706f2543Smrg#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
39706f2543Smrg#include "xf86Bus.h"
40706f2543Smrg#include "xf86Sbus.h"
41706f2543Smrg#endif
42706f2543Smrg
43706f2543Smrgtypedef struct _DevToConfig {
44706f2543Smrg    GDevRec GDev;
45706f2543Smrg    struct pci_device * pVideo;
46706f2543Smrg#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
47706f2543Smrg    sbusDevicePtr sVideo;
48706f2543Smrg#endif
49706f2543Smrg    int iDriver;
50706f2543Smrg} DevToConfigRec, *DevToConfigPtr;
51706f2543Smrg
52706f2543Smrgstatic DevToConfigPtr DevToConfig = NULL;
53706f2543Smrgstatic int nDevToConfig = 0, CurrentDriver;
54706f2543Smrg
55706f2543Smrgxf86MonPtr ConfiguredMonitor;
56706f2543SmrgBool xf86DoConfigurePass1 = TRUE;
57706f2543Smrgstatic Bool foundMouse = FALSE;
58706f2543Smrg
59706f2543Smrg#if   defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
60706f2543Smrgstatic char *DFLT_MOUSE_DEV = "/dev/sysmouse";
61706f2543Smrgstatic char *DFLT_MOUSE_PROTO = "auto";
62706f2543Smrg#elif defined(linux)
63706f2543Smrgstatic char DFLT_MOUSE_DEV[] = "/dev/input/mice";
64706f2543Smrgstatic char DFLT_MOUSE_PROTO[] = "auto";
65706f2543Smrg#else
66706f2543Smrgstatic char *DFLT_MOUSE_DEV = "/dev/mouse";
67706f2543Smrgstatic char *DFLT_MOUSE_PROTO = "auto";
68706f2543Smrg#endif
69706f2543Smrg
70706f2543Smrg/*
71706f2543Smrg * This is called by the driver, either through xf86Match???Instances() or
72706f2543Smrg * directly.  We allocate a GDevRec and fill it in as much as we can, letting
73706f2543Smrg * the caller fill in the rest and/or change it as it sees fit.
74706f2543Smrg */
75706f2543SmrgGDevPtr
76706f2543Smrgxf86AddBusDeviceToConfigure(const char *driver, BusType bus, void *busData, int chipset)
77706f2543Smrg{
78706f2543Smrg    int ret, i, j;
79706f2543Smrg
80706f2543Smrg    if (!xf86DoConfigure || !xf86DoConfigurePass1)
81706f2543Smrg	return NULL;
82706f2543Smrg
83706f2543Smrg    /* Check for duplicates */
84706f2543Smrg    for (i = 0;  i < nDevToConfig;  i++) {
85706f2543Smrg        switch (bus) {
86706f2543Smrg            case BUS_PCI:
87706f2543Smrg                ret = xf86PciConfigure(busData, DevToConfig[i].pVideo);
88706f2543Smrg                break;
89706f2543Smrg#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
90706f2543Smrg            case BUS_SBUS:
91706f2543Smrg                ret = xf86SbusConfigure(busData, DevToConfig[i].sVideo);
92706f2543Smrg                break;
93706f2543Smrg#endif
94706f2543Smrg#if defined(__arm32__)
95706f2543Smrg            case BUS_ISA:
96706f2543Smrg                break;
97706f2543Smrg#endif
98706f2543Smrg            default:
99706f2543Smrg                return NULL;
100706f2543Smrg        }
101706f2543Smrg        if (ret == 0)
102706f2543Smrg            goto out;
103706f2543Smrg    }
104706f2543Smrg
105706f2543Smrg    /* Allocate new structure occurrence */
106706f2543Smrg    i = nDevToConfig++;
107706f2543Smrg    DevToConfig =
108706f2543Smrg	xnfrealloc(DevToConfig, nDevToConfig * sizeof(DevToConfigRec));
109706f2543Smrg    memset(DevToConfig + i, 0, sizeof(DevToConfigRec));
110706f2543Smrg
111706f2543Smrg    DevToConfig[i].GDev.chipID =
112706f2543Smrg            DevToConfig[i].GDev.chipRev = DevToConfig[i].GDev.irq = -1;
113706f2543Smrg
114706f2543Smrg    DevToConfig[i].iDriver = CurrentDriver;
115706f2543Smrg
116706f2543Smrg    /* Fill in what we know, converting the driver name to lower case */
117706f2543Smrg    DevToConfig[i].GDev.driver = xnfalloc(strlen(driver) + 1);
118706f2543Smrg    for (j = 0;  (DevToConfig[i].GDev.driver[j] = tolower(driver[j]));  j++);
119706f2543Smrg
120706f2543Smrg    switch (bus) {
121706f2543Smrg        case BUS_PCI:
122706f2543Smrg            xf86PciConfigureNewDev(busData, DevToConfig[i].pVideo,
123706f2543Smrg                                   &DevToConfig[i].GDev, &chipset);
124706f2543Smrg            DevToConfig[i].pVideo = busData;
125706f2543Smrg	        break;
126706f2543Smrg#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
127706f2543Smrg        case BUS_SBUS:
128706f2543Smrg            xf86SbusConfigureNewDev(busData, DevToConfig[i].sVideo,
129706f2543Smrg                                    &DevToConfig[i].GDev);
130706f2543Smrg            DevToConfig[i].sVideo = busData;
131706f2543Smrg	        break;
132706f2543Smrg#endif
133706f2543Smrg#if defined(__arm32__)
134706f2543Smrg	case BUS_ISA:
135706f2543Smrg	    DevToConfig[i].GDev.busID = xnfalloc(6);
136706f2543Smrg	    strcpy(DevToConfig[i].GDev.busID, "ISA");
137706f2543Smrg	    break;
138706f2543Smrg#endif
139706f2543Smrg        default:
140706f2543Smrg	        break;
141706f2543Smrg    }
142706f2543Smrg
143706f2543Smrg    /* Get driver's available options */
144706f2543Smrg    if (xf86DriverList[CurrentDriver]->AvailableOptions)
145706f2543Smrg	DevToConfig[i].GDev.options = (OptionInfoPtr)
146706f2543Smrg	    (*xf86DriverList[CurrentDriver]->AvailableOptions)(chipset,
147706f2543Smrg							       bus);
148706f2543Smrg
149706f2543Smrg    return &DevToConfig[i].GDev;
150706f2543Smrg
151706f2543Smrgout:
152706f2543Smrg    return NULL;
153706f2543Smrg}
154706f2543Smrg
155706f2543Smrgstatic XF86ConfInputPtr
156706f2543SmrgconfigureInputSection (void)
157706f2543Smrg{
158706f2543Smrg    XF86ConfInputPtr mouse = NULL;
159706f2543Smrg    parsePrologue (XF86ConfInputPtr, XF86ConfInputRec)
160706f2543Smrg
161706f2543Smrg    ptr->inp_identifier = "Keyboard0";
162706f2543Smrg    ptr->inp_driver = "kbd";
163706f2543Smrg    ptr->list.next = NULL;
164706f2543Smrg#if defined(WSCONS_SUPPORT) && !defined(__i386__) && !defined(__amd64__)
165706f2543Smrg    ptr->inp_option_lst = xf86addNewOption(ptr->inp_option_lst,
166706f2543Smrg        xstrdup("Protocol"), "wskbd");
167706f2543Smrg    ptr->inp_option_lst = xf86addNewOption(ptr->inp_option_lst,
168706f2543Smrg        xstrdup("Device"), "/dev/wskbd");
169706f2543Smrg#endif
170706f2543Smrg
171706f2543Smrg    /* Crude mechanism to auto-detect mouse (os dependent) */
172706f2543Smrg    {
173706f2543Smrg	int fd;
174706f2543Smrg#ifdef WSCONS_SUPPORT
175706f2543Smrg	fd = open("/dev/wsmouse", 0);
176706f2543Smrg	if (fd >= 0) {
177706f2543Smrg	    DFLT_MOUSE_DEV = "/dev/wsmouse";
178706f2543Smrg	    DFLT_MOUSE_PROTO = "wsmouse";
179706f2543Smrg	    close(fd);
180706f2543Smrg	} else {
181706f2543Smrg	    ErrorF("cannot open /dev/wsmouse\n");
182706f2543Smrg	}
183706f2543Smrg#endif
184706f2543Smrg
185706f2543Smrg	fd = open(DFLT_MOUSE_DEV, 0);
186706f2543Smrg	if (fd != -1) {
187706f2543Smrg	    foundMouse = TRUE;
188706f2543Smrg	    close(fd);
189706f2543Smrg	}
190706f2543Smrg    }
191706f2543Smrg
192706f2543Smrg    mouse = calloc(1, sizeof(XF86ConfInputRec));
193706f2543Smrg    mouse->inp_identifier = "Mouse0";
194706f2543Smrg    mouse->inp_driver = "mouse";
195706f2543Smrg    mouse->inp_option_lst =
196706f2543Smrg		xf86addNewOption(mouse->inp_option_lst, strdup("Protocol"),
197706f2543Smrg				strdup(DFLT_MOUSE_PROTO));
198706f2543Smrg    mouse->inp_option_lst =
199706f2543Smrg		xf86addNewOption(mouse->inp_option_lst, strdup("Device"),
200706f2543Smrg				strdup(DFLT_MOUSE_DEV));
201706f2543Smrg    mouse->inp_option_lst =
202706f2543Smrg		xf86addNewOption(mouse->inp_option_lst, strdup("ZAxisMapping"),
203706f2543Smrg				strdup("4 5 6 7"));
204706f2543Smrg    ptr = (XF86ConfInputPtr)xf86addListItem((glp)ptr, (glp)mouse);
205706f2543Smrg    return ptr;
206706f2543Smrg}
207706f2543Smrg
208706f2543Smrgstatic XF86ConfScreenPtr
209706f2543SmrgconfigureScreenSection (int screennum)
210706f2543Smrg{
211706f2543Smrg    int i;
212706f2543Smrg    int depths[] = { 1, 4, 8, 15, 16, 24/*, 32*/ };
213706f2543Smrg    parsePrologue (XF86ConfScreenPtr, XF86ConfScreenRec)
214706f2543Smrg
215706f2543Smrg    XNFasprintf(&ptr->scrn_identifier, "Screen%d", screennum);
216706f2543Smrg    XNFasprintf(&ptr->scrn_monitor_str, "Monitor%d", screennum);
217706f2543Smrg    XNFasprintf(&ptr->scrn_device_str, "Card%d", screennum);
218706f2543Smrg
219706f2543Smrg    for (i=0; i<sizeof(depths)/sizeof(depths[0]); i++)
220706f2543Smrg    {
221706f2543Smrg	XF86ConfDisplayPtr display;
222706f2543Smrg
223706f2543Smrg	display = calloc(1, sizeof(XF86ConfDisplayRec));
224706f2543Smrg	display->disp_depth = depths[i];
225706f2543Smrg	display->disp_black.red = display->disp_white.red = -1;
226706f2543Smrg	display->disp_black.green = display->disp_white.green = -1;
227706f2543Smrg	display->disp_black.blue = display->disp_white.blue = -1;
228706f2543Smrg	ptr->scrn_display_lst = (XF86ConfDisplayPtr)xf86addListItem(
229706f2543Smrg				     (glp)ptr->scrn_display_lst, (glp)display);
230706f2543Smrg    }
231706f2543Smrg
232706f2543Smrg    return ptr;
233706f2543Smrg}
234706f2543Smrg
235706f2543Smrgstatic const char*
236706f2543SmrgoptionTypeToString(OptionValueType type)
237706f2543Smrg{
238706f2543Smrg    switch (type) {
239706f2543Smrg    case OPTV_NONE:
240706f2543Smrg        return "";
241706f2543Smrg    case OPTV_INTEGER:
242706f2543Smrg        return "<i>";
243706f2543Smrg    case OPTV_STRING:
244706f2543Smrg        return "<str>";
245706f2543Smrg    case OPTV_ANYSTR:
246706f2543Smrg       return "[<str>]";
247706f2543Smrg    case OPTV_REAL:
248706f2543Smrg        return "<f>";
249706f2543Smrg    case OPTV_BOOLEAN:
250706f2543Smrg        return "[<bool>]";
251706f2543Smrg    case OPTV_FREQ:
252706f2543Smrg        return "<freq>";
253706f2543Smrg    case OPTV_PERCENT:
254706f2543Smrg        return "<percent>";
255706f2543Smrg    default:
256706f2543Smrg        return "";
257706f2543Smrg    }
258706f2543Smrg}
259706f2543Smrg
260706f2543Smrgstatic XF86ConfDevicePtr
261706f2543SmrgconfigureDeviceSection (int screennum)
262706f2543Smrg{
263706f2543Smrg    OptionInfoPtr p;
264706f2543Smrg    int i = 0;
265706f2543Smrg    parsePrologue (XF86ConfDevicePtr, XF86ConfDeviceRec)
266706f2543Smrg
267706f2543Smrg    /* Move device info to parser structure */
268706f2543Smrg    if (asprintf(&ptr->dev_identifier, "Card%d", screennum) == -1)
269706f2543Smrg        ptr->dev_identifier = NULL;
270706f2543Smrg    ptr->dev_chipset = DevToConfig[screennum].GDev.chipset;
271706f2543Smrg    ptr->dev_busid = DevToConfig[screennum].GDev.busID;
272706f2543Smrg    ptr->dev_driver = DevToConfig[screennum].GDev.driver;
273706f2543Smrg    ptr->dev_ramdac = DevToConfig[screennum].GDev.ramdac;
274706f2543Smrg    for (i = 0;  (i < MAXDACSPEEDS) && (i < CONF_MAXDACSPEEDS);  i++)
275706f2543Smrg        ptr->dev_dacSpeeds[i] = DevToConfig[screennum].GDev.dacSpeeds[i];
276706f2543Smrg    ptr->dev_videoram = DevToConfig[screennum].GDev.videoRam;
277706f2543Smrg    ptr->dev_textclockfreq = DevToConfig[screennum].GDev.textClockFreq;
278706f2543Smrg    ptr->dev_bios_base = DevToConfig[screennum].GDev.BiosBase;
279706f2543Smrg    ptr->dev_mem_base = DevToConfig[screennum].GDev.MemBase;
280706f2543Smrg    ptr->dev_io_base = DevToConfig[screennum].GDev.IOBase;
281706f2543Smrg    ptr->dev_clockchip = DevToConfig[screennum].GDev.clockchip;
282706f2543Smrg    for (i = 0;  (i < MAXCLOCKS) && (i < DevToConfig[screennum].GDev.numclocks);  i++)
283706f2543Smrg        ptr->dev_clock[i] = DevToConfig[screennum].GDev.clock[i];
284706f2543Smrg    ptr->dev_clocks = i;
285706f2543Smrg    ptr->dev_chipid = DevToConfig[screennum].GDev.chipID;
286706f2543Smrg    ptr->dev_chiprev = DevToConfig[screennum].GDev.chipRev;
287706f2543Smrg    ptr->dev_irq = DevToConfig[screennum].GDev.irq;
288706f2543Smrg
289706f2543Smrg    /* Make sure older drivers don't segv */
290706f2543Smrg    if (DevToConfig[screennum].GDev.options) {
291706f2543Smrg    	/* Fill in the available driver options for people to use */
292706f2543Smrg	const char *descrip =
293706f2543Smrg	    "        ### Available Driver options are:-\n"
294706f2543Smrg	    "        ### Values: <i>: integer, <f>: float, "
295706f2543Smrg			"<bool>: \"True\"/\"False\",\n"
296706f2543Smrg	    "        ### <string>: \"String\", <freq>: \"<f> Hz/kHz/MHz\",\n"
297706f2543Smrg	    "        ### <percent>: \"<f>%\"\n"
298706f2543Smrg	    "        ### [arg]: arg optional\n";
299706f2543Smrg	ptr->dev_comment = strdup(descrip);
300706f2543Smrg	if (ptr->dev_comment) {
301706f2543Smrg    	    for (p = DevToConfig[screennum].GDev.options;
302706f2543Smrg		 p->name != NULL; p++) {
303706f2543Smrg		char *p_e;
304706f2543Smrg		const char *prefix = "        #Option     ";
305706f2543Smrg		const char *middle = " \t# ";
306706f2543Smrg		const char *suffix = "\n";
307706f2543Smrg		const char *opttype = optionTypeToString(p->type);
308706f2543Smrg		char *optname;
309706f2543Smrg		int len = strlen(ptr->dev_comment) + strlen(prefix) +
310706f2543Smrg			  strlen(middle) + strlen(suffix) + 1;
311706f2543Smrg
312706f2543Smrg		if (asprintf(&optname, "\"%s\"", p->name) == -1)
313706f2543Smrg		    break;
314706f2543Smrg
315706f2543Smrg		len += max(20, strlen(optname));
316706f2543Smrg		len += strlen(opttype);
317706f2543Smrg
318706f2543Smrg		ptr->dev_comment = realloc(ptr->dev_comment, len);
319706f2543Smrg		if (!ptr->dev_comment)
320706f2543Smrg		    break;
321706f2543Smrg		p_e = ptr->dev_comment + strlen(ptr->dev_comment);
322706f2543Smrg		sprintf(p_e, "%s%-20s%s%s%s", prefix, optname, middle,
323706f2543Smrg			opttype, suffix);
324706f2543Smrg		free(optname);
325706f2543Smrg	    }
326706f2543Smrg    	}
327706f2543Smrg    }
328706f2543Smrg
329706f2543Smrg    return ptr;
330706f2543Smrg}
331706f2543Smrg
332706f2543Smrgstatic XF86ConfLayoutPtr
333706f2543SmrgconfigureLayoutSection (void)
334706f2543Smrg{
335706f2543Smrg    int scrnum = 0;
336706f2543Smrg    parsePrologue (XF86ConfLayoutPtr, XF86ConfLayoutRec)
337706f2543Smrg
338706f2543Smrg    ptr->lay_identifier = "X.org Configured";
339706f2543Smrg
340706f2543Smrg    {
341706f2543Smrg	XF86ConfInputrefPtr iptr;
342706f2543Smrg
343706f2543Smrg	iptr = malloc (sizeof (XF86ConfInputrefRec));
344706f2543Smrg	iptr->list.next = NULL;
345706f2543Smrg	iptr->iref_option_lst = NULL;
346706f2543Smrg	iptr->iref_inputdev_str = "Mouse0";
347706f2543Smrg	iptr->iref_option_lst =
348706f2543Smrg		xf86addNewOption (iptr->iref_option_lst, strdup("CorePointer"), NULL);
349706f2543Smrg	ptr->lay_input_lst = (XF86ConfInputrefPtr)
350706f2543Smrg		xf86addListItem ((glp) ptr->lay_input_lst, (glp) iptr);
351706f2543Smrg    }
352706f2543Smrg
353706f2543Smrg    {
354706f2543Smrg	XF86ConfInputrefPtr iptr;
355706f2543Smrg
356706f2543Smrg	iptr = malloc (sizeof (XF86ConfInputrefRec));
357706f2543Smrg	iptr->list.next = NULL;
358706f2543Smrg	iptr->iref_option_lst = NULL;
359706f2543Smrg	iptr->iref_inputdev_str = "Keyboard0";
360706f2543Smrg	iptr->iref_option_lst =
361706f2543Smrg		xf86addNewOption (iptr->iref_option_lst, strdup("CoreKeyboard"), NULL);
362706f2543Smrg	ptr->lay_input_lst = (XF86ConfInputrefPtr)
363706f2543Smrg		xf86addListItem ((glp) ptr->lay_input_lst, (glp) iptr);
364706f2543Smrg    }
365706f2543Smrg
366706f2543Smrg    for (scrnum = 0;  scrnum < nDevToConfig;  scrnum++) {
367706f2543Smrg	XF86ConfAdjacencyPtr aptr;
368706f2543Smrg
369706f2543Smrg	aptr = malloc (sizeof (XF86ConfAdjacencyRec));
370706f2543Smrg	aptr->list.next = NULL;
371706f2543Smrg	aptr->adj_x = 0;
372706f2543Smrg	aptr->adj_y = 0;
373706f2543Smrg	aptr->adj_scrnum = scrnum;
374706f2543Smrg	XNFasprintf(&aptr->adj_screen_str, "Screen%d", scrnum);
375706f2543Smrg	if (scrnum == 0) {
376706f2543Smrg	    aptr->adj_where = CONF_ADJ_ABSOLUTE;
377706f2543Smrg	    aptr->adj_refscreen = NULL;
378706f2543Smrg	}
379706f2543Smrg	else {
380706f2543Smrg	    aptr->adj_where = CONF_ADJ_RIGHTOF;
381706f2543Smrg	    XNFasprintf(&aptr->adj_refscreen, "Screen%d", scrnum - 1);
382706f2543Smrg	}
383706f2543Smrg    	ptr->lay_adjacency_lst =
384706f2543Smrg	    (XF86ConfAdjacencyPtr)xf86addListItem((glp)ptr->lay_adjacency_lst,
385706f2543Smrg					      (glp)aptr);
386706f2543Smrg    }
387706f2543Smrg
388706f2543Smrg    return ptr;
389706f2543Smrg}
390706f2543Smrg
391706f2543Smrgstatic XF86ConfFlagsPtr
392706f2543SmrgconfigureFlagsSection (void)
393706f2543Smrg{
394706f2543Smrg    parsePrologue (XF86ConfFlagsPtr, XF86ConfFlagsRec)
395706f2543Smrg
396706f2543Smrg    return ptr;
397706f2543Smrg}
398706f2543Smrg
399706f2543Smrgstatic XF86ConfModulePtr
400706f2543SmrgconfigureModuleSection (void)
401706f2543Smrg{
402706f2543Smrg    char **elist, **el;
403706f2543Smrg    /* Find the list of extension & font modules. */
404706f2543Smrg    const char *esubdirs[] = {
405706f2543Smrg	"extensions",
406706f2543Smrg	"fonts",
407706f2543Smrg	NULL
408706f2543Smrg    };
409706f2543Smrg    parsePrologue (XF86ConfModulePtr, XF86ConfModuleRec)
410706f2543Smrg
411706f2543Smrg    elist = LoaderListDirs(esubdirs, NULL);
412706f2543Smrg    if (elist) {
413706f2543Smrg	for (el = elist; *el; el++) {
414706f2543Smrg	    XF86LoadPtr module;
415706f2543Smrg
416706f2543Smrg    	    module = calloc(1, sizeof(XF86LoadRec));
417706f2543Smrg    	    module->load_name = *el;
418706f2543Smrg            ptr->mod_load_lst = (XF86LoadPtr)xf86addListItem(
419706f2543Smrg                                (glp)ptr->mod_load_lst, (glp)module);
420706f2543Smrg    	}
421706f2543Smrg	free(elist);
422706f2543Smrg    }
423706f2543Smrg
424706f2543Smrg    return ptr;
425706f2543Smrg}
426706f2543Smrg
427706f2543Smrgstatic XF86ConfFilesPtr
428706f2543SmrgconfigureFilesSection (void)
429706f2543Smrg{
430706f2543Smrg    parsePrologue (XF86ConfFilesPtr, XF86ConfFilesRec)
431706f2543Smrg
432706f2543Smrg   if (xf86ModulePath)
433706f2543Smrg       ptr->file_modulepath = strdup(xf86ModulePath);
434706f2543Smrg   if (defaultFontPath)
435706f2543Smrg       ptr->file_fontpath = strdup(defaultFontPath);
436706f2543Smrg
437706f2543Smrg    return ptr;
438706f2543Smrg}
439706f2543Smrg
440706f2543Smrgstatic XF86ConfMonitorPtr
441706f2543SmrgconfigureMonitorSection (int screennum)
442706f2543Smrg{
443706f2543Smrg    parsePrologue (XF86ConfMonitorPtr, XF86ConfMonitorRec)
444706f2543Smrg
445706f2543Smrg    XNFasprintf(&ptr->mon_identifier, "Monitor%d", screennum);
446706f2543Smrg    ptr->mon_vendor = strdup("Monitor Vendor");
447706f2543Smrg    ptr->mon_modelname = strdup("Monitor Model");
448706f2543Smrg
449706f2543Smrg    return ptr;
450706f2543Smrg}
451706f2543Smrg
452706f2543Smrg/* Initialize Configure Monitor from Detailed Timing Block */
453706f2543Smrgstatic void handle_detailed_input(struct detailed_monitor_section *det_mon,
454706f2543Smrg                                  void *data)
455706f2543Smrg{
456706f2543Smrg    XF86ConfMonitorPtr ptr = (XF86ConfMonitorPtr) data;
457706f2543Smrg
458706f2543Smrg    switch (det_mon->type) {
459706f2543Smrg    case DS_NAME:
460706f2543Smrg        ptr->mon_modelname = realloc(ptr->mon_modelname,
461706f2543Smrg                                     strlen((char*)(det_mon->section.name)) +
462706f2543Smrg                                     1);
463706f2543Smrg        strcpy(ptr->mon_modelname,
464706f2543Smrg	      (char*)(det_mon->section.name));
465706f2543Smrg        break;
466706f2543Smrg    case DS_RANGES:
467706f2543Smrg        ptr->mon_hsync[ptr->mon_n_hsync].lo =
468706f2543Smrg            det_mon->section.ranges.min_h;
469706f2543Smrg        ptr->mon_hsync[ptr->mon_n_hsync].hi =
470706f2543Smrg            det_mon->section.ranges.max_h;
471706f2543Smrg        ptr->mon_n_vrefresh = 1;
472706f2543Smrg        ptr->mon_vrefresh[ptr->mon_n_hsync].lo =
473706f2543Smrg            det_mon->section.ranges.min_v;
474706f2543Smrg        ptr->mon_vrefresh[ptr->mon_n_hsync].hi =
475706f2543Smrg            det_mon->section.ranges.max_v;
476706f2543Smrg        ptr->mon_n_hsync++;
477706f2543Smrg    default:
478706f2543Smrg        break;
479706f2543Smrg    }
480706f2543Smrg}
481706f2543Smrg
482706f2543Smrgstatic XF86ConfMonitorPtr
483706f2543SmrgconfigureDDCMonitorSection (int screennum)
484706f2543Smrg{
485706f2543Smrg    int len, mon_width, mon_height;
486706f2543Smrg#define displaySizeMaxLen 80
487706f2543Smrg    char displaySize_string[displaySizeMaxLen];
488706f2543Smrg    int displaySizeLen;
489706f2543Smrg
490706f2543Smrg    parsePrologue (XF86ConfMonitorPtr, XF86ConfMonitorRec)
491706f2543Smrg
492706f2543Smrg    XNFasprintf(&ptr->mon_identifier, "Monitor%d", screennum);
493706f2543Smrg    ptr->mon_vendor = strdup(ConfiguredMonitor->vendor.name);
494706f2543Smrg    XNFasprintf(&ptr->mon_modelname, "%x", ConfiguredMonitor->vendor.prod_id);
495706f2543Smrg
496706f2543Smrg    /* features in centimetres, we want millimetres */
497706f2543Smrg    mon_width  = 10 * ConfiguredMonitor->features.hsize ;
498706f2543Smrg    mon_height = 10 * ConfiguredMonitor->features.vsize ;
499706f2543Smrg
500706f2543Smrg#ifdef CONFIGURE_DISPLAYSIZE
501706f2543Smrg    ptr->mon_width  = mon_width;
502706f2543Smrg    ptr->mon_height = mon_height;
503706f2543Smrg#else
504706f2543Smrg    if (mon_width && mon_height) {
505706f2543Smrg      /* when values available add DisplaySize option AS A COMMENT */
506706f2543Smrg
507706f2543Smrg      displaySizeLen = snprintf(displaySize_string, displaySizeMaxLen,
508706f2543Smrg				"\t#DisplaySize\t%5d %5d\t# mm\n",
509706f2543Smrg				mon_width, mon_height);
510706f2543Smrg
511706f2543Smrg      if (displaySizeLen>0 && displaySizeLen<displaySizeMaxLen) {
512706f2543Smrg	if (ptr->mon_comment) {
513706f2543Smrg	  len = strlen(ptr->mon_comment);
514706f2543Smrg	} else {
515706f2543Smrg	  len = 0;
516706f2543Smrg	}
517706f2543Smrg	if ((ptr->mon_comment =
518706f2543Smrg	     realloc(ptr->mon_comment, len + strlen(displaySize_string) + 1))) {
519706f2543Smrg	  strcpy(ptr->mon_comment + len, displaySize_string);
520706f2543Smrg	}
521706f2543Smrg      }
522706f2543Smrg    }
523706f2543Smrg#endif /* def CONFIGURE_DISPLAYSIZE */
524706f2543Smrg
525706f2543Smrg    xf86ForEachDetailedBlock(ConfiguredMonitor, handle_detailed_input,
526706f2543Smrg                             ptr);
527706f2543Smrg
528706f2543Smrg    if (ConfiguredMonitor->features.dpms) {
529706f2543Smrg      ptr->mon_option_lst = xf86addNewOption(ptr->mon_option_lst, strdup("DPMS"), NULL);
530706f2543Smrg    }
531706f2543Smrg
532706f2543Smrg    return ptr;
533706f2543Smrg}
534706f2543Smrg
535706f2543Smrg#if !defined(PATH_MAX)
536706f2543Smrg# define PATH_MAX 1024
537706f2543Smrg#endif
538706f2543Smrg
539706f2543Smrgvoid
540706f2543SmrgDoConfigure(void)
541706f2543Smrg{
542706f2543Smrg    int i,j, screennum = -1;
543706f2543Smrg    char *home = NULL;
544706f2543Smrg    char filename[PATH_MAX];
545706f2543Smrg    char *addslash = "";
546706f2543Smrg    XF86ConfigPtr xf86config = NULL;
547706f2543Smrg    char **vlist, **vl;
548706f2543Smrg    int *dev2screen;
549706f2543Smrg
550706f2543Smrg    vlist = xf86DriverlistFromCompile();
551706f2543Smrg
552706f2543Smrg    if (!vlist) {
553706f2543Smrg	ErrorF("Missing output drivers.  Configuration failed.\n");
554706f2543Smrg	goto bail;
555706f2543Smrg    }
556706f2543Smrg
557706f2543Smrg    ErrorF("List of video drivers:\n");
558706f2543Smrg    for (vl = vlist; *vl; vl++)
559706f2543Smrg	ErrorF("\t%s\n", *vl);
560706f2543Smrg
561706f2543Smrg    /* Load all the drivers that were found. */
562706f2543Smrg    xf86LoadModules(vlist, NULL);
563706f2543Smrg
564706f2543Smrg    free(vlist);
565706f2543Smrg
566706f2543Smrg    for (i = 0; i < xf86NumDrivers; i++) {
567706f2543Smrg	xorgHWFlags flags;
568706f2543Smrg	if (!xf86DriverList[i]->driverFunc
569706f2543Smrg	    || !xf86DriverList[i]->driverFunc(NULL,
570706f2543Smrg					      GET_REQUIRED_HW_INTERFACES,
571706f2543Smrg					      &flags)
572706f2543Smrg	    || NEED_IO_ENABLED(flags)) {
573706f2543Smrg	    xorgHWAccess = TRUE;
574706f2543Smrg	    break;
575706f2543Smrg	}
576706f2543Smrg    }
577706f2543Smrg    /* Enable full I/O access */
578706f2543Smrg    if (xorgHWAccess) {
579706f2543Smrg	if(!xf86EnableIO())
580706f2543Smrg	    /* oops, we have failed */
581706f2543Smrg	    xorgHWAccess = FALSE;
582706f2543Smrg    }
583706f2543Smrg
584706f2543Smrg    /* Create XF86Config file structure */
585706f2543Smrg    xf86config = calloc(1, sizeof(XF86ConfigRec));
586706f2543Smrg
587706f2543Smrg    /* Call all of the probe functions, reporting the results. */
588706f2543Smrg    for (CurrentDriver = 0;  CurrentDriver < xf86NumDrivers;  CurrentDriver++) {
589706f2543Smrg	xorgHWFlags flags;
590706f2543Smrg	Bool found_screen;
591706f2543Smrg	DriverRec * const drv = xf86DriverList[CurrentDriver];
592706f2543Smrg
593706f2543Smrg	if (!xorgHWAccess) {
594706f2543Smrg	    if (!drv->driverFunc
595706f2543Smrg		|| !drv->driverFunc( NULL, GET_REQUIRED_HW_INTERFACES, &flags )
596706f2543Smrg		|| NEED_IO_ENABLED(flags))
597706f2543Smrg		continue;
598706f2543Smrg	}
599706f2543Smrg
600706f2543Smrg	found_screen = xf86CallDriverProbe( drv, TRUE );
601706f2543Smrg	if ( found_screen && drv->Identify ) {
602706f2543Smrg	    (*drv->Identify)(0);
603706f2543Smrg	}
604706f2543Smrg    }
605706f2543Smrg
606706f2543Smrg    if (nDevToConfig <= 0) {
607706f2543Smrg	ErrorF("No devices to configure.  Configuration failed.\n");
608706f2543Smrg	goto bail;
609706f2543Smrg    }
610706f2543Smrg
611706f2543Smrg    /* Add device, monitor and screen sections for detected devices */
612706f2543Smrg    for (screennum = 0;  screennum < nDevToConfig;  screennum++) {
613706f2543Smrg    	XF86ConfDevicePtr DevicePtr;
614706f2543Smrg	XF86ConfMonitorPtr MonitorPtr;
615706f2543Smrg	XF86ConfScreenPtr ScreenPtr;
616706f2543Smrg
617706f2543Smrg	DevicePtr = configureDeviceSection(screennum);
618706f2543Smrg    	xf86config->conf_device_lst = (XF86ConfDevicePtr)xf86addListItem(
619706f2543Smrg			    (glp)xf86config->conf_device_lst, (glp)DevicePtr);
620706f2543Smrg	MonitorPtr = configureMonitorSection(screennum);
621706f2543Smrg    	xf86config->conf_monitor_lst = (XF86ConfMonitorPtr)xf86addListItem(
622706f2543Smrg			    (glp)xf86config->conf_monitor_lst, (glp)MonitorPtr);
623706f2543Smrg	ScreenPtr = configureScreenSection(screennum);
624706f2543Smrg    	xf86config->conf_screen_lst = (XF86ConfScreenPtr)xf86addListItem(
625706f2543Smrg			    (glp)xf86config->conf_screen_lst, (glp)ScreenPtr);
626706f2543Smrg    }
627706f2543Smrg
628706f2543Smrg    xf86config->conf_files = configureFilesSection();
629706f2543Smrg    xf86config->conf_modules = configureModuleSection();
630706f2543Smrg    xf86config->conf_flags = configureFlagsSection();
631706f2543Smrg    xf86config->conf_videoadaptor_lst = NULL;
632706f2543Smrg    xf86config->conf_modes_lst = NULL;
633706f2543Smrg    xf86config->conf_vendor_lst = NULL;
634706f2543Smrg    xf86config->conf_dri = NULL;
635706f2543Smrg    xf86config->conf_input_lst = configureInputSection();
636706f2543Smrg    xf86config->conf_layout_lst = configureLayoutSection();
637706f2543Smrg
638706f2543Smrg    home = getenv("HOME");
639706f2543Smrg    if ((home == NULL) || (home[0] == '\0')) {
640706f2543Smrg    	home = "/";
641706f2543Smrg    } else {
642706f2543Smrg	/* Determine if trailing slash is present or needed */
643706f2543Smrg	int l = strlen(home);
644706f2543Smrg
645706f2543Smrg	if (home[l-1] != '/') {
646706f2543Smrg	    addslash = "/";
647706f2543Smrg	}
648706f2543Smrg    }
649706f2543Smrg
650706f2543Smrg    snprintf(filename, sizeof(filename), "%s%s" XF86CONFIGFILE ".new",
651706f2543Smrg	     home, addslash);
652706f2543Smrg
653706f2543Smrg    if (xf86writeConfigFile(filename, xf86config) == 0) {
654706f2543Smrg	xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n",
655706f2543Smrg		filename, strerror(errno));
656706f2543Smrg	goto bail;
657706f2543Smrg    }
658706f2543Smrg
659706f2543Smrg    xf86DoConfigurePass1 = FALSE;
660706f2543Smrg    /* Try to get DDC information filled in */
661706f2543Smrg    xf86ConfigFile = filename;
662706f2543Smrg    if (xf86HandleConfigFile(FALSE) != CONFIG_OK) {
663706f2543Smrg	goto bail;
664706f2543Smrg    }
665706f2543Smrg
666706f2543Smrg    xf86DoConfigurePass1 = FALSE;
667706f2543Smrg
668706f2543Smrg    dev2screen = xnfcalloc(1,xf86NumDrivers*sizeof(int));
669706f2543Smrg
670706f2543Smrg    {
671706f2543Smrg	Bool *driverProbed = xnfcalloc(1,xf86NumDrivers*sizeof(Bool));
672706f2543Smrg	for (screennum = 0;  screennum < nDevToConfig;  screennum++) {
673706f2543Smrg	    int k,l,n,oldNumScreens;
674706f2543Smrg
675706f2543Smrg	    i = DevToConfig[screennum].iDriver;
676706f2543Smrg
677706f2543Smrg	    if (driverProbed[i]) continue;
678706f2543Smrg	    driverProbed[i] = TRUE;
679706f2543Smrg
680706f2543Smrg	    oldNumScreens = xf86NumScreens;
681706f2543Smrg
682706f2543Smrg	    xf86CallDriverProbe( xf86DriverList[i], FALSE );
683706f2543Smrg
684706f2543Smrg	    /* reorder */
685706f2543Smrg	    k = screennum > 0 ? screennum : 1;
686706f2543Smrg	    for (l = oldNumScreens; l < xf86NumScreens; l++) {
687706f2543Smrg	        /* is screen primary? */
688706f2543Smrg	        Bool primary = FALSE;
689706f2543Smrg		for (n = 0; n<xf86Screens[l]->numEntities; n++) {
690706f2543Smrg	            if (xf86IsEntityPrimary(xf86Screens[l]->entityList[n])) {
691706f2543Smrg		        dev2screen[0] = l;
692706f2543Smrg			primary = TRUE;
693706f2543Smrg			break;
694706f2543Smrg		    }
695706f2543Smrg		}
696706f2543Smrg		if (primary) continue;
697706f2543Smrg		/* not primary: assign it to next device of same driver */
698706f2543Smrg		/*
699706f2543Smrg		 * NOTE: we assume that devices in DevToConfig
700706f2543Smrg		 * and xf86Screens[] have the same order except
701706f2543Smrg		 * for the primary device which always comes first.
702706f2543Smrg		 */
703706f2543Smrg		for (; k < nDevToConfig; k++) {
704706f2543Smrg		    if (DevToConfig[k].iDriver == i) {
705706f2543Smrg		        dev2screen[k++] = l;
706706f2543Smrg			break;
707706f2543Smrg		    }
708706f2543Smrg		}
709706f2543Smrg	    }
710706f2543Smrg	}
711706f2543Smrg	free(driverProbed);
712706f2543Smrg    }
713706f2543Smrg
714706f2543Smrg
715706f2543Smrg    if (nDevToConfig != xf86NumScreens) {
716706f2543Smrg	ErrorF("Number of created screens does not match number of detected"
717706f2543Smrg	       " devices.\n  Configuration failed.\n");
718706f2543Smrg	goto bail;
719706f2543Smrg    }
720706f2543Smrg
721706f2543Smrg    xf86PostProbe();
722706f2543Smrg
723706f2543Smrg    for (j = 0; j < xf86NumScreens; j++) {
724706f2543Smrg	xf86Screens[j]->scrnIndex = j;
725706f2543Smrg    }
726706f2543Smrg
727706f2543Smrg    xf86freeMonitorList(xf86config->conf_monitor_lst);
728706f2543Smrg    xf86config->conf_monitor_lst = NULL;
729706f2543Smrg    xf86freeScreenList(xf86config->conf_screen_lst);
730706f2543Smrg    xf86config->conf_screen_lst = NULL;
731706f2543Smrg    for (j = 0; j < xf86NumScreens; j++) {
732706f2543Smrg	XF86ConfMonitorPtr MonitorPtr;
733706f2543Smrg	XF86ConfScreenPtr ScreenPtr;
734706f2543Smrg
735706f2543Smrg	ConfiguredMonitor = NULL;
736706f2543Smrg
737706f2543Smrg	if ((*xf86Screens[dev2screen[j]]->PreInit)(xf86Screens[dev2screen[j]],
738706f2543Smrg						   PROBE_DETECT) &&
739706f2543Smrg	    ConfiguredMonitor) {
740706f2543Smrg	    MonitorPtr = configureDDCMonitorSection(j);
741706f2543Smrg	} else {
742706f2543Smrg	    MonitorPtr = configureMonitorSection(j);
743706f2543Smrg	}
744706f2543Smrg	ScreenPtr = configureScreenSection(j);
745706f2543Smrg	xf86config->conf_monitor_lst = (XF86ConfMonitorPtr)xf86addListItem(
746706f2543Smrg		(glp)xf86config->conf_monitor_lst, (glp)MonitorPtr);
747706f2543Smrg	xf86config->conf_screen_lst = (XF86ConfScreenPtr)xf86addListItem(
748706f2543Smrg		(glp)xf86config->conf_screen_lst, (glp)ScreenPtr);
749706f2543Smrg    }
750706f2543Smrg
751706f2543Smrg    if (xf86writeConfigFile(filename, xf86config) == 0) {
752706f2543Smrg	xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n",
753706f2543Smrg		filename, strerror(errno));
754706f2543Smrg	goto bail;
755706f2543Smrg    }
756706f2543Smrg
757706f2543Smrg    ErrorF("\n");
758706f2543Smrg
759706f2543Smrg    if (!foundMouse) {
760706f2543Smrg	ErrorF("\n"__XSERVERNAME__" is not able to detect your mouse.\n"
761706f2543Smrg		"Edit the file and correct the Device.\n");
762706f2543Smrg    } else {
763706f2543Smrg	ErrorF("\n"__XSERVERNAME__" detected your mouse at device %s.\n"
764706f2543Smrg		"Please check your config if the mouse is still not\n"
765706f2543Smrg		"operational, as by default "__XSERVERNAME__
766706f2543Smrg	       " tries to autodetect\n"
767706f2543Smrg		"the protocol.\n",DFLT_MOUSE_DEV);
768706f2543Smrg    }
769706f2543Smrg
770706f2543Smrg    if (xf86NumScreens > 1) {
771706f2543Smrg	ErrorF("\n"__XSERVERNAME__
772706f2543Smrg	       " has configured a multihead system, please check your config.\n");
773706f2543Smrg    }
774706f2543Smrg
775706f2543Smrg    ErrorF("\nYour %s file is %s\n\n", XF86CONFIGFILE ,filename);
776706f2543Smrg    ErrorF("To test the server, run 'X -config %s'\n\n", filename);
777706f2543Smrg
778706f2543Smrgbail:
779706f2543Smrg    OsCleanup(TRUE);
780706f2543Smrg    AbortDDX();
781706f2543Smrg    fflush(stderr);
782706f2543Smrg    exit(0);
783706f2543Smrg}
784