xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

xf86platformBus.c (22577B)


      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"
     55 int platformSlotClaimed;
     56 
     57 int xf86_num_platform_devices;
     58 
     59 struct xf86_platform_device *xf86_platform_devices;
     60 
     61 int
     62 xf86_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 
     77 int
     78 xf86_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 
     90 Bool
     91 xf86_get_platform_device_unowned(int index)
     92 {
     93     return (xf86_platform_devices[index].flags & XF86_PDEV_UNOWNED) ?
     94         TRUE : FALSE;
     95 }
     96 
     97 struct xf86_platform_device *
     98 xf86_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 
    116 static Bool
    117 xf86IsPrimaryPlatform(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 
    134 static void
    135 platform_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 
    155 static Bool
    156 xf86_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 
    174 static Bool
    175 MatchToken(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 
    211 static Bool
    212 OutputClassMatches(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 
    223 static void
    224 xf86OutputClassDriverList(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  */
    245 void
    246 xf86PlatformMatchDriver(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 
    275 int
    276 xf86platformProbe(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 
    353 void
    354 xf86MergeOutputClassOptions(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 
    397 static int
    398 xf86ClaimPlatformSlot(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 
    423 static int
    424 xf86UnclaimPlatformSlot(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 
    446 static 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 
    489 static Bool
    490 probeSingleDevice(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 
    518 static Bool
    519 isGPUDevice(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 
    531 int
    532 xf86platformProbeDev(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 
    585 int
    586 xf86platformAddGPUDevices(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 
    613 int
    614 xf86platformAddDevice(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 
    695 void
    696 xf86platformRemoveDevice(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 */
    744 void 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 
    757 void 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