| @@ -1,584 +1,588 @@ | | | @@ -1,584 +1,588 @@ |
1 | /* $NetBSD: drm_drv.c,v 1.1.2.8 2013/07/24 03:22:26 riastradh Exp $ */ | | 1 | /* $NetBSD: drm_drv.c,v 1.1.2.9 2013/07/24 03:22:42 riastradh Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2013 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2013 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Taylor R. Campbell. | | 8 | * by Taylor R. Campbell. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | __KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.1.2.8 2013/07/24 03:22:26 riastradh Exp $"); | | 33 | __KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.1.2.9 2013/07/24 03:22:42 riastradh Exp $"); |
34 | | | 34 | |
35 | #include <sys/param.h> | | 35 | #include <sys/param.h> |
36 | #include <sys/types.h> | | 36 | #include <sys/types.h> |
37 | #include <sys/conf.h> | | 37 | #include <sys/conf.h> |
38 | #include <sys/device.h> | | 38 | #include <sys/device.h> |
39 | #include <sys/file.h> | | 39 | #include <sys/file.h> |
40 | #include <sys/filedesc.h> | | 40 | #include <sys/filedesc.h> |
41 | #include <sys/ioccom.h> | | 41 | #include <sys/ioccom.h> |
42 | #include <sys/kauth.h> | | 42 | #include <sys/kauth.h> |
43 | #if 0 /* XXX drm event poll */ | | 43 | #if 0 /* XXX drm event poll */ |
44 | #include <sys/poll.h> | | 44 | #include <sys/poll.h> |
45 | #include <sys/select.h> | | 45 | #include <sys/select.h> |
46 | #endif | | 46 | #endif |
47 | | | 47 | |
48 | #include <drm/drmP.h> | | 48 | #include <drm/drmP.h> |
49 | | | 49 | |
50 | static int drm_minor_types[] = { | | 50 | static int drm_minor_types[] = { |
51 | DRM_MINOR_LEGACY, | | 51 | DRM_MINOR_LEGACY, |
52 | DRM_MINOR_CONTROL, | | 52 | DRM_MINOR_CONTROL, |
53 | #if 0 /* XXX Nothing seems to use this? */ | | 53 | #if 0 /* XXX Nothing seems to use this? */ |
54 | DRM_MINOR_RENDER, | | 54 | DRM_MINOR_RENDER, |
55 | #endif | | 55 | #endif |
56 | }; | | 56 | }; |
57 | | | 57 | |
58 | struct drm_softc { | | 58 | struct drm_softc { |
59 | struct drm_device *sc_drm_dev; | | 59 | struct drm_device *sc_drm_dev; |
60 | struct drm_minor sc_minor[__arraycount(drm_minor_types)]; | | 60 | struct drm_minor sc_minor[__arraycount(drm_minor_types)]; |
61 | }; | | 61 | }; |
62 | | | 62 | |
63 | static int drm_match(device_t, cfdata_t, void *); | | 63 | static int drm_match(device_t, cfdata_t, void *); |
64 | static void drm_attach(device_t, device_t, void *); | | 64 | static void drm_attach(device_t, device_t, void *); |
65 | #if 0 /* XXX drm detach */ | | 65 | #if 0 /* XXX drm detach */ |
66 | static int drm_detach(device_t, int); | | 66 | static int drm_detach(device_t, int); |
67 | #endif | | 67 | #endif |
68 | | | 68 | |
69 | static struct drm_softc *drm_dev_softc(dev_t); | | 69 | static struct drm_softc *drm_dev_softc(dev_t); |
70 | static struct drm_minor *drm_dev_minor(dev_t); | | 70 | static struct drm_minor *drm_dev_minor(dev_t); |
71 | | | 71 | |
72 | static dev_type_open(drm_open); | | 72 | static dev_type_open(drm_open); |
73 | | | 73 | |
74 | static int drm_close(struct file *); | | 74 | static int drm_close(struct file *); |
75 | static int drm_read(struct file *, off_t *, struct uio *, kauth_cred_t, | | 75 | static int drm_read(struct file *, off_t *, struct uio *, kauth_cred_t, |
76 | int); | | 76 | int); |
77 | static int drm_poll(struct file *, int); | | 77 | static int drm_poll(struct file *, int); |
78 | static int drm_stat(struct file *, struct stat *); | | 78 | static int drm_stat(struct file *, struct stat *); |
79 | static int drm_ioctl(struct file *, unsigned long, void *); | | 79 | static int drm_ioctl(struct file *, unsigned long, void *); |
80 | static int drm_version_string(char *, size_t *, const char *); | | 80 | static int drm_version_string(char *, size_t *, const char *); |
81 | | | 81 | |
82 | static drm_ioctl_t drm_version; | | 82 | static drm_ioctl_t drm_version; |
83 | | | 83 | |
84 | /* XXX Can this be pushed into struct drm_device? */ | | 84 | /* XXX Can this be pushed into struct drm_device? */ |
85 | struct mutex drm_global_mutex; | | 85 | struct mutex drm_global_mutex; |
86 | | | 86 | |
87 | #define DRM_IOCTL_DEF(IOCTL, FUNC, FLAGS) \ | | 87 | #define DRM_IOCTL_DEF(IOCTL, FUNC, FLAGS) \ |
88 | [DRM_IOCTL_NR(IOCTL)] = { \ | | 88 | [DRM_IOCTL_NR(IOCTL)] = { \ |
89 | .cmd = (IOCTL), \ | | 89 | .cmd = (IOCTL), \ |
90 | .flags = (FLAGS), \ | | 90 | .flags = (FLAGS), \ |
91 | .func = (FUNC), \ | | 91 | .func = (FUNC), \ |
92 | .cmd_drv = 0, \ | | 92 | .cmd_drv = 0, \ |
93 | } | | 93 | } |
94 | | | 94 | |
95 | /* Table copied verbatim from dist/drm/drm_drv.c. */ | | 95 | /* Table copied verbatim from dist/drm/drm_drv.c. */ |
96 | static const struct drm_ioctl_desc drm_ioctls[] = { | | 96 | static const struct drm_ioctl_desc drm_ioctls[] = { |
97 | DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED), | | 97 | DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED), |
98 | DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0), | | 98 | DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0), |
99 | DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0), | | 99 | DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0), |
100 | DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY), | | 100 | DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY), |
101 | DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED), | | 101 | DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED), |
102 | DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED), | | 102 | DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED), |
103 | DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED), | | 103 | DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED), |
104 | DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED), | | 104 | DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED), |
105 | DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER), | | 105 | DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER), |
106 | | | 106 | |
107 | DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 107 | DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
108 | DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 108 | DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
109 | DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 109 | DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
110 | DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER), | | 110 | DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER), |
111 | | | 111 | |
112 | DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 112 | DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
113 | DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH), | | 113 | DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH), |
114 | | | 114 | |
115 | DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 115 | DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
116 | DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH), | | 116 | DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH), |
117 | | | 117 | |
118 | DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY), | | 118 | DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY), |
119 | DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY), | | 119 | DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY), |
120 | | | 120 | |
121 | DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY), | | 121 | DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY), |
122 | DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 122 | DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
123 | DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 123 | DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
124 | DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH), | | 124 | DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH), |
125 | DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 125 | DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
126 | DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 126 | DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
127 | DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH), | | 127 | DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH), |
128 | | | 128 | |
129 | DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 129 | DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
130 | DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 130 | DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
131 | | | 131 | |
132 | DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH), | | 132 | DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH), |
133 | DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH), | | 133 | DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH), |
134 | | | 134 | |
135 | DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH), | | 135 | DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH), |
136 | | | 136 | |
137 | DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 137 | DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
138 | DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 138 | DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
139 | DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH), | | 139 | DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH), |
140 | DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH), | | 140 | DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH), |
141 | DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH), | | 141 | DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH), |
142 | /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */ | | 142 | /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */ |
143 | DRM_IOCTL_DEF(DRM_IOCTL_DMA, NULL, DRM_AUTH), | | 143 | DRM_IOCTL_DEF(DRM_IOCTL_DMA, NULL, DRM_AUTH), |
144 | | | 144 | |
145 | DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 145 | DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
146 | | | 146 | |
147 | #if __OS_HAS_AGP | | 147 | #if __OS_HAS_AGP |
148 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 148 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
149 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 149 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
150 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 150 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
151 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH), | | 151 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH), |
152 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 152 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
153 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 153 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
154 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 154 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
155 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 155 | DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
156 | #endif | | 156 | #endif |
157 | | | 157 | |
158 | DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 158 | DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
159 | DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 159 | DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
160 | | | 160 | |
161 | DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED), | | 161 | DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED), |
162 | | | 162 | |
163 | DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0), | | 163 | DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0), |
164 | | | 164 | |
165 | DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | | 165 | DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
166 | | | 166 | |
167 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED), | | 167 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED), |
168 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED), | | 168 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED), |
169 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED), | | 169 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED), |
170 | | | 170 | |
171 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 171 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
172 | | | 172 | |
173 | #ifndef __NetBSD__ /* XXX drm prime */ | | 173 | #ifndef __NetBSD__ /* XXX drm prime */ |
174 | DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED), | | 174 | DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED), |
175 | DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED), | | 175 | DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED), |
176 | #endif | | 176 | #endif |
177 | | | 177 | |
178 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 178 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
179 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 179 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
180 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 180 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
181 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 181 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
182 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 182 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
183 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 183 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
184 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED), | | 184 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED), |
185 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED), | | 185 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED), |
186 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 186 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
187 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 187 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
188 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 188 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
189 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 189 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
190 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 190 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
191 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 191 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
192 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 192 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
193 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 193 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
194 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 194 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
195 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 195 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
196 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 196 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
197 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 197 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
198 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 198 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
199 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 199 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
200 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 200 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
201 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 201 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
202 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 202 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
203 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | | 203 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
204 | }; | | 204 | }; |
205 | | | 205 | |
206 | const struct cdevsw drm_cdevsw = { | | 206 | const struct cdevsw drm_cdevsw = { |
207 | .d_open = drm_open, | | 207 | .d_open = drm_open, |
208 | .d_close = noclose, | | 208 | .d_close = noclose, |
209 | .d_read = noread, | | 209 | .d_read = noread, |
210 | .d_write = nowrite, | | 210 | .d_write = nowrite, |
211 | .d_ioctl = noioctl, | | 211 | .d_ioctl = noioctl, |
212 | .d_stop = nostop, | | 212 | .d_stop = nostop, |
213 | .d_tty = notty, | | 213 | .d_tty = notty, |
214 | .d_poll = nopoll, | | 214 | .d_poll = nopoll, |
215 | .d_mmap = nommap, | | 215 | .d_mmap = nommap, |
216 | .d_kqfilter = nokqfilter, | | 216 | .d_kqfilter = nokqfilter, |
217 | /* XXX was D_TTY | D_NEGOFFSAFE */ | | 217 | /* XXX was D_TTY | D_NEGOFFSAFE */ |
218 | /* XXX Add D_MPSAFE some day... */ | | 218 | /* XXX Add D_MPSAFE some day... */ |
219 | .d_flag = D_NEGOFFSAFE, | | 219 | .d_flag = D_NEGOFFSAFE, |
220 | }; | | 220 | }; |
221 | | | 221 | |
222 | /* XXX Does this get declared automatically by config? */ | | 222 | /* XXX Does this get declared automatically by config? */ |
223 | extern struct cfdriver drm_cd; | | 223 | extern struct cfdriver drm_cd; |
224 | | | 224 | |
225 | static const struct fileops drm_fileops = { | | 225 | static const struct fileops drm_fileops = { |
226 | .fo_read = drm_read, | | 226 | .fo_read = drm_read, |
227 | .fo_write = fbadop_write, | | 227 | .fo_write = fbadop_write, |
228 | .fo_ioctl = drm_ioctl, | | 228 | .fo_ioctl = drm_ioctl, |
229 | .fo_fcntl = fnullop_fcntl, | | 229 | .fo_fcntl = fnullop_fcntl, |
230 | .fo_poll = drm_poll, | | 230 | .fo_poll = drm_poll, |
231 | .fo_stat = drm_stat, | | 231 | .fo_stat = drm_stat, |
232 | .fo_close = drm_close, | | 232 | .fo_close = drm_close, |
233 | .fo_kqfilter = fnullop_kqfilter, | | 233 | .fo_kqfilter = fnullop_kqfilter, |
234 | .fo_restart = fnullop_restart, | | 234 | .fo_restart = fnullop_restart, |
235 | }; | | 235 | }; |
236 | | | 236 | |
237 | CFATTACH_DECL_NEW(drm, sizeof(struct drm_minor), | | 237 | CFATTACH_DECL_NEW(drm, sizeof(struct drm_minor), |
238 | drm_match, drm_attach, NULL /* XXX drm_detach */, NULL); | | 238 | drm_match, drm_attach, NULL /* XXX drm_detach */, NULL); |
239 | | | 239 | |
240 | static int | | 240 | static int |
241 | drm_match(device_t parent __unused, cfdata_t match __unused, | | 241 | drm_match(device_t parent __unused, cfdata_t match __unused, |
242 | void *aux __unused) | | 242 | void *aux __unused) |
243 | { | | 243 | { |
244 | | | 244 | |
245 | return 1; | | 245 | return 1; |
246 | } | | 246 | } |
247 | | | 247 | |
248 | static void | | 248 | static void |
249 | drm_attach(device_t parent, device_t self, void *aux) | | 249 | drm_attach(device_t parent, device_t self, void *aux) |
250 | { | | 250 | { |
251 | struct drm_softc *sc = device_private(self); | | 251 | struct drm_softc *sc = device_private(self); |
252 | struct drm_device *dev = aux; | | 252 | struct drm_device *dev = aux; |
253 | unsigned int i; | | 253 | unsigned int i; |
254 | | | 254 | |
255 | KASSERT(sc != NULL); | | 255 | KASSERT(sc != NULL); |
256 | KASSERT(dev != NULL); | | 256 | KASSERT(dev != NULL); |
257 | KASSERT(dev->driver != NULL); | | 257 | KASSERT(dev->driver != NULL); |
258 | KASSERT(device_unit(self) >= 0); | | 258 | KASSERT(device_unit(self) >= 0); |
259 | | | 259 | |
260 | if (device_unit(self) >= 64) /* XXX Need to do something here! */ | | 260 | if (device_unit(self) >= 64) /* XXX Need to do something here! */ |
261 | return; | | 261 | return; |
262 | | | 262 | |
263 | for (i = 0; i < __arraycount(drm_minor_types); i++) { | | 263 | for (i = 0; i < __arraycount(drm_minor_types); i++) { |
264 | sc->sc_minor[i].index = (i * 64) + device_unit(self); | | 264 | sc->sc_minor[i].index = (i * 64) + device_unit(self); |
265 | sc->sc_minor[i].type = drm_minor_types[i]; | | 265 | sc->sc_minor[i].type = drm_minor_types[i]; |
266 | sc->sc_minor[i].device = | | 266 | sc->sc_minor[i].device = |
267 | makedev(cdevsw_lookup_major(&drm_cdevsw), | | 267 | makedev(cdevsw_lookup_major(&drm_cdevsw), |
268 | sc->sc_minor[i].index); | | 268 | sc->sc_minor[i].index); |
269 | sc->sc_minor[i].kdev = self; | | 269 | sc->sc_minor[i].kdev = self; |
270 | sc->sc_minor[i].dev = dev; | | 270 | sc->sc_minor[i].dev = dev; |
271 | sc->sc_minor[i].master = NULL; | | 271 | sc->sc_minor[i].master = NULL; |
272 | INIT_LIST_HEAD(&sc->sc_minor[i].master_list); | | 272 | INIT_LIST_HEAD(&sc->sc_minor[i].master_list); |
273 | (void)memset(&sc->sc_minor[i].mode_group, 0, | | 273 | (void)memset(&sc->sc_minor[i].mode_group, 0, |
274 | sizeof(sc->sc_minor[i].mode_group)); | | 274 | sizeof(sc->sc_minor[i].mode_group)); |
275 | } | | 275 | } |
276 | | | 276 | |
277 | #if 0 /* XXX drm wsdisplay */ | | 277 | #if 0 /* XXX drm wsdisplay */ |
278 | attach wsdisplay; | | 278 | attach wsdisplay; |
279 | #endif | | 279 | #endif |
280 | } | | 280 | } |
281 | | | 281 | |
282 | #if 0 /* XXX drm detach */ | | 282 | #if 0 /* XXX drm detach */ |
283 | static int | | 283 | static int |
284 | drm_detach(device_t self, int flags) | | 284 | drm_detach(device_t self, int flags) |
285 | { | | 285 | { |
286 | struct drm_softc *const sc = device_private(self); | | 286 | struct drm_softc *const sc = device_private(self); |
287 | KASSERT(sc != NULL); | | 287 | KASSERT(sc != NULL); |
288 | struct drm_device *const dev = sc->sc_minor.dev; | | 288 | struct drm_device *const dev = sc->sc_minor.dev; |
289 | KASSERT(dev != NULL); | | 289 | KASSERT(dev != NULL); |
290 | | | 290 | |
291 | drm_sysctl_cleanup(dev); | | 291 | drm_sysctl_cleanup(dev); |
292 | drm_ctxbitmap_cleanup(dev); | | 292 | drm_ctxbitmap_cleanup(dev); |
293 | clean up mtrr crap; | | 293 | clean up mtrr crap; |
294 | do the last close; | | 294 | do the last close; |
295 | unload it all; | | 295 | unload it all; |
296 | vblank clenaup; | | 296 | vblank clenaup; |
297 | kill hash tables; | | 297 | kill hash tables; |
298 | and more; | | 298 | and more; |
299 | in a different order; | | 299 | in a different order; |
300 | } | | 300 | } |
301 | #endif | | 301 | #endif |
302 | | | 302 | |
303 | static struct drm_softc * | | 303 | static struct drm_softc * |
304 | drm_dev_softc(dev_t d) | | 304 | drm_dev_softc(dev_t d) |
305 | { | | 305 | { |
306 | return device_lookup_private(&drm_cd, (minor(d) % 64)); | | 306 | return device_lookup_private(&drm_cd, (minor(d) % 64)); |
307 | } | | 307 | } |
308 | | | 308 | |
309 | static struct drm_minor * | | 309 | static struct drm_minor * |
310 | drm_dev_minor(dev_t d) | | 310 | drm_dev_minor(dev_t d) |
311 | { | | 311 | { |
312 | struct drm_softc *const sc = drm_dev_softc(d); | | 312 | struct drm_softc *const sc = drm_dev_softc(d); |
313 | | | 313 | |
314 | if (sc == NULL) | | 314 | if (sc == NULL) |
315 | return NULL; | | 315 | return NULL; |
316 | | | 316 | |
317 | const unsigned int i = minor(d) / 64; | | 317 | const unsigned int i = minor(d) / 64; |
318 | if (i >= __arraycount(drm_minor_types)) | | 318 | if (i >= __arraycount(drm_minor_types)) |
319 | return NULL; | | 319 | return NULL; |
320 | | | 320 | |
321 | return &sc->sc_minor[i]; | | 321 | return &sc->sc_minor[i]; |
322 | } | | 322 | } |
323 | | | 323 | |
324 | static int | | 324 | static int |
325 | drm_open(dev_t d, int flags, int fmt, struct lwp *l) | | 325 | drm_open(dev_t d, int flags, int fmt, struct lwp *l) |
326 | { | | 326 | { |
327 | struct drm_minor *const dminor = drm_dev_minor(d); | | 327 | struct drm_minor *const dminor = drm_dev_minor(d); |
328 | int fd; | | 328 | int fd; |
329 | struct file *fp; | | 329 | struct file *fp; |
330 | int error; | | 330 | int error; |
331 | | | 331 | |
332 | if (dminor == NULL) { | | 332 | if (dminor == NULL) { |
333 | error = ENXIO; | | 333 | error = ENXIO; |
334 | goto fail0; | | 334 | goto fail0; |
335 | } | | 335 | } |
336 | | | 336 | |
337 | if (flags & O_EXCL) { | | 337 | if (flags & O_EXCL) { |
338 | error = EBUSY; | | 338 | error = EBUSY; |
339 | goto fail0; | | 339 | goto fail0; |
340 | } | | 340 | } |
341 | | | 341 | |
342 | if (dminor->dev->switch_power_state != DRM_SWITCH_POWER_ON) { | | 342 | if (dminor->dev->switch_power_state != DRM_SWITCH_POWER_ON) { |
343 | error = EINVAL; | | 343 | error = EINVAL; |
344 | goto fail0; | | 344 | goto fail0; |
345 | } | | 345 | } |
346 | | | 346 | |
347 | error = fd_allocfile(&fp, &fd); | | 347 | error = fd_allocfile(&fp, &fd); |
348 | if (error) | | 348 | if (error) |
349 | goto fail0; | | 349 | goto fail0; |
350 | | | 350 | |
351 | struct drm_file *const file = kmem_zalloc(sizeof(*file), KM_SLEEP); | | 351 | struct drm_file *const file = kmem_zalloc(sizeof(*file), KM_SLEEP); |
352 | | | 352 | |
353 | /* XXX errno Linux->NetBSD */ | | 353 | /* XXX errno Linux->NetBSD */ |
354 | error = -drm_open_file(file, fp, dminor); | | 354 | error = -drm_open_file(file, fp, dminor); |
355 | if (error) | | 355 | if (error) |
356 | goto fail2; | | 356 | goto fail2; |
357 | | | 357 | |
358 | error = fd_clone(fp, fd, flags, &drm_fileops, file); | | 358 | error = fd_clone(fp, fd, flags, &drm_fileops, file); |
359 | KASSERT(error == EMOVEFD); /* XXX */ | | 359 | KASSERT(error == EMOVEFD); /* XXX */ |
360 | | | 360 | |
361 | /* Success! (But error has to be EMOVEFD, not 0.) */ | | 361 | /* Success! (But error has to be EMOVEFD, not 0.) */ |
362 | return error; | | 362 | return error; |
363 | | | 363 | |
364 | fail2: | | 364 | fail2: |
365 | kmem_free(file, sizeof(*file)); | | 365 | kmem_free(file, sizeof(*file)); |
366 | | | 366 | |
367 | fail1: __unused | | 367 | fail1: __unused |
368 | fd_abort(curproc, fp, fd); | | 368 | fd_abort(curproc, fp, fd); |
369 | | | 369 | |
370 | fail0: | | 370 | fail0: |
371 | return error; | | 371 | return error; |
372 | } | | 372 | } |
373 | | | 373 | |
374 | static int | | 374 | static int |
375 | drm_close(struct file *fp) | | 375 | drm_close(struct file *fp) |
376 | { | | 376 | { |
377 | struct drm_file *const file = fp->f_data; | | 377 | struct drm_file *const file = fp->f_data; |
378 | | | 378 | |
379 | /* XXX errno Linux->NetBSD */ | | 379 | /* XXX errno Linux->NetBSD */ |
380 | return -drm_close_file(file); | | 380 | return -drm_close_file(file); |
381 | } | | 381 | } |
382 | | | 382 | |
383 | /* | | 383 | /* |
384 | * XXX According to the old drm port, doing nothing but succeeding in | | 384 | * XXX According to the old drm port, doing nothing but succeeding in |
385 | * drm_read and drm_poll is a kludge for compatibility with old X | | 385 | * drm_read and drm_poll is a kludge for compatibility with old X |
386 | * servers. However, it's not clear to me from the drm2 code that this | | 386 | * servers. However, it's not clear to me from the drm2 code that this |
387 | * is the right thing; in fact, it looks like a load of bollocks. | | 387 | * is the right thing; in fact, it looks like a load of bollocks. |
388 | */ | | 388 | */ |
389 | | | 389 | |
390 | static int | | 390 | static int |
391 | drm_read(struct file *fp __unused, off_t *off __unused, | | 391 | drm_read(struct file *fp __unused, off_t *off __unused, |
392 | struct uio *uio __unused, kauth_cred_t cred __unused, int flags __unused) | | 392 | struct uio *uio __unused, kauth_cred_t cred __unused, int flags __unused) |
393 | { | | 393 | { |
394 | #if 1 /* XXX drm event poll */ | | 394 | #if 1 /* XXX drm event poll */ |
395 | return 0; | | 395 | return 0; |
396 | #else | | 396 | #else |
397 | /* XXX How do flags figure into this? */ | | 397 | /* XXX How do flags figure into this? */ |
398 | struct drm_file *const file = fp->f_data; | | 398 | struct drm_file *const file = fp->f_data; |
399 | struct drm_pending_event *event; | | 399 | struct drm_pending_event *event; |
400 | int error; | | 400 | int error; |
401 | | | 401 | |
402 | if (off != 0) | | 402 | if (off != 0) |
403 | return EINVAL; | | 403 | return EINVAL; |
404 | | | 404 | |
405 | for (;;) { | | 405 | for (;;) { |
406 | error = drm_dequeue_event(file, uio->uio_resid, &event); | | 406 | error = drm_dequeue_event(file, uio->uio_resid, &event); |
407 | if (error) { | | 407 | if (error) { |
408 | /* XXX errno Linux->NetBSD */ | | 408 | /* XXX errno Linux->NetBSD */ |
409 | return -error; | | 409 | return -error; |
410 | } | | 410 | } |
411 | | | 411 | |
412 | if (event == NULL) | | 412 | if (event == NULL) |
413 | break; | | 413 | break; |
414 | | | 414 | |
415 | error = uiomove(event->event, event->event->length, uio); | | 415 | error = uiomove(event->event, event->event->length, uio); |
416 | if (error) /* XXX Requeue the event? */ | | 416 | if (error) /* XXX Requeue the event? */ |
417 | return error; | | 417 | return error; |
418 | } | | 418 | } |
419 | | | 419 | |
420 | /* Success! */ | | 420 | /* Success! */ |
421 | return 0; | | 421 | return 0; |
422 | #endif | | 422 | #endif |
423 | } | | 423 | } |
424 | | | 424 | |
425 | static int | | 425 | static int |
426 | drm_poll(struct file *fp __unused, int events __unused) | | 426 | drm_poll(struct file *fp __unused, int events __unused) |
427 | { | | 427 | { |
428 | #if 1 /* XXX drm event poll */ | | 428 | #if 1 /* XXX drm event poll */ |
429 | /* | | 429 | /* |
430 | * XXX Let's worry about this later. Notifiers need to be | | 430 | * XXX Let's worry about this later. Notifiers need to be |
431 | * modified to call selnotify. | | 431 | * modified to call selnotify. |
432 | */ | | 432 | */ |
433 | return 0; | | 433 | return 0; |
434 | #else | | 434 | #else |
435 | struct drm_file *const file = fp->f_data; | | 435 | struct drm_file *const file = fp->f_data; |
436 | int revents = 0; | | 436 | int revents = 0; |
437 | unsigned long flags; | | 437 | unsigned long flags; |
438 | | | 438 | |
439 | spin_lock_irqsave(&file->minor->dev->event_lock, flags); | | 439 | spin_lock_irqsave(&file->minor->dev->event_lock, flags); |
440 | | | 440 | |
441 | if (events & (POLLIN | POLLRDNORM)) { | | 441 | if (events & (POLLIN | POLLRDNORM)) { |
442 | if (!list_empty(&file->event_list)) | | 442 | if (!list_empty(&file->event_list)) |
443 | revents |= (events & (POLLIN | POLLRDNORM)); | | 443 | revents |= (events & (POLLIN | POLLRDNORM)); |
444 | } | | 444 | } |
445 | | | 445 | |
446 | if (revents == 0) { | | 446 | if (revents == 0) { |
447 | if (events & (POLLIN | POLLRDNORM)) | | 447 | if (events & (POLLIN | POLLRDNORM)) |
448 | selrecord(curlwp, &file->event_sel); | | 448 | selrecord(curlwp, &file->event_sel); |
449 | } | | 449 | } |
450 | | | 450 | |
451 | spin_unlock_irqrestore(&file->minor->dev->event_lock, flags); | | 451 | spin_unlock_irqrestore(&file->minor->dev->event_lock, flags); |
452 | | | 452 | |
453 | return revents; | | 453 | return revents; |
454 | #endif | | 454 | #endif |
455 | } | | 455 | } |
456 | | | 456 | |
457 | static int | | 457 | static int |
458 | drm_stat(struct file *fp, struct stat *st) | | 458 | drm_stat(struct file *fp, struct stat *st) |
459 | { | | 459 | { |
460 | struct drm_file *const file = fp->f_data; | | 460 | struct drm_file *const file = fp->f_data; |
461 | | | 461 | |
462 | (void)memset(st, 0, sizeof(*st)); | | 462 | (void)memset(st, 0, sizeof(*st)); |
463 | | | 463 | |
464 | st->st_dev = file->minor->device; | | 464 | st->st_dev = file->minor->device; |
465 | st->st_ino = 0; /* XXX (dev,ino) uniqueness bleh */ | | 465 | st->st_ino = 0; /* XXX (dev,ino) uniqueness bleh */ |
466 | st->st_uid = kauth_cred_geteuid(fp->f_cred); | | 466 | st->st_uid = kauth_cred_geteuid(fp->f_cred); |
467 | st->st_gid = kauth_cred_getegid(fp->f_cred); | | 467 | st->st_gid = kauth_cred_getegid(fp->f_cred); |
468 | st->st_mode = S_IFCHR; /* XXX what? */ | | 468 | st->st_mode = S_IFCHR; /* XXX what? */ |
469 | /* XXX what else? */ | | 469 | /* XXX what else? */ |
470 | | | 470 | |
471 | return 0; | | 471 | return 0; |
472 | } | | 472 | } |
473 | | | 473 | |
474 | static int | | 474 | static int |
475 | drm_ioctl(struct file *fp, unsigned long cmd, void *data) | | 475 | drm_ioctl(struct file *fp, unsigned long cmd, void *data) |
476 | { | | 476 | { |
477 | struct drm_file *const file = fp->f_data; | | 477 | struct drm_file *const file = fp->f_data; |
478 | const unsigned int nr = DRM_IOCTL_NR(cmd); | | 478 | const unsigned int nr = DRM_IOCTL_NR(cmd); |
479 | int error; | | 479 | int error; |
480 | | | 480 | |
481 | switch (cmd) { | | 481 | switch (cmd) { |
482 | case FIONBIO: | | 482 | case FIONBIO: |
483 | case FIOASYNC: | | 483 | case FIOASYNC: |
484 | return 0; | | 484 | return 0; |
485 | | | 485 | |
486 | #if 0 /* XXX why? */ | | 486 | #if 0 /* XXX why? */ |
487 | case SIOCSPGRP: | | 487 | case SIOCSPGRP: |
488 | case TIOCSPGRP: | | 488 | case TIOCSPGRP: |
489 | case FIOSETOWN: | | 489 | case FIOSETOWN: |
490 | return fsetown(&dev->buf_pgid, cmd, data); | | 490 | return fsetown(&dev->buf_pgid, cmd, data); |
491 | | | 491 | |
492 | case SIOCGPGRP: | | 492 | case SIOCGPGRP: |
493 | case TIOCGPGRP: | | 493 | case TIOCGPGRP: |
494 | case FIOGETOWN: | | 494 | case FIOGETOWN: |
495 | return fgetown(&dev->buf_pgid, cmd, data); | | 495 | return fgetown(&dev->buf_pgid, cmd, data); |
496 | #endif | | 496 | #endif |
497 | | | 497 | |
498 | default: | | 498 | default: |
499 | break; | | 499 | break; |
500 | } | | 500 | } |
501 | | | 501 | |
502 | if (IOCGROUP(cmd) != DRM_IOCTL_BASE) | | 502 | if (IOCGROUP(cmd) != DRM_IOCTL_BASE) |
503 | return EINVAL; | | 503 | return EINVAL; |
504 | | | 504 | |
505 | KASSERT(file != NULL); | | 505 | KASSERT(file != NULL); |
506 | KASSERT(file->minor != NULL); | | 506 | KASSERT(file->minor != NULL); |
507 | KASSERT(file->minor->dev != NULL); | | 507 | KASSERT(file->minor->dev != NULL); |
508 | struct drm_device *const dev = file->minor->dev; | | 508 | struct drm_device *const dev = file->minor->dev; |
509 | const struct drm_ioctl_desc *ioctl; | | 509 | const struct drm_ioctl_desc *ioctl; |
510 | | | 510 | |
511 | if ((DRM_COMMAND_BASE <= nr) && (nr < DRM_COMMAND_END)) { | | 511 | if ((DRM_COMMAND_BASE <= nr) && (nr < DRM_COMMAND_END)) { |
512 | const unsigned int driver_nr = nr - DRM_COMMAND_BASE; | | 512 | const unsigned int driver_nr = nr - DRM_COMMAND_BASE; |
513 | if (driver_nr >= dev->driver->num_ioctls) | | 513 | if (driver_nr >= dev->driver->num_ioctls) |
514 | return EINVAL; | | 514 | return EINVAL; |
515 | ioctl = &dev->driver->ioctls[driver_nr]; | | 515 | ioctl = &dev->driver->ioctls[driver_nr]; |
516 | } else if (nr < __arraycount(drm_ioctls)) { | | 516 | } else if (nr < __arraycount(drm_ioctls)) { |
517 | ioctl = &drm_ioctls[nr]; | | 517 | ioctl = &drm_ioctls[nr]; |
518 | } else { | | 518 | } else { |
519 | ioctl = NULL; | | 519 | ioctl = NULL; |
520 | } | | 520 | } |
521 | | | 521 | |
522 | if ((ioctl == NULL) || (ioctl->func == NULL)) | | 522 | if ((ioctl == NULL) || (ioctl->func == NULL)) |
523 | return EINVAL; | | 523 | return EINVAL; |
524 | | | 524 | |
525 | if (ISSET(ioctl->flags, DRM_ROOT_ONLY) && !DRM_SUSER()) | | 525 | if (ISSET(ioctl->flags, DRM_ROOT_ONLY) && !DRM_SUSER()) |
526 | return EACCES; | | 526 | return EACCES; |
527 | | | 527 | |
528 | if (ISSET(ioctl->flags, DRM_AUTH) && !file->authenticated) | | 528 | if (ISSET(ioctl->flags, DRM_AUTH) && !file->authenticated) |
529 | return EACCES; | | 529 | return EACCES; |
530 | | | 530 | |
531 | if (ISSET(ioctl->flags, DRM_MASTER) && (file->master == NULL)) | | 531 | if (ISSET(ioctl->flags, DRM_MASTER) && (file->master == NULL)) |
532 | return EACCES; | | 532 | return EACCES; |
533 | | | 533 | |
| | | 534 | if (!ISSET(ioctl->flags, DRM_CONTROL_ALLOW) && |
| | | 535 | (file->minor->type == DRM_MINOR_CONTROL)) |
| | | 536 | return EACCES; |
| | | 537 | |
534 | atomic_inc(&dev->ioctl_count); | | 538 | atomic_inc(&dev->ioctl_count); |
535 | if (!ISSET(ioctl->flags, DRM_UNLOCKED)) | | 539 | if (!ISSET(ioctl->flags, DRM_UNLOCKED)) |
536 | mutex_lock(&drm_global_mutex); | | 540 | mutex_lock(&drm_global_mutex); |
537 | | | 541 | |
538 | /* XXX errno Linux->NetBSD */ | | 542 | /* XXX errno Linux->NetBSD */ |
539 | error = -(*ioctl->func)(dev, data, file); | | 543 | error = -(*ioctl->func)(dev, data, file); |
540 | | | 544 | |
541 | if (!ISSET(ioctl->flags, DRM_UNLOCKED)) | | 545 | if (!ISSET(ioctl->flags, DRM_UNLOCKED)) |
542 | mutex_unlock(&drm_global_mutex); | | 546 | mutex_unlock(&drm_global_mutex); |
543 | atomic_dec(&dev->ioctl_count); | | 547 | atomic_dec(&dev->ioctl_count); |
544 | | | 548 | |
545 | return error; | | 549 | return error; |
546 | } | | 550 | } |
547 | | | 551 | |
548 | static int | | 552 | static int |
549 | drm_version_string(char *target, size_t *lenp, const char *source) | | 553 | drm_version_string(char *target, size_t *lenp, const char *source) |
550 | { | | 554 | { |
551 | const size_t len = strlen(source); | | 555 | const size_t len = strlen(source); |
552 | const size_t trunc_len = MIN(len, *lenp); | | 556 | const size_t trunc_len = MIN(len, *lenp); |
553 | | | 557 | |
554 | *lenp = len; | | 558 | *lenp = len; |
555 | if ((trunc_len > 0) && (target != NULL)) | | 559 | if ((trunc_len > 0) && (target != NULL)) |
556 | return copyoutstr(source, target, trunc_len, NULL); | | 560 | return copyoutstr(source, target, trunc_len, NULL); |
557 | | | 561 | |
558 | return 0; | | 562 | return 0; |
559 | } | | 563 | } |
560 | | | 564 | |
561 | static int | | 565 | static int |
562 | drm_version(struct drm_device *dev, void *data, struct drm_file *file) | | 566 | drm_version(struct drm_device *dev, void *data, struct drm_file *file) |
563 | { | | 567 | { |
564 | struct drm_version *v = data; | | 568 | struct drm_version *v = data; |
565 | int error; | | 569 | int error; |
566 | | | 570 | |
567 | v->version_major = dev->driver->major; | | 571 | v->version_major = dev->driver->major; |
568 | v->version_minor = dev->driver->minor; | | 572 | v->version_minor = dev->driver->minor; |
569 | v->version_patchlevel = dev->driver->patchlevel; | | 573 | v->version_patchlevel = dev->driver->patchlevel; |
570 | | | 574 | |
571 | error = drm_version_string(v->name, &v->name_len, dev->driver->name); | | 575 | error = drm_version_string(v->name, &v->name_len, dev->driver->name); |
572 | if (error) | | 576 | if (error) |
573 | goto out; | | 577 | goto out; |
574 | | | 578 | |
575 | error = drm_version_string(v->date, &v->date_len, dev->driver->date); | | 579 | error = drm_version_string(v->date, &v->date_len, dev->driver->date); |
576 | if (error) | | 580 | if (error) |
577 | goto out; | | 581 | goto out; |
578 | | | 582 | |
579 | error = drm_version_string(v->desc, &v->desc_len, dev->driver->desc); | | 583 | error = drm_version_string(v->desc, &v->desc_len, dev->driver->desc); |
580 | if (error) | | 584 | if (error) |
581 | goto out; | | 585 | goto out; |
582 | out: | | 586 | out: |
583 | return error; | | 587 | return error; |
584 | } | | 588 | } |