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