FreeBSD/Linux Kernel Cross Reference
sys/dev/drm/drm_drv.h
1 /* drm_drv.h -- Generic driver template -*- linux-c -*-
2 * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com */
3 /*-
4 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 * Gareth Hughes <gareth@valinux.com>
30 *
31 * $FreeBSD$
32 */
33
34 /*
35 * To use this template, you must at least define the following (samples
36 * given for the MGA driver):
37 *
38 * #define DRIVER_AUTHOR "VA Linux Systems, Inc."
39 *
40 * #define DRIVER_NAME "mga"
41 * #define DRIVER_DESC "Matrox G200/G400"
42 * #define DRIVER_DATE "20001127"
43 *
44 * #define DRIVER_MAJOR 2
45 * #define DRIVER_MINOR 0
46 * #define DRIVER_PATCHLEVEL 2
47 *
48 * #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( mga_ioctls )
49 *
50 * #define DRM(x) mga_##x
51 */
52
53 #ifndef __MUST_HAVE_AGP
54 #define __MUST_HAVE_AGP 0
55 #endif
56 #ifndef __HAVE_CTX_BITMAP
57 #define __HAVE_CTX_BITMAP 0
58 #endif
59 #ifndef __HAVE_IRQ
60 #define __HAVE_IRQ 0
61 #endif
62 #ifndef __HAVE_DMA_QUEUE
63 #define __HAVE_DMA_QUEUE 0
64 #endif
65 #ifndef __HAVE_DMA_SCHEDULE
66 #define __HAVE_DMA_SCHEDULE 0
67 #endif
68 #ifndef __HAVE_DMA_QUIESCENT
69 #define __HAVE_DMA_QUIESCENT 0
70 #endif
71 #ifndef __HAVE_RELEASE
72 #define __HAVE_RELEASE 0
73 #endif
74 #ifndef __HAVE_COUNTERS
75 #define __HAVE_COUNTERS 0
76 #endif
77 #ifndef __HAVE_SG
78 #define __HAVE_SG 0
79 #endif
80
81 #ifndef DRIVER_PREINIT
82 #define DRIVER_PREINIT(dev) do {} while (0)
83 #endif
84 #ifndef DRIVER_POSTINIT
85 #define DRIVER_POSTINIT(dev) do {} while (0)
86 #endif
87 #ifndef DRIVER_PRERELEASE
88 #define DRIVER_PRERELEASE()
89 #endif
90 #ifndef DRIVER_PRETAKEDOWN
91 #define DRIVER_PRETAKEDOWN(dev)
92 #endif
93 #ifndef DRIVER_POSTCLEANUP
94 #define DRIVER_POSTCLEANUP()
95 #endif
96 #ifndef DRIVER_PRESETUP
97 #define DRIVER_PRESETUP()
98 #endif
99 #ifndef DRIVER_POSTSETUP
100 #define DRIVER_POSTSETUP()
101 #endif
102 #ifndef DRIVER_IOCTLS
103 #define DRIVER_IOCTLS
104 #endif
105 #ifndef DRIVER_OPEN_HELPER
106 #define DRIVER_OPEN_HELPER( priv, dev )
107 #endif
108 #ifndef DRIVER_FOPS
109 #endif
110
111 #if 1 && DRM_DEBUG_CODE
112 int DRM(flags) = DRM_FLAG_DEBUG;
113 #else
114 int DRM(flags) = 0;
115 #endif
116
117 static int DRM(init)(device_t nbdev);
118 static void DRM(cleanup)(drm_device_t *dev);
119
120 #ifdef __FreeBSD__
121 #define DRIVER_SOFTC(unit) \
122 ((drm_device_t *) devclass_get_softc(DRM(devclass), unit))
123
124 #if __REALLY_HAVE_AGP
125 MODULE_DEPEND(DRIVER_NAME, agp, 1, 1, 1);
126 #endif
127 MODULE_DEPEND(DRIVER_NAME, mem, 1, 1, 1);
128 #endif /* __FreeBSD__ */
129
130 #ifdef __NetBSD__
131 #define DRIVER_SOFTC(unit) \
132 ((drm_device_t *) device_lookup(&DRM(cd), unit))
133 #endif /* __NetBSD__ */
134
135 static drm_ioctl_desc_t DRM(ioctls)[] = {
136 [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { DRM(version), 0, 0 },
137 [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { DRM(getunique), 0, 0 },
138 [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { DRM(getmagic), 0, 0 },
139 #if __HAVE_IRQ
140 [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { DRM(irq_by_busid), 0, 1 },
141 #endif
142 [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { DRM(getmap), 0, 0 },
143 [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { DRM(getclient), 0, 0 },
144 [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { DRM(getstats), 0, 0 },
145 [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = { DRM(setversion), 0, 1 },
146
147 [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { DRM(setunique), 1, 1 },
148 [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { DRM(noop), 1, 1 },
149 [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { DRM(noop), 1, 1 },
150 [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { DRM(authmagic), 1, 1 },
151
152 [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { DRM(addmap), 1, 1 },
153 [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { DRM(rmmap), 1, 0 },
154
155 #if __HAVE_CTX_BITMAP
156 [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { DRM(setsareactx), 1, 1 },
157 [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { DRM(getsareactx), 1, 0 },
158 #endif
159
160 [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { DRM(addctx), 1, 1 },
161 [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { DRM(rmctx), 1, 1 },
162 [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { DRM(modctx), 1, 1 },
163 [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { DRM(getctx), 1, 0 },
164 [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { DRM(switchctx), 1, 1 },
165 [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { DRM(newctx), 1, 1 },
166 [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { DRM(resctx), 1, 0 },
167
168 [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { DRM(adddraw), 1, 1 },
169 [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { DRM(rmdraw), 1, 1 },
170
171 [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { DRM(lock), 1, 0 },
172 [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { DRM(unlock), 1, 0 },
173 [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { DRM(noop), 1, 0 },
174
175 #if __HAVE_DMA
176 [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { DRM(addbufs), 1, 1 },
177 [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { DRM(markbufs), 1, 1 },
178 [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { DRM(infobufs), 1, 0 },
179 [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { DRM(mapbufs), 1, 0 },
180 [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { DRM(freebufs), 1, 0 },
181 /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
182 #endif
183 #if __HAVE_IRQ || __HAVE_DMA
184 [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { DRM(control), 1, 1 },
185 #endif
186
187 #if __REALLY_HAVE_AGP
188 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { DRM(agp_acquire), 1, 1 },
189 [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { DRM(agp_release), 1, 1 },
190 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { DRM(agp_enable), 1, 1 },
191 [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { DRM(agp_info), 1, 0 },
192 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { DRM(agp_alloc), 1, 1 },
193 [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { DRM(agp_free), 1, 1 },
194 [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { DRM(agp_bind), 1, 1 },
195 [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { DRM(agp_unbind), 1, 1 },
196 #endif
197
198 #if __HAVE_SG
199 [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { DRM(sg_alloc), 1, 1 },
200 [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { DRM(sg_free), 1, 1 },
201 #endif
202
203 #if __HAVE_VBL_IRQ
204 [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = { DRM(wait_vblank), 0, 0 },
205 #endif
206
207 DRIVER_IOCTLS
208 };
209
210 #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( DRM(ioctls) )
211
212 const char *DRM(find_description)(int vendor, int device);
213
214 #ifdef __FreeBSD__
215 static struct cdevsw DRM(cdevsw) = {
216 #if __FreeBSD_version >= 502103
217 .d_version = D_VERSION,
218 #endif
219 .d_open = DRM( open ),
220 .d_close = DRM( close ),
221 .d_read = DRM( read ),
222 .d_ioctl = DRM( ioctl ),
223 .d_poll = DRM( poll ),
224 .d_mmap = DRM( mmap ),
225 .d_name = DRIVER_NAME,
226 #if __FreeBSD_version >= 502103
227 .d_flags = D_TRACKCLOSE | D_NEEDGIANT,
228 #else
229 .d_maj = 145,
230 .d_flags = D_TRACKCLOSE,
231 #endif
232 #if __FreeBSD_version < 500000
233 .d_bmaj = -1
234 #endif
235 };
236
237 #include "dev/drm/drm_pciids.h"
238
239 static drm_pci_id_list_t DRM(pciidlist)[] = {
240 DRM(PCI_IDS)
241 };
242
243 static int DRM(probe)(device_t dev)
244 {
245 const char *s = NULL;
246 int pciid, vendor, device;
247
248 /* XXX: Cope with agp bridge device? */
249 if (!strcmp(device_get_name(dev), "drmsub"))
250 pciid = pci_get_devid(device_get_parent(dev));
251 else
252 pciid = pci_get_devid(dev);
253
254 vendor = (pciid & 0x0000ffff);
255 device = (pciid & 0xffff0000) >> 16;
256
257 s = DRM(find_description)(vendor, device);
258 if (s != NULL) {
259 device_set_desc(dev, s);
260 return 0;
261 }
262
263 return ENXIO;
264 }
265
266 static int DRM(attach)(device_t dev)
267 {
268 return DRM(init)(dev);
269 }
270
271 static int DRM(detach)(device_t dev)
272 {
273 DRM(cleanup)(device_get_softc(dev));
274 return 0;
275 }
276 static device_method_t DRM(methods)[] = {
277 /* Device interface */
278 DEVMETHOD(device_probe, DRM(probe)),
279 DEVMETHOD(device_attach, DRM(attach)),
280 DEVMETHOD(device_detach, DRM(detach)),
281
282 { 0, 0 }
283 };
284
285 static driver_t DRM(driver) = {
286 "drm",
287 DRM(methods),
288 sizeof(drm_device_t),
289 };
290
291 static devclass_t DRM(devclass);
292
293 #elif defined(__NetBSD__)
294
295 static struct cdevsw DRM(cdevsw) = {
296 DRM(open),
297 DRM(close),
298 DRM(read),
299 nowrite,
300 DRM(ioctl),
301 nostop,
302 notty,
303 DRM(poll),
304 DRM(mmap),
305 nokqfilter,
306 D_TTY
307 };
308
309 int DRM(refcnt) = 0;
310 #if __NetBSD_Version__ >= 106080000
311 MOD_DEV( DRIVER_NAME, DRIVER_NAME, NULL, -1, &DRM(cdevsw), CDEV_MAJOR);
312 #else
313 MOD_DEV( DRIVER_NAME, LM_DT_CHAR, CDEV_MAJOR, &DRM(cdevsw) );
314 #endif
315
316 int DRM(lkmentry)(struct lkm_table *lkmtp, int cmd, int ver);
317 static int DRM(lkmhandle)(struct lkm_table *lkmtp, int cmd);
318
319 int DRM(modprobe)();
320 int DRM(probe)(struct pci_attach_args *pa);
321 void DRM(attach)(struct pci_attach_args *pa, dev_t kdev);
322
323 int DRM(lkmentry)(struct lkm_table *lkmtp, int cmd, int ver) {
324 DISPATCH(lkmtp, cmd, ver, DRM(lkmhandle), DRM(lkmhandle), DRM(lkmhandle));
325 }
326
327 static int DRM(lkmhandle)(struct lkm_table *lkmtp, int cmd)
328 {
329 int j, error = 0;
330 #if defined(__NetBSD__) && (__NetBSD_Version__ > 106080000)
331 struct lkm_dev *args = lkmtp->private.lkm_dev;
332 #endif
333
334 switch(cmd) {
335 case LKM_E_LOAD:
336 if (lkmexists(lkmtp))
337 return EEXIST;
338
339 if(DRM(modprobe)())
340 return 0;
341
342 return 1;
343
344 case LKM_E_UNLOAD:
345 if (DRM(refcnt) > 0)
346 return (EBUSY);
347 break;
348 case LKM_E_STAT:
349 break;
350
351 default:
352 error = EIO;
353 break;
354 }
355
356 return error;
357 }
358
359 int DRM(modprobe)() {
360 struct pci_attach_args pa;
361 int error = 0;
362 if((error = pci_find_device(&pa, DRM(probe))) != 0)
363 DRM(attach)(&pa, 0);
364
365 return error;
366 }
367
368 int DRM(probe)(struct pci_attach_args *pa)
369 {
370 const char *desc;
371
372 desc = DRM(find_description)(PCI_VENDOR(pa->pa_id),
373 PCI_PRODUCT(pa->pa_id));
374 if (desc != NULL) {
375 return 1;
376 }
377
378 return 0;
379 }
380
381 void DRM(attach)(struct pci_attach_args *pa, dev_t kdev)
382 {
383 int i;
384 drm_device_t *dev;
385
386 config_makeroom(kdev, &DRM(cd));
387 DRM(cd).cd_devs[(kdev)] = DRM(alloc)(sizeof(drm_device_t),
388 DRM_MEM_DRIVER);
389 dev = DRIVER_SOFTC(kdev);
390
391 memset(dev, 0, sizeof(drm_device_t));
392 memcpy(&dev->pa, pa, sizeof(dev->pa));
393
394 DRM_INFO("%s", DRM(find_description)(PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id)));
395 DRM(init)(dev);
396 }
397
398 int DRM(detach)(struct device *self, int flags)
399 {
400 DRM(cleanup)((drm_device_t *)self);
401 return 0;
402 }
403
404 int DRM(activate)(struct device *self, enum devact act)
405 {
406 switch (act) {
407 case DVACT_ACTIVATE:
408 return (EOPNOTSUPP);
409 break;
410
411 case DVACT_DEACTIVATE:
412 /* FIXME */
413 break;
414 }
415 return (0);
416 }
417 #endif /* __NetBSD__ */
418
419 const char *DRM(find_description)(int vendor, int device) {
420 int i = 0;
421
422 for (i = 0; DRM(pciidlist)[i].vendor != 0; i++) {
423 if ((DRM(pciidlist)[i].vendor == vendor) &&
424 (DRM(pciidlist)[i].device == device)) {
425 return DRM(pciidlist)[i].name;
426 }
427 }
428 return NULL;
429 }
430
431 /* Initialize the DRM on first open. */
432 static int DRM(setup)( drm_device_t *dev )
433 {
434 int i;
435
436 DRM_SPINLOCK_ASSERT(&dev->dev_lock);
437
438 DRIVER_PRESETUP();
439 dev->buf_use = 0;
440
441 #if __HAVE_DMA
442 i = DRM(dma_setup)( dev );
443 if ( i != 0 )
444 return i;
445 #endif
446
447 dev->counters = 6 + __HAVE_COUNTERS;
448 dev->types[0] = _DRM_STAT_LOCK;
449 dev->types[1] = _DRM_STAT_OPENS;
450 dev->types[2] = _DRM_STAT_CLOSES;
451 dev->types[3] = _DRM_STAT_IOCTLS;
452 dev->types[4] = _DRM_STAT_LOCKS;
453 dev->types[5] = _DRM_STAT_UNLOCKS;
454 #ifdef __HAVE_COUNTER6
455 dev->types[6] = __HAVE_COUNTER6;
456 #endif
457 #ifdef __HAVE_COUNTER7
458 dev->types[7] = __HAVE_COUNTER7;
459 #endif
460 #ifdef __HAVE_COUNTER8
461 dev->types[8] = __HAVE_COUNTER8;
462 #endif
463 #ifdef __HAVE_COUNTER9
464 dev->types[9] = __HAVE_COUNTER9;
465 #endif
466 #ifdef __HAVE_COUNTER10
467 dev->types[10] = __HAVE_COUNTER10;
468 #endif
469 #ifdef __HAVE_COUNTER11
470 dev->types[11] = __HAVE_COUNTER11;
471 #endif
472 #ifdef __HAVE_COUNTER12
473 dev->types[12] = __HAVE_COUNTER12;
474 #endif
475 #ifdef __HAVE_COUNTER13
476 dev->types[13] = __HAVE_COUNTER13;
477 #endif
478 #ifdef __HAVE_COUNTER14
479 dev->types[14] = __HAVE_COUNTER14;
480 #endif
481 #ifdef __HAVE_COUNTER15
482 dev->types[14] = __HAVE_COUNTER14;
483 #endif
484
485 for ( i = 0 ; i < DRM_ARRAY_SIZE(dev->counts) ; i++ )
486 atomic_set( &dev->counts[i], 0 );
487
488 for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
489 dev->magiclist[i].head = NULL;
490 dev->magiclist[i].tail = NULL;
491 }
492
493 dev->lock.hw_lock = NULL;
494 dev->lock.lock_queue = 0;
495 dev->irq_enabled = 0;
496 dev->context_flag = 0;
497 dev->last_context = 0;
498 dev->if_version = 0;
499
500 #ifdef __FreeBSD__
501 dev->buf_sigio = NULL;
502 #elif defined(__NetBSD__)
503 dev->buf_pgid = 0;
504 #endif
505
506 DRM_DEBUG( "\n" );
507
508 DRIVER_POSTSETUP();
509 return 0;
510 }
511
512 /* Free resources associated with the DRM on the last close. */
513 static int DRM(takedown)( drm_device_t *dev )
514 {
515 drm_magic_entry_t *pt, *next;
516 drm_local_map_t *map;
517 drm_map_list_entry_t *list;
518 int i;
519
520 DRM_SPINLOCK_ASSERT(&dev->dev_lock);
521
522 DRM_DEBUG( "\n" );
523
524 DRIVER_PRETAKEDOWN(dev);
525 #if __HAVE_IRQ
526 if (dev->irq_enabled)
527 DRM(irq_uninstall)( dev );
528 #endif
529
530 if ( dev->unique ) {
531 DRM(free)( dev->unique, strlen( dev->unique ) + 1,
532 DRM_MEM_DRIVER );
533 dev->unique = NULL;
534 dev->unique_len = 0;
535 }
536 /* Clear pid list */
537 for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
538 for ( pt = dev->magiclist[i].head ; pt ; pt = next ) {
539 next = pt->next;
540 DRM(free)( pt, sizeof(*pt), DRM_MEM_MAGIC );
541 }
542 dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
543 }
544
545 #if __REALLY_HAVE_AGP
546 /* Clear AGP information */
547 if ( dev->agp ) {
548 drm_agp_mem_t *entry;
549 drm_agp_mem_t *nexte;
550
551 /* Remove AGP resources, but leave dev->agp
552 intact until DRM(cleanup) is called. */
553 for ( entry = dev->agp->memory ; entry ; entry = nexte ) {
554 nexte = entry->next;
555 if ( entry->bound ) DRM(unbind_agp)( entry->handle );
556 DRM(free_agp)( entry->handle, entry->pages );
557 DRM(free)( entry, sizeof(*entry), DRM_MEM_AGPLISTS );
558 }
559 dev->agp->memory = NULL;
560
561 if ( dev->agp->acquired ) DRM(agp_do_release)();
562
563 dev->agp->acquired = 0;
564 dev->agp->enabled = 0;
565 }
566 #endif
567 #if __REALLY_HAVE_SG
568 if (dev->sg != NULL) {
569 DRM(sg_cleanup)(dev->sg);
570 dev->sg = NULL;
571 }
572 #endif
573
574 if (dev->maplist != NULL) {
575 while ((list=TAILQ_FIRST(dev->maplist))) {
576 map = list->map;
577 switch ( map->type ) {
578 case _DRM_REGISTERS:
579 DRM(ioremapfree)(map);
580 /* FALLTHROUGH */
581 case _DRM_FRAME_BUFFER:
582 #if __REALLY_HAVE_MTRR
583 if (map->mtrr) {
584 int __unused retcode;
585
586 retcode = DRM(mtrr_del)(map->offset,
587 map->size, DRM_MTRR_WC);
588 DRM_DEBUG("mtrr_del = %d", retcode);
589 }
590 #endif
591 break;
592 case _DRM_SHM:
593 DRM(free)(map->handle,
594 map->size,
595 DRM_MEM_SAREA);
596 break;
597
598 case _DRM_AGP:
599 case _DRM_SCATTER_GATHER:
600 /* Do nothing here, because this is all
601 * handled in the AGP/GART/SG functions.
602 */
603 break;
604 }
605 TAILQ_REMOVE(dev->maplist, list, link);
606 DRM(free)(list, sizeof(*list), DRM_MEM_MAPS);
607 DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
608 }
609 }
610
611 #if __HAVE_DMA
612 DRM(dma_takedown)( dev );
613 #endif
614 if ( dev->lock.hw_lock ) {
615 dev->lock.hw_lock = NULL; /* SHM removed */
616 dev->lock.filp = NULL;
617 DRM_WAKEUP_INT((void *)&dev->lock.lock_queue);
618 }
619
620 return 0;
621 }
622
623 /* linux: drm_init is called via init_module at module load time, or via
624 * linux/init/main.c (this is not currently supported).
625 * bsd: drm_init is called via the attach function per device.
626 */
627 static int DRM(init)( device_t nbdev )
628 {
629 int unit;
630 #ifdef __FreeBSD__
631 drm_device_t *dev;
632 #elif defined(__NetBSD__)
633 drm_device_t *dev = nbdev;
634 #endif
635 #if __HAVE_CTX_BITMAP
636 int retcode;
637 #endif
638 DRM_DEBUG( "\n" );
639 DRIVER_PREINIT(dev);
640
641 #ifdef __FreeBSD__
642 unit = device_get_unit(nbdev);
643 dev = device_get_softc(nbdev);
644 memset( (void *)dev, 0, sizeof(*dev) );
645
646 if (!strcmp(device_get_name(nbdev), "drmsub"))
647 dev->device = device_get_parent(nbdev);
648 else
649 dev->device = nbdev;
650
651 dev->devnode = make_dev( &DRM(cdevsw),
652 unit,
653 DRM_DEV_UID,
654 DRM_DEV_GID,
655 DRM_DEV_MODE,
656 "dri/card%d", unit );
657 #if __FreeBSD_version >= 500000
658 mtx_init(&dev->dev_lock, "drm device", NULL, MTX_DEF);
659 #endif
660 #elif defined(__NetBSD__)
661 unit = minor(dev->device.dv_unit);
662 #endif
663
664 dev->irq = pci_get_irq(dev->device);
665 /* XXX Fix domain number (alpha hoses) */
666 dev->pci_domain = 0;
667 dev->pci_bus = pci_get_bus(dev->device);
668 dev->pci_slot = pci_get_slot(dev->device);
669 dev->pci_func = pci_get_function(dev->device);
670
671 dev->maplist = DRM(calloc)(1, sizeof(*dev->maplist), DRM_MEM_MAPS);
672 if (dev->maplist == NULL) {
673 retcode = ENOMEM;
674 goto error;
675 }
676 TAILQ_INIT(dev->maplist);
677
678 dev->name = DRIVER_NAME;
679 DRM(mem_init)();
680 DRM(sysctl_init)(dev);
681 TAILQ_INIT(&dev->files);
682
683 #if __REALLY_HAVE_AGP
684 dev->agp = DRM(agp_init)();
685 #if __MUST_HAVE_AGP
686 if ( dev->agp == NULL ) {
687 DRM_ERROR( "Cannot initialize the agpgart module.\n" );
688 retcode = DRM_ERR(ENOMEM);
689 goto error;
690 }
691 #endif /* __MUST_HAVE_AGP */
692 #if __REALLY_HAVE_MTRR
693 if (dev->agp) {
694 if (DRM(mtrr_add)(dev->agp->info.ai_aperture_base,
695 dev->agp->info.ai_aperture_size, DRM_MTRR_WC) == 0)
696 dev->agp->mtrr = 1;
697 }
698 #endif /* __REALLY_HAVE_MTRR */
699 #endif /* __REALLY_HAVE_AGP */
700
701 #if __HAVE_CTX_BITMAP
702 retcode = DRM(ctxbitmap_init)( dev );
703 if (retcode != 0) {
704 DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
705 goto error;
706 }
707 #endif
708
709 DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
710 DRIVER_NAME,
711 DRIVER_MAJOR,
712 DRIVER_MINOR,
713 DRIVER_PATCHLEVEL,
714 DRIVER_DATE,
715 unit );
716
717 DRIVER_POSTINIT(dev);
718
719 return 0;
720
721 error:
722 DRM(sysctl_cleanup)(dev);
723 DRM_LOCK();
724 DRM(takedown)(dev);
725 DRM_UNLOCK();
726 #ifdef __FreeBSD__
727 destroy_dev(dev->devnode);
728 #if __FreeBSD_version >= 500000
729 mtx_destroy(&dev->dev_lock);
730 #endif
731 #endif
732 DRM(free)(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
733 return retcode;
734 }
735
736 /* linux: drm_cleanup is called via cleanup_module at module unload time.
737 * bsd: drm_cleanup is called per device at module unload time.
738 * FIXME: NetBSD
739 */
740 static void DRM(cleanup)(drm_device_t *dev)
741 {
742
743 DRM_DEBUG( "\n" );
744
745 DRM(sysctl_cleanup)( dev );
746 #ifdef __FreeBSD__
747 destroy_dev(dev->devnode);
748 #endif
749 #if __HAVE_CTX_BITMAP
750 DRM(ctxbitmap_cleanup)( dev );
751 #endif
752
753 #if __REALLY_HAVE_AGP && __REALLY_HAVE_MTRR
754 if (dev->agp && dev->agp->mtrr) {
755 int __unused retcode;
756
757 retcode = DRM(mtrr_del)(dev->agp->info.ai_aperture_base,
758 dev->agp->info.ai_aperture_size, DRM_MTRR_WC);
759 DRM_DEBUG("mtrr_del = %d", retcode);
760 }
761 #endif
762
763 DRM_LOCK();
764 DRM(takedown)( dev );
765 DRM_UNLOCK();
766
767 #if __REALLY_HAVE_AGP
768 if ( dev->agp ) {
769 DRM(agp_uninit)();
770 DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
771 dev->agp = NULL;
772 }
773 #endif
774 DRIVER_POSTCLEANUP();
775 DRM(mem_uninit)();
776 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
777 mtx_destroy(&dev->dev_lock);
778 #endif
779 DRM(free)(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
780 }
781
782
783 int DRM(version)( DRM_IOCTL_ARGS )
784 {
785 drm_version_t version;
786 int len;
787
788 DRM_COPY_FROM_USER_IOCTL( version, (drm_version_t *)data, sizeof(version) );
789
790 #define DRM_COPY( name, value ) \
791 len = strlen( value ); \
792 if ( len > name##_len ) len = name##_len; \
793 name##_len = strlen( value ); \
794 if ( len && name ) { \
795 if ( DRM_COPY_TO_USER( name, value, len ) ) \
796 return DRM_ERR(EFAULT); \
797 }
798
799 version.version_major = DRIVER_MAJOR;
800 version.version_minor = DRIVER_MINOR;
801 version.version_patchlevel = DRIVER_PATCHLEVEL;
802
803 DRM_COPY( version.name, DRIVER_NAME );
804 DRM_COPY( version.date, DRIVER_DATE );
805 DRM_COPY( version.desc, DRIVER_DESC );
806
807 DRM_COPY_TO_USER_IOCTL( (drm_version_t *)data, version, sizeof(version) );
808
809 return 0;
810 }
811
812 int DRM(open)(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
813 {
814 drm_device_t *dev = NULL;
815 int retcode = 0;
816
817 dev = DRIVER_SOFTC(minor(kdev));
818
819 DRM_DEBUG( "open_count = %d\n", dev->open_count );
820
821 retcode = DRM(open_helper)(kdev, flags, fmt, p, dev);
822
823 if ( !retcode ) {
824 atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
825 DRM_LOCK();
826 #ifdef __FreeBSD__
827 device_busy(dev->device);
828 #endif
829 if ( !dev->open_count++ )
830 retcode = DRM(setup)( dev );
831 DRM_UNLOCK();
832 }
833
834 return retcode;
835 }
836
837 int DRM(close)(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
838 {
839 drm_file_t *priv;
840 DRM_DEVICE;
841 int retcode = 0;
842 DRMFILE filp = (void *)(uintptr_t)(DRM_CURRENTPID);
843
844 DRM_DEBUG( "open_count = %d\n", dev->open_count );
845
846 DRM_LOCK();
847
848 priv = DRM(find_file_by_proc)(dev, p);
849 if (!priv) {
850 DRM_UNLOCK();
851 DRM_DEBUG("can't find authenticator\n");
852 return EINVAL;
853 }
854
855 DRIVER_PRERELEASE();
856
857 /* ========================================================
858 * Begin inline drm_release
859 */
860
861 #ifdef __FreeBSD__
862 DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
863 DRM_CURRENTPID, (long)dev->device, dev->open_count );
864 #elif defined(__NetBSD__)
865 DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
866 DRM_CURRENTPID, (long)&dev->device, dev->open_count);
867 #endif
868
869 if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
870 && dev->lock.filp == filp) {
871 DRM_DEBUG("Process %d dead, freeing lock for context %d\n",
872 DRM_CURRENTPID,
873 _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
874 #if __HAVE_RELEASE
875 DRIVER_RELEASE();
876 #endif
877 DRM(lock_free)(dev,
878 &dev->lock.hw_lock->lock,
879 _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
880
881 /* FIXME: may require heavy-handed reset of
882 hardware at this point, possibly
883 processed via a callback to the X
884 server. */
885 }
886 #if __HAVE_RELEASE
887 else if ( dev->lock.hw_lock ) {
888 /* The lock is required to reclaim buffers */
889 for (;;) {
890 if ( !dev->lock.hw_lock ) {
891 /* Device has been unregistered */
892 retcode = DRM_ERR(EINTR);
893 break;
894 }
895 if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
896 DRM_KERNEL_CONTEXT ) ) {
897 dev->lock.pid = DRM_CURRENTPID;
898 dev->lock.lock_time = jiffies;
899 atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
900 break; /* Got lock */
901 }
902 /* Contention */
903 #if defined(__FreeBSD__) && __FreeBSD_version > 500000
904 retcode = msleep((void *)&dev->lock.lock_queue,
905 dev->dev_lock, PZERO | PCATCH, "drmlk2", 0);
906 #else
907 retcode = tsleep((void *)&dev->lock.lock_queue,
908 PZERO | PCATCH, "drmlk2", 0);
909 #endif
910 if (retcode)
911 break;
912 }
913 if (retcode == 0) {
914 DRIVER_RELEASE();
915 DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
916 DRM_KERNEL_CONTEXT );
917 }
918 }
919 #elif __HAVE_DMA
920 DRM(reclaim_buffers)( dev, (void *)(uintptr_t)priv->pid );
921 #endif
922
923 #if defined (__FreeBSD__) && (__FreeBSD_version >= 500000)
924 funsetown(&dev->buf_sigio);
925 #elif defined(__FreeBSD__)
926 funsetown(dev->buf_sigio);
927 #elif defined(__NetBSD__)
928 dev->buf_pgid = 0;
929 #endif /* __NetBSD__ */
930
931 if (--priv->refs == 0) {
932 TAILQ_REMOVE(&dev->files, priv, link);
933 DRM(free)( priv, sizeof(*priv), DRM_MEM_FILES );
934 }
935
936 /* ========================================================
937 * End inline drm_release
938 */
939
940 atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
941 #ifdef __FreeBSD__
942 device_unbusy(dev->device);
943 #endif
944 if (--dev->open_count == 0) {
945 retcode = DRM(takedown)(dev);
946 }
947
948 DRM_UNLOCK();
949
950 return retcode;
951 }
952
953 /* DRM(ioctl) is called whenever a process performs an ioctl on /dev/drm.
954 */
955 int DRM(ioctl)(struct cdev *kdev, u_long cmd, caddr_t data, int flags,
956 DRM_STRUCTPROC *p)
957 {
958 DRM_DEVICE;
959 int retcode = 0;
960 drm_ioctl_desc_t *ioctl;
961 int (*func)(DRM_IOCTL_ARGS);
962 int nr = DRM_IOCTL_NR(cmd);
963 drm_file_t *priv;
964
965 DRM_GET_PRIV_WITH_RETURN(priv, (DRMFILE)(uintptr_t)DRM_CURRENTPID);
966
967 atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
968 ++priv->ioctl_count;
969
970 #ifdef __FreeBSD__
971 DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
972 DRM_CURRENTPID, cmd, nr, (long)dev->device, priv->authenticated );
973 #elif defined(__NetBSD__)
974 DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
975 DRM_CURRENTPID, cmd, nr, (long)&dev->device, priv->authenticated );
976 #endif
977
978 switch (cmd) {
979 case FIONBIO:
980 case FIOASYNC:
981 return 0;
982
983 #ifdef __FreeBSD__
984 case FIOSETOWN:
985 return fsetown(*(int *)data, &dev->buf_sigio);
986
987 case FIOGETOWN:
988 #if (__FreeBSD_version >= 500000)
989 *(int *) data = fgetown(&dev->buf_sigio);
990 #else
991 *(int *) data = fgetown(dev->buf_sigio);
992 #endif
993 return 0;
994 #endif /* __FreeBSD__ */
995 #ifdef __NetBSD__
996 case TIOCSPGRP:
997 dev->buf_pgid = *(int *)data;
998 return 0;
999
1000 case TIOCGPGRP:
1001 *(int *)data = dev->buf_pgid;
1002 return 0;
1003 #endif /* __NetBSD__ */
1004 }
1005
1006 if (nr >= DRIVER_IOCTL_COUNT || IOCGROUP(cmd) != DRM_IOCTL_BASE)
1007 return EINVAL;
1008
1009 ioctl = &DRM(ioctls)[nr];
1010 func = ioctl->func;
1011
1012 if (func == NULL) {
1013 DRM_DEBUG( "no function\n" );
1014 return EINVAL;
1015 }
1016 if ((ioctl->root_only && DRM_SUSER(p)) || (ioctl->auth_needed &&
1017 !priv->authenticated))
1018 return EACCES;
1019
1020 retcode = func(kdev, cmd, data, flags, p, (void *)(uintptr_t)DRM_CURRENTPID);
1021
1022 return DRM_ERR(retcode);
1023 }
1024
1025 int DRM(lock)( DRM_IOCTL_ARGS )
1026 {
1027 DRM_DEVICE;
1028 drm_lock_t lock;
1029 int ret = 0;
1030
1031 DRM_COPY_FROM_USER_IOCTL( lock, (drm_lock_t *)data, sizeof(lock) );
1032
1033 if ( lock.context == DRM_KERNEL_CONTEXT ) {
1034 DRM_ERROR( "Process %d using kernel context %d\n",
1035 DRM_CURRENTPID, lock.context );
1036 return DRM_ERR(EINVAL);
1037 }
1038
1039 DRM_DEBUG( "%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
1040 lock.context, DRM_CURRENTPID,
1041 dev->lock.hw_lock->lock, lock.flags );
1042
1043 #if __HAVE_DMA_QUEUE
1044 if ( lock.context < 0 )
1045 return DRM_ERR(EINVAL);
1046 #endif
1047
1048 DRM_LOCK();
1049 for (;;) {
1050 if (DRM(lock_take)(&dev->lock.hw_lock->lock, lock.context)) {
1051 dev->lock.filp = (void *)(uintptr_t)DRM_CURRENTPID;
1052 dev->lock.lock_time = jiffies;
1053 atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
1054 break; /* Got lock */
1055 }
1056
1057 /* Contention */
1058 #if defined(__FreeBSD__) && __FreeBSD_version > 500000
1059 ret = msleep((void *)&dev->lock.lock_queue, &dev->dev_lock,
1060 PZERO | PCATCH, "drmlk2", 0);
1061 #else
1062 ret = tsleep((void *)&dev->lock.lock_queue, PZERO | PCATCH,
1063 "drmlk2", 0);
1064 #endif
1065 if (ret != 0)
1066 break;
1067 }
1068 DRM_UNLOCK();
1069 DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
1070
1071 if (ret != 0)
1072 return ret;
1073
1074 /* XXX: Add signal blocking here */
1075
1076 #if __HAVE_DMA_QUIESCENT
1077 if (lock.flags & _DRM_LOCK_QUIESCENT) {
1078 DRIVER_DMA_QUIESCENT();
1079 }
1080 #endif
1081
1082 return 0;
1083 }
1084
1085
1086 int DRM(unlock)( DRM_IOCTL_ARGS )
1087 {
1088 DRM_DEVICE;
1089 drm_lock_t lock;
1090
1091 DRM_COPY_FROM_USER_IOCTL( lock, (drm_lock_t *)data, sizeof(lock) ) ;
1092
1093 if ( lock.context == DRM_KERNEL_CONTEXT ) {
1094 DRM_ERROR( "Process %d using kernel context %d\n",
1095 DRM_CURRENTPID, lock.context );
1096 return DRM_ERR(EINVAL);
1097 }
1098
1099 atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
1100
1101 DRM_LOCK();
1102 DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock,
1103 DRM_KERNEL_CONTEXT );
1104 #if __HAVE_DMA_SCHEDULE
1105 DRM(dma_schedule)( dev, 1 );
1106 #endif
1107
1108 if ( DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
1109 DRM_KERNEL_CONTEXT ) ) {
1110 DRM_ERROR( "\n" );
1111 }
1112 DRM_UNLOCK();
1113
1114 return 0;
1115 }
1116
1117 #if DRM_LINUX
1118
1119 #include <sys/sysproto.h>
1120
1121 MODULE_DEPEND(DRIVER_NAME, linux, 1, 1, 1);
1122
1123 #define LINUX_IOCTL_DRM_MIN 0x6400
1124 #define LINUX_IOCTL_DRM_MAX 0x64ff
1125
1126 static linux_ioctl_function_t DRM(linux_ioctl);
1127 static struct linux_ioctl_handler DRM(handler) = {DRM(linux_ioctl),
1128 LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX};
1129
1130 SYSINIT(DRM(register), SI_SUB_KLD, SI_ORDER_MIDDLE,
1131 linux_ioctl_register_handler, &DRM(handler));
1132 SYSUNINIT(DRM(unregister), SI_SUB_KLD, SI_ORDER_MIDDLE,
1133 linux_ioctl_unregister_handler, &DRM(handler));
1134
1135 /* The bits for in/out are switched on Linux */
1136 #define LINUX_IOC_IN IOC_OUT
1137 #define LINUX_IOC_OUT IOC_IN
1138
1139 static int
1140 DRM(linux_ioctl)(DRM_STRUCTPROC *p, struct linux_ioctl_args* args)
1141 {
1142 int error;
1143 int cmd = args->cmd;
1144
1145 args->cmd &= ~(LINUX_IOC_IN | LINUX_IOC_OUT);
1146 if (cmd & LINUX_IOC_IN)
1147 args->cmd |= IOC_IN;
1148 if (cmd & LINUX_IOC_OUT)
1149 args->cmd |= IOC_OUT;
1150
1151 error = ioctl(p, (struct ioctl_args *)args);
1152
1153 return error;
1154 }
1155 #endif /* DRM_LINUX */
Cache object: 965507e738619942ca2f95fb60e528a6
|