Line data Source code
1 : /* $OpenBSD: drm_drv.c,v 1.158 2018/06/25 22:29:16 kettenis Exp $ */
2 : /*-
3 : * Copyright 2007-2009 Owain G. Ainsworth <oga@openbsd.org>
4 : * Copyright © 2008 Intel Corporation
5 : * Copyright 2003 Eric Anholt
6 : * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
7 : * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
8 : * All Rights Reserved.
9 : *
10 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice (including the next
18 : * paragraph) shall be included in all copies or substantial portions of the
19 : * Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25 : * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26 : * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 : * OTHER DEALINGS IN THE SOFTWARE.
28 : *
29 : * Authors:
30 : * Rickard E. (Rik) Faith <faith@valinux.com>
31 : * Daryll Strauss <daryll@valinux.com>
32 : * Gareth Hughes <gareth@valinux.com>
33 : * Eric Anholt <eric@anholt.net>
34 : * Owain Ainsworth <oga@openbsd.org>
35 : *
36 : */
37 :
38 : /** @file drm_drv.c
39 : * The catch-all file for DRM device support, including module setup/teardown,
40 : * open/close, and ioctl dispatch.
41 : */
42 :
43 : #include <sys/param.h>
44 : #include <sys/fcntl.h>
45 : #include <sys/filio.h>
46 : #include <sys/limits.h>
47 : #include <sys/pledge.h>
48 : #include <sys/poll.h>
49 : #include <sys/specdev.h>
50 : #include <sys/systm.h>
51 : #include <sys/ttycom.h> /* for TIOCSGRP */
52 : #include <sys/vnode.h>
53 : #include <sys/event.h>
54 :
55 : #include <uvm/uvm.h>
56 : #include <uvm/uvm_device.h>
57 :
58 : #include "drmP.h"
59 : #include "drm.h"
60 : #include "drm_sarea.h"
61 : #include "drm_internal.h"
62 :
63 : #ifdef DRMDEBUG
64 : int drm_debug_flag = 1;
65 : #endif
66 :
67 : int drm_firstopen(struct drm_device *);
68 : int drm_lastclose(struct drm_device *);
69 : void drm_attach(struct device *, struct device *, void *);
70 : int drm_probe(struct device *, void *, void *);
71 : int drm_detach(struct device *, int);
72 : void drm_quiesce(struct drm_device *);
73 : void drm_wakeup(struct drm_device *);
74 : int drm_activate(struct device *, int);
75 : int drmprint(void *, const char *);
76 : int drmsubmatch(struct device *, void *, void *);
77 : int drm_do_ioctl(struct drm_device *, int, u_long, caddr_t);
78 : int drm_dequeue_event(struct drm_device *, struct drm_file *, size_t,
79 : struct drm_pending_event **);
80 :
81 : int drm_getunique(struct drm_device *, void *, struct drm_file *);
82 : int drm_version(struct drm_device *, void *, struct drm_file *);
83 : int drm_setversion(struct drm_device *, void *, struct drm_file *);
84 : int drm_getmagic(struct drm_device *, void *, struct drm_file *);
85 : int drm_authmagic(struct drm_device *, void *, struct drm_file *);
86 : int drm_getpciinfo(struct drm_device *, void *, struct drm_file *);
87 : int drm_file_cmp(struct drm_file *, struct drm_file *);
88 0 : SPLAY_PROTOTYPE(drm_file_tree, drm_file, link, drm_file_cmp);
89 :
90 : int drm_setunique(struct drm_device *, void *, struct drm_file *);
91 : int drm_noop(struct drm_device *, void *, struct drm_file *);
92 :
93 : int drm_getcap(struct drm_device *, void *, struct drm_file *);
94 : int drm_setclientcap(struct drm_device *, void *, struct drm_file *);
95 :
96 : #define DRM_IOCTL_DEF(ioctl, _func, _flags) \
97 : [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0}
98 :
99 : /** Ioctl table */
100 : static struct drm_ioctl_desc drm_ioctls[] = {
101 : DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED|DRM_RENDER_ALLOW),
102 : DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
103 : DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
104 : #ifdef __linux__
105 : DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
106 : DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED),
107 : DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
108 : DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
109 : #endif
110 : DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW),
111 : DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
112 : DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
113 :
114 : DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
115 : DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
116 : DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
117 : DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
118 :
119 : #ifdef __linux__
120 : DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
121 : DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
122 :
123 : DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
124 : DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
125 : #else
126 : DRM_IOCTL_DEF(DRM_IOCTL_GET_PCIINFO, drm_getpciinfo, DRM_UNLOCKED|DRM_RENDER_ALLOW),
127 :
128 : DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
129 : DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_noop, DRM_AUTH),
130 : #endif
131 :
132 : #ifdef __linux__
133 : DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY),
134 : DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY),
135 : #else
136 : /* On OpenBSD xorg privdrop has already occurred before this point */
137 : DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_noop, DRM_UNLOCKED|DRM_RENDER_ALLOW),
138 : DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_noop, DRM_UNLOCKED|DRM_RENDER_ALLOW),
139 : #endif
140 :
141 : #ifdef __linux__
142 : DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
143 : DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
144 : #endif
145 : DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
146 : #ifdef __linux__
147 : DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
148 : DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
149 : DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
150 : #else
151 : DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
152 : DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
153 : #endif
154 : #ifdef __linux__
155 : DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
156 : #endif
157 :
158 : DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
159 : DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
160 :
161 : #ifdef __linux__
162 : DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
163 : DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
164 : #endif
165 :
166 : DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
167 :
168 : #ifdef __linux__
169 : DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
170 : DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
171 : DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
172 : #else
173 : DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
174 : DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_noop, DRM_AUTH),
175 : #endif
176 : #ifdef __linux__
177 : DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
178 : DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
179 : DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma_ioctl, DRM_AUTH),
180 :
181 : DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
182 :
183 : #if __OS_HAS_AGP
184 : DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
185 : DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
186 : DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
187 : DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
188 : DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
189 : DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
190 : DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
191 : DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
192 : #endif
193 :
194 : DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
195 : DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
196 : #endif
197 :
198 : DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
199 :
200 : DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
201 :
202 : DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
203 :
204 : DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
205 : DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
206 : DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
207 :
208 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
209 :
210 : DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
211 : DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
212 :
213 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
214 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
215 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
216 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
217 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
218 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
219 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
220 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
221 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
222 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
223 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
224 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
225 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
226 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
227 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
228 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
229 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
230 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
231 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
232 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
233 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
234 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
235 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
236 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
237 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
238 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
239 : DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
240 : };
241 :
242 : #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
243 :
244 : int
245 0 : pledge_ioctl_drm(struct proc *p, long com, dev_t device)
246 : {
247 0 : struct drm_device *dev = drm_get_device_from_kdev(device);
248 0 : unsigned int nr = DRM_IOCTL_NR(com);
249 : const struct drm_ioctl_desc *ioctl;
250 :
251 0 : if (dev == NULL)
252 0 : return EPERM;
253 :
254 0 : if (nr < DRM_CORE_IOCTL_COUNT &&
255 0 : ((nr < DRM_COMMAND_BASE || nr >= DRM_COMMAND_END)))
256 0 : ioctl = &drm_ioctls[nr];
257 0 : else if (nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END &&
258 0 : nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)
259 0 : ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
260 : else
261 0 : return EPERM;
262 :
263 0 : if (ioctl->flags & DRM_RENDER_ALLOW)
264 0 : return 0;
265 :
266 : /*
267 : * These are dangerous, but we have to allow them until we
268 : * have prime/dma-buf support.
269 : */
270 0 : switch (com) {
271 : case DRM_IOCTL_GET_MAGIC:
272 : case DRM_IOCTL_GEM_OPEN:
273 0 : return 0;
274 : }
275 :
276 0 : return EPERM;
277 0 : }
278 :
279 : int
280 0 : drm_setunique(struct drm_device *dev, void *data,
281 : struct drm_file *file_priv)
282 : {
283 : /*
284 : * Deprecated in DRM version 1.1, and will return EBUSY
285 : * when setversion has
286 : * requested version 1.1 or greater.
287 : */
288 0 : return (-EBUSY);
289 : }
290 :
291 : /** No-op ioctl. */
292 0 : int drm_noop(struct drm_device *dev, void *data,
293 : struct drm_file *file_priv)
294 : {
295 0 : return 0;
296 : }
297 :
298 0 : int drm_invalid_op(struct drm_device *dev, void *data,
299 : struct drm_file *file_priv)
300 : {
301 0 : return -EINVAL;
302 : }
303 :
304 : /*
305 : * attach drm to a pci-based driver.
306 : *
307 : * This function does all the pci-specific calculations for the
308 : * drm_attach_args.
309 : */
310 : struct device *
311 0 : drm_attach_pci(struct drm_driver *driver, struct pci_attach_args *pa,
312 : int is_agp, int console, struct device *dev)
313 : {
314 0 : struct drm_attach_args arg;
315 : pcireg_t subsys;
316 :
317 0 : arg.driver = driver;
318 0 : arg.dmat = pa->pa_dmat;
319 0 : arg.bst = pa->pa_memt;
320 0 : arg.is_agp = is_agp;
321 0 : arg.console = console;
322 :
323 0 : arg.pci_vendor = PCI_VENDOR(pa->pa_id);
324 0 : arg.pci_device = PCI_PRODUCT(pa->pa_id);
325 :
326 0 : subsys = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
327 0 : arg.pci_subvendor = PCI_VENDOR(subsys);
328 0 : arg.pci_subdevice = PCI_PRODUCT(subsys);
329 :
330 0 : arg.pci_revision = PCI_REVISION(pa->pa_class);
331 :
332 0 : arg.pa = pa;
333 0 : arg.pc = pa->pa_pc;
334 0 : arg.tag = pa->pa_tag;
335 0 : arg.bridgetag = pa->pa_bridgetag;
336 :
337 0 : arg.busid_len = 20;
338 0 : arg.busid = malloc(arg.busid_len + 1, M_DRM, M_NOWAIT);
339 0 : if (arg.busid == NULL) {
340 0 : printf("%s: no memory for drm\n", dev->dv_xname);
341 0 : return (NULL);
342 : }
343 0 : snprintf(arg.busid, arg.busid_len, "pci:%04x:%02x:%02x.%1x",
344 0 : pa->pa_domain, pa->pa_bus, pa->pa_device, pa->pa_function);
345 :
346 0 : return (config_found_sm(dev, &arg, drmprint, drmsubmatch));
347 0 : }
348 :
349 : int
350 0 : drmprint(void *aux, const char *pnp)
351 : {
352 0 : if (pnp != NULL)
353 0 : printf("drm at %s", pnp);
354 0 : return (UNCONF);
355 : }
356 :
357 : int
358 0 : drmsubmatch(struct device *parent, void *match, void *aux)
359 : {
360 : extern struct cfdriver drm_cd;
361 0 : struct cfdata *cf = match;
362 :
363 : /* only allow drm to attach */
364 0 : if (cf->cf_driver == &drm_cd)
365 0 : return ((*cf->cf_attach->ca_match)(parent, match, aux));
366 0 : return (0);
367 0 : }
368 :
369 : int
370 0 : drm_pciprobe(struct pci_attach_args *pa, const struct drm_pcidev *idlist)
371 : {
372 : const struct drm_pcidev *id_entry;
373 :
374 0 : id_entry = drm_find_description(PCI_VENDOR(pa->pa_id),
375 0 : PCI_PRODUCT(pa->pa_id), idlist);
376 0 : if (id_entry != NULL)
377 0 : return 1;
378 :
379 0 : return 0;
380 0 : }
381 :
382 : int
383 0 : drm_probe(struct device *parent, void *match, void *aux)
384 : {
385 0 : struct cfdata *cf = match;
386 0 : struct drm_attach_args *da = aux;
387 :
388 0 : if (cf->drmdevcf_console != DRMDEVCF_CONSOLE_UNK) {
389 : /*
390 : * If console-ness of device specified, either match
391 : * exactly (at high priority), or fail.
392 : */
393 0 : if (cf->drmdevcf_console != 0 && da->console != 0)
394 0 : return (10);
395 : else
396 0 : return (0);
397 : }
398 :
399 : /* If console-ness unspecified, it wins. */
400 0 : return (1);
401 0 : }
402 :
403 : void
404 0 : drm_attach(struct device *parent, struct device *self, void *aux)
405 : {
406 0 : struct drm_device *dev = (struct drm_device *)self;
407 0 : struct drm_attach_args *da = aux;
408 0 : int bus, slot, func;
409 : int ret;
410 :
411 0 : dev->dev = self;
412 :
413 0 : dev->dev_private = parent;
414 0 : dev->driver = da->driver;
415 :
416 0 : dev->dmat = da->dmat;
417 0 : dev->bst = da->bst;
418 0 : dev->unique = da->busid;
419 0 : dev->unique_len = da->busid_len;
420 0 : dev->pdev = &dev->_pdev;
421 0 : dev->pci_vendor = dev->pdev->vendor = da->pci_vendor;
422 0 : dev->pci_device = dev->pdev->device = da->pci_device;
423 0 : dev->pdev->subsystem_vendor = da->pci_subvendor;
424 0 : dev->pdev->subsystem_device = da->pci_subdevice;
425 0 : dev->pdev->revision = da->pci_revision;
426 :
427 0 : pci_decompose_tag(da->pc, da->tag, &bus, &slot, &func);
428 0 : dev->pdev->bus = &dev->pdev->_bus;
429 0 : dev->pdev->bus->pc = da->pc;
430 0 : dev->pdev->bus->number = bus;
431 0 : dev->pdev->bus->bridgetag = da->bridgetag;
432 0 : dev->pdev->devfn = PCI_DEVFN(slot, func);
433 :
434 0 : dev->pc = da->pc;
435 0 : dev->pdev->pc = da->pc;
436 0 : dev->bridgetag = da->bridgetag;
437 0 : dev->pdev->tag = da->tag;
438 0 : dev->pdev->pci = (struct pci_softc *)parent->dv_parent;
439 :
440 0 : rw_init(&dev->struct_mutex, "drmdevlk");
441 0 : mtx_init(&dev->event_lock, IPL_TTY);
442 0 : mtx_init(&dev->quiesce_mtx, IPL_NONE);
443 :
444 0 : SPLAY_INIT(&dev->files);
445 0 : INIT_LIST_HEAD(&dev->vblank_event_list);
446 :
447 0 : if (drm_core_check_feature(dev, DRIVER_USE_AGP)) {
448 : #if __OS_HAS_AGP
449 0 : if (da->is_agp)
450 0 : dev->agp = drm_agp_init();
451 : #endif
452 0 : if (dev->agp != NULL) {
453 0 : if (drm_mtrr_add(dev->agp->info.ai_aperture_base,
454 0 : dev->agp->info.ai_aperture_size, DRM_MTRR_WC) == 0)
455 0 : dev->agp->mtrr = 1;
456 : }
457 : }
458 :
459 0 : if (dev->driver->gem_size > 0) {
460 0 : KASSERT(dev->driver->gem_size >= sizeof(struct drm_gem_object));
461 : /* XXX unique name */
462 0 : pool_init(&dev->objpl, dev->driver->gem_size, 0, IPL_NONE, 0,
463 : "drmobjpl", NULL);
464 0 : }
465 :
466 0 : if (dev->driver->driver_features & DRIVER_GEM) {
467 0 : ret = drm_gem_init(dev);
468 0 : if (ret) {
469 0 : DRM_ERROR("Cannot initialize graphics execution manager (GEM)\n");
470 : goto error;
471 : }
472 : }
473 :
474 0 : printf("\n");
475 0 : return;
476 :
477 : error:
478 0 : drm_lastclose(dev);
479 0 : dev->dev_private = NULL;
480 0 : }
481 :
482 : int
483 0 : drm_detach(struct device *self, int flags)
484 : {
485 0 : struct drm_device *dev = (struct drm_device *)self;
486 :
487 0 : drm_lastclose(dev);
488 :
489 0 : if (dev->driver->driver_features & DRIVER_GEM)
490 0 : drm_gem_destroy(dev);
491 :
492 0 : if (dev->driver->driver_features & DRIVER_GEM)
493 0 : pool_destroy(&dev->objpl);
494 :
495 0 : drm_vblank_cleanup(dev);
496 :
497 0 : if (dev->agp && dev->agp->mtrr) {
498 : int retcode;
499 :
500 0 : retcode = drm_mtrr_del(0, dev->agp->info.ai_aperture_base,
501 0 : dev->agp->info.ai_aperture_size, DRM_MTRR_WC);
502 : DRM_DEBUG("mtrr_del = %d", retcode);
503 0 : }
504 :
505 :
506 0 : if (dev->agp != NULL) {
507 0 : drm_free(dev->agp);
508 0 : dev->agp = NULL;
509 0 : }
510 :
511 0 : return 0;
512 : }
513 :
514 : void
515 0 : drm_quiesce(struct drm_device *dev)
516 : {
517 0 : mtx_enter(&dev->quiesce_mtx);
518 0 : dev->quiesce = 1;
519 0 : while (dev->quiesce_count > 0) {
520 0 : msleep(&dev->quiesce_count, &dev->quiesce_mtx,
521 : PZERO, "drmqui", 0);
522 : }
523 0 : mtx_leave(&dev->quiesce_mtx);
524 0 : }
525 :
526 : void
527 0 : drm_wakeup(struct drm_device *dev)
528 : {
529 0 : mtx_enter(&dev->quiesce_mtx);
530 0 : dev->quiesce = 0;
531 0 : wakeup(&dev->quiesce);
532 0 : mtx_leave(&dev->quiesce_mtx);
533 0 : }
534 :
535 : int
536 0 : drm_activate(struct device *self, int act)
537 : {
538 0 : struct drm_device *dev = (struct drm_device *)self;
539 :
540 0 : switch (act) {
541 : case DVACT_QUIESCE:
542 0 : drm_quiesce(dev);
543 0 : break;
544 : case DVACT_WAKEUP:
545 0 : drm_wakeup(dev);
546 0 : break;
547 : }
548 :
549 0 : return (0);
550 : }
551 :
552 : struct cfattach drm_ca = {
553 : sizeof(struct drm_device), drm_probe, drm_attach,
554 : drm_detach, drm_activate
555 : };
556 :
557 : struct cfdriver drm_cd = {
558 : 0, "drm", DV_DULL
559 : };
560 :
561 : const struct drm_pcidev *
562 0 : drm_find_description(int vendor, int device, const struct drm_pcidev *idlist)
563 : {
564 : int i = 0;
565 :
566 0 : for (i = 0; idlist[i].vendor != 0; i++) {
567 0 : if ((idlist[i].vendor == vendor) &&
568 0 : (idlist[i].device == device) &&
569 0 : (idlist[i].subvendor == PCI_ANY_ID) &&
570 0 : (idlist[i].subdevice == PCI_ANY_ID))
571 0 : return &idlist[i];
572 : }
573 0 : return NULL;
574 0 : }
575 :
576 : int
577 0 : drm_file_cmp(struct drm_file *f1, struct drm_file *f2)
578 : {
579 0 : return (f1->minor < f2->minor ? -1 : f1->minor > f2->minor);
580 : }
581 :
582 0 : SPLAY_GENERATE(drm_file_tree, drm_file, link, drm_file_cmp);
583 :
584 : struct drm_file *
585 0 : drm_find_file_by_minor(struct drm_device *dev, int minor)
586 : {
587 0 : struct drm_file key;
588 :
589 0 : key.minor = minor;
590 0 : return (SPLAY_FIND(drm_file_tree, &dev->files, &key));
591 0 : }
592 :
593 : struct drm_device *
594 0 : drm_get_device_from_kdev(dev_t kdev)
595 : {
596 0 : int unit = minor(kdev) & ((1 << CLONE_SHIFT) - 1);
597 :
598 0 : if (unit < drm_cd.cd_ndevs)
599 0 : return drm_cd.cd_devs[unit];
600 :
601 0 : return NULL;
602 0 : }
603 :
604 : int
605 0 : drm_firstopen(struct drm_device *dev)
606 : {
607 0 : if (dev->driver->firstopen)
608 0 : dev->driver->firstopen(dev);
609 :
610 0 : dev->magicid = 1;
611 :
612 0 : if (!drm_core_check_feature(dev, DRIVER_MODESET))
613 0 : dev->irq_enabled = 0;
614 0 : dev->if_version = 0;
615 :
616 0 : dev->buf_pgid = 0;
617 :
618 : DRM_DEBUG("\n");
619 :
620 0 : return 0;
621 : }
622 :
623 : int
624 0 : drm_lastclose(struct drm_device *dev)
625 : {
626 : DRM_DEBUG("\n");
627 :
628 0 : if (dev->driver->lastclose != NULL)
629 0 : dev->driver->lastclose(dev);
630 :
631 0 : if (!drm_core_check_feature(dev, DRIVER_MODESET) && dev->irq_enabled)
632 0 : drm_irq_uninstall(dev);
633 :
634 : #if __OS_HAS_AGP
635 0 : if (!drm_core_check_feature(dev, DRIVER_MODESET))
636 0 : drm_agp_takedown(dev);
637 : #endif
638 :
639 0 : return 0;
640 : }
641 :
642 : void
643 0 : filt_drmdetach(struct knote *kn)
644 : {
645 0 : struct drm_device *dev = kn->kn_hook;
646 : int s;
647 :
648 0 : s = spltty();
649 0 : SLIST_REMOVE(&dev->note, kn, knote, kn_selnext);
650 0 : splx(s);
651 0 : }
652 :
653 : int
654 0 : filt_drmkms(struct knote *kn, long hint)
655 : {
656 0 : if (kn->kn_sfflags & hint)
657 0 : kn->kn_fflags |= hint;
658 0 : return (kn->kn_fflags != 0);
659 : }
660 :
661 : struct filterops drm_filtops =
662 : { 1, NULL, filt_drmdetach, filt_drmkms };
663 :
664 : int
665 0 : drmkqfilter(dev_t kdev, struct knote *kn)
666 : {
667 : struct drm_device *dev = NULL;
668 : int s;
669 :
670 0 : dev = drm_get_device_from_kdev(kdev);
671 0 : if (dev == NULL || dev->dev_private == NULL)
672 0 : return (ENXIO);
673 :
674 0 : switch (kn->kn_filter) {
675 : case EVFILT_DEVICE:
676 0 : kn->kn_fop = &drm_filtops;
677 : break;
678 : default:
679 0 : return (EINVAL);
680 : }
681 :
682 0 : kn->kn_hook = dev;
683 :
684 0 : s = spltty();
685 0 : SLIST_INSERT_HEAD(&dev->note, kn, kn_selnext);
686 0 : splx(s);
687 :
688 0 : return (0);
689 0 : }
690 :
691 : int
692 0 : drmopen(dev_t kdev, int flags, int fmt, struct proc *p)
693 : {
694 : struct drm_device *dev = NULL;
695 0 : struct drm_file *file_priv;
696 : int ret = 0;
697 :
698 0 : dev = drm_get_device_from_kdev(kdev);
699 0 : if (dev == NULL || dev->dev_private == NULL)
700 0 : return (ENXIO);
701 :
702 : DRM_DEBUG("open_count = %d\n", dev->open_count);
703 :
704 0 : if (flags & O_EXCL)
705 0 : return (EBUSY); /* No exclusive opens */
706 :
707 0 : mutex_lock(&dev->struct_mutex);
708 0 : if (dev->open_count++ == 0) {
709 : mutex_unlock(&dev->struct_mutex);
710 0 : if ((ret = drm_firstopen(dev)) != 0)
711 : goto err;
712 : } else {
713 : mutex_unlock(&dev->struct_mutex);
714 : }
715 :
716 : /* always allocate at least enough space for our data */
717 0 : file_priv = drm_calloc(1, max(dev->driver->file_priv_size,
718 : sizeof(*file_priv)));
719 0 : if (file_priv == NULL) {
720 : ret = ENOMEM;
721 0 : goto err;
722 : }
723 :
724 0 : file_priv->filp = (void *)&file_priv;
725 0 : file_priv->minor = minor(kdev);
726 0 : INIT_LIST_HEAD(&file_priv->fbs);
727 0 : INIT_LIST_HEAD(&file_priv->event_list);
728 0 : file_priv->event_space = 4096; /* 4k for event buffer */
729 : DRM_DEBUG("minor = %d\n", file_priv->minor);
730 :
731 : /* for compatibility root is always authenticated */
732 0 : file_priv->authenticated = DRM_SUSER(p);
733 :
734 0 : if (dev->driver->driver_features & DRIVER_GEM)
735 0 : drm_gem_open(dev, file_priv);
736 :
737 0 : if (drm_core_check_feature(dev, DRIVER_PRIME))
738 0 : drm_prime_init_file_private(&file_priv->prime);
739 :
740 0 : if (dev->driver->open) {
741 0 : ret = dev->driver->open(dev, file_priv);
742 0 : if (ret != 0) {
743 : goto free_priv;
744 : }
745 : }
746 :
747 0 : mutex_lock(&dev->struct_mutex);
748 : /* first opener automatically becomes master if root */
749 0 : if (SPLAY_EMPTY(&dev->files) && !DRM_SUSER(p)) {
750 0 : mutex_unlock(&dev->struct_mutex);
751 : ret = EPERM;
752 0 : goto free_priv;
753 : }
754 :
755 0 : file_priv->is_master = SPLAY_EMPTY(&dev->files);
756 :
757 0 : SPLAY_INSERT(drm_file_tree, &dev->files, file_priv);
758 0 : mutex_unlock(&dev->struct_mutex);
759 :
760 0 : return (0);
761 :
762 : free_priv:
763 0 : drm_free(file_priv);
764 : err:
765 0 : mutex_lock(&dev->struct_mutex);
766 0 : --dev->open_count;
767 0 : mutex_unlock(&dev->struct_mutex);
768 0 : return (ret);
769 0 : }
770 :
771 : int
772 0 : drmclose(dev_t kdev, int flags, int fmt, struct proc *p)
773 : {
774 0 : struct drm_device *dev = drm_get_device_from_kdev(kdev);
775 : struct drm_file *file_priv;
776 : struct drm_pending_event *e, *et;
777 : struct drm_pending_vblank_event *v, *vt;
778 : int retcode = 0;
779 :
780 0 : if (dev == NULL)
781 0 : return (ENXIO);
782 :
783 : DRM_DEBUG("open_count = %d\n", dev->open_count);
784 :
785 0 : mutex_lock(&dev->struct_mutex);
786 0 : file_priv = drm_find_file_by_minor(dev, minor(kdev));
787 0 : if (file_priv == NULL) {
788 0 : DRM_ERROR("can't find authenticator\n");
789 : retcode = EINVAL;
790 0 : goto done;
791 : }
792 0 : mutex_unlock(&dev->struct_mutex);
793 :
794 0 : if (dev->driver->close != NULL)
795 0 : dev->driver->close(dev, file_priv);
796 0 : if (dev->driver->preclose != NULL)
797 0 : dev->driver->preclose(dev, file_priv);
798 :
799 : DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
800 : DRM_CURRENTPID, (long)&dev->device, dev->open_count);
801 :
802 0 : mtx_enter(&dev->event_lock);
803 :
804 : /* Remove pending flips */
805 0 : list_for_each_entry_safe(v, vt, &dev->vblank_event_list, base.link)
806 0 : if (v->base.file_priv == file_priv) {
807 0 : list_del(&v->base.link);
808 0 : drm_vblank_put(dev, v->pipe);
809 0 : v->base.destroy(&v->base);
810 0 : }
811 :
812 : /* Remove unconsumed events */
813 0 : list_for_each_entry_safe(e, et, &file_priv->event_list, link) {
814 0 : list_del(&e->link);
815 0 : e->destroy(e);
816 : }
817 :
818 0 : mtx_leave(&dev->event_lock);
819 :
820 0 : if (dev->driver->driver_features & DRIVER_MODESET)
821 0 : drm_fb_release(file_priv);
822 :
823 0 : if (dev->driver->driver_features & DRIVER_GEM)
824 0 : drm_gem_release(dev, file_priv);
825 :
826 0 : mutex_lock(&dev->struct_mutex);
827 :
828 0 : dev->buf_pgid = 0;
829 :
830 0 : if (dev->driver->postclose)
831 0 : dev->driver->postclose(dev, file_priv);
832 :
833 :
834 0 : if (drm_core_check_feature(dev, DRIVER_PRIME))
835 0 : drm_prime_destroy_file_private(&file_priv->prime);
836 :
837 0 : SPLAY_REMOVE(drm_file_tree, &dev->files, file_priv);
838 0 : drm_free(file_priv);
839 :
840 : done:
841 0 : if (--dev->open_count == 0) {
842 : mutex_unlock(&dev->struct_mutex);
843 0 : retcode = drm_lastclose(dev);
844 0 : } else
845 : mutex_unlock(&dev->struct_mutex);
846 :
847 0 : return (retcode);
848 0 : }
849 :
850 : int
851 0 : drm_do_ioctl(struct drm_device *dev, int minor, u_long cmd, caddr_t data)
852 : {
853 : struct drm_file *file_priv;
854 : const struct drm_ioctl_desc *ioctl;
855 : drm_ioctl_t *func;
856 0 : unsigned int nr = DRM_IOCTL_NR(cmd);
857 : int retcode = -EINVAL;
858 : unsigned int usize, asize;
859 :
860 0 : mutex_lock(&dev->struct_mutex);
861 0 : file_priv = drm_find_file_by_minor(dev, minor);
862 0 : mutex_unlock(&dev->struct_mutex);
863 0 : if (file_priv == NULL) {
864 0 : DRM_ERROR("can't find authenticator\n");
865 0 : return -EINVAL;
866 : }
867 :
868 : DRM_DEBUG("pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
869 : DRM_CURRENTPID, cmd, (u_int)DRM_IOCTL_NR(cmd), (long)&dev->device,
870 : file_priv->authenticated);
871 :
872 0 : switch (cmd) {
873 : case FIONBIO:
874 : case FIOASYNC:
875 0 : return 0;
876 :
877 : case TIOCSPGRP:
878 0 : dev->buf_pgid = *(int *)data;
879 0 : return 0;
880 :
881 : case TIOCGPGRP:
882 0 : *(int *)data = dev->buf_pgid;
883 0 : return 0;
884 : }
885 :
886 0 : if ((nr >= DRM_CORE_IOCTL_COUNT) &&
887 0 : ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
888 0 : return (-EINVAL);
889 0 : if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
890 0 : (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
891 : uint32_t drv_size;
892 0 : ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
893 0 : drv_size = IOCPARM_LEN(ioctl->cmd_drv);
894 0 : usize = asize = IOCPARM_LEN(cmd);
895 0 : if (drv_size > asize)
896 0 : asize = drv_size;
897 0 : } else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
898 : uint32_t drv_size;
899 0 : ioctl = &drm_ioctls[nr];
900 :
901 0 : drv_size = IOCPARM_LEN(ioctl->cmd_drv);
902 0 : usize = asize = IOCPARM_LEN(cmd);
903 0 : if (drv_size > asize)
904 0 : asize = drv_size;
905 0 : cmd = ioctl->cmd;
906 : } else
907 0 : return (-EINVAL);
908 :
909 0 : func = ioctl->func;
910 0 : if (!func) {
911 : DRM_DEBUG("no function\n");
912 0 : return (-EINVAL);
913 : }
914 :
915 0 : if (((ioctl->flags & DRM_ROOT_ONLY) && !DRM_SUSER(curproc)) ||
916 0 : ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
917 0 : ((ioctl->flags & DRM_MASTER) && !file_priv->is_master))
918 0 : return (-EACCES);
919 :
920 : if (ioctl->flags & DRM_UNLOCKED)
921 : retcode = func(dev, data, file_priv);
922 : else {
923 : /* XXX lock */
924 : retcode = func(dev, data, file_priv);
925 : /* XXX unlock */
926 : }
927 :
928 0 : return (retcode);
929 0 : }
930 :
931 : /* drmioctl is called whenever a process performs an ioctl on /dev/drm.
932 : */
933 : int
934 0 : drmioctl(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p)
935 : {
936 0 : struct drm_device *dev = drm_get_device_from_kdev(kdev);
937 : int error;
938 :
939 0 : if (dev == NULL)
940 0 : return ENODEV;
941 :
942 0 : mtx_enter(&dev->quiesce_mtx);
943 0 : while (dev->quiesce)
944 0 : msleep(&dev->quiesce, &dev->quiesce_mtx, PZERO, "drmioc", 0);
945 0 : dev->quiesce_count++;
946 0 : mtx_leave(&dev->quiesce_mtx);
947 :
948 0 : error = -drm_do_ioctl(dev, minor(kdev), cmd, data);
949 0 : if (error < 0 && error != ERESTART && error != EJUSTRETURN)
950 0 : printf("%s: cmd 0x%lx errno %d\n", __func__, cmd, error);
951 :
952 0 : mtx_enter(&dev->quiesce_mtx);
953 0 : dev->quiesce_count--;
954 0 : if (dev->quiesce)
955 0 : wakeup(&dev->quiesce_count);
956 0 : mtx_leave(&dev->quiesce_mtx);
957 :
958 0 : return (error);
959 0 : }
960 :
961 : int
962 0 : drmread(dev_t kdev, struct uio *uio, int ioflag)
963 : {
964 0 : struct drm_device *dev = drm_get_device_from_kdev(kdev);
965 : struct drm_file *file_priv;
966 0 : struct drm_pending_event *ev;
967 : int error = 0;
968 :
969 0 : if (dev == NULL)
970 0 : return (ENXIO);
971 :
972 0 : mutex_lock(&dev->struct_mutex);
973 0 : file_priv = drm_find_file_by_minor(dev, minor(kdev));
974 0 : mutex_unlock(&dev->struct_mutex);
975 0 : if (file_priv == NULL)
976 0 : return (ENXIO);
977 :
978 : /*
979 : * The semantics are a little weird here. We will wait until we
980 : * have events to process, but as soon as we have events we will
981 : * only deliver as many as we have.
982 : * Note that events are atomic, if the read buffer will not fit in
983 : * a whole event, we won't read any of it out.
984 : */
985 0 : mtx_enter(&dev->event_lock);
986 0 : while (error == 0 && list_empty(&file_priv->event_list)) {
987 0 : if (ioflag & IO_NDELAY) {
988 0 : mtx_leave(&dev->event_lock);
989 0 : return (EAGAIN);
990 : }
991 0 : error = msleep(&file_priv->event_wait, &dev->event_lock,
992 : PWAIT | PCATCH, "drmread", 0);
993 : }
994 0 : if (error) {
995 0 : mtx_leave(&dev->event_lock);
996 0 : return (error);
997 : }
998 0 : while (drm_dequeue_event(dev, file_priv, uio->uio_resid, &ev)) {
999 0 : MUTEX_ASSERT_UNLOCKED(&dev->event_lock);
1000 : /* XXX we always destroy the event on error. */
1001 0 : error = uiomove(ev->event, ev->event->length, uio);
1002 0 : ev->destroy(ev);
1003 0 : if (error)
1004 : break;
1005 0 : mtx_enter(&dev->event_lock);
1006 : }
1007 0 : MUTEX_ASSERT_UNLOCKED(&dev->event_lock);
1008 :
1009 0 : return (error);
1010 0 : }
1011 :
1012 : /*
1013 : * Deqeue an event from the file priv in question. returning 1 if an
1014 : * event was found. We take the resid from the read as a parameter because
1015 : * we will only dequeue and event if the read buffer has space to fit the
1016 : * entire thing.
1017 : *
1018 : * We are called locked, but we will *unlock* the queue on return so that
1019 : * we may sleep to copyout the event.
1020 : */
1021 : int
1022 0 : drm_dequeue_event(struct drm_device *dev, struct drm_file *file_priv,
1023 : size_t resid, struct drm_pending_event **out)
1024 : {
1025 : struct drm_pending_event *e = NULL;
1026 : int gotone = 0;
1027 :
1028 0 : MUTEX_ASSERT_LOCKED(&dev->event_lock);
1029 :
1030 0 : *out = NULL;
1031 0 : if (list_empty(&file_priv->event_list))
1032 : goto out;
1033 0 : e = list_first_entry(&file_priv->event_list,
1034 : struct drm_pending_event, link);
1035 0 : if (e->event->length > resid)
1036 : goto out;
1037 :
1038 0 : file_priv->event_space += e->event->length;
1039 0 : list_del(&e->link);
1040 0 : *out = e;
1041 0 : gotone = 1;
1042 :
1043 : out:
1044 0 : mtx_leave(&dev->event_lock);
1045 :
1046 0 : return (gotone);
1047 : }
1048 :
1049 : /* XXX kqfilter ... */
1050 : int
1051 0 : drmpoll(dev_t kdev, int events, struct proc *p)
1052 : {
1053 0 : struct drm_device *dev = drm_get_device_from_kdev(kdev);
1054 : struct drm_file *file_priv;
1055 : int revents = 0;
1056 :
1057 0 : if (dev == NULL)
1058 0 : return (POLLERR);
1059 :
1060 0 : mutex_lock(&dev->struct_mutex);
1061 0 : file_priv = drm_find_file_by_minor(dev, minor(kdev));
1062 0 : mutex_unlock(&dev->struct_mutex);
1063 0 : if (file_priv == NULL)
1064 0 : return (POLLERR);
1065 :
1066 0 : mtx_enter(&dev->event_lock);
1067 0 : if (events & (POLLIN | POLLRDNORM)) {
1068 0 : if (!list_empty(&file_priv->event_list))
1069 0 : revents |= events & (POLLIN | POLLRDNORM);
1070 : else
1071 0 : selrecord(p, &file_priv->rsel);
1072 : }
1073 0 : mtx_leave(&dev->event_lock);
1074 :
1075 0 : return (revents);
1076 0 : }
1077 :
1078 : paddr_t
1079 0 : drmmmap(dev_t kdev, off_t offset, int prot)
1080 : {
1081 0 : return -1;
1082 : }
1083 :
1084 : /*
1085 : * Beginning in revision 1.1 of the DRM interface, getunique will return
1086 : * a unique in the form pci:oooo:bb:dd.f (o=domain, b=bus, d=device, f=function)
1087 : * before setunique has been called. The format for the bus-specific part of
1088 : * the unique is not defined for any other bus.
1089 : */
1090 : int
1091 0 : drm_getunique(struct drm_device *dev, void *data, struct drm_file *file_priv)
1092 : {
1093 0 : struct drm_unique *u = data;
1094 :
1095 0 : if (u->unique_len >= dev->unique_len) {
1096 0 : if (DRM_COPY_TO_USER(u->unique, dev->unique, dev->unique_len))
1097 0 : return -EFAULT;
1098 : }
1099 0 : u->unique_len = dev->unique_len;
1100 :
1101 0 : return 0;
1102 0 : }
1103 :
1104 : int
1105 0 : drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
1106 : {
1107 0 : struct drm_get_cap *req = data;
1108 :
1109 0 : req->value = 0;
1110 0 : switch (req->capability) {
1111 : case DRM_CAP_DUMB_BUFFER:
1112 0 : if (dev->driver->dumb_create)
1113 0 : req->value = 1;
1114 : break;
1115 : case DRM_CAP_VBLANK_HIGH_CRTC:
1116 0 : req->value = 1;
1117 0 : break;
1118 : case DRM_CAP_DUMB_PREFERRED_DEPTH:
1119 0 : req->value = dev->mode_config.preferred_depth;
1120 0 : break;
1121 : case DRM_CAP_DUMB_PREFER_SHADOW:
1122 0 : req->value = dev->mode_config.prefer_shadow;
1123 0 : break;
1124 : case DRM_CAP_PRIME:
1125 0 : req->value |= dev->driver->prime_fd_to_handle ? DRM_PRIME_CAP_IMPORT : 0;
1126 0 : req->value |= dev->driver->prime_handle_to_fd ? DRM_PRIME_CAP_EXPORT : 0;
1127 0 : break;
1128 : case DRM_CAP_TIMESTAMP_MONOTONIC:
1129 0 : req->value = drm_timestamp_monotonic;
1130 0 : break;
1131 : case DRM_CAP_ASYNC_PAGE_FLIP:
1132 0 : req->value = dev->mode_config.async_page_flip;
1133 0 : break;
1134 : case DRM_CAP_CURSOR_WIDTH:
1135 0 : if (dev->mode_config.cursor_width)
1136 0 : req->value = dev->mode_config.cursor_width;
1137 : else
1138 0 : req->value = 64;
1139 : break;
1140 : case DRM_CAP_CURSOR_HEIGHT:
1141 0 : if (dev->mode_config.cursor_height)
1142 0 : req->value = dev->mode_config.cursor_height;
1143 : else
1144 0 : req->value = 64;
1145 : break;
1146 : default:
1147 0 : return -EINVAL;
1148 : }
1149 0 : return 0;
1150 0 : }
1151 :
1152 : /**
1153 : * Set device/driver capabilities
1154 : */
1155 : int
1156 0 : drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
1157 : {
1158 0 : struct drm_set_client_cap *req = data;
1159 :
1160 0 : switch (req->capability) {
1161 : case DRM_CLIENT_CAP_STEREO_3D:
1162 0 : if (req->value > 1)
1163 0 : return -EINVAL;
1164 0 : file_priv->stereo_allowed = req->value;
1165 : break;
1166 : default:
1167 0 : return -EINVAL;
1168 : }
1169 :
1170 0 : return 0;
1171 0 : }
1172 :
1173 : #define DRM_IF_MAJOR 1
1174 : #define DRM_IF_MINOR 4
1175 :
1176 : int
1177 0 : drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv)
1178 : {
1179 0 : struct drm_version *version = data;
1180 : int len;
1181 :
1182 : #define DRM_COPY(name, value) \
1183 : len = strlen( value ); \
1184 : if ( len > name##_len ) len = name##_len; \
1185 : name##_len = strlen( value ); \
1186 : if ( len && name ) { \
1187 : if ( DRM_COPY_TO_USER( name, value, len ) ) \
1188 : return -EFAULT; \
1189 : }
1190 :
1191 0 : version->version_major = dev->driver->major;
1192 0 : version->version_minor = dev->driver->minor;
1193 0 : version->version_patchlevel = dev->driver->patchlevel;
1194 :
1195 0 : DRM_COPY(version->name, dev->driver->name);
1196 0 : DRM_COPY(version->date, dev->driver->date);
1197 0 : DRM_COPY(version->desc, dev->driver->desc);
1198 :
1199 0 : return 0;
1200 0 : }
1201 :
1202 : int
1203 0 : drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_priv)
1204 : {
1205 0 : struct drm_set_version ver, *sv = data;
1206 : int if_version;
1207 :
1208 : /* Save the incoming data, and set the response before continuing
1209 : * any further.
1210 : */
1211 0 : ver = *sv;
1212 0 : sv->drm_di_major = DRM_IF_MAJOR;
1213 0 : sv->drm_di_minor = DRM_IF_MINOR;
1214 0 : sv->drm_dd_major = dev->driver->major;
1215 0 : sv->drm_dd_minor = dev->driver->minor;
1216 :
1217 : /*
1218 : * We no longer support interface versions less than 1.1, so error
1219 : * out if the xserver is too old. 1.1 always ties the drm to a
1220 : * certain busid, this was done on attach
1221 : */
1222 0 : if (ver.drm_di_major != -1) {
1223 0 : if (ver.drm_di_major != DRM_IF_MAJOR || ver.drm_di_minor < 1 ||
1224 0 : ver.drm_di_minor > DRM_IF_MINOR) {
1225 0 : return -EINVAL;
1226 : }
1227 0 : if_version = DRM_IF_VERSION(ver.drm_di_major, ver.drm_dd_minor);
1228 0 : dev->if_version = imax(if_version, dev->if_version);
1229 0 : }
1230 :
1231 0 : if (ver.drm_dd_major != -1) {
1232 0 : if (ver.drm_dd_major != dev->driver->major ||
1233 0 : ver.drm_dd_minor < 0 ||
1234 0 : ver.drm_dd_minor > dev->driver->minor)
1235 0 : return -EINVAL;
1236 : }
1237 :
1238 0 : return 0;
1239 0 : }
1240 :
1241 : struct drm_dmamem *
1242 0 : drm_dmamem_alloc(bus_dma_tag_t dmat, bus_size_t size, bus_size_t alignment,
1243 : int nsegments, bus_size_t maxsegsz, int mapflags, int loadflags)
1244 : {
1245 : struct drm_dmamem *mem;
1246 : size_t strsize;
1247 : /*
1248 : * segs is the last member of the struct since we modify the size
1249 : * to allow extra segments if more than one are allowed.
1250 : */
1251 0 : strsize = sizeof(*mem) + (sizeof(bus_dma_segment_t) * (nsegments - 1));
1252 0 : mem = malloc(strsize, M_DRM, M_NOWAIT | M_ZERO);
1253 0 : if (mem == NULL)
1254 0 : return (NULL);
1255 :
1256 0 : mem->size = size;
1257 :
1258 0 : if (bus_dmamap_create(dmat, size, nsegments, maxsegsz, 0,
1259 0 : BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mem->map) != 0)
1260 : goto strfree;
1261 :
1262 0 : if (bus_dmamem_alloc(dmat, size, alignment, 0, mem->segs, nsegments,
1263 0 : &mem->nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0)
1264 : goto destroy;
1265 :
1266 0 : if (bus_dmamem_map(dmat, mem->segs, mem->nsegs, size,
1267 0 : &mem->kva, BUS_DMA_NOWAIT | mapflags) != 0)
1268 : goto free;
1269 :
1270 0 : if (bus_dmamap_load(dmat, mem->map, mem->kva, size,
1271 0 : NULL, BUS_DMA_NOWAIT | loadflags) != 0)
1272 : goto unmap;
1273 :
1274 0 : return (mem);
1275 :
1276 : unmap:
1277 0 : bus_dmamem_unmap(dmat, mem->kva, size);
1278 : free:
1279 0 : bus_dmamem_free(dmat, mem->segs, mem->nsegs);
1280 : destroy:
1281 0 : bus_dmamap_destroy(dmat, mem->map);
1282 : strfree:
1283 0 : free(mem, M_DRM, 0);
1284 :
1285 0 : return (NULL);
1286 0 : }
1287 :
1288 : void
1289 0 : drm_dmamem_free(bus_dma_tag_t dmat, struct drm_dmamem *mem)
1290 : {
1291 0 : if (mem == NULL)
1292 : return;
1293 :
1294 0 : bus_dmamap_unload(dmat, mem->map);
1295 0 : bus_dmamem_unmap(dmat, mem->kva, mem->size);
1296 0 : bus_dmamem_free(dmat, mem->segs, mem->nsegs);
1297 0 : bus_dmamap_destroy(dmat, mem->map);
1298 0 : free(mem, M_DRM, 0);
1299 0 : }
1300 :
1301 : struct drm_dma_handle *
1302 0 : drm_pci_alloc(struct drm_device *dev, size_t size, size_t align)
1303 : {
1304 : struct drm_dma_handle *dmah;
1305 :
1306 0 : dmah = malloc(sizeof(*dmah), M_DRM, M_WAITOK);
1307 0 : dmah->mem = drm_dmamem_alloc(dev->dmat, size, align, 1, size,
1308 : BUS_DMA_NOCACHE, 0);
1309 0 : if (dmah->mem == NULL) {
1310 0 : free(dmah, M_DRM, sizeof(*dmah));
1311 0 : return NULL;
1312 : }
1313 0 : dmah->busaddr = dmah->mem->segs[0].ds_addr;
1314 0 : dmah->size = dmah->mem->size;
1315 0 : dmah->vaddr = dmah->mem->kva;
1316 0 : return (dmah);
1317 0 : }
1318 :
1319 : void
1320 0 : drm_pci_free(struct drm_device *dev, struct drm_dma_handle *dmah)
1321 : {
1322 0 : if (dmah == NULL)
1323 : return;
1324 :
1325 0 : drm_dmamem_free(dev->dmat, dmah->mem);
1326 0 : free(dmah, M_DRM, sizeof(*dmah));
1327 0 : }
1328 :
1329 : /**
1330 : * Called by the client, this returns a unique magic number to be authorized
1331 : * by the master.
1332 : *
1333 : * The master may use its own knowledge of the client (such as the X
1334 : * connection that the magic is passed over) to determine if the magic number
1335 : * should be authenticated.
1336 : */
1337 : int
1338 0 : drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
1339 : {
1340 0 : struct drm_auth *auth = data;
1341 :
1342 0 : if (dev->magicid == 0)
1343 0 : dev->magicid = 1;
1344 :
1345 : /* Find unique magic */
1346 0 : if (file_priv->magic) {
1347 0 : auth->magic = file_priv->magic;
1348 0 : } else {
1349 0 : mutex_lock(&dev->struct_mutex);
1350 0 : file_priv->magic = auth->magic = dev->magicid++;
1351 0 : mutex_unlock(&dev->struct_mutex);
1352 : DRM_DEBUG("%d\n", auth->magic);
1353 : }
1354 :
1355 : DRM_DEBUG("%u\n", auth->magic);
1356 0 : return 0;
1357 : }
1358 :
1359 : /**
1360 : * Marks the client associated with the given magic number as authenticated.
1361 : */
1362 : int
1363 0 : drm_authmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
1364 : {
1365 : struct drm_file *p;
1366 0 : struct drm_auth *auth = data;
1367 : int ret = -EINVAL;
1368 :
1369 : DRM_DEBUG("%u\n", auth->magic);
1370 :
1371 0 : if (auth->magic == 0)
1372 0 : return ret;
1373 :
1374 0 : mutex_lock(&dev->struct_mutex);
1375 0 : SPLAY_FOREACH(p, drm_file_tree, &dev->files) {
1376 0 : if (p->magic == auth->magic) {
1377 0 : p->authenticated = 1;
1378 0 : p->magic = 0;
1379 : ret = 0;
1380 0 : break;
1381 : }
1382 : }
1383 0 : mutex_unlock(&dev->struct_mutex);
1384 :
1385 0 : return ret;
1386 0 : }
1387 :
1388 : /*
1389 : * Compute order. Can be made faster.
1390 : */
1391 : int
1392 0 : drm_order(unsigned long size)
1393 : {
1394 : int order;
1395 : unsigned long tmp;
1396 :
1397 0 : for (order = 0, tmp = size; tmp >>= 1; ++order)
1398 : ;
1399 :
1400 0 : if (size & ~(1 << order))
1401 0 : ++order;
1402 :
1403 0 : return order;
1404 : }
1405 :
1406 0 : int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask)
1407 : {
1408 0 : pci_chipset_tag_t pc = dev->pc;
1409 : pcitag_t tag;
1410 0 : int pos ;
1411 : pcireg_t xcap, lnkcap = 0, lnkcap2 = 0;
1412 : pcireg_t id;
1413 :
1414 0 : *mask = 0;
1415 :
1416 0 : if (dev->bridgetag == NULL)
1417 0 : return -EINVAL;
1418 0 : tag = *dev->bridgetag;
1419 :
1420 0 : if (!pci_get_capability(pc, tag, PCI_CAP_PCIEXPRESS,
1421 : &pos, NULL))
1422 0 : return -EINVAL;
1423 :
1424 0 : id = pci_conf_read(pc, tag, PCI_ID_REG);
1425 :
1426 : /* we've been informed via and serverworks don't make the cut */
1427 0 : if (PCI_VENDOR(id) == PCI_VENDOR_VIATECH ||
1428 0 : PCI_VENDOR(id) == PCI_VENDOR_RCC)
1429 0 : return -EINVAL;
1430 :
1431 0 : lnkcap = pci_conf_read(pc, tag, pos + PCI_PCIE_LCAP);
1432 0 : xcap = pci_conf_read(pc, tag, pos + PCI_PCIE_XCAP);
1433 0 : if (PCI_PCIE_XCAP_VER(xcap) >= 2)
1434 0 : lnkcap2 = pci_conf_read(pc, tag, pos + PCI_PCIE_LCAP2);
1435 :
1436 0 : lnkcap &= 0x0f;
1437 0 : lnkcap2 &= 0xfe;
1438 :
1439 0 : if (lnkcap2) { /* PCIE GEN 3.0 */
1440 0 : if (lnkcap2 & 2)
1441 0 : *mask |= DRM_PCIE_SPEED_25;
1442 0 : if (lnkcap2 & 4)
1443 0 : *mask |= DRM_PCIE_SPEED_50;
1444 0 : if (lnkcap2 & 8)
1445 0 : *mask |= DRM_PCIE_SPEED_80;
1446 : } else {
1447 0 : if (lnkcap & 1)
1448 0 : *mask |= DRM_PCIE_SPEED_25;
1449 0 : if (lnkcap & 2)
1450 0 : *mask |= DRM_PCIE_SPEED_50;
1451 : }
1452 :
1453 : DRM_INFO("probing gen 2 caps for device 0x%04x:0x%04x = %x/%x\n",
1454 : PCI_VENDOR(id), PCI_PRODUCT(id), lnkcap, lnkcap2);
1455 0 : return 0;
1456 0 : }
1457 :
1458 : int
1459 0 : drm_getpciinfo(struct drm_device *dev, void *data, struct drm_file *file_priv)
1460 : {
1461 0 : struct drm_pciinfo *info = data;
1462 :
1463 0 : info->domain = 0;
1464 0 : info->bus = dev->pdev->bus->number;
1465 0 : info->dev = PCI_SLOT(dev->pdev->devfn);
1466 0 : info->func = PCI_FUNC(dev->pdev->devfn);
1467 0 : info->vendor_id = dev->pdev->vendor;
1468 0 : info->device_id = dev->pdev->device;
1469 0 : info->subvendor_id = dev->pdev->subsystem_vendor;
1470 0 : info->subdevice_id = dev->pdev->subsystem_device;
1471 0 : info->revision_id = 0;
1472 :
1473 0 : return 0;
1474 : }
|