aboutsummaryrefslogtreecommitdiffstats
path: root/libkms
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
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')
-rw-r--r--libkms/Makefile.am7
-rw-r--r--libkms/api.c28
-rw-r--r--libkms/internal.h2
-rw-r--r--libkms/linux.c129
4 files changed, 135 insertions, 31 deletions
diff --git a/libkms/Makefile.am b/libkms/Makefile.am
index 23f78e08..293045c2 100644
--- a/libkms/Makefile.am
+++ b/libkms/Makefile.am
@@ -5,8 +5,11 @@ AM_CFLAGS = \
5libkms_la_LTLIBRARIES = libkms.la 5libkms_la_LTLIBRARIES = libkms.la
6libkms_ladir = $(libdir) 6libkms_ladir = $(libdir)
7libkms_la_LDFLAGS = -version-number 1:0:0 -no-undefined 7libkms_la_LDFLAGS = -version-number 1:0:0 -no-undefined
8libkms_la_LIBADD = \ 8libkms_la_LIBADD =
9 $(LIBUDEV_LIBS) 9
10#if HAVE_LIBUDEV
11#libkms_la_LIBADD += $(LIBUDEV_LIBS)
12#endif
10 13
11libkms_la_SOURCES = \ 14libkms_la_SOURCES = \
12 linux.c \ 15 linux.c \
diff --git a/libkms/api.c b/libkms/api.c
index 12dcd9a1..7696918a 100644
--- a/libkms/api.c
+++ b/libkms/api.c
@@ -32,35 +32,9 @@
32#include <string.h> 32#include <string.h>
33#include "internal.h" 33#include "internal.h"
34 34
35struct create_record
36{
37 unsigned vendor;
38 unsigned chip;
39 int (*func)(int fd, struct kms_driver **out);
40};
41
42static struct create_record table[] = {
43 { 0x8086, 0x2a42, intel_create }, /* i965 */
44#ifdef HAVE_VMWGFX
45 { 0x15ad, 0x0405, vmwgfx_create }, /* VMware vGPU */
46#endif
47 { 0, 0, NULL },
48};
49
50int kms_create(int fd, struct kms_driver **out) 35int kms_create(int fd, struct kms_driver **out)
51{ 36{
52 unsigned vendor_id, chip_id; 37 return linux_create(fd, out);
53 int ret, i;
54
55 ret = linux_get_pciid_from_fd(fd, &vendor_id, &chip_id);
56 if (ret)
57 return ret;
58
59 for (i = 0; table[i].func; i++)
60 if (table[i].vendor == vendor_id && table[i].chip == chip_id)
61 return table[i].func(fd, out);
62
63 return -ENOSYS;
64} 38}
65 39
66int kms_get_prop(struct kms_driver *kms, unsigned key, unsigned *out) 40int kms_get_prop(struct kms_driver *kms, unsigned key, unsigned *out)
diff --git a/libkms/internal.h b/libkms/internal.h
index a441266b..9d1c5f7c 100644
--- a/libkms/internal.h
+++ b/libkms/internal.h
@@ -62,7 +62,7 @@ struct kms_bo
62 unsigned handle; 62 unsigned handle;
63}; 63};
64 64
65int linux_get_pciid_from_fd(int fd, unsigned *vendor_id, unsigned *chip_id); 65int linux_create(int fd, struct kms_driver **out);
66 66
67int vmwgfx_create(int fd, struct kms_driver **out); 67int vmwgfx_create(int fd, struct kms_driver **out);
68 68
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}