xref: /OK3568_Linux_fs/external/xserver/hw/xfree86/common/xf86AutoConfig.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright 2003 by David H. Dawes.
3*4882a593Smuzhiyun  * Copyright 2003 by X-Oz Technologies.
4*4882a593Smuzhiyun  * All rights reserved.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining a
7*4882a593Smuzhiyun  * copy of this software and associated documentation files (the "Software"),
8*4882a593Smuzhiyun  * to deal in the Software without restriction, including without limitation
9*4882a593Smuzhiyun  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10*4882a593Smuzhiyun  * and/or sell copies of the Software, and to permit persons to whom the
11*4882a593Smuzhiyun  * Software is furnished to do so, subject to the following conditions:
12*4882a593Smuzhiyun  *
13*4882a593Smuzhiyun  * The above copyright notice and this permission notice shall be included in
14*4882a593Smuzhiyun  * all copies or substantial portions of the Software.
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*4882a593Smuzhiyun  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*4882a593Smuzhiyun  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19*4882a593Smuzhiyun  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20*4882a593Smuzhiyun  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21*4882a593Smuzhiyun  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22*4882a593Smuzhiyun  * OTHER DEALINGS IN THE SOFTWARE.
23*4882a593Smuzhiyun  *
24*4882a593Smuzhiyun  * Except as contained in this notice, the name of the copyright holder(s)
25*4882a593Smuzhiyun  * and author(s) shall not be used in advertising or otherwise to promote
26*4882a593Smuzhiyun  * the sale, use or other dealings in this Software without prior written
27*4882a593Smuzhiyun  * authorization from the copyright holder(s) and author(s).
28*4882a593Smuzhiyun  *
29*4882a593Smuzhiyun  * Author: David Dawes <dawes@XFree86.Org>.
30*4882a593Smuzhiyun  */
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #ifdef HAVE_XORG_CONFIG_H
33*4882a593Smuzhiyun #include <xorg-config.h>
34*4882a593Smuzhiyun #endif
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #include "xf86.h"
37*4882a593Smuzhiyun #include "xf86Parser.h"
38*4882a593Smuzhiyun #include "xf86tokens.h"
39*4882a593Smuzhiyun #include "xf86Config.h"
40*4882a593Smuzhiyun #include "xf86MatchDrivers.h"
41*4882a593Smuzhiyun #include "xf86Priv.h"
42*4882a593Smuzhiyun #include "xf86_OSlib.h"
43*4882a593Smuzhiyun #include "xf86platformBus.h"
44*4882a593Smuzhiyun #include "xf86pciBus.h"
45*4882a593Smuzhiyun #ifdef __sparc__
46*4882a593Smuzhiyun #include "xf86sbusBus.h"
47*4882a593Smuzhiyun #endif
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun #ifdef __sun
50*4882a593Smuzhiyun #include <sys/visual_io.h>
51*4882a593Smuzhiyun #include <ctype.h>
52*4882a593Smuzhiyun #endif
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun /* Sections for the default built-in configuration. */
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun #define BUILTIN_DEVICE_NAME \
57*4882a593Smuzhiyun 	"\"Builtin Default %s Device %d\""
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun #define BUILTIN_DEVICE_SECTION_PRE \
60*4882a593Smuzhiyun 	"Section \"Device\"\n" \
61*4882a593Smuzhiyun 	"\tIdentifier\t" BUILTIN_DEVICE_NAME "\n" \
62*4882a593Smuzhiyun 	"\tDriver\t\"%s\"\n"
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun #define BUILTIN_DEVICE_SECTION_POST \
65*4882a593Smuzhiyun 	"EndSection\n\n"
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun #define BUILTIN_DEVICE_SECTION \
68*4882a593Smuzhiyun 	BUILTIN_DEVICE_SECTION_PRE \
69*4882a593Smuzhiyun 	BUILTIN_DEVICE_SECTION_POST
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun #define BUILTIN_SCREEN_NAME \
72*4882a593Smuzhiyun 	"\"Builtin Default %s Screen %d\""
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun #define BUILTIN_SCREEN_SECTION \
75*4882a593Smuzhiyun 	"Section \"Screen\"\n" \
76*4882a593Smuzhiyun 	"\tIdentifier\t" BUILTIN_SCREEN_NAME "\n" \
77*4882a593Smuzhiyun 	"\tDevice\t" BUILTIN_DEVICE_NAME "\n" \
78*4882a593Smuzhiyun 	"EndSection\n\n"
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun #define BUILTIN_LAYOUT_SECTION_PRE \
81*4882a593Smuzhiyun 	"Section \"ServerLayout\"\n" \
82*4882a593Smuzhiyun 	"\tIdentifier\t\"Builtin Default Layout\"\n"
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun #define BUILTIN_LAYOUT_SCREEN_LINE \
85*4882a593Smuzhiyun 	"\tScreen\t" BUILTIN_SCREEN_NAME "\n"
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun #define BUILTIN_LAYOUT_SECTION_POST \
88*4882a593Smuzhiyun 	"EndSection\n\n"
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun static const char **builtinConfig = NULL;
91*4882a593Smuzhiyun static int builtinLines = 0;
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun static void listPossibleVideoDrivers(XF86MatchedDrivers *md);
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun /*
96*4882a593Smuzhiyun  * A built-in config file is stored as an array of strings, with each string
97*4882a593Smuzhiyun  * representing a single line.  AppendToConfig() breaks up the string "s"
98*4882a593Smuzhiyun  * into lines, and appends those lines it to builtinConfig.
99*4882a593Smuzhiyun  */
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun static void
AppendToList(const char * s,const char *** list,int * lines)102*4882a593Smuzhiyun AppendToList(const char *s, const char ***list, int *lines)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun     char *str, *newstr, *p;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun     str = xnfstrdup(s);
107*4882a593Smuzhiyun     for (p = strtok(str, "\n"); p; p = strtok(NULL, "\n")) {
108*4882a593Smuzhiyun         (*lines)++;
109*4882a593Smuzhiyun         *list = xnfreallocarray(*list, *lines + 1, sizeof(**list));
110*4882a593Smuzhiyun         newstr = xnfalloc(strlen(p) + 2);
111*4882a593Smuzhiyun         strcpy(newstr, p);
112*4882a593Smuzhiyun         strcat(newstr, "\n");
113*4882a593Smuzhiyun         (*list)[*lines - 1] = newstr;
114*4882a593Smuzhiyun         (*list)[*lines] = NULL;
115*4882a593Smuzhiyun     }
116*4882a593Smuzhiyun     free(str);
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun static void
FreeList(const char *** list,int * lines)120*4882a593Smuzhiyun FreeList(const char ***list, int *lines)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun     int i;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun     for (i = 0; i < *lines; i++) {
125*4882a593Smuzhiyun         free((char *) ((*list)[i]));
126*4882a593Smuzhiyun     }
127*4882a593Smuzhiyun     free(*list);
128*4882a593Smuzhiyun     *list = NULL;
129*4882a593Smuzhiyun     *lines = 0;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun static void
FreeConfig(void)133*4882a593Smuzhiyun FreeConfig(void)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun     FreeList(&builtinConfig, &builtinLines);
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun static void
AppendToConfig(const char * s)139*4882a593Smuzhiyun AppendToConfig(const char *s)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun     AppendToList(s, &builtinConfig, &builtinLines);
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun void
xf86AddMatchedDriver(XF86MatchedDrivers * md,const char * driver)145*4882a593Smuzhiyun xf86AddMatchedDriver(XF86MatchedDrivers *md, const char *driver)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun     int j;
148*4882a593Smuzhiyun     int nmatches = md->nmatches;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun     for (j = 0; j < nmatches; ++j) {
151*4882a593Smuzhiyun         if (xf86NameCmp(md->matches[j], driver) == 0) {
152*4882a593Smuzhiyun             // Driver already in matched drivers
153*4882a593Smuzhiyun             return;
154*4882a593Smuzhiyun         }
155*4882a593Smuzhiyun     }
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun     if (nmatches < MATCH_DRIVERS_LIMIT) {
158*4882a593Smuzhiyun         md->matches[nmatches] = xnfstrdup(driver);
159*4882a593Smuzhiyun         md->nmatches++;
160*4882a593Smuzhiyun     }
161*4882a593Smuzhiyun     else {
162*4882a593Smuzhiyun         xf86Msg(X_WARNING, "Too many drivers registered, can't add %s\n", driver);
163*4882a593Smuzhiyun     }
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun Bool
xf86AutoConfig(void)167*4882a593Smuzhiyun xf86AutoConfig(void)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun     XF86MatchedDrivers md;
170*4882a593Smuzhiyun     int i;
171*4882a593Smuzhiyun     const char **cp;
172*4882a593Smuzhiyun     char buf[1024];
173*4882a593Smuzhiyun     ConfigStatus ret;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun     /* Make sure config rec is there */
176*4882a593Smuzhiyun     if (xf86allocateConfig() != NULL) {
177*4882a593Smuzhiyun         ret = CONFIG_OK;    /* OK so far */
178*4882a593Smuzhiyun     }
179*4882a593Smuzhiyun     else {
180*4882a593Smuzhiyun         xf86Msg(X_ERROR, "Couldn't allocate Config record.\n");
181*4882a593Smuzhiyun         return FALSE;
182*4882a593Smuzhiyun     }
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun     listPossibleVideoDrivers(&md);
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun     for (i = 0; i < md.nmatches; i++) {
187*4882a593Smuzhiyun         snprintf(buf, sizeof(buf), BUILTIN_DEVICE_SECTION,
188*4882a593Smuzhiyun                 md.matches[i], 0, md.matches[i]);
189*4882a593Smuzhiyun         AppendToConfig(buf);
190*4882a593Smuzhiyun         snprintf(buf, sizeof(buf), BUILTIN_SCREEN_SECTION,
191*4882a593Smuzhiyun                 md.matches[i], 0, md.matches[i], 0);
192*4882a593Smuzhiyun         AppendToConfig(buf);
193*4882a593Smuzhiyun     }
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun     AppendToConfig(BUILTIN_LAYOUT_SECTION_PRE);
196*4882a593Smuzhiyun     for (i = 0; i < md.nmatches; i++) {
197*4882a593Smuzhiyun         snprintf(buf, sizeof(buf), BUILTIN_LAYOUT_SCREEN_LINE,
198*4882a593Smuzhiyun                 md.matches[i], 0);
199*4882a593Smuzhiyun         AppendToConfig(buf);
200*4882a593Smuzhiyun     }
201*4882a593Smuzhiyun     AppendToConfig(BUILTIN_LAYOUT_SECTION_POST);
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun     for (i = 0; i < md.nmatches; i++) {
204*4882a593Smuzhiyun         free(md.matches[i]);
205*4882a593Smuzhiyun     }
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun     xf86MsgVerb(X_DEFAULT, 0,
208*4882a593Smuzhiyun                 "Using default built-in configuration (%d lines)\n",
209*4882a593Smuzhiyun                 builtinLines);
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun     xf86MsgVerb(X_DEFAULT, 3, "--- Start of built-in configuration ---\n");
212*4882a593Smuzhiyun     for (cp = builtinConfig; *cp; cp++)
213*4882a593Smuzhiyun         xf86ErrorFVerb(3, "\t%s", *cp);
214*4882a593Smuzhiyun     xf86MsgVerb(X_DEFAULT, 3, "--- End of built-in configuration ---\n");
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun     xf86initConfigFiles();
217*4882a593Smuzhiyun     xf86setBuiltinConfig(builtinConfig);
218*4882a593Smuzhiyun     ret = xf86HandleConfigFile(TRUE);
219*4882a593Smuzhiyun     FreeConfig();
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun     if (ret != CONFIG_OK)
222*4882a593Smuzhiyun         xf86Msg(X_ERROR, "Error parsing the built-in default configuration.\n");
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun     return ret == CONFIG_OK;
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun static void
listPossibleVideoDrivers(XF86MatchedDrivers * md)228*4882a593Smuzhiyun listPossibleVideoDrivers(XF86MatchedDrivers *md)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun     md->nmatches = 0;
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun #ifdef XSERVER_PLATFORM_BUS
233*4882a593Smuzhiyun     xf86PlatformMatchDriver(md);
234*4882a593Smuzhiyun #endif
235*4882a593Smuzhiyun #ifdef __sun
236*4882a593Smuzhiyun     /* Check for driver type based on /dev/fb type and if valid, use
237*4882a593Smuzhiyun        it instead of PCI bus probe results */
238*4882a593Smuzhiyun     if (xf86Info.consoleFd >= 0) {
239*4882a593Smuzhiyun         struct vis_identifier visid;
240*4882a593Smuzhiyun         const char *cp;
241*4882a593Smuzhiyun         int iret;
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun         SYSCALL(iret = ioctl(xf86Info.consoleFd, VIS_GETIDENTIFIER, &visid));
244*4882a593Smuzhiyun         if (iret < 0) {
245*4882a593Smuzhiyun             int fbfd;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun             fbfd = open(xf86SolarisFbDev, O_RDONLY);
248*4882a593Smuzhiyun             if (fbfd >= 0) {
249*4882a593Smuzhiyun                 SYSCALL(iret = ioctl(fbfd, VIS_GETIDENTIFIER, &visid));
250*4882a593Smuzhiyun                 close(fbfd);
251*4882a593Smuzhiyun             }
252*4882a593Smuzhiyun         }
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun         if (iret < 0) {
255*4882a593Smuzhiyun             xf86Msg(X_WARNING,
256*4882a593Smuzhiyun                     "could not get frame buffer identifier from %s\n",
257*4882a593Smuzhiyun                     xf86SolarisFbDev);
258*4882a593Smuzhiyun         }
259*4882a593Smuzhiyun         else {
260*4882a593Smuzhiyun             xf86Msg(X_PROBED, "console driver: %s\n", visid.name);
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun             /* Special case from before the general case was set */
263*4882a593Smuzhiyun             if (strcmp(visid.name, "NVDAnvda") == 0) {
264*4882a593Smuzhiyun                 xf86AddMatchedDriver(md, "nvidia");
265*4882a593Smuzhiyun             }
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun             /* General case - split into vendor name (initial all-caps
268*4882a593Smuzhiyun                prefix) & driver name (rest of the string). */
269*4882a593Smuzhiyun             if (strcmp(visid.name, "SUNWtext") != 0) {
270*4882a593Smuzhiyun                 for (cp = visid.name; (*cp != '\0') && isupper(*cp); cp++) {
271*4882a593Smuzhiyun                     /* find end of all uppercase vendor section */
272*4882a593Smuzhiyun                 }
273*4882a593Smuzhiyun                 if ((cp != visid.name) && (*cp != '\0')) {
274*4882a593Smuzhiyun                     char *vendorName = xnfstrdup(visid.name);
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun                     vendorName[cp - visid.name] = '\0';
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun                     xf86AddMatchedDriver(md, vendorName);
279*4882a593Smuzhiyun                     xf86AddMatchedDriver(md, cp);
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun                     free(vendorName);
282*4882a593Smuzhiyun                 }
283*4882a593Smuzhiyun             }
284*4882a593Smuzhiyun         }
285*4882a593Smuzhiyun     }
286*4882a593Smuzhiyun #endif
287*4882a593Smuzhiyun #ifdef __sparc__
288*4882a593Smuzhiyun     char *sbusDriver = sparcDriverName();
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun     if (sbusDriver)
291*4882a593Smuzhiyun         xf86AddMatchedDriver(md, sbusDriver);
292*4882a593Smuzhiyun #endif
293*4882a593Smuzhiyun #ifdef XSERVER_LIBPCIACCESS
294*4882a593Smuzhiyun     xf86PciMatchDriver(md);
295*4882a593Smuzhiyun #endif
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun #if defined(__linux__)
298*4882a593Smuzhiyun     xf86AddMatchedDriver(md, "modesetting");
299*4882a593Smuzhiyun #endif
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun #if !defined(__sun)
302*4882a593Smuzhiyun     /* Fallback to platform default frame buffer driver */
303*4882a593Smuzhiyun #if !defined(__linux__) && defined(__sparc__)
304*4882a593Smuzhiyun     xf86AddMatchedDriver(md, "wsfb");
305*4882a593Smuzhiyun #else
306*4882a593Smuzhiyun     xf86AddMatchedDriver(md, "fbdev");
307*4882a593Smuzhiyun #endif
308*4882a593Smuzhiyun #endif                          /* !__sun */
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun     /* Fallback to platform default hardware */
311*4882a593Smuzhiyun #if defined(__i386__) || defined(__amd64__) || defined(__hurd__)
312*4882a593Smuzhiyun     xf86AddMatchedDriver(md, "vesa");
313*4882a593Smuzhiyun #elif defined(__sparc__) && !defined(__sun)
314*4882a593Smuzhiyun     xf86AddMatchedDriver(md, "sunffb");
315*4882a593Smuzhiyun #endif
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun /* copy a screen section and enter the desired driver
319*4882a593Smuzhiyun  * and insert it at i in the list of screens */
320*4882a593Smuzhiyun static Bool
copyScreen(confScreenPtr oscreen,GDevPtr odev,int i,char * driver)321*4882a593Smuzhiyun copyScreen(confScreenPtr oscreen, GDevPtr odev, int i, char *driver)
322*4882a593Smuzhiyun {
323*4882a593Smuzhiyun     confScreenPtr nscreen;
324*4882a593Smuzhiyun     GDevPtr cptr = NULL;
325*4882a593Smuzhiyun     char *identifier;
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun     nscreen = malloc(sizeof(confScreenRec));
328*4882a593Smuzhiyun     if (!nscreen)
329*4882a593Smuzhiyun         return FALSE;
330*4882a593Smuzhiyun     memcpy(nscreen, oscreen, sizeof(confScreenRec));
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun     cptr = malloc(sizeof(GDevRec));
333*4882a593Smuzhiyun     if (!cptr) {
334*4882a593Smuzhiyun         free(nscreen);
335*4882a593Smuzhiyun         return FALSE;
336*4882a593Smuzhiyun     }
337*4882a593Smuzhiyun     memcpy(cptr, odev, sizeof(GDevRec));
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun     if (asprintf(&identifier, "Autoconfigured Video Device %s", driver)
340*4882a593Smuzhiyun         == -1) {
341*4882a593Smuzhiyun         free(cptr);
342*4882a593Smuzhiyun         free(nscreen);
343*4882a593Smuzhiyun         return FALSE;
344*4882a593Smuzhiyun     }
345*4882a593Smuzhiyun     cptr->driver = driver;
346*4882a593Smuzhiyun     cptr->identifier = identifier;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun     xf86ConfigLayout.screens[i].screen = nscreen;
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun     /* now associate the new driver entry with the new screen entry */
351*4882a593Smuzhiyun     xf86ConfigLayout.screens[i].screen->device = cptr;
352*4882a593Smuzhiyun     cptr->myScreenSection = xf86ConfigLayout.screens[i].screen;
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun     return TRUE;
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun GDevPtr
autoConfigDevice(GDevPtr preconf_device)358*4882a593Smuzhiyun autoConfigDevice(GDevPtr preconf_device)
359*4882a593Smuzhiyun {
360*4882a593Smuzhiyun     GDevPtr ptr = NULL;
361*4882a593Smuzhiyun     XF86MatchedDrivers md;
362*4882a593Smuzhiyun     int num_screens = 0, i;
363*4882a593Smuzhiyun     screenLayoutPtr slp;
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun     if (!xf86configptr) {
366*4882a593Smuzhiyun         return NULL;
367*4882a593Smuzhiyun     }
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun     /* If there's a configured section with no driver chosen, use it */
370*4882a593Smuzhiyun     if (preconf_device) {
371*4882a593Smuzhiyun         ptr = preconf_device;
372*4882a593Smuzhiyun     }
373*4882a593Smuzhiyun     else {
374*4882a593Smuzhiyun         ptr = calloc(1, sizeof(GDevRec));
375*4882a593Smuzhiyun         if (!ptr) {
376*4882a593Smuzhiyun             return NULL;
377*4882a593Smuzhiyun         }
378*4882a593Smuzhiyun         ptr->chipID = -1;
379*4882a593Smuzhiyun         ptr->chipRev = -1;
380*4882a593Smuzhiyun         ptr->irq = -1;
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun         ptr->active = TRUE;
383*4882a593Smuzhiyun         ptr->claimed = FALSE;
384*4882a593Smuzhiyun         ptr->identifier = "Autoconfigured Video Device";
385*4882a593Smuzhiyun         ptr->driver = NULL;
386*4882a593Smuzhiyun     }
387*4882a593Smuzhiyun     if (!ptr->driver) {
388*4882a593Smuzhiyun         /* get all possible video drivers and count them */
389*4882a593Smuzhiyun         listPossibleVideoDrivers(&md);
390*4882a593Smuzhiyun         for (i = 0; i < md.nmatches; i++) {
391*4882a593Smuzhiyun             xf86Msg(X_DEFAULT, "Matched %s as autoconfigured driver %d\n",
392*4882a593Smuzhiyun                     md.matches[i], i);
393*4882a593Smuzhiyun         }
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun         slp = xf86ConfigLayout.screens;
396*4882a593Smuzhiyun         if (slp) {
397*4882a593Smuzhiyun             /* count the number of screens and make space for
398*4882a593Smuzhiyun              * a new screen for each additional possible driver
399*4882a593Smuzhiyun              * minus one for the already existing first one
400*4882a593Smuzhiyun              * plus one for the terminating NULL */
401*4882a593Smuzhiyun             for (; slp[num_screens].screen; num_screens++);
402*4882a593Smuzhiyun             xf86ConfigLayout.screens = xnfcalloc(num_screens + md.nmatches,
403*4882a593Smuzhiyun                                                  sizeof(screenLayoutRec));
404*4882a593Smuzhiyun             xf86ConfigLayout.screens[0] = slp[0];
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun             /* do the first match and set that for the original first screen */
407*4882a593Smuzhiyun             ptr->driver = md.matches[0];
408*4882a593Smuzhiyun             if (!xf86ConfigLayout.screens[0].screen->device) {
409*4882a593Smuzhiyun                 xf86ConfigLayout.screens[0].screen->device = ptr;
410*4882a593Smuzhiyun                 ptr->myScreenSection = xf86ConfigLayout.screens[0].screen;
411*4882a593Smuzhiyun             }
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun             /* for each other driver found, copy the first screen, insert it
414*4882a593Smuzhiyun              * into the list of screens and set the driver */
415*4882a593Smuzhiyun             for (i = 1; i < md.nmatches; i++) {
416*4882a593Smuzhiyun                 if (!copyScreen(slp[0].screen, ptr, i, md.matches[i]))
417*4882a593Smuzhiyun                     return NULL;
418*4882a593Smuzhiyun             }
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun             /* shift the rest of the original screen list
421*4882a593Smuzhiyun              * to the end of the current screen list
422*4882a593Smuzhiyun              *
423*4882a593Smuzhiyun              * TODO Handle rest of multiple screen sections */
424*4882a593Smuzhiyun             for (i = 1; i < num_screens; i++) {
425*4882a593Smuzhiyun                 xf86ConfigLayout.screens[i + md.nmatches] = slp[i];
426*4882a593Smuzhiyun             }
427*4882a593Smuzhiyun             xf86ConfigLayout.screens[num_screens + md.nmatches - 1].screen =
428*4882a593Smuzhiyun                 NULL;
429*4882a593Smuzhiyun             free(slp);
430*4882a593Smuzhiyun         }
431*4882a593Smuzhiyun         else {
432*4882a593Smuzhiyun             /* layout does not have any screens, not much to do */
433*4882a593Smuzhiyun             ptr->driver = md.matches[0];
434*4882a593Smuzhiyun             for (i = 1; i < md.nmatches; i++) {
435*4882a593Smuzhiyun                 free(md.matches[i]);
436*4882a593Smuzhiyun             }
437*4882a593Smuzhiyun         }
438*4882a593Smuzhiyun     }
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun     xf86Msg(X_DEFAULT, "Assigned the driver to the xf86ConfigLayout\n");
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun     return ptr;
443*4882a593Smuzhiyun }
444