2 * Copyright © 2012 Red Hat.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
22 * Author: Dave Airlie <airlied@redhat.com>
26 * This file contains the interfaces to the bus-specific code
29 #ifdef HAVE_XORG_CONFIG_H
30 #include <xorg-config.h>
33 #ifdef XSERVER_PLATFORM_BUS
36 #include <pciaccess.h>
43 #include "xf86_OSproc.h"
48 #include "xf86platformBus.h"
51 int platformSlotClaimed
;
53 int xf86_num_platform_devices
;
55 static struct xf86_platform_device
*xf86_platform_devices
;
58 xf86_add_platform_device(struct OdevAttributes
*attribs
)
60 xf86_platform_devices
= xnfrealloc(xf86_platform_devices
,
61 (sizeof(struct xf86_platform_device
)
62 * (xf86_num_platform_devices
+ 1)));
64 xf86_platform_devices
[xf86_num_platform_devices
].attribs
= attribs
;
65 xf86_platform_devices
[xf86_num_platform_devices
].pdev
= NULL
;
67 xf86_num_platform_devices
++;
72 xf86_remove_platform_device(int dev_index
)
76 config_odev_free_attribute_list(xf86_platform_devices
[dev_index
].attribs
);
78 for (j
= dev_index
; j
< xf86_num_platform_devices
- 1; j
++)
79 memcpy(&xf86_platform_devices
[j
], &xf86_platform_devices
[j
+ 1], sizeof(struct xf86_platform_device
));
80 xf86_num_platform_devices
--;
85 xf86_add_platform_device_attrib(int index
, int attrib_id
, char *attrib_name
)
87 struct xf86_platform_device
*device
= &xf86_platform_devices
[index
];
89 return config_odev_add_attribute(device
->attribs
, attrib_id
, attrib_name
);
93 xf86_get_platform_attrib(int index
, int attrib_id
)
95 struct xf86_platform_device
*device
= &xf86_platform_devices
[index
];
96 struct OdevAttribute
*oa
;
98 xorg_list_for_each_entry(oa
, &device
->attribs
->list
, member
) {
99 if (oa
->attrib_id
== attrib_id
)
100 return oa
->attrib_name
;
106 xf86_get_platform_device_attrib(struct xf86_platform_device
*device
, int attrib_id
)
108 struct OdevAttribute
*oa
;
110 xorg_list_for_each_entry(oa
, &device
->attribs
->list
, member
) {
111 if (oa
->attrib_id
== attrib_id
)
112 return oa
->attrib_name
;
118 xf86_get_platform_device_unowned(int index
)
120 return xf86_platform_devices
[index
].attribs
->unowned
;
124 * xf86IsPrimaryPlatform() -- return TRUE if primary device
125 * is a platform device and it matches this one.
129 xf86IsPrimaryPlatform(struct xf86_platform_device
*plat
)
131 return ((primaryBus
.type
== BUS_PLATFORM
) && (plat
== primaryBus
.id
.plat
));
135 platform_find_pci_info(struct xf86_platform_device
*pd
, char *busid
)
137 struct pci_slot_match devmatch
;
138 struct pci_device
*info
;
139 struct pci_device_iterator
*iter
;
142 ret
= sscanf(busid
, "pci:%04x:%02x:%02x.%u",
143 &devmatch
.domain
, &devmatch
.bus
, &devmatch
.dev
,
148 iter
= pci_slot_match_iterator_create(&devmatch
);
149 info
= pci_device_next(iter
);
152 pci_device_probe(info
);
153 if (pci_device_is_boot_vga(info
)) {
154 primaryBus
.type
= BUS_PLATFORM
;
155 primaryBus
.id
.plat
= pd
;
158 pci_iterator_destroy(iter
);
163 xf86_check_platform_slot(const struct xf86_platform_device
*pd
)
167 for (i
= 0; i
< xf86NumEntities
; i
++) {
168 const EntityPtr u
= xf86Entities
[i
];
170 if (pd
->pdev
&& u
->bus
.type
== BUS_PCI
)
171 return !MATCH_PCI_DEVICES(pd
->pdev
, u
->bus
.id
.pci
);
172 if ((u
->bus
.type
== BUS_PLATFORM
) && (pd
== u
->bus
.id
.plat
)) {
180 * @return The numbers of found devices that match with the current system
184 xf86PlatformMatchDriver(char *matches
[], int nmatches
)
187 struct pci_device
*info
= NULL
;
190 for (pass
= 0; pass
< 2; pass
++) {
191 for (i
= 0; i
< xf86_num_platform_devices
; i
++) {
193 if (xf86IsPrimaryPlatform(&xf86_platform_devices
[i
]) && (pass
== 1))
195 else if (!xf86IsPrimaryPlatform(&xf86_platform_devices
[i
]) && (pass
== 0))
198 info
= xf86_platform_devices
[i
].pdev
;
201 xf86MatchDriverFromFiles(matches
, info
->vendor_id
, info
->device_id
);
204 for (j
= 0; (j
< nmatches
) && (matches
[j
]); j
++) {
205 /* find end of matches list */
208 if ((info
!= NULL
) && (j
< nmatches
)) {
209 j
+= xf86VideoPtrToDriverList(info
, &(matches
[j
]), nmatches
- j
);
217 xf86platformProbe(void)
222 config_odev_probe(xf86PlatformDeviceProbe
);
224 if (!xf86scanpci()) {
228 for (i
= 0; i
< xf86_num_platform_devices
; i
++) {
229 char *busid
= xf86_get_platform_attrib(i
, ODEV_ATTRIB_BUSID
);
231 if (pci
&& (strncmp(busid
, "pci:", 4) == 0)) {
232 platform_find_pci_info(&xf86_platform_devices
[i
], busid
);
239 xf86ClaimPlatformSlot(struct xf86_platform_device
* d
, DriverPtr drvp
,
240 int chipset
, GDevPtr dev
, Bool active
)
245 if (xf86_check_platform_slot(d
)) {
246 num
= xf86AllocateEntity();
247 p
= xf86Entities
[num
];
249 p
->chipset
= chipset
;
250 p
->bus
.type
= BUS_PLATFORM
;
255 xf86AddDevToEntity(num
, dev
);
257 platformSlotClaimed
++;
265 xf86UnclaimPlatformSlot(struct xf86_platform_device
*d
, GDevPtr dev
)
269 for (i
= 0; i
< xf86NumEntities
; i
++) {
270 const EntityPtr p
= xf86Entities
[i
];
272 if ((p
->bus
.type
== BUS_PLATFORM
) && (p
->bus
.id
.plat
== d
)) {
274 xf86RemoveDevFromEntity(i
, dev
);
275 platformSlotClaimed
--;
276 p
->bus
.type
= BUS_NONE
;
284 #define END_OF_MATCHES(m) \
285 (((m).vendor_id == 0) && ((m).device_id == 0) && ((m).subvendor_id == 0))
287 static Bool
doPlatformProbe(struct xf86_platform_device
*dev
, DriverPtr drvp
,
288 GDevPtr gdev
, int flags
, intptr_t match_data
)
290 Bool foundScreen
= FALSE
;
293 if (gdev
->screen
== 0 && !xf86_check_platform_slot(dev
))
296 entity
= xf86ClaimPlatformSlot(dev
, drvp
, 0,
299 if ((entity
== -1) && (gdev
->screen
> 0)) {
302 for (nent
= 0; nent
< xf86NumEntities
; nent
++) {
303 EntityPtr pEnt
= xf86Entities
[nent
];
305 if (pEnt
->bus
.type
!= BUS_PLATFORM
)
307 if (pEnt
->bus
.id
.plat
== dev
) {
309 xf86AddDevToEntity(nent
, gdev
);
315 if (drvp
->platformProbe(drvp
, entity
, flags
, dev
, match_data
))
318 xf86UnclaimPlatformSlot(dev
, gdev
);
324 probeSingleDevice(struct xf86_platform_device
*dev
, DriverPtr drvp
, GDevPtr gdev
, int flags
)
327 Bool foundScreen
= FALSE
;
328 struct pci_device
*pPci
;
329 const struct pci_id_match
*const devices
= drvp
->supported_devices
;
331 if (dev
->pdev
&& devices
) {
332 int device_id
= dev
->pdev
->device_id
;
334 for (k
= 0; !END_OF_MATCHES(devices
[k
]); k
++) {
335 if (PCI_ID_COMPARE(devices
[k
].vendor_id
, pPci
->vendor_id
)
336 && PCI_ID_COMPARE(devices
[k
].device_id
, device_id
)
337 && ((devices
[k
].device_class_mask
& pPci
->device_class
)
338 == devices
[k
].device_class
)) {
339 foundScreen
= doPlatformProbe(dev
, drvp
, gdev
, flags
, devices
[k
].match_data
);
345 else if (dev
->pdev
&& !devices
)
348 foundScreen
= doPlatformProbe(dev
, drvp
, gdev
, flags
, 0);
353 xf86platformProbeDev(DriverPtr drvp
)
355 Bool foundScreen
= FALSE
;
357 const unsigned numDevs
= xf86MatchDevice(drvp
->driverName
, &devList
);
360 /* find the main device or any device specificed in xorg.conf */
361 for (i
= 0; i
< numDevs
; i
++) {
362 for (j
= 0; j
< xf86_num_platform_devices
; j
++) {
363 if (devList
[i
]->busID
&& *devList
[i
]->busID
) {
364 if (xf86PlatformDeviceCheckBusID(&xf86_platform_devices
[j
], devList
[i
]->busID
))
368 /* for non-seat0 servers assume first device is the master */
369 if (ServerIsNotSeat0())
371 if (xf86_platform_devices
[j
].pdev
) {
372 if (xf86IsPrimaryPlatform(&xf86_platform_devices
[j
]))
378 if (j
== xf86_num_platform_devices
)
381 foundScreen
= probeSingleDevice(&xf86_platform_devices
[j
], drvp
, devList
[i
], 0);
386 /* if autoaddgpu devices is enabled then go find a few more and add them as GPU screens */
387 if (xf86Info
.autoAddGPU
&& numDevs
) {
388 for (j
= 0; j
< xf86_num_platform_devices
; j
++) {
389 probeSingleDevice(&xf86_platform_devices
[j
], drvp
, devList
[0], PLATFORM_PROBE_GPU_SCREEN
);
397 xf86platformAddDevice(int index
)
399 int i
, old_screens
, scr_index
;
400 DriverPtr drvp
= NULL
;
402 screenLayoutPtr layout
;
403 static char *hotplug_driver_name
= "modesetting";
405 /* force load the driver for now */
406 xf86LoadOneModule(hotplug_driver_name
, NULL
);
408 for (i
= 0; i
< xf86NumDrivers
; i
++) {
409 if (!xf86DriverList
[i
])
412 if (!strcmp(xf86DriverList
[i
]->driverName
, hotplug_driver_name
)) {
413 drvp
= xf86DriverList
[i
];
417 if (i
== xf86NumDrivers
)
420 old_screens
= xf86NumGPUScreens
;
421 entity
= xf86ClaimPlatformSlot(&xf86_platform_devices
[index
],
423 if (!drvp
->platformProbe(drvp
, entity
, PLATFORM_PROBE_GPU_SCREEN
, &xf86_platform_devices
[index
], 0)) {
424 xf86UnclaimPlatformSlot(&xf86_platform_devices
[index
], NULL
);
426 if (old_screens
== xf86NumGPUScreens
)
430 for (layout
= xf86ConfigLayout
.screens
; layout
->screen
!= NULL
;
432 xf86GPUScreens
[i
]->confScreen
= layout
->screen
;
436 if (xf86GPUScreens
[i
]->PreInit
&&
437 xf86GPUScreens
[i
]->PreInit(xf86GPUScreens
[i
], 0))
438 xf86GPUScreens
[i
]->configured
= TRUE
;
440 if (!xf86GPUScreens
[i
]->configured
) {
441 ErrorF("hotplugged device %d didn't configure\n", i
);
442 xf86DeleteScreen(xf86GPUScreens
[i
]);
446 scr_index
= AddGPUScreen(xf86GPUScreens
[i
]->ScreenInit
, 0, NULL
);
447 if (scr_index
== -1) {
448 xf86DeleteScreen(xf86GPUScreens
[i
]);
449 xf86UnclaimPlatformSlot(&xf86_platform_devices
[index
], NULL
);
450 xf86NumGPUScreens
= old_screens
;
453 dixSetPrivate(&xf86GPUScreens
[i
]->pScreen
->devPrivates
,
454 xf86ScreenKey
, xf86GPUScreens
[i
]);
456 CreateScratchPixmapsForScreen(xf86GPUScreens
[i
]->pScreen
);
458 if (xf86GPUScreens
[i
]->pScreen
->CreateScreenResources
&&
459 !(*xf86GPUScreens
[i
]->pScreen
->CreateScreenResources
) (xf86GPUScreens
[i
]->pScreen
)) {
460 RemoveGPUScreen(xf86GPUScreens
[i
]->pScreen
);
461 xf86DeleteScreen(xf86GPUScreens
[i
]);
462 xf86UnclaimPlatformSlot(&xf86_platform_devices
[index
], NULL
);
463 xf86NumGPUScreens
= old_screens
;
466 /* attach unbound to 0 protocol screen */
467 AttachUnboundGPU(xf86Screens
[0]->pScreen
, xf86GPUScreens
[i
]->pScreen
);
469 RRResourcesChanged(xf86Screens
[0]->pScreen
);
470 RRTellChanged(xf86Screens
[0]->pScreen
);
476 xf86platformRemoveDevice(int index
)
482 for (ent_num
= 0; ent_num
< xf86NumEntities
; ent_num
++) {
483 entity
= xf86Entities
[ent_num
];
484 if (entity
->bus
.type
== BUS_PLATFORM
&&
485 entity
->bus
.id
.plat
== &xf86_platform_devices
[index
])
488 if (ent_num
== xf86NumEntities
)
492 for (i
= 0; i
< xf86NumGPUScreens
; i
++) {
493 for (j
= 0; j
< xf86GPUScreens
[i
]->numEntities
; j
++)
494 if (xf86GPUScreens
[i
]->entityList
[j
] == ent_num
) {
502 ErrorF("failed to find screen to remove\n");
506 xf86GPUScreens
[i
]->pScreen
->CloseScreen(xf86GPUScreens
[i
]->pScreen
);
508 RemoveGPUScreen(xf86GPUScreens
[i
]->pScreen
);
509 xf86DeleteScreen(xf86GPUScreens
[i
]);
511 xf86UnclaimPlatformSlot(&xf86_platform_devices
[index
], NULL
);
513 xf86_remove_platform_device(index
);
515 RRResourcesChanged(xf86Screens
[0]->pScreen
);
516 RRTellChanged(xf86Screens
[0]->pScreen
);
521 /* called on return from VT switch to find any new devices */
522 void xf86platformVTProbe(void)
526 for (i
= 0; i
< xf86_num_platform_devices
; i
++) {
527 if (xf86_platform_devices
[i
].attribs
->unowned
== FALSE
)
530 xf86_platform_devices
[i
].attribs
->unowned
= FALSE
;
531 xf86PlatformReprobeDevice(i
, xf86_platform_devices
[i
].attribs
);