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