Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / os-support / linux / lnx_platform.c
CommitLineData
a09e091a
JB
1#ifdef HAVE_XORG_CONFIG_H
2#include <xorg-config.h>
3#endif
4
5#ifdef XSERVER_PLATFORM_BUS
6
7#include <xf86drm.h>
8#include <fcntl.h>
9#include <unistd.h>
10#include <errno.h>
11#include <string.h>
12
13/* Linux platform device support */
14#include "xf86_OSproc.h"
15
16#include "xf86.h"
17#include "xf86platformBus.h"
18#include "xf86Bus.h"
19
20#include "hotplug.h"
21
22static Bool
23get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
24{
25 drmSetVersion sv;
26 char *buf;
27 int fd;
28 int err = 0;
29
30 fd = open(path, O_RDWR, O_CLOEXEC);
31 if (fd == -1)
32 return FALSE;
33
34 sv.drm_di_major = 1;
35 sv.drm_di_minor = 4;
36 sv.drm_dd_major = -1; /* Don't care */
37 sv.drm_dd_minor = -1; /* Don't care */
38
39 err = drmSetInterfaceVersion(fd, &sv);
40 if (err) {
41 ErrorF("setversion 1.4 failed: %s\n", strerror(-err));
42 goto out;
43 }
44
45 /* for a delayed probe we've already added the device */
46 if (delayed_index == -1) {
47 xf86_add_platform_device(attribs);
48 delayed_index = xf86_num_platform_devices - 1;
49 }
50
51 buf = drmGetBusid(fd);
52 xf86_add_platform_device_attrib(delayed_index,
53 ODEV_ATTRIB_BUSID, buf);
54 drmFreeBusid(buf);
55out:
56 close(fd);
57 return (err == 0);
58}
59
60Bool
61xf86PlatformDeviceCheckBusID(struct xf86_platform_device *device, const char *busid)
62{
63 struct OdevAttribute *attrib;
64 const char *syspath = NULL;
65 BusType bustype;
66 const char *id;
67 xorg_list_for_each_entry(attrib, &device->attribs->list, member) {
68 if (attrib->attrib_id == ODEV_ATTRIB_SYSPATH) {
69 syspath = attrib->attrib_name;
70 break;
71 }
72 }
73
74 if (!syspath)
75 return FALSE;
76
77 bustype = StringToBusType(busid, &id);
78 if (bustype == BUS_PCI) {
79 struct pci_device *pPci = device->pdev;
80 if (xf86ComparePciBusString(busid,
81 ((pPci->domain << 8)
82 | pPci->bus),
83 pPci->dev, pPci->func)) {
84 return TRUE;
85 }
86 }
87 else if (bustype == BUS_PLATFORM) {
88 /* match on the minimum string */
89 int len = strlen(id);
90
91 if (strlen(syspath) < strlen(id))
92 len = strlen(syspath);
93
94 if (strncmp(id, syspath, len))
95 return FALSE;
96 return TRUE;
97 }
98 return FALSE;
99}
100
101void
102xf86PlatformReprobeDevice(int index, struct OdevAttributes *attribs)
103{
104 Bool ret;
105 char *dpath;
106 dpath = xf86_get_platform_attrib(index, ODEV_ATTRIB_PATH);
107
108 ret = get_drm_info(attribs, dpath, index);
109 if (ret == FALSE) {
110 xf86_remove_platform_device(index);
111 return;
112 }
113 ret = xf86platformAddDevice(index);
114 if (ret == -1)
115 xf86_remove_platform_device(index);
116}
117
118void
119xf86PlatformDeviceProbe(struct OdevAttributes *attribs)
120{
121 struct OdevAttribute *attrib;
122 int i;
123 char *path = NULL;
124 Bool ret;
125
126 xorg_list_for_each_entry(attrib, &attribs->list, member) {
127 if (attrib->attrib_id == ODEV_ATTRIB_PATH) {
128 path = attrib->attrib_name;
129 break;
130 }
131 }
132 if (!path)
133 goto out_free;
134
135 for (i = 0; i < xf86_num_platform_devices; i++) {
136 char *dpath;
137 dpath = xf86_get_platform_attrib(i, ODEV_ATTRIB_PATH);
138
139 if (!strcmp(path, dpath))
140 break;
141 }
142
143 if (i != xf86_num_platform_devices)
144 goto out_free;
145
146 LogMessage(X_INFO, "xfree86: Adding drm device (%s)\n", path);
147
148 if (!xf86VTOwner()) {
149 /* if we don't currently own the VT then don't probe the device,
150 just mark it as unowned for later use */
151 attribs->unowned = TRUE;
152 xf86_add_platform_device(attribs);
153 return;
154 }
155
156 ret = get_drm_info(attribs, path, -1);
157 if (ret == FALSE)
158 goto out_free;
159
160 return;
161
162out_free:
163 config_odev_free_attribute_list(attribs);
164}
165
166void NewGPUDeviceRequest(struct OdevAttributes *attribs)
167{
168 int old_num = xf86_num_platform_devices;
169 int ret;
170 xf86PlatformDeviceProbe(attribs);
171
172 if (old_num == xf86_num_platform_devices)
173 return;
174
175 if (xf86_get_platform_device_unowned(xf86_num_platform_devices - 1) == TRUE)
176 return;
177
178 ret = xf86platformAddDevice(xf86_num_platform_devices-1);
179 if (ret == -1)
180 xf86_remove_platform_device(xf86_num_platform_devices-1);
181
182 ErrorF("xf86: found device %d\n", xf86_num_platform_devices);
183 return;
184}
185
186void DeleteGPUDeviceRequest(struct OdevAttributes *attribs)
187{
188 struct OdevAttribute *attrib;
189 int index;
190 char *syspath = NULL;
191
192 xorg_list_for_each_entry(attrib, &attribs->list, member) {
193 if (attrib->attrib_id == ODEV_ATTRIB_SYSPATH) {
194 syspath = attrib->attrib_name;
195 break;
196 }
197 }
198
199 for (index = 0; index < xf86_num_platform_devices; index++) {
200 char *dspath;
201 dspath = xf86_get_platform_attrib(index, ODEV_ATTRIB_SYSPATH);
202 if (!strcmp(syspath, dspath))
203 break;
204 }
205
206 if (index == xf86_num_platform_devices)
207 goto out;
208
209 ErrorF("xf86: remove device %d %s\n", index, syspath);
210
211 if (xf86_get_platform_device_unowned(index) == TRUE)
212 xf86_remove_platform_device(index);
213 else
214 xf86platformRemoveDevice(index);
215out:
216 config_odev_free_attribute_list(attribs);
217}
218
219#endif