aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakob Bornecrantz2010-01-12 11:53:49 -0600
committerJakob Bornecrantz2010-01-12 15:10:12 -0600
commitd920fa9d0b54873d53f03a006d0fe3df11136b74 (patch)
tree43178c3fb49a55920ebbfb66ae111d5e1b735491 /libkms/linux.c
parentd207a38701d664ac818829249d4d2566349bb359 (diff)
downloadexternal-libdrm-d920fa9d0b54873d53f03a006d0fe3df11136b74.tar.gz
external-libdrm-d920fa9d0b54873d53f03a006d0fe3df11136b74.tar.xz
external-libdrm-d920fa9d0b54873d53f03a006d0fe3df11136b74.zip
libkms: Use sysfs instead of udev to find driver
Udev code is still there just commented out.
Diffstat (limited to 'libkms/linux.c')
-rw-r--r--libkms/linux.c129
1 files changed, 128 insertions, 1 deletions
diff --git a/libkms/linux.c b/libkms/linux.c
index 2b08b854..94e1b526 100644
--- a/libkms/linux.c
+++ b/libkms/linux.c
@@ -30,17 +30,111 @@
30 */ 30 */
31 31
32 32
33#include "config.h"
33#include <errno.h> 34#include <errno.h>
34#include <stdio.h> 35#include <stdio.h>
36#include <stdlib.h>
35#include <xf86drm.h> 37#include <xf86drm.h>
38#include <string.h>
39#include <unistd.h>
40
36#include <sys/stat.h> 41#include <sys/stat.h>
37 42
38#include "internal.h" 43#include "internal.h"
39 44
45#define PATH_SIZE 512
46
47static int
48linux_name_from_sysfs(int fd, char **out)
49{
50 char path[PATH_SIZE+1] = ""; /* initialize to please valgrind */
51 char link[PATH_SIZE+1] = "";
52 struct stat buffer;
53 unsigned maj, min;
54 char* slash_name;
55 int ret;
56
57 /*
58 * Inside the sysfs directory for the device there is a symlink
59 * to the directory representing the driver module, that path
60 * happens to hold the name of the driver.
61 *
62 * So lets get the symlink for the drm device. Then read the link
63 * and filter out the last directory which happens to be the name
64 * of the driver, which we can use to load the correct interface.
65 *
66 * Thanks to Ray Strode of Plymouth for the code.
67 */
68
69 ret = fstat(fd, &buffer);
70 if (ret)
71 return ret;
72
73 if (!S_ISCHR(buffer.st_mode))
74 return -EINVAL;
75
76 maj = major(buffer.st_rdev);
77 min = minor(buffer.st_rdev);
78
79 snprintf(path, PATH_SIZE, "/sys/dev/char/%d:%d/device/driver", maj, min);
80
81 if (readlink(path, link, PATH_SIZE) < 0)
82 return -EINVAL;
83
84 /* link looks something like this: ../../../bus/pci/drivers/intel */
85 slash_name = strrchr(link, '/');
86 if (!slash_name)
87 return -EINVAL;
88
89 /* copy name and at the same time remove the slash */
90 *out = strdup(slash_name + 1);
91 return 0;
92}
93
94static int
95linux_from_sysfs(int fd, struct kms_driver **out)
96{
97 char *name;
98 int ret;
99
100 ret = linux_name_from_sysfs(fd, &name);
101 if (ret)
102 return ret;
103
104 if (!strcmp(name, "intel"))
105 ret = intel_create(fd, out);
106#ifdef HAVE_VMWGFX
107 else if (!strcmp(name, "vmwgfx"))
108 ret = vmwgfx_create(fd, out);
109#endif
110 else
111 ret = -ENOSYS;
112
113 free(name);
114 return ret;
115}
116
117#if 0
40#define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE 118#define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE
41#include <libudev.h> 119#include <libudev.h>
42 120
43int linux_get_pciid_from_fd(int fd, unsigned *vendor_id, unsigned *chip_id) 121struct create_record
122{
123 unsigned vendor;
124 unsigned chip;
125 int (*func)(int fd, struct kms_driver **out);
126};
127
128static struct create_record table[] = {
129 { 0x8086, 0x2a42, intel_create }, /* i965 */
130#ifdef HAVE_VMWGFX
131 { 0x15ad, 0x0405, vmwgfx_create }, /* VMware vGPU */
132#endif
133 { 0, 0, NULL },
134};
135
136static int
137linux_get_pciid_from_fd(int fd, unsigned *vendor_id, unsigned *chip_id)
44{ 138{
45 struct udev *udev; 139 struct udev *udev;
46 struct udev_device *device; 140 struct udev_device *device;
@@ -86,3 +180,36 @@ err_free_udev:
86 udev_unref(udev); 180 udev_unref(udev);
87 return -EINVAL; 181 return -EINVAL;
88} 182}
183
184static int
185linux_from_udev(int fd, struct kms_driver **out)
186{
187 unsigned vendor_id, chip_id;
188 int ret, i;
189
190 ret = linux_get_pciid_from_fd(fd, &vendor_id, &chip_id);
191 if (ret)
192 return ret;
193
194 for (i = 0; table[i].func; i++)
195 if (table[i].vendor == vendor_id && table[i].chip == chip_id)
196 return table[i].func(fd, out);
197
198 return -ENOSYS;
199}
200#else
201static int
202linux_from_udev(int fd, struct kms_driver **out)
203{
204 return -ENOSYS;
205}
206#endif
207
208int
209linux_create(int fd, struct kms_driver **out)
210{
211 if (!linux_from_udev(fd, out))
212 return 0;
213
214 return linux_from_sysfs(fd, out);
215}