105b261ecSmrg/*
205b261ecSmrg * Copyright 2003 by David H. Dawes.
305b261ecSmrg * Copyright 2003 by X-Oz Technologies.
405b261ecSmrg * All rights reserved.
505b261ecSmrg *
605b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a
705b261ecSmrg * copy of this software and associated documentation files (the "Software"),
805b261ecSmrg * to deal in the Software without restriction, including without limitation
905b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1005b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the
1105b261ecSmrg * Software is furnished to do so, subject to the following conditions:
12f7df2e56Smrg *
1305b261ecSmrg * The above copyright notice and this permission notice shall be included in
1405b261ecSmrg * all copies or substantial portions of the Software.
15f7df2e56Smrg *
1605b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1705b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1805b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1905b261ecSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
2005b261ecSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2105b261ecSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2205b261ecSmrg * OTHER DEALINGS IN THE SOFTWARE.
23f7df2e56Smrg *
2405b261ecSmrg * Except as contained in this notice, the name of the copyright holder(s)
2505b261ecSmrg * and author(s) shall not be used in advertising or otherwise to promote
2605b261ecSmrg * the sale, use or other dealings in this Software without prior written
2705b261ecSmrg * authorization from the copyright holder(s) and author(s).
28f7df2e56Smrg *
2905b261ecSmrg * Author: David Dawes <dawes@XFree86.Org>.
3005b261ecSmrg */
3105b261ecSmrg
3205b261ecSmrg#ifdef HAVE_XORG_CONFIG_H
3305b261ecSmrg#include <xorg-config.h>
3405b261ecSmrg#endif
3505b261ecSmrg
3605b261ecSmrg#include "xf86.h"
3705b261ecSmrg#include "xf86Parser.h"
3805b261ecSmrg#include "xf86tokens.h"
3905b261ecSmrg#include "xf86Config.h"
407e31ba66Smrg#include "xf86MatchDrivers.h"
4105b261ecSmrg#include "xf86Priv.h"
4205b261ecSmrg#include "xf86_OSlib.h"
43f7df2e56Smrg#include "xf86platformBus.h"
444202a189Smrg#include "xf86pciBus.h"
45637ac9abSmrg#ifdef __sparc__
46f7df2e56Smrg#include "xf86sbusBus.h"
47637ac9abSmrg#endif
4805b261ecSmrg
497e31ba66Smrg#ifdef __sun
50f7df2e56Smrg#include <sys/visual_io.h>
51f7df2e56Smrg#include <ctype.h>
52637ac9abSmrg#endif
5305b261ecSmrg
5418a93be0Smacallan#ifdef __NetBSD__
5518a93be0Smacallan#if defined(__sparc__) || defined(__sparc64__)
5618a93be0Smacallan#include <dev/sun/fbio.h>
5718a93be0Smacallanextern struct sbus_devtable sbusDeviceTable[];
5818a93be0Smacallan#endif /* sparc / sparc64 */
5918a93be0Smacallan#endif /* NetBSD */
6018a93be0Smacallan
61637ac9abSmrg/* Sections for the default built-in configuration. */
6205b261ecSmrg
6305b261ecSmrg#define BUILTIN_DEVICE_NAME \
6405b261ecSmrg	"\"Builtin Default %s Device %d\""
6505b261ecSmrg
6605b261ecSmrg#define BUILTIN_DEVICE_SECTION_PRE \
6705b261ecSmrg	"Section \"Device\"\n" \
6805b261ecSmrg	"\tIdentifier\t" BUILTIN_DEVICE_NAME "\n" \
6905b261ecSmrg	"\tDriver\t\"%s\"\n"
7005b261ecSmrg
7105b261ecSmrg#define BUILTIN_DEVICE_SECTION_POST \
7205b261ecSmrg	"EndSection\n\n"
7305b261ecSmrg
7405b261ecSmrg#define BUILTIN_DEVICE_SECTION \
7505b261ecSmrg	BUILTIN_DEVICE_SECTION_PRE \
7605b261ecSmrg	BUILTIN_DEVICE_SECTION_POST
7705b261ecSmrg
7805b261ecSmrg#define BUILTIN_SCREEN_NAME \
7905b261ecSmrg	"\"Builtin Default %s Screen %d\""
8005b261ecSmrg
8105b261ecSmrg#define BUILTIN_SCREEN_SECTION \
8205b261ecSmrg	"Section \"Screen\"\n" \
8305b261ecSmrg	"\tIdentifier\t" BUILTIN_SCREEN_NAME "\n" \
8405b261ecSmrg	"\tDevice\t" BUILTIN_DEVICE_NAME "\n" \
8505b261ecSmrg	"EndSection\n\n"
8605b261ecSmrg
8705b261ecSmrg#define BUILTIN_LAYOUT_SECTION_PRE \
8805b261ecSmrg	"Section \"ServerLayout\"\n" \
8905b261ecSmrg	"\tIdentifier\t\"Builtin Default Layout\"\n"
9005b261ecSmrg
9105b261ecSmrg#define BUILTIN_LAYOUT_SCREEN_LINE \
9205b261ecSmrg	"\tScreen\t" BUILTIN_SCREEN_NAME "\n"
9305b261ecSmrg
9405b261ecSmrg#define BUILTIN_LAYOUT_SECTION_POST \
9505b261ecSmrg	"EndSection\n\n"
9605b261ecSmrg
9705b261ecSmrgstatic const char **builtinConfig = NULL;
9805b261ecSmrgstatic int builtinLines = 0;
99637ac9abSmrg
1007e31ba66Smrgstatic void listPossibleVideoDrivers(XF86MatchedDrivers *md);
10105b261ecSmrg
10205b261ecSmrg/*
10305b261ecSmrg * A built-in config file is stored as an array of strings, with each string
10405b261ecSmrg * representing a single line.  AppendToConfig() breaks up the string "s"
10505b261ecSmrg * into lines, and appends those lines it to builtinConfig.
10605b261ecSmrg */
10705b261ecSmrg
10805b261ecSmrgstatic void
10905b261ecSmrgAppendToList(const char *s, const char ***list, int *lines)
11005b261ecSmrg{
11105b261ecSmrg    char *str, *newstr, *p;
11205b261ecSmrg
11305b261ecSmrg    str = xnfstrdup(s);
11405b261ecSmrg    for (p = strtok(str, "\n"); p; p = strtok(NULL, "\n")) {
115f7df2e56Smrg        (*lines)++;
116f7df2e56Smrg        *list = xnfreallocarray(*list, *lines + 1, sizeof(**list));
117f7df2e56Smrg        newstr = xnfalloc(strlen(p) + 2);
118f7df2e56Smrg        strcpy(newstr, p);
119f7df2e56Smrg        strcat(newstr, "\n");
120f7df2e56Smrg        (*list)[*lines - 1] = newstr;
121f7df2e56Smrg        (*list)[*lines] = NULL;
12205b261ecSmrg    }
1234202a189Smrg    free(str);
12405b261ecSmrg}
12505b261ecSmrg
12605b261ecSmrgstatic void
12705b261ecSmrgFreeList(const char ***list, int *lines)
12805b261ecSmrg{
12905b261ecSmrg    int i;
13005b261ecSmrg
13105b261ecSmrg    for (i = 0; i < *lines; i++) {
132f7df2e56Smrg        free((char *) ((*list)[i]));
13305b261ecSmrg    }
1344202a189Smrg    free(*list);
13505b261ecSmrg    *list = NULL;
13605b261ecSmrg    *lines = 0;
13705b261ecSmrg}
13805b261ecSmrg
13905b261ecSmrgstatic void
14005b261ecSmrgFreeConfig(void)
14105b261ecSmrg{
14205b261ecSmrg    FreeList(&builtinConfig, &builtinLines);
14305b261ecSmrg}
14405b261ecSmrg
14505b261ecSmrgstatic void
14605b261ecSmrgAppendToConfig(const char *s)
14705b261ecSmrg{
14805b261ecSmrg    AppendToList(s, &builtinConfig, &builtinLines);
14905b261ecSmrg}
15005b261ecSmrg
1517e31ba66Smrgvoid
1527e31ba66Smrgxf86AddMatchedDriver(XF86MatchedDrivers *md, const char *driver)
1537e31ba66Smrg{
1547e31ba66Smrg    int j;
1557e31ba66Smrg    int nmatches = md->nmatches;
1567e31ba66Smrg
1577e31ba66Smrg    for (j = 0; j < nmatches; ++j) {
1587e31ba66Smrg        if (xf86NameCmp(md->matches[j], driver) == 0) {
1597e31ba66Smrg            // Driver already in matched drivers
1607e31ba66Smrg            return;
1617e31ba66Smrg        }
1627e31ba66Smrg    }
1637e31ba66Smrg
1647e31ba66Smrg    if (nmatches < MATCH_DRIVERS_LIMIT) {
1657e31ba66Smrg        md->matches[nmatches] = xnfstrdup(driver);
1667e31ba66Smrg        md->nmatches++;
1677e31ba66Smrg    }
1687e31ba66Smrg    else {
1697e31ba66Smrg        xf86Msg(X_WARNING, "Too many drivers registered, can't add %s\n", driver);
1707e31ba66Smrg    }
1717e31ba66Smrg}
1727e31ba66Smrg
17305b261ecSmrgBool
17405b261ecSmrgxf86AutoConfig(void)
17505b261ecSmrg{
1767e31ba66Smrg    XF86MatchedDrivers md;
1777e31ba66Smrg    int i;
178637ac9abSmrg    const char **cp;
17905b261ecSmrg    char buf[1024];
18005b261ecSmrg    ConfigStatus ret;
18105b261ecSmrg
1827e31ba66Smrg    /* Make sure config rec is there */
1837e31ba66Smrg    if (xf86allocateConfig() != NULL) {
1847e31ba66Smrg        ret = CONFIG_OK;    /* OK so far */
1857e31ba66Smrg    }
1867e31ba66Smrg    else {
1877e31ba66Smrg        xf86Msg(X_ERROR, "Couldn't allocate Config record.\n");
1887e31ba66Smrg        return FALSE;
1897e31ba66Smrg    }
1907e31ba66Smrg
1917e31ba66Smrg    listPossibleVideoDrivers(&md);
19205b261ecSmrg
1937e31ba66Smrg    for (i = 0; i < md.nmatches; i++) {
1947e31ba66Smrg        snprintf(buf, sizeof(buf), BUILTIN_DEVICE_SECTION,
1957e31ba66Smrg                md.matches[i], 0, md.matches[i]);
196f7df2e56Smrg        AppendToConfig(buf);
1977e31ba66Smrg        snprintf(buf, sizeof(buf), BUILTIN_SCREEN_SECTION,
1987e31ba66Smrg                md.matches[i], 0, md.matches[i], 0);
199f7df2e56Smrg        AppendToConfig(buf);
20005b261ecSmrg    }
20105b261ecSmrg
20205b261ecSmrg    AppendToConfig(BUILTIN_LAYOUT_SECTION_PRE);
2037e31ba66Smrg    for (i = 0; i < md.nmatches; i++) {
2047e31ba66Smrg        snprintf(buf, sizeof(buf), BUILTIN_LAYOUT_SCREEN_LINE,
2057e31ba66Smrg                md.matches[i], 0);
206f7df2e56Smrg        AppendToConfig(buf);
20705b261ecSmrg    }
20805b261ecSmrg    AppendToConfig(BUILTIN_LAYOUT_SECTION_POST);
20905b261ecSmrg
2107e31ba66Smrg    for (i = 0; i < md.nmatches; i++) {
2117e31ba66Smrg        free(md.matches[i]);
212637ac9abSmrg    }
213637ac9abSmrg
21405b261ecSmrg    xf86MsgVerb(X_DEFAULT, 0,
215f7df2e56Smrg                "Using default built-in configuration (%d lines)\n",
216f7df2e56Smrg                builtinLines);
21705b261ecSmrg
21805b261ecSmrg    xf86MsgVerb(X_DEFAULT, 3, "--- Start of built-in configuration ---\n");
219637ac9abSmrg    for (cp = builtinConfig; *cp; cp++)
220f7df2e56Smrg        xf86ErrorFVerb(3, "\t%s", *cp);
22105b261ecSmrg    xf86MsgVerb(X_DEFAULT, 3, "--- End of built-in configuration ---\n");
2224202a189Smrg
2234202a189Smrg    xf86initConfigFiles();
22405b261ecSmrg    xf86setBuiltinConfig(builtinConfig);
22505b261ecSmrg    ret = xf86HandleConfigFile(TRUE);
22605b261ecSmrg    FreeConfig();
22705b261ecSmrg
22805b261ecSmrg    if (ret != CONFIG_OK)
229f7df2e56Smrg        xf86Msg(X_ERROR, "Error parsing the built-in default configuration.\n");
23005b261ecSmrg
2314202a189Smrg    return ret == CONFIG_OK;
23205b261ecSmrg}
233637ac9abSmrg
234637ac9abSmrgstatic void
2357e31ba66SmrglistPossibleVideoDrivers(XF86MatchedDrivers *md)
236637ac9abSmrg{
2377e31ba66Smrg    md->nmatches = 0;
238637ac9abSmrg
239f7df2e56Smrg/* XXXMRG:  xorg-server 1.10/1.18 -- merge into xf86PlatformMatchDriver()? */
24018a93be0Smacallan#ifdef __NetBSD__
24118a93be0Smacallan#if defined(__shark)
242efe9ba86Smrg    xf86AddMatchedDriver(md, "chips");
243efe9ba86Smrg    xf86AddMatchedDriver(md, "igs");
24418a93be0Smacallan#elif defined(__sgimips)
245efe9ba86Smrg    xf86AddMatchedDriver(md, "crime");
246efe9ba86Smrg    xf86AddMatchedDriver(md, "newport");
24718a93be0Smacallan#elif defined(__sparc) || defined(__sparc64)
24818a93be0Smacallan    /* dig through /dev/fb* */
24918a93be0Smacallan    {
25018a93be0Smacallan    	struct fbtype fbt;
25118a93be0Smacallan	int j = 0, fd = 0, dev;
25218a93be0Smacallan	char fbpath[32];
25318a93be0Smacallan
25418a93be0Smacallan	for (j = 0; j < 10; j++) {
25518a93be0Smacallan	    snprintf(fbpath, 31, "/dev/fb%d", j);
25618a93be0Smacallan	    xf86Msg(X_ERROR,"%s: trying %s\n", __func__, fbpath);
25718a93be0Smacallan	    fd = open(fbpath, O_RDONLY, 0);
25818a93be0Smacallan	    if (fd == -1) continue;
25918a93be0Smacallan	    memset(&fbt, 0, sizeof(fbt));
26018a93be0Smacallan	    if (ioctl(fd, FBIOGTYPE, &fbt) == -1) {
26118a93be0Smacallan	    	close(fd);
26218a93be0Smacallan		continue;
26318a93be0Smacallan	    }
26418a93be0Smacallan	    close(fd);
26518a93be0Smacallan	    dev = 0;
26618a93be0Smacallan	    while ((sbusDeviceTable[dev].fbType != 0) &&
26718a93be0Smacallan	           (sbusDeviceTable[dev].fbType != fbt.fb_type))
26818a93be0Smacallan		dev++;
26918a93be0Smacallan	    if (sbusDeviceTable[dev].fbType == fbt.fb_type) {
27018a93be0Smacallan		xf86Msg(X_ERROR,"%s: found %s\n", __func__,
27118a93be0Smacallan		    sbusDeviceTable[dev].driverName);
272efe9ba86Smrg	        xf86AddMatchedDriver(md, sbusDeviceTable[dev].driverName);
27318a93be0Smacallan	    }
27418a93be0Smacallan	}
27518a93be0Smacallan    }
27618a93be0Smacallan#endif
27718a93be0Smacallan
27818a93be0Smacallan#else /* !NetBSD */
279f7df2e56Smrg#ifdef XSERVER_PLATFORM_BUS
2807e31ba66Smrg    xf86PlatformMatchDriver(md);
281f7df2e56Smrg#endif
2827e31ba66Smrg#ifdef __sun
283637ac9abSmrg    /* Check for driver type based on /dev/fb type and if valid, use
284637ac9abSmrg       it instead of PCI bus probe results */
2857e31ba66Smrg    if (xf86Info.consoleFd >= 0) {
286f7df2e56Smrg        struct vis_identifier visid;
287f7df2e56Smrg        const char *cp;
288f7df2e56Smrg        int iret;
289f7df2e56Smrg
290f7df2e56Smrg        SYSCALL(iret = ioctl(xf86Info.consoleFd, VIS_GETIDENTIFIER, &visid));
291f7df2e56Smrg        if (iret < 0) {
292f7df2e56Smrg            int fbfd;
293f7df2e56Smrg
294f7df2e56Smrg            fbfd = open(xf86SolarisFbDev, O_RDONLY);
295f7df2e56Smrg            if (fbfd >= 0) {
296f7df2e56Smrg                SYSCALL(iret = ioctl(fbfd, VIS_GETIDENTIFIER, &visid));
297f7df2e56Smrg                close(fbfd);
298f7df2e56Smrg            }
299f7df2e56Smrg        }
300637ac9abSmrg
301f7df2e56Smrg        if (iret < 0) {
302f7df2e56Smrg            xf86Msg(X_WARNING,
303f7df2e56Smrg                    "could not get frame buffer identifier from %s\n",
304f7df2e56Smrg                    xf86SolarisFbDev);
305f7df2e56Smrg        }
306f7df2e56Smrg        else {
307f7df2e56Smrg            xf86Msg(X_PROBED, "console driver: %s\n", visid.name);
308637ac9abSmrg
309f7df2e56Smrg            /* Special case from before the general case was set */
310f7df2e56Smrg            if (strcmp(visid.name, "NVDAnvda") == 0) {
3117e31ba66Smrg                xf86AddMatchedDriver(md, "nvidia");
312f7df2e56Smrg            }
313637ac9abSmrg
314f7df2e56Smrg            /* General case - split into vendor name (initial all-caps
315f7df2e56Smrg               prefix) & driver name (rest of the string). */
316f7df2e56Smrg            if (strcmp(visid.name, "SUNWtext") != 0) {
317f7df2e56Smrg                for (cp = visid.name; (*cp != '\0') && isupper(*cp); cp++) {
318f7df2e56Smrg                    /* find end of all uppercase vendor section */
319f7df2e56Smrg                }
320f7df2e56Smrg                if ((cp != visid.name) && (*cp != '\0')) {
321f7df2e56Smrg                    char *vendorName = xnfstrdup(visid.name);
322f7df2e56Smrg
323f7df2e56Smrg                    vendorName[cp - visid.name] = '\0';
324f7df2e56Smrg
3257e31ba66Smrg                    xf86AddMatchedDriver(md, vendorName);
3267e31ba66Smrg                    xf86AddMatchedDriver(md, cp);
3277e31ba66Smrg
3287e31ba66Smrg                    free(vendorName);
329f7df2e56Smrg                }
330f7df2e56Smrg            }
331f7df2e56Smrg        }
332637ac9abSmrg    }
333637ac9abSmrg#endif
334637ac9abSmrg#ifdef __sparc__
3357e31ba66Smrg    char *sbusDriver = sparcDriverName();
336f7df2e56Smrg
3377e31ba66Smrg    if (sbusDriver)
3387e31ba66Smrg        xf86AddMatchedDriver(md, sbusDriver);
339637ac9abSmrg#endif
34018a93be0Smacallan#endif /* NetBSD */
341f7df2e56Smrg#ifdef XSERVER_LIBPCIACCESS
3427e31ba66Smrg    xf86PciMatchDriver(md);
343f7df2e56Smrg#endif
344637ac9abSmrg
345f7df2e56Smrg#if defined(__linux__)
3467e31ba66Smrg    xf86AddMatchedDriver(md, "modesetting");
347f7df2e56Smrg#endif
348637ac9abSmrg
349ac2a9f9bSmaya#if defined(__NetBSD__) && \
350ac2a9f9bSmaya    (defined(__aarch64__) || defined(__arm__) || \
351ac2a9f9bSmaya     defined(__i386__) || defined(__amd64__))
3522cb0653bSjmcneill    xf86AddMatchedDriver(md, "modesetting");
3532cb0653bSjmcneill#endif
3542cb0653bSjmcneill
3557a3fb2faSmaya#if defined(__linux__)
3567e31ba66Smrg    xf86AddMatchedDriver(md, "fbdev");
357637ac9abSmrg#endif
358fdb9fcb3Sjmcneill
359f7df2e56Smrg    /* Fallback to platform default hardware */
3600b3f0b9fSjmcneill#if defined(__i386__) || defined(__amd64__) || defined(__hurd__)
3617e31ba66Smrg    xf86AddMatchedDriver(md, "vesa");
3627e31ba66Smrg#elif defined(__sparc__) && !defined(__sun)
3637e31ba66Smrg    xf86AddMatchedDriver(md, "sunffb");
3647a3fb2faSmaya#endif
3650b3f0b9fSjmcneill
3660b3f0b9fSjmcneill#if defined(__NetBSD__)
3670b3f0b9fSjmcneill    xf86AddMatchedDriver(md, "wsfb");
3680b3f0b9fSjmcneill#endif
369637ac9abSmrg}
370637ac9abSmrg
3714202a189Smrg/* copy a screen section and enter the desired driver
3724202a189Smrg * and insert it at i in the list of screens */
3734202a189Smrgstatic Bool
3744202a189SmrgcopyScreen(confScreenPtr oscreen, GDevPtr odev, int i, char *driver)
375637ac9abSmrg{
37665b04b38Smrg    confScreenPtr nscreen;
3774202a189Smrg    GDevPtr cptr = NULL;
378f7df2e56Smrg    char *identifier;
3794202a189Smrg
38065b04b38Smrg    nscreen = malloc(sizeof(confScreenRec));
38165b04b38Smrg    if (!nscreen)
3824202a189Smrg        return FALSE;
38365b04b38Smrg    memcpy(nscreen, oscreen, sizeof(confScreenRec));
3844202a189Smrg
38565b04b38Smrg    cptr = malloc(sizeof(GDevRec));
38665b04b38Smrg    if (!cptr) {
38765b04b38Smrg        free(nscreen);
3884202a189Smrg        return FALSE;
38965b04b38Smrg    }
3904202a189Smrg    memcpy(cptr, odev, sizeof(GDevRec));
3914202a189Smrg
392f7df2e56Smrg    if (asprintf(&identifier, "Autoconfigured Video Device %s", driver)
39365b04b38Smrg        == -1) {
39465b04b38Smrg        free(cptr);
39565b04b38Smrg        free(nscreen);
39665b04b38Smrg        return FALSE;
39765b04b38Smrg    }
3984202a189Smrg    cptr->driver = driver;
399f7df2e56Smrg    cptr->identifier = identifier;
4004202a189Smrg
40165b04b38Smrg    xf86ConfigLayout.screens[i].screen = nscreen;
40265b04b38Smrg
4034202a189Smrg    /* now associate the new driver entry with the new screen entry */
4044202a189Smrg    xf86ConfigLayout.screens[i].screen->device = cptr;
4054202a189Smrg    cptr->myScreenSection = xf86ConfigLayout.screens[i].screen;
4064202a189Smrg
4074202a189Smrg    return TRUE;
4084202a189Smrg}
4094202a189Smrg
4104202a189SmrgGDevPtr
4114202a189SmrgautoConfigDevice(GDevPtr preconf_device)
4124202a189Smrg{
4134202a189Smrg    GDevPtr ptr = NULL;
4147e31ba66Smrg    XF86MatchedDrivers md;
4157e31ba66Smrg    int num_screens = 0, i;
4164202a189Smrg    screenLayoutPtr slp;
417637ac9abSmrg
4184202a189Smrg    if (!xf86configptr) {
4194202a189Smrg        return NULL;
4204202a189Smrg    }
4214202a189Smrg
4224202a189Smrg    /* If there's a configured section with no driver chosen, use it */
4234202a189Smrg    if (preconf_device) {
4244202a189Smrg        ptr = preconf_device;
425f7df2e56Smrg    }
426f7df2e56Smrg    else {
4274202a189Smrg        ptr = calloc(1, sizeof(GDevRec));
4284202a189Smrg        if (!ptr) {
4294202a189Smrg            return NULL;
4304202a189Smrg        }
4314202a189Smrg        ptr->chipID = -1;
4324202a189Smrg        ptr->chipRev = -1;
4334202a189Smrg        ptr->irq = -1;
4344202a189Smrg
4354202a189Smrg        ptr->active = TRUE;
4364202a189Smrg        ptr->claimed = FALSE;
4374202a189Smrg        ptr->identifier = "Autoconfigured Video Device";
4384202a189Smrg        ptr->driver = NULL;
4394202a189Smrg    }
4404202a189Smrg    if (!ptr->driver) {
4414202a189Smrg        /* get all possible video drivers and count them */
4427e31ba66Smrg        listPossibleVideoDrivers(&md);
4437e31ba66Smrg        for (i = 0; i < md.nmatches; i++) {
4444202a189Smrg            xf86Msg(X_DEFAULT, "Matched %s as autoconfigured driver %d\n",
4457e31ba66Smrg                    md.matches[i], i);
4464202a189Smrg        }
447637ac9abSmrg
4484202a189Smrg        slp = xf86ConfigLayout.screens;
4494202a189Smrg        if (slp) {
4504202a189Smrg            /* count the number of screens and make space for
4514202a189Smrg             * a new screen for each additional possible driver
4524202a189Smrg             * minus one for the already existing first one
4534202a189Smrg             * plus one for the terminating NULL */
4544202a189Smrg            for (; slp[num_screens].screen; num_screens++);
4557e31ba66Smrg            xf86ConfigLayout.screens = xnfcalloc(num_screens + md.nmatches,
456f7df2e56Smrg                                                 sizeof(screenLayoutRec));
4574202a189Smrg            xf86ConfigLayout.screens[0] = slp[0];
4584202a189Smrg
4594202a189Smrg            /* do the first match and set that for the original first screen */
4607e31ba66Smrg            ptr->driver = md.matches[0];
4614202a189Smrg            if (!xf86ConfigLayout.screens[0].screen->device) {
4624202a189Smrg                xf86ConfigLayout.screens[0].screen->device = ptr;
4634202a189Smrg                ptr->myScreenSection = xf86ConfigLayout.screens[0].screen;
4644202a189Smrg            }
465637ac9abSmrg
4664202a189Smrg            /* for each other driver found, copy the first screen, insert it
4674202a189Smrg             * into the list of screens and set the driver */
4687e31ba66Smrg            for (i = 1; i < md.nmatches; i++) {
4697e31ba66Smrg                if (!copyScreen(slp[0].screen, ptr, i, md.matches[i]))
4704202a189Smrg                    return NULL;
4714202a189Smrg            }
472637ac9abSmrg
4734202a189Smrg            /* shift the rest of the original screen list
4744202a189Smrg             * to the end of the current screen list
4754202a189Smrg             *
4764202a189Smrg             * TODO Handle rest of multiple screen sections */
4774202a189Smrg            for (i = 1; i < num_screens; i++) {
4787e31ba66Smrg                xf86ConfigLayout.screens[i + md.nmatches] = slp[i];
4794202a189Smrg            }
4807e31ba66Smrg            xf86ConfigLayout.screens[num_screens + md.nmatches - 1].screen =
481f7df2e56Smrg                NULL;
4824202a189Smrg            free(slp);
483f7df2e56Smrg        }
484f7df2e56Smrg        else {
4854202a189Smrg            /* layout does not have any screens, not much to do */
4867e31ba66Smrg            ptr->driver = md.matches[0];
4877e31ba66Smrg            for (i = 1; i < md.nmatches; i++) {
4887e31ba66Smrg                free(md.matches[i]);
4894202a189Smrg            }
490637ac9abSmrg        }
491637ac9abSmrg    }
492637ac9abSmrg
4934202a189Smrg    xf86Msg(X_DEFAULT, "Assigned the driver to the xf86ConfigLayout\n");
4944202a189Smrg
4954202a189Smrg    return ptr;
496637ac9abSmrg}
497