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