diff options
author | Jakob Bornecrantz | 2010-01-07 20:51:04 -0600 |
---|---|---|
committer | Jakob Bornecrantz | 2010-01-07 21:05:00 -0600 |
commit | 9042d72109d8ae448b8e0f23b93067cc37deff23 (patch) | |
tree | 3b23755f0161f3c40531ffee33bfe84afc9bcef8 | |
parent | 04f90a44709a48fb932ea954011cb551659bf246 (diff) | |
download | external-libdrm-9042d72109d8ae448b8e0f23b93067cc37deff23.tar.gz external-libdrm-9042d72109d8ae448b8e0f23b93067cc37deff23.tar.xz external-libdrm-9042d72109d8ae448b8e0f23b93067cc37deff23.zip |
libkms: Pick driver backend via pci id that we get from udev
-rw-r--r-- | libkms/Makefile.am | 4 | ||||
-rw-r--r-- | libkms/api.c | 29 | ||||
-rw-r--r-- | libkms/internal.h | 2 | ||||
-rw-r--r-- | libkms/linux.c | 88 |
4 files changed, 118 insertions, 5 deletions
diff --git a/libkms/Makefile.am b/libkms/Makefile.am index 62d154b8..1ecad774 100644 --- a/libkms/Makefile.am +++ b/libkms/Makefile.am | |||
@@ -5,9 +5,11 @@ AM_CFLAGS = \ | |||
5 | libkms_la_LTLIBRARIES = libkms.la | 5 | libkms_la_LTLIBRARIES = libkms.la |
6 | libkms_ladir = $(libdir) | 6 | libkms_ladir = $(libdir) |
7 | libkms_la_LDFLAGS = -version-number 1:0:0 -no-undefined | 7 | libkms_la_LDFLAGS = -version-number 1:0:0 -no-undefined |
8 | libkms_la_LIBADD = | 8 | libkms_la_LIBADD = \ |
9 | $(LIBUDEV_LIBS) | ||
9 | 10 | ||
10 | libkms_la_SOURCES = \ | 11 | libkms_la_SOURCES = \ |
12 | linux.c \ | ||
11 | api.c | 13 | api.c |
12 | 14 | ||
13 | if HAVE_VMWGFX | 15 | if HAVE_VMWGFX |
diff --git a/libkms/api.c b/libkms/api.c index 478fa38c..6cec4b96 100644 --- a/libkms/api.c +++ b/libkms/api.c | |||
@@ -32,13 +32,34 @@ | |||
32 | #include <string.h> | 32 | #include <string.h> |
33 | #include "internal.h" | 33 | #include "internal.h" |
34 | 34 | ||
35 | int kms_create(int fd, struct kms_driver **out) | 35 | struct create_record |
36 | { | 36 | { |
37 | unsigned vendor; | ||
38 | unsigned chip; | ||
39 | int (*func)(int fd, struct kms_driver **out); | ||
40 | }; | ||
41 | |||
42 | static struct create_record table[] = { | ||
37 | #ifdef HAVE_VMWGFX | 43 | #ifdef HAVE_VMWGFX |
38 | return vmwgfx_create(fd, out); | 44 | { 0x15ad, 0x0405, vmwgfx_create }, /* VMware vGPU */ |
39 | #else | ||
40 | return -ENOSYS; | ||
41 | #endif | 45 | #endif |
46 | { 0, 0, NULL }, | ||
47 | }; | ||
48 | |||
49 | int kms_create(int fd, struct kms_driver **out) | ||
50 | { | ||
51 | unsigned vendor_id, chip_id; | ||
52 | int ret, i; | ||
53 | |||
54 | ret = linux_get_pciid_from_fd(fd, &vendor_id, &chip_id); | ||
55 | if (ret) | ||
56 | return ret; | ||
57 | |||
58 | for (i = 0; table[i].func; i++) | ||
59 | if (table[i].vendor == vendor_id && table[i].chip == chip_id) | ||
60 | return table[i].func(fd, out); | ||
61 | |||
62 | return -ENOSYS; | ||
42 | } | 63 | } |
43 | 64 | ||
44 | int kms_get_prop(struct kms_driver *kms, unsigned key, unsigned *out) | 65 | int kms_get_prop(struct kms_driver *kms, unsigned key, unsigned *out) |
diff --git a/libkms/internal.h b/libkms/internal.h index f1a2b1cf..cdc27053 100644 --- a/libkms/internal.h +++ b/libkms/internal.h | |||
@@ -62,6 +62,8 @@ struct kms_bo | |||
62 | unsigned handle; | 62 | unsigned handle; |
63 | }; | 63 | }; |
64 | 64 | ||
65 | int linux_get_pciid_from_fd(int fd, unsigned *vendor_id, unsigned *chip_id); | ||
66 | |||
65 | int vmwgfx_create(int fd, struct kms_driver **out); | 67 | int vmwgfx_create(int fd, struct kms_driver **out); |
66 | 68 | ||
67 | #endif | 69 | #endif |
diff --git a/libkms/linux.c b/libkms/linux.c new file mode 100644 index 00000000..2b08b854 --- /dev/null +++ b/libkms/linux.c | |||
@@ -0,0 +1,88 @@ | |||
1 | /************************************************************************** | ||
2 | * | ||
3 | * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA | ||
4 | * All Rights Reserved. | ||
5 | * | ||
6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
7 | * copy of this software and associated documentation files (the | ||
8 | * "Software"), to deal in the Software without restriction, including | ||
9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
11 | * permit persons to whom the Software is furnished to do so, subject to | ||
12 | * the following conditions: | ||
13 | * | ||
14 | * The above copyright notice and this permission notice (including the | ||
15 | * next paragraph) shall be included in all copies or substantial portions | ||
16 | * of the Software. | ||
17 | * | ||
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
25 | * | ||
26 | **************************************************************************/ | ||
27 | /* | ||
28 | * Thanks to krh and jcristau for the tips on | ||
29 | * going from fd to pci id via fstat and udev. | ||
30 | */ | ||
31 | |||
32 | |||
33 | #include <errno.h> | ||
34 | #include <stdio.h> | ||
35 | #include <xf86drm.h> | ||
36 | #include <sys/stat.h> | ||
37 | |||
38 | #include "internal.h" | ||
39 | |||
40 | #define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE | ||
41 | #include <libudev.h> | ||
42 | |||
43 | int linux_get_pciid_from_fd(int fd, unsigned *vendor_id, unsigned *chip_id) | ||
44 | { | ||
45 | struct udev *udev; | ||
46 | struct udev_device *device; | ||
47 | struct udev_device *parent; | ||
48 | const char *pci_id; | ||
49 | struct stat buffer; | ||
50 | int ret; | ||
51 | |||
52 | ret = fstat(fd, &buffer); | ||
53 | if (ret) | ||
54 | return -EINVAL; | ||
55 | |||
56 | if (!S_ISCHR(buffer.st_mode)) | ||
57 | return -EINVAL; | ||
58 | |||
59 | udev = udev_new(); | ||
60 | if (!udev) | ||
61 | return -ENOMEM; | ||
62 | |||
63 | device = udev_device_new_from_devnum(udev, 'c', buffer.st_rdev); | ||
64 | if (!device) | ||
65 | goto err_free_udev; | ||
66 | |||
67 | parent = udev_device_get_parent(device); | ||
68 | if (!parent) | ||
69 | goto err_free_device; | ||
70 | |||
71 | pci_id = udev_device_get_property_value(parent, "PCI_ID"); | ||
72 | if (!pci_id) | ||
73 | goto err_free_device; | ||
74 | |||
75 | if (sscanf(pci_id, "%x:%x", vendor_id, chip_id) != 2) | ||
76 | goto err_free_device; | ||
77 | |||
78 | udev_device_unref(device); | ||
79 | udev_unref(udev); | ||
80 | |||
81 | return 0; | ||
82 | |||
83 | err_free_device: | ||
84 | udev_device_unref(device); | ||
85 | err_free_udev: | ||
86 | udev_unref(udev); | ||
87 | return -EINVAL; | ||
88 | } | ||