xf86platformBus.c revision 1b5d61b8
1/* 2 * Copyright © 2012 Red Hat. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 * DEALINGS IN THE SOFTWARE. 21 * 22 * Author: Dave Airlie <airlied@redhat.com> 23 */ 24 25/* 26 * This file contains the interfaces to the bus-specific code 27 */ 28 29#ifdef HAVE_XORG_CONFIG_H 30#include <xorg-config.h> 31#endif 32 33#ifdef XSERVER_PLATFORM_BUS 34#include <errno.h> 35 36#include <pciaccess.h> 37#include <fcntl.h> 38#include <unistd.h> 39#include "os.h" 40#include "hotplug.h" 41#include "systemd-logind.h" 42 43#include "loaderProcs.h" 44#include "xf86.h" 45#include "xf86_OSproc.h" 46#include "xf86Priv.h" 47#include "xf86str.h" 48#include "xf86Bus.h" 49#include "Pci.h" 50#include "xf86platformBus.h" 51#include "xf86Config.h" 52 53#include "randrstr.h" 54int platformSlotClaimed; 55 56int xf86_num_platform_devices; 57 58struct xf86_platform_device *xf86_platform_devices; 59 60int 61xf86_add_platform_device(struct OdevAttributes *attribs, Bool unowned) 62{ 63 xf86_platform_devices = xnfreallocarray(xf86_platform_devices, 64 xf86_num_platform_devices + 1, 65 sizeof(struct xf86_platform_device)); 66 67 xf86_platform_devices[xf86_num_platform_devices].attribs = attribs; 68 xf86_platform_devices[xf86_num_platform_devices].pdev = NULL; 69 xf86_platform_devices[xf86_num_platform_devices].flags = 70 unowned ? XF86_PDEV_UNOWNED : 0; 71 72 xf86_num_platform_devices++; 73 return 0; 74} 75 76int 77xf86_remove_platform_device(int dev_index) 78{ 79 int j; 80 81 config_odev_free_attributes(xf86_platform_devices[dev_index].attribs); 82 83 for (j = dev_index; j < xf86_num_platform_devices - 1; j++) 84 memcpy(&xf86_platform_devices[j], &xf86_platform_devices[j + 1], sizeof(struct xf86_platform_device)); 85 xf86_num_platform_devices--; 86 return 0; 87} 88 89Bool 90xf86_get_platform_device_unowned(int index) 91{ 92 return (xf86_platform_devices[index].flags & XF86_PDEV_UNOWNED) ? 93 TRUE : FALSE; 94} 95 96struct xf86_platform_device * 97xf86_find_platform_device_by_devnum(int major, int minor) 98{ 99 int i, attr_major, attr_minor; 100 101 for (i = 0; i < xf86_num_platform_devices; i++) { 102 attr_major = xf86_platform_odev_attributes(i)->major; 103 attr_minor = xf86_platform_odev_attributes(i)->minor; 104 if (attr_major == major && attr_minor == minor) 105 return &xf86_platform_devices[i]; 106 } 107 return NULL; 108} 109 110/* 111 * xf86IsPrimaryPlatform() -- return TRUE if primary device 112 * is a platform device and it matches this one. 113 */ 114 115static Bool 116xf86IsPrimaryPlatform(struct xf86_platform_device *plat) 117{ 118 /* Add max. 1 screen for the IgnorePrimary fallback path */ 119 if (xf86ProbeIgnorePrimary && xf86NumScreens == 0) 120 return TRUE; 121 122 if (primaryBus.type == BUS_PLATFORM) 123 return plat == primaryBus.id.plat; 124#ifdef XSERVER_LIBPCIACCESS 125 if (primaryBus.type == BUS_PCI) 126 if (plat->pdev) 127 if (MATCH_PCI_DEVICES(primaryBus.id.pci, plat->pdev)) 128 return TRUE; 129#endif 130 return FALSE; 131} 132 133static void 134platform_find_pci_info(struct xf86_platform_device *pd, char *busid) 135{ 136 struct pci_slot_match devmatch; 137 struct pci_device *info; 138 struct pci_device_iterator *iter; 139 int ret; 140 141 ret = sscanf(busid, "pci:%04x:%02x:%02x.%u", 142 &devmatch.domain, &devmatch.bus, &devmatch.dev, 143 &devmatch.func); 144 if (ret != 4) 145 return; 146 147 iter = pci_slot_match_iterator_create(&devmatch); 148 info = pci_device_next(iter); 149 if (info) 150 pd->pdev = info; 151 pci_iterator_destroy(iter); 152} 153 154static Bool 155xf86_check_platform_slot(const struct xf86_platform_device *pd) 156{ 157 int i; 158 159 for (i = 0; i < xf86NumEntities; i++) { 160 const EntityPtr u = xf86Entities[i]; 161 162 if (pd->pdev && u->bus.type == BUS_PCI && 163 MATCH_PCI_DEVICES(pd->pdev, u->bus.id.pci)) { 164 return FALSE; 165 } 166 if ((u->bus.type == BUS_PLATFORM) && (pd == u->bus.id.plat)) { 167 return FALSE; 168 } 169 } 170 return TRUE; 171} 172 173static Bool 174MatchToken(const char *value, struct xorg_list *patterns, 175 int (*compare)(const char *, const char *)) 176{ 177 const xf86MatchGroup *group; 178 179 /* If there are no patterns, accept the match */ 180 if (xorg_list_is_empty(patterns)) 181 return TRUE; 182 183 /* If there are patterns but no attribute, reject the match */ 184 if (!value) 185 return FALSE; 186 187 /* 188 * Otherwise, iterate the list of patterns ensuring each entry has a 189 * match. Each list entry is a separate Match line of the same type. 190 */ 191 xorg_list_for_each_entry(group, patterns, entry) { 192 Bool match = FALSE; 193 char *const *cur; 194 195 for (cur = group->values; *cur; cur++) { 196 if ((*compare)(value, *cur) == 0) { 197 match = TRUE; 198 break; 199 } 200 } 201 202 if (!match) 203 return FALSE; 204 } 205 206 /* All the entries in the list matched the attribute */ 207 return TRUE; 208} 209 210static Bool 211OutputClassMatches(const XF86ConfOutputClassPtr oclass, 212 struct xf86_platform_device *dev) 213{ 214 char *driver = dev->attribs->driver; 215 216 if (!MatchToken(driver, &oclass->match_driver, strcmp)) 217 return FALSE; 218 219 return TRUE; 220} 221 222static void 223xf86OutputClassDriverList(int index, XF86MatchedDrivers *md) 224{ 225 XF86ConfOutputClassPtr cl; 226 227 for (cl = xf86configptr->conf_outputclass_lst; cl; cl = cl->list.next) { 228 if (OutputClassMatches(cl, &xf86_platform_devices[index])) { 229 char *path = xf86_platform_odev_attributes(index)->path; 230 231 xf86Msg(X_INFO, "Applying OutputClass \"%s\" to %s\n", 232 cl->identifier, path); 233 xf86Msg(X_NONE, "\tloading driver: %s\n", cl->driver); 234 235 xf86AddMatchedDriver(md, cl->driver); 236 } 237 } 238} 239 240/** 241 * @return The numbers of found devices that match with the current system 242 * drivers. 243 */ 244void 245xf86PlatformMatchDriver(XF86MatchedDrivers *md) 246{ 247 int i; 248 struct pci_device *info = NULL; 249 int pass = 0; 250 251 for (pass = 0; pass < 2; pass++) { 252 for (i = 0; i < xf86_num_platform_devices; i++) { 253 254 if (xf86IsPrimaryPlatform(&xf86_platform_devices[i]) && (pass == 1)) 255 continue; 256 else if (!xf86IsPrimaryPlatform(&xf86_platform_devices[i]) && (pass == 0)) 257 continue; 258 259 xf86OutputClassDriverList(i, md); 260 261 info = xf86_platform_devices[i].pdev; 262#ifdef __linux__ 263 if (info) 264 xf86MatchDriverFromFiles(info->vendor_id, info->device_id, md); 265#endif 266 267 if (info != NULL) { 268 xf86VideoPtrToDriverList(info, md); 269 } 270 } 271 } 272} 273 274int 275xf86platformProbe(void) 276{ 277 int i; 278 Bool pci = TRUE; 279 XF86ConfOutputClassPtr cl, cl_head = (xf86configptr) ? 280 xf86configptr->conf_outputclass_lst : NULL; 281 char *old_path, *path = NULL; 282 283 config_odev_probe(xf86PlatformDeviceProbe); 284 285 if (!xf86scanpci()) { 286 pci = FALSE; 287 } 288 289 for (i = 0; i < xf86_num_platform_devices; i++) { 290 char *busid = xf86_platform_odev_attributes(i)->busid; 291 292 if (pci && (strncmp(busid, "pci:", 4) == 0)) { 293 platform_find_pci_info(&xf86_platform_devices[i], busid); 294 } 295 296 /* 297 * Deal with OutputClass ModulePath directives, these must be 298 * processed before we do any module loading. 299 */ 300 for (cl = cl_head; cl; cl = cl->list.next) { 301 if (!OutputClassMatches(cl, &xf86_platform_devices[i])) 302 continue; 303 304 if (cl->modulepath && xf86ModPathFrom != X_CMDLINE) { 305 old_path = path; 306 XNFasprintf(&path, "%s,%s", cl->modulepath, 307 path ? path : xf86ModulePath); 308 free(old_path); 309 xf86Msg(X_CONFIG, "OutputClass \"%s\" ModulePath extended to \"%s\"\n", 310 cl->identifier, path); 311 LoaderSetPath(path); 312 } 313 } 314 } 315 316 free(path); 317 318 /* First see if there is an OutputClass match marking a device as primary */ 319 for (i = 0; i < xf86_num_platform_devices; i++) { 320 struct xf86_platform_device *dev = &xf86_platform_devices[i]; 321 for (cl = cl_head; cl; cl = cl->list.next) { 322 if (!OutputClassMatches(cl, dev)) 323 continue; 324 325 if (xf86CheckBoolOption(cl->option_lst, "PrimaryGPU", FALSE)) { 326 xf86Msg(X_CONFIG, "OutputClass \"%s\" setting %s as PrimaryGPU\n", 327 cl->identifier, dev->attribs->path); 328 primaryBus.type = BUS_PLATFORM; 329 primaryBus.id.plat = dev; 330 return 0; 331 } 332 } 333 } 334 335 /* Then check for pci_device_is_boot_vga() */ 336 for (i = 0; i < xf86_num_platform_devices; i++) { 337 struct xf86_platform_device *dev = &xf86_platform_devices[i]; 338 339 if (!dev->pdev) 340 continue; 341 342 pci_device_probe(dev->pdev); 343 if (pci_device_is_boot_vga(dev->pdev)) { 344 primaryBus.type = BUS_PLATFORM; 345 primaryBus.id.plat = dev; 346 } 347 } 348 349 return 0; 350} 351 352void 353xf86MergeOutputClassOptions(int entityIndex, void **options) 354{ 355 const EntityPtr entity = xf86Entities[entityIndex]; 356 struct xf86_platform_device *dev = NULL; 357 XF86ConfOutputClassPtr cl; 358 XF86OptionPtr classopts; 359 int i = 0; 360 361 switch (entity->bus.type) { 362 case BUS_PLATFORM: 363 dev = entity->bus.id.plat; 364 break; 365 case BUS_PCI: 366 for (i = 0; i < xf86_num_platform_devices; i++) { 367 if (MATCH_PCI_DEVICES(xf86_platform_devices[i].pdev, 368 entity->bus.id.pci)) { 369 dev = &xf86_platform_devices[i]; 370 break; 371 } 372 } 373 break; 374 default: 375 xf86Msg(X_DEBUG, "xf86MergeOutputClassOptions unsupported bus type %d\n", 376 entity->bus.type); 377 } 378 379 if (!dev) 380 return; 381 382 for (cl = xf86configptr->conf_outputclass_lst; cl; cl = cl->list.next) { 383 if (!OutputClassMatches(cl, dev) || !cl->option_lst) 384 continue; 385 386 xf86Msg(X_INFO, "Applying OutputClass \"%s\" options to %s\n", 387 cl->identifier, dev->attribs->path); 388 389 classopts = xf86optionListDup(cl->option_lst); 390 *options = xf86optionListMerge(*options, classopts); 391 } 392} 393 394static int 395xf86ClaimPlatformSlot(struct xf86_platform_device * d, DriverPtr drvp, 396 int chipset, GDevPtr dev, Bool active) 397{ 398 EntityPtr p = NULL; 399 int num; 400 401 if (xf86_check_platform_slot(d)) { 402 num = xf86AllocateEntity(); 403 p = xf86Entities[num]; 404 p->driver = drvp; 405 p->chipset = chipset; 406 p->bus.type = BUS_PLATFORM; 407 p->bus.id.plat = d; 408 p->active = active; 409 p->inUse = FALSE; 410 if (dev) 411 xf86AddDevToEntity(num, dev); 412 413 platformSlotClaimed++; 414 return num; 415 } 416 else 417 return -1; 418} 419 420static int 421xf86UnclaimPlatformSlot(struct xf86_platform_device *d, GDevPtr dev) 422{ 423 int i; 424 425 for (i = 0; i < xf86NumEntities; i++) { 426 const EntityPtr p = xf86Entities[i]; 427 428 if ((p->bus.type == BUS_PLATFORM) && (p->bus.id.plat == d)) { 429 if (dev) 430 xf86RemoveDevFromEntity(i, dev); 431 platformSlotClaimed--; 432 p->bus.type = BUS_NONE; 433 return 0; 434 } 435 } 436 return 0; 437} 438 439 440#define END_OF_MATCHES(m) \ 441 (((m).vendor_id == 0) && ((m).device_id == 0) && ((m).subvendor_id == 0)) 442 443static Bool doPlatformProbe(struct xf86_platform_device *dev, DriverPtr drvp, 444 GDevPtr gdev, int flags, intptr_t match_data) 445{ 446 Bool foundScreen = FALSE; 447 int entity; 448 449 if (gdev && gdev->screen == 0 && !xf86_check_platform_slot(dev)) 450 return FALSE; 451 452 entity = xf86ClaimPlatformSlot(dev, drvp, 0, 453 gdev, gdev ? gdev->active : 0); 454 455 if ((entity == -1) && gdev && (gdev->screen > 0)) { 456 unsigned nent; 457 458 for (nent = 0; nent < xf86NumEntities; nent++) { 459 EntityPtr pEnt = xf86Entities[nent]; 460 461 if (pEnt->bus.type != BUS_PLATFORM) 462 continue; 463 if (pEnt->bus.id.plat == dev) { 464 entity = nent; 465 xf86AddDevToEntity(nent, gdev); 466 break; 467 } 468 } 469 } 470 if (entity != -1) { 471 if ((dev->flags & XF86_PDEV_SERVER_FD) && (!drvp->driverFunc || 472 !drvp->driverFunc(NULL, SUPPORTS_SERVER_FDS, NULL))) { 473 systemd_logind_release_fd(dev->attribs->major, dev->attribs->minor, dev->attribs->fd); 474 dev->attribs->fd = -1; 475 dev->flags &= ~XF86_PDEV_SERVER_FD; 476 } 477 478 if (drvp->platformProbe(drvp, entity, flags, dev, match_data)) 479 foundScreen = TRUE; 480 else 481 xf86UnclaimPlatformSlot(dev, gdev); 482 } 483 return foundScreen; 484} 485 486static Bool 487probeSingleDevice(struct xf86_platform_device *dev, DriverPtr drvp, GDevPtr gdev, int flags) 488{ 489 int k; 490 Bool foundScreen = FALSE; 491 struct pci_device *pPci; 492 const struct pci_id_match *const devices = drvp->supported_devices; 493 494 if (dev->pdev && devices) { 495 int device_id = dev->pdev->device_id; 496 pPci = dev->pdev; 497 for (k = 0; !END_OF_MATCHES(devices[k]); k++) { 498 if (PCI_ID_COMPARE(devices[k].vendor_id, pPci->vendor_id) 499 && PCI_ID_COMPARE(devices[k].device_id, device_id) 500 && ((devices[k].device_class_mask & pPci->device_class) 501 == devices[k].device_class)) { 502 foundScreen = doPlatformProbe(dev, drvp, gdev, flags, devices[k].match_data); 503 if (foundScreen) 504 break; 505 } 506 } 507 } 508 else if (dev->pdev && !devices) 509 return FALSE; 510 else 511 foundScreen = doPlatformProbe(dev, drvp, gdev, flags, 0); 512 return foundScreen; 513} 514 515static Bool 516isGPUDevice(GDevPtr gdev) 517{ 518 int i; 519 520 for (i = 0; i < gdev->myScreenSection->num_gpu_devices; i++) { 521 if (gdev == gdev->myScreenSection->gpu_devices[i]) 522 return TRUE; 523 } 524 525 return FALSE; 526} 527 528int 529xf86platformProbeDev(DriverPtr drvp) 530{ 531 Bool foundScreen = FALSE; 532 GDevPtr *devList; 533 const unsigned numDevs = xf86MatchDevice(drvp->driverName, &devList); 534 int i, j; 535 536 /* find the main device or any device specificed in xorg.conf */ 537 for (i = 0; i < numDevs; i++) { 538 /* skip inactive devices */ 539 if (!devList[i]->active) 540 continue; 541 542 for (j = 0; j < xf86_num_platform_devices; j++) { 543 if (devList[i]->busID && *devList[i]->busID) { 544 if (xf86PlatformDeviceCheckBusID(&xf86_platform_devices[j], devList[i]->busID)) 545 break; 546 } 547 else { 548 /* for non-seat0 servers assume first device is the master */ 549 if (ServerIsNotSeat0()) 550 break; 551 552 if (xf86IsPrimaryPlatform(&xf86_platform_devices[j])) 553 break; 554 } 555 } 556 557 if (j == xf86_num_platform_devices) 558 continue; 559 560 foundScreen = probeSingleDevice(&xf86_platform_devices[j], drvp, devList[i], 561 isGPUDevice(devList[i]) ? PLATFORM_PROBE_GPU_SCREEN : 0); 562 } 563 564 free(devList); 565 566 return foundScreen; 567} 568 569int 570xf86platformAddGPUDevices(DriverPtr drvp) 571{ 572 Bool foundScreen = FALSE; 573 GDevPtr *devList; 574 int j; 575 576 if (!drvp->platformProbe) 577 return FALSE; 578 579 xf86MatchDevice(drvp->driverName, &devList); 580 581 /* if autoaddgpu devices is enabled then go find any unclaimed platform 582 * devices and add them as GPU screens */ 583 if (xf86Info.autoAddGPU) { 584 for (j = 0; j < xf86_num_platform_devices; j++) { 585 if (probeSingleDevice(&xf86_platform_devices[j], drvp, 586 devList ? devList[0] : NULL, 587 PLATFORM_PROBE_GPU_SCREEN)) 588 foundScreen = TRUE; 589 } 590 } 591 592 free(devList); 593 594 return foundScreen; 595} 596 597int 598xf86platformAddDevice(int index) 599{ 600 int i, old_screens, scr_index; 601 DriverPtr drvp = NULL; 602 screenLayoutPtr layout; 603 static const char *hotplug_driver_name = "modesetting"; 604 605 if (!xf86Info.autoAddGPU) 606 return -1; 607 608 /* force load the driver for now */ 609 xf86LoadOneModule(hotplug_driver_name, NULL); 610 611 for (i = 0; i < xf86NumDrivers; i++) { 612 if (!xf86DriverList[i]) 613 continue; 614 615 if (!strcmp(xf86DriverList[i]->driverName, hotplug_driver_name)) { 616 drvp = xf86DriverList[i]; 617 break; 618 } 619 } 620 if (i == xf86NumDrivers) 621 return -1; 622 623 old_screens = xf86NumGPUScreens; 624 doPlatformProbe(&xf86_platform_devices[index], drvp, NULL, 625 PLATFORM_PROBE_GPU_SCREEN, 0); 626 if (old_screens == xf86NumGPUScreens) 627 return -1; 628 i = old_screens; 629 630 for (layout = xf86ConfigLayout.screens; layout->screen != NULL; 631 layout++) { 632 xf86GPUScreens[i]->confScreen = layout->screen; 633 break; 634 } 635 636 if (xf86GPUScreens[i]->PreInit && 637 xf86GPUScreens[i]->PreInit(xf86GPUScreens[i], 0)) 638 xf86GPUScreens[i]->configured = TRUE; 639 640 if (!xf86GPUScreens[i]->configured) { 641 ErrorF("hotplugged device %d didn't configure\n", i); 642 xf86DeleteScreen(xf86GPUScreens[i]); 643 return -1; 644 } 645 646 scr_index = AddGPUScreen(xf86GPUScreens[i]->ScreenInit, 0, NULL); 647 if (scr_index == -1) { 648 xf86DeleteScreen(xf86GPUScreens[i]); 649 xf86UnclaimPlatformSlot(&xf86_platform_devices[index], NULL); 650 xf86NumGPUScreens = old_screens; 651 return -1; 652 } 653 dixSetPrivate(&xf86GPUScreens[i]->pScreen->devPrivates, 654 xf86ScreenKey, xf86GPUScreens[i]); 655 656 CreateScratchPixmapsForScreen(xf86GPUScreens[i]->pScreen); 657 658 if (xf86GPUScreens[i]->pScreen->CreateScreenResources && 659 !(*xf86GPUScreens[i]->pScreen->CreateScreenResources) (xf86GPUScreens[i]->pScreen)) { 660 RemoveGPUScreen(xf86GPUScreens[i]->pScreen); 661 xf86DeleteScreen(xf86GPUScreens[i]); 662 xf86UnclaimPlatformSlot(&xf86_platform_devices[index], NULL); 663 xf86NumGPUScreens = old_screens; 664 return -1; 665 } 666 /* attach unbound to 0 protocol screen */ 667 AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen); 668 669 RRResourcesChanged(xf86Screens[0]->pScreen); 670 RRTellChanged(xf86Screens[0]->pScreen); 671 672 return 0; 673} 674 675void 676xf86platformRemoveDevice(int index) 677{ 678 EntityPtr entity; 679 int ent_num, i, j; 680 Bool found; 681 682 for (ent_num = 0; ent_num < xf86NumEntities; ent_num++) { 683 entity = xf86Entities[ent_num]; 684 if (entity->bus.type == BUS_PLATFORM && 685 entity->bus.id.plat == &xf86_platform_devices[index]) 686 break; 687 } 688 if (ent_num == xf86NumEntities) 689 goto out; 690 691 found = FALSE; 692 for (i = 0; i < xf86NumGPUScreens; i++) { 693 for (j = 0; j < xf86GPUScreens[i]->numEntities; j++) 694 if (xf86GPUScreens[i]->entityList[j] == ent_num) { 695 found = TRUE; 696 break; 697 } 698 if (found) 699 break; 700 } 701 if (!found) { 702 ErrorF("failed to find screen to remove\n"); 703 goto out; 704 } 705 706 xf86GPUScreens[i]->pScreen->CloseScreen(xf86GPUScreens[i]->pScreen); 707 708 RemoveGPUScreen(xf86GPUScreens[i]->pScreen); 709 xf86DeleteScreen(xf86GPUScreens[i]); 710 711 xf86UnclaimPlatformSlot(&xf86_platform_devices[index], NULL); 712 713 xf86_remove_platform_device(index); 714 715 RRResourcesChanged(xf86Screens[0]->pScreen); 716 RRTellChanged(xf86Screens[0]->pScreen); 717 out: 718 return; 719} 720 721/* called on return from VT switch to find any new devices */ 722void xf86platformVTProbe(void) 723{ 724 int i; 725 726 for (i = 0; i < xf86_num_platform_devices; i++) { 727 if (!(xf86_platform_devices[i].flags & XF86_PDEV_UNOWNED)) 728 continue; 729 730 xf86_platform_devices[i].flags &= ~XF86_PDEV_UNOWNED; 731 xf86PlatformReprobeDevice(i, xf86_platform_devices[i].attribs); 732 } 733} 734 735void xf86platformPrimary(void) 736{ 737 /* use the first platform device as a fallback */ 738 if (primaryBus.type == BUS_NONE) { 739 xf86Msg(X_INFO, "no primary bus or device found\n"); 740 741 if (xf86_num_platform_devices > 0) { 742 primaryBus.id.plat = &xf86_platform_devices[0]; 743 primaryBus.type = BUS_PLATFORM; 744 745 xf86Msg(X_NONE, "\tfalling back to %s\n", primaryBus.id.plat->attribs->syspath); 746 } 747 } 748} 749#endif 750