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