xref: /openbsd-src/sys/dev/pci/drm/drm_drv.c (revision 2b0358df1d88d06ef4139321dd05bd5e05d91eaf)
1 /*-
2  * Copyright 2003 Eric Anholt
3  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
4  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24  * OTHER DEALINGS IN THE SOFTWARE.
25  *
26  * Authors:
27  *    Rickard E. (Rik) Faith <faith@valinux.com>
28  *    Daryll Strauss <daryll@valinux.com>
29  *    Gareth Hughes <gareth@valinux.com>
30  *
31  */
32 
33 /** @file drm_drv.c
34  * The catch-all file for DRM device support, including module setup/teardown,
35  * open/close, and ioctl dispatch.
36  */
37 
38 #include <sys/limits.h>
39 #include <sys/ttycom.h> /* for TIOCSGRP */
40 
41 #include "drmP.h"
42 #include "drm.h"
43 #include "drm_sarea.h"
44 
45 #ifdef DRM_DEBUG_DEFAULT_ON
46 int drm_debug_flag = 1;
47 #else
48 int drm_debug_flag = 0;
49 #endif
50 
51 int	 drm_firstopen(struct drm_device *);
52 int	 drm_lastclose(struct drm_device *);
53 void	 drm_attach(struct device *, struct device *, void *);
54 int	 drm_probe(struct device *, void *, void *);
55 int	 drm_detach(struct device *, int);
56 int	 drm_activate(struct device *, enum devact);
57 int	 drmprint(void *, const char *);
58 
59 int	 drm_getunique(struct drm_device *, void *, struct drm_file *);
60 int	 drm_version(struct drm_device *, void *, struct drm_file *);
61 int	 drm_setversion(struct drm_device *, void *, struct drm_file *);
62 int	 drm_getmagic(struct drm_device *, void *, struct drm_file *);
63 int	 drm_authmagic(struct drm_device *, void *, struct drm_file *);
64 int	 drm_file_cmp(struct drm_file *, struct drm_file *);
65 SPLAY_PROTOTYPE(drm_file_tree, drm_file, link, drm_file_cmp);
66 
67 /*
68  * attach drm to a pci-based driver.
69  *
70  * This function does all the pci-specific calculations for the
71  * drm_attach_args.
72  */
73 struct device *
74 drm_attach_pci(const struct drm_driver_info *driver, struct pci_attach_args *pa,
75     int is_agp, struct device *dev)
76 {
77 	struct drm_attach_args arg;
78 
79 	arg.driver = driver;
80 	arg.dmat = pa->pa_dmat;
81 	arg.bst = pa->pa_memt;
82 	arg.irq = pa->pa_intrline;
83 	arg.is_agp = is_agp;
84 
85 	arg.busid_len = 20;
86 	arg.busid = malloc(arg.busid_len + 1, M_DRM, M_NOWAIT);
87 	if (arg.busid == NULL) {
88 		printf("%s: no memory for drm\n", dev->dv_xname);
89 		return (NULL);
90 	}
91 	snprintf(arg.busid, arg.busid_len, "pci:%04x:%02x:%02x.%1x",
92 	    pa->pa_domain, pa->pa_bus, pa->pa_device, pa->pa_function);
93 
94 	return (config_found(dev, &arg, drmprint));
95 }
96 
97 int
98 drmprint(void *aux, const char *pnp)
99 {
100 	if (pnp != NULL)
101 		printf("drm at %s", pnp);
102 	return (UNCONF);
103 }
104 
105 int
106 drm_pciprobe(struct pci_attach_args *pa, const struct drm_pcidev *idlist)
107 {
108 	const struct drm_pcidev *id_entry;
109 
110 	id_entry = drm_find_description(PCI_VENDOR(pa->pa_id),
111 	    PCI_PRODUCT(pa->pa_id), idlist);
112 	if (id_entry != NULL)
113 		return 1;
114 
115 	return 0;
116 }
117 
118 int
119 drm_probe(struct device *parent, void *match, void *aux)
120 {
121 	struct drm_attach_args *da = aux;
122 
123 	return (da->driver != NULL ? 1 : 0);
124 }
125 
126 void
127 drm_attach(struct device *parent, struct device *self, void *aux)
128 {
129 	struct drm_device	*dev = (struct drm_device *)self;
130 	struct drm_attach_args	*da = aux;
131 
132 	dev->dev_private = parent;
133 	dev->driver = da->driver;
134 
135 	dev->dmat = da->dmat;
136 	dev->bst = da->bst;
137 	dev->irq = da->irq;
138 	dev->unique = da->busid;
139 	dev->unique_len = da->busid_len;
140 
141 	rw_init(&dev->dev_lock, "drmdevlk");
142 	mtx_init(&dev->lock.spinlock, IPL_NONE);
143 
144 	TAILQ_INIT(&dev->maplist);
145 	SPLAY_INIT(&dev->files);
146 
147 	if (dev->driver->vblank_pipes != 0 && drm_vblank_init(dev,
148 	    dev->driver->vblank_pipes)) {
149 		printf(": failed to allocate vblank data\n");
150 		goto error;
151 	}
152 
153 	/*
154 	 * the dma buffers api is just weird. offset 1Gb to ensure we don't
155 	 * conflict with it.
156 	 */
157 	dev->handle_ext = extent_create("drmext", 1024*1024*1024, LONG_MAX,
158 	    M_DRM, NULL, NULL, EX_NOWAIT | EX_NOCOALESCE);
159 	if (dev->handle_ext == NULL) {
160 		DRM_ERROR("Failed to initialise handle extent\n");
161 		goto error;
162 	}
163 
164 	if (dev->driver->flags & DRIVER_AGP) {
165 		if (da->is_agp)
166 			dev->agp = drm_agp_init();
167 		if (dev->driver->flags & DRIVER_AGP_REQUIRE &&
168 		    dev->agp == NULL) {
169 			printf(": couldn't find agp\n");
170 			goto error;
171 		}
172 		if (dev->agp != NULL) {
173 			if (drm_mtrr_add(dev->agp->info.ai_aperture_base,
174 			    dev->agp->info.ai_aperture_size, DRM_MTRR_WC) == 0)
175 				dev->agp->mtrr = 1;
176 		}
177 	}
178 
179 	if (drm_ctxbitmap_init(dev) != 0) {
180 		printf(": couldn't allocate memory for context bitmap.\n");
181 		goto error;
182 	}
183 	printf("\n");
184 	return;
185 
186 error:
187 	drm_lastclose(dev);
188 }
189 
190 int
191 drm_detach(struct device *self, int flags)
192 {
193 	struct drm_device *dev = (struct drm_device *)self;
194 
195 	drm_lastclose(dev);
196 
197 	drm_ctxbitmap_cleanup(dev);
198 
199 	extent_destroy(dev->handle_ext);
200 
201 	drm_vblank_cleanup(dev);
202 
203 	if (dev->agp && dev->agp->mtrr) {
204 		int retcode;
205 
206 		retcode = drm_mtrr_del(0, dev->agp->info.ai_aperture_base,
207 		    dev->agp->info.ai_aperture_size, DRM_MTRR_WC);
208 		DRM_DEBUG("mtrr_del = %d", retcode);
209 	}
210 
211 
212 	if (dev->agp != NULL) {
213 		drm_free(dev->agp);
214 		dev->agp = NULL;
215 	}
216 
217 	return 0;
218 }
219 
220 int
221 drm_activate(struct device *self, enum devact act)
222 {
223 	switch (act) {
224 	case DVACT_ACTIVATE:
225 		return (EOPNOTSUPP);
226 		break;
227 
228 	case DVACT_DEACTIVATE:
229 		/* FIXME */
230 		break;
231 	}
232 	return (0);
233 }
234 
235 struct cfattach drm_ca = {
236 	sizeof(struct drm_device), drm_probe, drm_attach,
237 	drm_detach, drm_activate
238 };
239 
240 struct cfdriver drm_cd = {
241 	0, "drm", DV_DULL
242 };
243 
244 const struct drm_pcidev *
245 drm_find_description(int vendor, int device, const struct drm_pcidev *idlist)
246 {
247 	int i = 0;
248 
249 	for (i = 0; idlist[i].vendor != 0; i++) {
250 		if ((idlist[i].vendor == vendor) &&
251 		    (idlist[i].device == device))
252 			return &idlist[i];
253 	}
254 	return NULL;
255 }
256 
257 int
258 drm_file_cmp(struct drm_file *f1, struct drm_file *f2)
259 {
260 	return (f1->minor < f2->minor ? -1 : f1->minor > f2->minor);
261 }
262 
263 SPLAY_GENERATE(drm_file_tree, drm_file, link, drm_file_cmp);
264 
265 struct drm_file *
266 drm_find_file_by_minor(struct drm_device *dev, int minor)
267 {
268 	struct drm_file	key;
269 
270 	key.minor = minor;
271 	return (SPLAY_FIND(drm_file_tree, &dev->files, &key));
272 }
273 
274 int
275 drm_firstopen(struct drm_device *dev)
276 {
277 	struct drm_local_map	*map;
278 	int			 i;
279 
280 	/* prebuild the SAREA */
281 	i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM,
282 	    _DRM_CONTAINS_LOCK, &map);
283 	if (i != 0)
284 		return i;
285 
286 	if (dev->driver->firstopen)
287 		dev->driver->firstopen(dev);
288 
289 	if (dev->driver->flags & DRIVER_DMA) {
290 		if ((i = drm_dma_setup(dev)) != 0)
291 			return (i);
292 	}
293 
294 	dev->magicid = 1;
295 
296 	dev->irq_enabled = 0;
297 	dev->if_version = 0;
298 
299 	dev->buf_pgid = 0;
300 
301 	DRM_DEBUG("\n");
302 
303 	return 0;
304 }
305 
306 int
307 drm_lastclose(struct drm_device *dev)
308 {
309 	struct drm_local_map	*map, *mapsave;
310 
311 	DRM_DEBUG("\n");
312 
313 	if (dev->driver->lastclose != NULL)
314 		dev->driver->lastclose(dev);
315 
316 	if (dev->irq_enabled)
317 		drm_irq_uninstall(dev);
318 
319 	drm_agp_takedown(dev);
320 	drm_dma_takedown(dev);
321 
322 	DRM_LOCK();
323 	if (dev->sg != NULL) {
324 		struct drm_sg_mem *sg = dev->sg;
325 		dev->sg = NULL;
326 
327 		DRM_UNLOCK();
328 		drm_sg_cleanup(dev, sg);
329 		DRM_LOCK();
330 	}
331 
332 	for (map = TAILQ_FIRST(&dev->maplist); map != TAILQ_END(&dev->maplist);
333 	    map = mapsave) {
334 		mapsave = TAILQ_NEXT(map, link);
335 		if ((map->flags & _DRM_DRIVER) == 0)
336 			drm_rmmap_locked(dev, map);
337 	}
338 
339 	if (dev->lock.hw_lock != NULL) {
340 		dev->lock.hw_lock = NULL; /* SHM removed */
341 		dev->lock.file_priv = NULL;
342 		wakeup(&dev->lock); /* there should be nothing sleeping on it */
343 	}
344 	DRM_UNLOCK();
345 
346 	return 0;
347 }
348 
349 int
350 drmopen(dev_t kdev, int flags, int fmt, struct proc *p)
351 {
352 	struct drm_device	*dev = NULL;
353 	struct drm_file		*priv;
354 	int			 ret = 0;
355 
356 	dev = drm_get_device_from_kdev(kdev);
357 	if (dev == NULL)
358 		return (ENXIO);
359 
360 	DRM_DEBUG("open_count = %d\n", dev->open_count);
361 
362 	if (flags & O_EXCL)
363 		return (EBUSY); /* No exclusive opens */
364 
365 	DRM_LOCK();
366 	if (dev->open_count++ == 0) {
367 		DRM_UNLOCK();
368 		if ((ret = drm_firstopen(dev)) != 0)
369 			goto err;
370 	} else {
371 		DRM_UNLOCK();
372 	}
373 
374 	/* always allocate at least enough space for our data */
375 	priv = drm_calloc(1, max(dev->driver->file_priv_size,
376 	    sizeof(*priv)));
377 	if (priv == NULL) {
378 		ret = ENOMEM;
379 		goto err;
380 	}
381 
382 	priv->kdev = kdev;
383 	priv->flags = flags;
384 	priv->minor = minor(kdev);
385 	DRM_DEBUG("minor = %d\n", priv->minor);
386 
387 	/* for compatibility root is always authenticated */
388 	priv->authenticated = DRM_SUSER(p);
389 
390 	if (dev->driver->open) {
391 		ret = dev->driver->open(dev, priv);
392 		if (ret != 0) {
393 			goto free_priv;
394 		}
395 	}
396 
397 	DRM_LOCK();
398 	/* first opener automatically becomes master if root */
399 	if (SPLAY_EMPTY(&dev->files) && !DRM_SUSER(p)) {
400 		DRM_UNLOCK();
401 		ret = EPERM;
402 		goto free_priv;
403 	}
404 
405 	priv->master = SPLAY_EMPTY(&dev->files);
406 
407 	SPLAY_INSERT(drm_file_tree, &dev->files, priv);
408 	DRM_UNLOCK();
409 
410 	return (0);
411 
412 free_priv:
413 	drm_free(priv);
414 err:
415 	DRM_LOCK();
416 	--dev->open_count;
417 	DRM_UNLOCK();
418 	return (ret);
419 }
420 
421 int
422 drmclose(dev_t kdev, int flags, int fmt, struct proc *p)
423 {
424 	struct drm_device *dev = drm_get_device_from_kdev(kdev);
425 	struct drm_file *file_priv;
426 	int retcode = 0;
427 
428 	if (dev == NULL)
429 		return (ENXIO);
430 
431 	DRM_DEBUG("open_count = %d\n", dev->open_count);
432 
433 	DRM_LOCK();
434 	file_priv = drm_find_file_by_minor(dev, minor(kdev));
435 	if (file_priv == NULL) {
436 		DRM_ERROR("can't find authenticator\n");
437 		retcode = EINVAL;
438 		goto done;
439 	}
440 	DRM_UNLOCK();
441 
442 	if (dev->driver->close != NULL)
443 		dev->driver->close(dev, file_priv);
444 
445 	DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
446 	    DRM_CURRENTPID, (long)&dev->device, dev->open_count);
447 
448 	if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
449 	    && dev->lock.file_priv == file_priv) {
450 		DRM_DEBUG("Process %d dead, freeing lock for context %d\n",
451 		    DRM_CURRENTPID,
452 		    _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
453 		if (dev->driver->reclaim_buffers_locked != NULL)
454 			dev->driver->reclaim_buffers_locked(dev, file_priv);
455 
456 		drm_lock_free(&dev->lock,
457 		    _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
458 	} else if (dev->driver->reclaim_buffers_locked != NULL &&
459 	    dev->lock.hw_lock != NULL) {
460 		mtx_enter(&dev->lock.spinlock);
461 		/* The lock is required to reclaim buffers */
462 		for (;;) {
463 			if (dev->lock.hw_lock == NULL) {
464 				/* Device has been unregistered */
465 				retcode = EINTR;
466 				break;
467 			}
468 			if (drm_lock_take(&dev->lock, DRM_KERNEL_CONTEXT)) {
469 				dev->lock.file_priv = file_priv;
470 				break;	/* Got lock */
471 			}
472 				/* Contention */
473 			retcode = msleep(&dev->lock,
474 			    &dev->lock.spinlock, PZERO | PCATCH, "drmlk2", 0);
475 			if (retcode)
476 				break;
477 		}
478 		mtx_leave(&dev->lock.spinlock);
479 		if (retcode == 0) {
480 			dev->driver->reclaim_buffers_locked(dev, file_priv);
481 			drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT);
482 		}
483 	}
484 
485 	if (dev->driver->flags & DRIVER_DMA &&
486 	    !dev->driver->reclaim_buffers_locked)
487 		drm_reclaim_buffers(dev, file_priv);
488 
489 	dev->buf_pgid = 0;
490 
491 	DRM_LOCK();
492 	SPLAY_REMOVE(drm_file_tree, &dev->files, file_priv);
493 	drm_free(file_priv);
494 
495 done:
496 	if (--dev->open_count == 0) {
497 		DRM_UNLOCK();
498 		retcode = drm_lastclose(dev);
499 	}
500 
501 	DRM_UNLOCK();
502 
503 	return (retcode);
504 }
505 
506 /* drmioctl is called whenever a process performs an ioctl on /dev/drm.
507  */
508 int
509 drmioctl(dev_t kdev, u_long cmd, caddr_t data, int flags,
510     struct proc *p)
511 {
512 	struct drm_device *dev = drm_get_device_from_kdev(kdev);
513 	struct drm_file *file_priv;
514 
515 	if (dev == NULL)
516 		return ENODEV;
517 
518 	DRM_LOCK();
519 	file_priv = drm_find_file_by_minor(dev, minor(kdev));
520 	DRM_UNLOCK();
521 	if (file_priv == NULL) {
522 		DRM_ERROR("can't find authenticator\n");
523 		return EINVAL;
524 	}
525 
526 	++file_priv->ioctl_count;
527 
528 	DRM_DEBUG("pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
529 	    DRM_CURRENTPID, cmd, DRM_IOCTL_NR(cmd), (long)&dev->device,
530 	    file_priv->authenticated);
531 
532 	switch (cmd) {
533 	case FIONBIO:
534 	case FIOASYNC:
535 		return 0;
536 
537 	case TIOCSPGRP:
538 		dev->buf_pgid = *(int *)data;
539 		return 0;
540 
541 	case TIOCGPGRP:
542 		*(int *)data = dev->buf_pgid;
543 		return 0;
544 	case DRM_IOCTL_VERSION:
545 		return (drm_version(dev, data, file_priv));
546 	case DRM_IOCTL_GET_UNIQUE:
547 		return (drm_getunique(dev, data, file_priv));
548 	case DRM_IOCTL_GET_MAGIC:
549 		return (drm_getmagic(dev, data, file_priv));
550 	case DRM_IOCTL_WAIT_VBLANK:
551 		return (drm_wait_vblank(dev, data, file_priv));
552 	case DRM_IOCTL_MODESET_CTL:
553 		return (drm_modeset_ctl(dev, data, file_priv));
554 
555 	/* removed */
556 	case DRM_IOCTL_GET_MAP:
557 		/* FALLTHROUGH */
558 	case DRM_IOCTL_GET_CLIENT:
559 		/* FALLTHROUGH */
560 	case DRM_IOCTL_GET_STATS:
561 		return (EINVAL);
562 	/*
563 	 * no-oped ioctls, we don't check permissions on them because
564 	 * they do nothing. they'll be removed as soon as userland is
565 	 * definitely purged
566 	 */
567 	case DRM_IOCTL_SET_SAREA_CTX:
568 	case DRM_IOCTL_BLOCK:
569 	case DRM_IOCTL_UNBLOCK:
570 	case DRM_IOCTL_MOD_CTX:
571 	case DRM_IOCTL_MARK_BUFS:
572 	case DRM_IOCTL_FINISH:
573 	case DRM_IOCTL_INFO_BUFS:
574 	case DRM_IOCTL_SWITCH_CTX:
575 	case DRM_IOCTL_NEW_CTX:
576 	case DRM_IOCTL_GET_SAREA_CTX:
577 		return (0);
578 	}
579 
580 	if (file_priv->authenticated == 1) {
581 		switch (cmd) {
582 		case DRM_IOCTL_RM_MAP:
583 			return (drm_rmmap_ioctl(dev, data, file_priv));
584 		case DRM_IOCTL_GET_CTX:
585 			return (drm_getctx(dev, data, file_priv));
586 		case DRM_IOCTL_RES_CTX:
587 			return (drm_resctx(dev, data, file_priv));
588 		case DRM_IOCTL_LOCK:
589 			return (drm_lock(dev, data, file_priv));
590 		case DRM_IOCTL_UNLOCK:
591 			return (drm_unlock(dev, data, file_priv));
592 		case DRM_IOCTL_MAP_BUFS:
593 			return (drm_mapbufs(dev, data, file_priv));
594 		case DRM_IOCTL_FREE_BUFS:
595 			return (drm_freebufs(dev, data, file_priv));
596 		case DRM_IOCTL_DMA:
597 			return (drm_dma(dev, data, file_priv));
598 		case DRM_IOCTL_AGP_INFO:
599 			return (drm_agp_info_ioctl(dev, data, file_priv));
600 		}
601 	}
602 
603 	/* master is always root */
604 	if (file_priv->master == 1) {
605 		switch(cmd) {
606 		case DRM_IOCTL_SET_VERSION:
607 			return (drm_setversion(dev, data, file_priv));
608 		case DRM_IOCTL_IRQ_BUSID:
609 			return (drm_irq_by_busid(dev, data, file_priv));
610 		case DRM_IOCTL_AUTH_MAGIC:
611 			return (drm_authmagic(dev, data, file_priv));
612 		case DRM_IOCTL_ADD_MAP:
613 			return (drm_addmap_ioctl(dev, data, file_priv));
614 		case DRM_IOCTL_ADD_CTX:
615 			return (drm_addctx(dev, data, file_priv));
616 		case DRM_IOCTL_RM_CTX:
617 			return (drm_rmctx(dev, data, file_priv));
618 		case DRM_IOCTL_ADD_BUFS:
619 			return (drm_addbufs(dev, (struct drm_buf_desc *)data));
620 		case DRM_IOCTL_CONTROL:
621 			return (drm_control(dev, data, file_priv));
622 		case DRM_IOCTL_AGP_ACQUIRE:
623 			return (drm_agp_acquire_ioctl(dev, data, file_priv));
624 		case DRM_IOCTL_AGP_RELEASE:
625 			return (drm_agp_release_ioctl(dev, data, file_priv));
626 		case DRM_IOCTL_AGP_ENABLE:
627 			return (drm_agp_enable_ioctl(dev, data, file_priv));
628 		case DRM_IOCTL_AGP_ALLOC:
629 			return (drm_agp_alloc_ioctl(dev, data, file_priv));
630 		case DRM_IOCTL_AGP_FREE:
631 			return (drm_agp_free_ioctl(dev, data, file_priv));
632 		case DRM_IOCTL_AGP_BIND:
633 			return (drm_agp_bind_ioctl(dev, data, file_priv));
634 		case DRM_IOCTL_AGP_UNBIND:
635 			return (drm_agp_unbind_ioctl(dev, data, file_priv));
636 		case DRM_IOCTL_SG_ALLOC:
637 			return (drm_sg_alloc_ioctl(dev, data, file_priv));
638 		case DRM_IOCTL_SG_FREE:
639 			return (drm_sg_free(dev, data, file_priv));
640 		case DRM_IOCTL_ADD_DRAW:
641 		case DRM_IOCTL_RM_DRAW:
642 		case DRM_IOCTL_UPDATE_DRAW:
643 			/*
644 			 * Support removed from kernel since it's not used.
645 			 * just return zero until userland stops calling this
646 			 * ioctl.
647 			 */
648 			return (0);
649 		case DRM_IOCTL_SET_UNIQUE:
650 		/*
651 		 * Deprecated in DRM version 1.1, and will return EBUSY
652 		 * when setversion has
653 		 * requested version 1.1 or greater.
654 		 */
655 			return (EBUSY);
656 		}
657 	}
658 	if (dev->driver->ioctl != NULL)
659 		return (dev->driver->ioctl(dev, cmd, data, file_priv));
660 	else
661 		return (EINVAL);
662 }
663 
664 struct drm_local_map *
665 drm_getsarea(struct drm_device *dev)
666 {
667 	struct drm_local_map	*map;
668 
669 	DRM_LOCK();
670 	TAILQ_FOREACH(map, &dev->maplist, link) {
671 		if (map->type == _DRM_SHM && (map->flags & _DRM_CONTAINS_LOCK))
672 			break;
673 	}
674 	DRM_UNLOCK();
675 	return (map);
676 }
677 
678 paddr_t
679 drmmmap(dev_t kdev, off_t offset, int prot)
680 {
681 	struct drm_device	*dev = drm_get_device_from_kdev(kdev);
682 	struct drm_local_map	*map;
683 	struct drm_file		*priv;
684 	enum drm_map_type	 type;
685 
686 	if (dev == NULL)
687 		return (-1);
688 
689 	DRM_LOCK();
690 	priv = drm_find_file_by_minor(dev, minor(kdev));
691 	DRM_UNLOCK();
692 	if (priv == NULL) {
693 		DRM_ERROR("can't find authenticator\n");
694 		return (-1);
695 	}
696 
697 	if (!priv->authenticated)
698 		return (-1);
699 
700 	if (dev->dma && offset >= 0 && offset < ptoa(dev->dma->page_count)) {
701 		struct drm_device_dma *dma = dev->dma;
702 		paddr_t	phys = -1;
703 
704 		rw_enter_write(&dma->dma_lock);
705 		if (dma->pagelist != NULL)
706 			phys = atop(dma->pagelist[offset >> PAGE_SHIFT]);
707 		rw_exit_write(&dma->dma_lock);
708 
709 		return (phys);
710 	}
711 
712 	/*
713 	 * A sequential search of a linked list is
714  	 * fine here because: 1) there will only be
715 	 * about 5-10 entries in the list and, 2) a
716 	 * DRI client only has to do this mapping
717 	 * once, so it doesn't have to be optimized
718 	 * for performance, even if the list was a
719 	 * bit longer.
720 	 */
721 	DRM_LOCK();
722 	TAILQ_FOREACH(map, &dev->maplist, link) {
723 		if (offset >= map->ext &&
724 		    offset < map->ext + map->size) {
725 			offset -= map->ext;
726 			break;
727 		}
728 	}
729 
730 	if (map == NULL) {
731 		DRM_UNLOCK();
732 		DRM_DEBUG("can't find map\n");
733 		return (-1);
734 	}
735 	if (((map->flags & _DRM_RESTRICTED) && priv->master == 0)) {
736 		DRM_UNLOCK();
737 		DRM_DEBUG("restricted map\n");
738 		return (-1);
739 	}
740 	type = map->type;
741 	DRM_UNLOCK();
742 
743 	switch (type) {
744 	case _DRM_FRAME_BUFFER:
745 	case _DRM_REGISTERS:
746 	case _DRM_AGP:
747 		return (atop(offset + map->offset));
748 		break;
749 	/* XXX unify all the bus_dmamem_mmap bits */
750 	case _DRM_SCATTER_GATHER:
751 		return (bus_dmamem_mmap(dev->dmat, dev->sg->mem->segs,
752 		    dev->sg->mem->nsegs, map->offset - dev->sg->handle +
753 		    offset, prot, BUS_DMA_NOWAIT));
754 	case _DRM_SHM:
755 	case _DRM_CONSISTENT:
756 		return (bus_dmamem_mmap(dev->dmat, map->dmamem->segs,
757 		    map->dmamem->nsegs, offset, prot, BUS_DMA_NOWAIT));
758 	default:
759 		DRM_ERROR("bad map type %d\n", type);
760 		return (-1);	/* This should never happen. */
761 	}
762 	/* NOTREACHED */
763 }
764 
765 /*
766  * Beginning in revision 1.1 of the DRM interface, getunique will return
767  * a unique in the form pci:oooo:bb:dd.f (o=domain, b=bus, d=device, f=function)
768  * before setunique has been called.  The format for the bus-specific part of
769  * the unique is not defined for any other bus.
770  */
771 int
772 drm_getunique(struct drm_device *dev, void *data, struct drm_file *file_priv)
773 {
774 	struct drm_unique	 *u = data;
775 
776 	if (u->unique_len >= dev->unique_len) {
777 		if (DRM_COPY_TO_USER(u->unique, dev->unique, dev->unique_len))
778 			return EFAULT;
779 	}
780 	u->unique_len = dev->unique_len;
781 
782 	return 0;
783 }
784 
785 #define DRM_IF_MAJOR	1
786 #define DRM_IF_MINOR	2
787 
788 int
789 drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv)
790 {
791 	struct drm_version	*version = data;
792 	int			 len;
793 
794 #define DRM_COPY(name, value)						\
795 	len = strlen( value );						\
796 	if ( len > name##_len ) len = name##_len;			\
797 	name##_len = strlen( value );					\
798 	if ( len && name ) {						\
799 		if ( DRM_COPY_TO_USER( name, value, len ) )		\
800 			return EFAULT;				\
801 	}
802 
803 	version->version_major = dev->driver->major;
804 	version->version_minor = dev->driver->minor;
805 	version->version_patchlevel = dev->driver->patchlevel;
806 
807 	DRM_COPY(version->name, dev->driver->name);
808 	DRM_COPY(version->date, dev->driver->date);
809 	DRM_COPY(version->desc, dev->driver->desc);
810 
811 	return 0;
812 }
813 
814 int
815 drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_priv)
816 {
817 	struct drm_set_version	ver, *sv = data;
818 	int			if_version;
819 
820 	/* Save the incoming data, and set the response before continuing
821 	 * any further.
822 	 */
823 	ver = *sv;
824 	sv->drm_di_major = DRM_IF_MAJOR;
825 	sv->drm_di_minor = DRM_IF_MINOR;
826 	sv->drm_dd_major = dev->driver->major;
827 	sv->drm_dd_minor = dev->driver->minor;
828 
829 	/*
830 	 * We no longer support interface versions less than 1.1, so error
831 	 * out if the xserver is too old. 1.1 always ties the drm to a
832 	 * certain busid, this was done on attach
833 	 */
834 	if (ver.drm_di_major != -1) {
835 		if (ver.drm_di_major != DRM_IF_MAJOR || ver.drm_di_minor < 1 ||
836 		    ver.drm_di_minor > DRM_IF_MINOR) {
837 			return EINVAL;
838 		}
839 		if_version = DRM_IF_VERSION(ver.drm_di_major, ver.drm_dd_minor);
840 		dev->if_version = imax(if_version, dev->if_version);
841 	}
842 
843 	if (ver.drm_dd_major != -1) {
844 		if (ver.drm_dd_major != dev->driver->major ||
845 		    ver.drm_dd_minor < 0 ||
846 		    ver.drm_dd_minor > dev->driver->minor)
847 			return EINVAL;
848 	}
849 
850 	return 0;
851 }
852 
853 struct drm_dmamem *
854 drm_dmamem_alloc(bus_dma_tag_t dmat, bus_size_t size, bus_size_t alignment,
855     int nsegments, bus_size_t maxsegsz, int mapflags, int loadflags)
856 {
857 	struct drm_dmamem	*mem;
858 	size_t			 strsize;
859 	/*
860 	 * segs is the last member of the struct since we modify the size
861 	 * to allow extra segments if more than one are allowed.
862 	 */
863 	strsize = sizeof(*mem) + (sizeof(bus_dma_segment_t) * (nsegments - 1));
864 	mem = malloc(strsize, M_DRM, M_NOWAIT | M_ZERO);
865 	if (mem == NULL)
866 		return (NULL);
867 
868 	mem->size = size;
869 
870 	if (bus_dmamap_create(dmat, size, nsegments, maxsegsz, 0,
871 	    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mem->map) != 0)
872 		goto strfree;
873 
874 	if (bus_dmamem_alloc(dmat, size, alignment, 0,
875 	    mem->segs, nsegments, &mem->nsegs, BUS_DMA_NOWAIT) != 0)
876 		goto destroy;
877 
878 	if (bus_dmamem_map(dmat, mem->segs, mem->nsegs, size,
879 	    &mem->kva, BUS_DMA_NOWAIT | mapflags) != 0)
880 		goto free;
881 
882 	if (bus_dmamap_load(dmat, mem->map, mem->kva, size,
883 	    NULL, BUS_DMA_NOWAIT | loadflags) != 0)
884 		goto unmap;
885 	bzero(mem->kva, size);
886 
887 	return (mem);
888 
889 unmap:
890 	bus_dmamem_unmap(dmat, mem->kva, size);
891 free:
892 	bus_dmamem_free(dmat, mem->segs, mem->nsegs);
893 destroy:
894 	bus_dmamap_destroy(dmat, mem->map);
895 strfree:
896 	free(mem, M_DRM);
897 
898 	return (NULL);
899 }
900 
901 void
902 drm_dmamem_free(bus_dma_tag_t dmat, struct drm_dmamem *mem)
903 {
904 	if (mem == NULL)
905 		return;
906 
907 	bus_dmamap_unload(dmat, mem->map);
908 	bus_dmamem_unmap(dmat, mem->kva, mem->size);
909 	bus_dmamem_free(dmat, mem->segs, mem->nsegs);
910 	bus_dmamap_destroy(dmat, mem->map);
911 	free(mem, M_DRM);
912 }
913 
914 /**
915  * Called by the client, this returns a unique magic number to be authorized
916  * by the master.
917  *
918  * The master may use its own knowledge of the client (such as the X
919  * connection that the magic is passed over) to determine if the magic number
920  * should be authenticated.
921  */
922 int
923 drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
924 {
925 	struct drm_auth		*auth = data;
926 
927 	if (dev->magicid == 0)
928 		dev->magicid = 1;
929 
930 	/* Find unique magic */
931 	if (file_priv->magic) {
932 		auth->magic = file_priv->magic;
933 	} else {
934 		DRM_LOCK();
935 		file_priv->magic = auth->magic = dev->magicid++;
936 		DRM_UNLOCK();
937 		DRM_DEBUG("%d\n", auth->magic);
938 	}
939 
940 	DRM_DEBUG("%u\n", auth->magic);
941 
942 	return (0);
943 }
944 
945 /**
946  * Marks the client associated with the given magic number as authenticated.
947  */
948 int
949 drm_authmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
950 {
951 	struct drm_file	*p;
952 	struct drm_auth	*auth = data;
953 	int		 ret = EINVAL;
954 
955 	DRM_DEBUG("%u\n", auth->magic);
956 
957 	if (auth->magic == 0)
958 		return (ret);
959 
960 	DRM_LOCK();
961 	SPLAY_FOREACH(p, drm_file_tree, &dev->files) {
962 		if (p->magic == auth->magic) {
963 			p->authenticated = 1;
964 			p->magic = 0;
965 			ret = 0;
966 			break;
967 		}
968 	}
969 	DRM_UNLOCK();
970 
971 	return (ret);
972 }
973