xref: /OK3568_Linux_fs/external/xserver/hw/xfree86/common/xf86platformBus.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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"
54 int platformSlotClaimed;
55 
56 int xf86_num_platform_devices;
57 
58 struct xf86_platform_device *xf86_platform_devices;
59 
60 int
xf86_add_platform_device(struct OdevAttributes * attribs,Bool unowned)61 xf86_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 
76 int
xf86_remove_platform_device(int dev_index)77 xf86_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 
89 Bool
xf86_get_platform_device_unowned(int index)90 xf86_get_platform_device_unowned(int index)
91 {
92     return (xf86_platform_devices[index].flags & XF86_PDEV_UNOWNED) ?
93         TRUE : FALSE;
94 }
95 
96 struct xf86_platform_device *
xf86_find_platform_device_by_devnum(int major,int minor)97 xf86_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 
115 static Bool
xf86IsPrimaryPlatform(struct xf86_platform_device * plat)116 xf86IsPrimaryPlatform(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 
133 static void
platform_find_pci_info(struct xf86_platform_device * pd,char * busid)134 platform_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 
154 static Bool
xf86_check_platform_slot(const struct xf86_platform_device * pd)155 xf86_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 
173 static Bool
MatchToken(const char * value,struct xorg_list * patterns,int (* compare)(const char *,const char *))174 MatchToken(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 
210 static Bool
OutputClassMatches(const XF86ConfOutputClassPtr oclass,struct xf86_platform_device * dev)211 OutputClassMatches(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 
222 static void
xf86OutputClassDriverList(int index,XF86MatchedDrivers * md)223 xf86OutputClassDriverList(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  */
244 void
xf86PlatformMatchDriver(XF86MatchedDrivers * md)245 xf86PlatformMatchDriver(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 
274 int
xf86platformProbe(void)275 xf86platformProbe(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 
352 void
xf86MergeOutputClassOptions(int entityIndex,void ** options)353 xf86MergeOutputClassOptions(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 
394 static int
xf86ClaimPlatformSlot(struct xf86_platform_device * d,DriverPtr drvp,int chipset,GDevPtr dev,Bool active)395 xf86ClaimPlatformSlot(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 
420 static int
xf86UnclaimPlatformSlot(struct xf86_platform_device * d,GDevPtr dev)421 xf86UnclaimPlatformSlot(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 
doPlatformProbe(struct xf86_platform_device * dev,DriverPtr drvp,GDevPtr gdev,int flags,intptr_t match_data)443 static 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 
486 static Bool
probeSingleDevice(struct xf86_platform_device * dev,DriverPtr drvp,GDevPtr gdev,int flags)487 probeSingleDevice(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 
515 static Bool
isGPUDevice(GDevPtr gdev)516 isGPUDevice(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 
528 int
xf86platformProbeDev(DriverPtr drvp)529 xf86platformProbeDev(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         const char *devpath;
539 
540         /* skip inactive devices */
541         if (!devList[i]->active)
542             continue;
543 
544         /* This is specific to modesetting. */
545         devpath = xf86FindOptionValue(devList[i]->options, "kmsdev");
546 
547         for (j = 0; j < xf86_num_platform_devices; j++) {
548             if (devpath && *devpath) {
549                 if (strcmp(xf86_platform_devices[j].attribs->path, devpath) == 0)
550                     break;
551             } else if (devList[i]->busID && *devList[i]->busID) {
552                 if (xf86PlatformDeviceCheckBusID(&xf86_platform_devices[j], devList[i]->busID))
553                     break;
554             }
555             else {
556                 /* for non-seat0 servers assume first device is the master */
557                 if (ServerIsNotSeat0())
558                     break;
559 
560                 if (xf86IsPrimaryPlatform(&xf86_platform_devices[j]))
561                     break;
562             }
563         }
564 
565         if (j == xf86_num_platform_devices)
566              continue;
567 
568         foundScreen = probeSingleDevice(&xf86_platform_devices[j], drvp, devList[i],
569                                         isGPUDevice(devList[i]) ? PLATFORM_PROBE_GPU_SCREEN : 0);
570     }
571 
572     free(devList);
573 
574     return foundScreen;
575 }
576 
577 int
xf86platformAddGPUDevices(DriverPtr drvp)578 xf86platformAddGPUDevices(DriverPtr drvp)
579 {
580     Bool foundScreen = FALSE;
581     GDevPtr *devList;
582     int j;
583 
584     if (!drvp->platformProbe)
585         return FALSE;
586 
587     xf86MatchDevice(drvp->driverName, &devList);
588 
589     /* if autoaddgpu devices is enabled then go find any unclaimed platform
590      * devices and add them as GPU screens */
591     if (xf86Info.autoAddGPU) {
592         for (j = 0; j < xf86_num_platform_devices; j++) {
593             if (probeSingleDevice(&xf86_platform_devices[j], drvp,
594                                   devList ?  devList[0] : NULL,
595                                   PLATFORM_PROBE_GPU_SCREEN))
596                 foundScreen = TRUE;
597         }
598     }
599 
600     free(devList);
601 
602     return foundScreen;
603 }
604 
605 int
xf86platformAddDevice(int index)606 xf86platformAddDevice(int index)
607 {
608     int i, old_screens, scr_index;
609     DriverPtr drvp = NULL;
610     screenLayoutPtr layout;
611     static const char *hotplug_driver_name = "modesetting";
612 
613     if (!xf86Info.autoAddGPU)
614         return -1;
615 
616     /* force load the driver for now */
617     xf86LoadOneModule(hotplug_driver_name, NULL);
618 
619     for (i = 0; i < xf86NumDrivers; i++) {
620         if (!xf86DriverList[i])
621             continue;
622 
623         if (!strcmp(xf86DriverList[i]->driverName, hotplug_driver_name)) {
624             drvp = xf86DriverList[i];
625             break;
626         }
627     }
628     if (i == xf86NumDrivers)
629         return -1;
630 
631     old_screens = xf86NumGPUScreens;
632     doPlatformProbe(&xf86_platform_devices[index], drvp, NULL,
633                     PLATFORM_PROBE_GPU_SCREEN, 0);
634     if (old_screens == xf86NumGPUScreens)
635         return -1;
636     i = old_screens;
637 
638     for (layout = xf86ConfigLayout.screens; layout->screen != NULL;
639          layout++) {
640         xf86GPUScreens[i]->confScreen = layout->screen;
641         break;
642     }
643 
644     if (xf86GPUScreens[i]->PreInit &&
645         xf86GPUScreens[i]->PreInit(xf86GPUScreens[i], 0))
646         xf86GPUScreens[i]->configured = TRUE;
647 
648     if (!xf86GPUScreens[i]->configured) {
649         ErrorF("hotplugged device %d didn't configure\n", i);
650         xf86DeleteScreen(xf86GPUScreens[i]);
651         return -1;
652     }
653 
654    scr_index = AddGPUScreen(xf86GPUScreens[i]->ScreenInit, 0, NULL);
655    if (scr_index == -1) {
656        xf86DeleteScreen(xf86GPUScreens[i]);
657        xf86UnclaimPlatformSlot(&xf86_platform_devices[index], NULL);
658        xf86NumGPUScreens = old_screens;
659        return -1;
660    }
661    dixSetPrivate(&xf86GPUScreens[i]->pScreen->devPrivates,
662                  xf86ScreenKey, xf86GPUScreens[i]);
663 
664    CreateScratchPixmapsForScreen(xf86GPUScreens[i]->pScreen);
665 
666    if (xf86GPUScreens[i]->pScreen->CreateScreenResources &&
667        !(*xf86GPUScreens[i]->pScreen->CreateScreenResources) (xf86GPUScreens[i]->pScreen)) {
668        RemoveGPUScreen(xf86GPUScreens[i]->pScreen);
669        xf86DeleteScreen(xf86GPUScreens[i]);
670        xf86UnclaimPlatformSlot(&xf86_platform_devices[index], NULL);
671        xf86NumGPUScreens = old_screens;
672        return -1;
673    }
674    /* attach unbound to 0 protocol screen */
675    AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen);
676 
677    RRResourcesChanged(xf86Screens[0]->pScreen);
678    RRTellChanged(xf86Screens[0]->pScreen);
679 
680    return 0;
681 }
682 
683 void
xf86platformRemoveDevice(int index)684 xf86platformRemoveDevice(int index)
685 {
686     EntityPtr entity;
687     int ent_num, i, j;
688     Bool found;
689 
690     for (ent_num = 0; ent_num < xf86NumEntities; ent_num++) {
691         entity = xf86Entities[ent_num];
692         if (entity->bus.type == BUS_PLATFORM &&
693             entity->bus.id.plat == &xf86_platform_devices[index])
694             break;
695     }
696     if (ent_num == xf86NumEntities)
697         goto out;
698 
699     found = FALSE;
700     for (i = 0; i < xf86NumGPUScreens; i++) {
701         for (j = 0; j < xf86GPUScreens[i]->numEntities; j++)
702             if (xf86GPUScreens[i]->entityList[j] == ent_num) {
703                 found = TRUE;
704                 break;
705             }
706         if (found)
707             break;
708     }
709     if (!found) {
710         ErrorF("failed to find screen to remove\n");
711         goto out;
712     }
713 
714     xf86GPUScreens[i]->pScreen->CloseScreen(xf86GPUScreens[i]->pScreen);
715 
716     RemoveGPUScreen(xf86GPUScreens[i]->pScreen);
717     xf86DeleteScreen(xf86GPUScreens[i]);
718 
719     xf86UnclaimPlatformSlot(&xf86_platform_devices[index], NULL);
720 
721     xf86_remove_platform_device(index);
722 
723     RRResourcesChanged(xf86Screens[0]->pScreen);
724     RRTellChanged(xf86Screens[0]->pScreen);
725  out:
726     return;
727 }
728 
729 /* called on return from VT switch to find any new devices */
xf86platformVTProbe(void)730 void xf86platformVTProbe(void)
731 {
732     int i;
733 
734     for (i = 0; i < xf86_num_platform_devices; i++) {
735         if (!(xf86_platform_devices[i].flags & XF86_PDEV_UNOWNED))
736             continue;
737 
738         xf86_platform_devices[i].flags &= ~XF86_PDEV_UNOWNED;
739         xf86PlatformReprobeDevice(i, xf86_platform_devices[i].attribs);
740     }
741 }
742 
xf86platformPrimary(void)743 void xf86platformPrimary(void)
744 {
745     /* use the first platform device as a fallback */
746     if (primaryBus.type == BUS_NONE) {
747         xf86Msg(X_INFO, "no primary bus or device found\n");
748 
749         if (xf86_num_platform_devices > 0) {
750             primaryBus.id.plat = &xf86_platform_devices[0];
751             primaryBus.type = BUS_PLATFORM;
752 
753             xf86Msg(X_NONE, "\tfalling back to %s\n", primaryBus.id.plat->attribs->syspath);
754         }
755     }
756 }
757 #endif
758