1 /* drm_drv.h -- Generic driver template -*- linux-c -*-
2 * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
4 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
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:
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
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.
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 * Gareth Hughes <gareth@valinux.com>
31 * $FreeBSD: src/sys/dev/drm/drm_drv.h,v 1.13.2.1 2003/04/26 07:05:28 anholt Exp $
32 * $DragonFly: src/sys/dev/drm/drm_drv.h,v 1.16 2007/04/30 07:18:48 dillon Exp $
36 * To use this template, you must at least define the following (samples
37 * given for the MGA driver):
39 * #define DRIVER_AUTHOR "VA Linux Systems, Inc."
41 * #define DRIVER_NAME "mga"
42 * #define DRIVER_DESC "Matrox G200/G400"
43 * #define DRIVER_DATE "20001127"
45 * #define DRIVER_MAJOR 2
46 * #define DRIVER_MINOR 0
47 * #define DRIVER_PATCHLEVEL 2
49 * #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( mga_ioctls )
51 * #define DRM(x) mga_##x
54 #ifndef __MUST_HAVE_AGP
55 #define __MUST_HAVE_AGP 0
57 #ifndef __HAVE_CTX_BITMAP
58 #define __HAVE_CTX_BITMAP 0
60 #ifndef __HAVE_DMA_IRQ
61 #define __HAVE_DMA_IRQ 0
63 #ifndef __HAVE_DMA_QUEUE
64 #define __HAVE_DMA_QUEUE 0
66 #ifndef __HAVE_DMA_SCHEDULE
67 #define __HAVE_DMA_SCHEDULE 0
69 #ifndef __HAVE_DMA_QUIESCENT
70 #define __HAVE_DMA_QUIESCENT 0
72 #ifndef __HAVE_RELEASE
73 #define __HAVE_RELEASE 0
75 #ifndef __HAVE_COUNTERS
76 #define __HAVE_COUNTERS 0
82 #ifndef DRIVER_PREINIT
83 #define DRIVER_PREINIT()
85 #ifndef DRIVER_POSTINIT
86 #define DRIVER_POSTINIT()
88 #ifndef DRIVER_PRERELEASE
89 #define DRIVER_PRERELEASE()
91 #ifndef DRIVER_PRETAKEDOWN
92 #define DRIVER_PRETAKEDOWN()
94 #ifndef DRIVER_POSTCLEANUP
95 #define DRIVER_POSTCLEANUP()
97 #ifndef DRIVER_PRESETUP
98 #define DRIVER_PRESETUP()
100 #ifndef DRIVER_POSTSETUP
101 #define DRIVER_POSTSETUP()
103 #ifndef DRIVER_IOCTLS
104 #define DRIVER_IOCTLS
109 #if 1 && DRM_DEBUG_CODE
110 int DRM(flags
) = DRM_FLAG_DEBUG
;
115 static int DRM(init
)(device_t nbdev
);
116 static void DRM(cleanup
)(device_t nbdev
);
118 #if defined(__DragonFly__) || defined(__FreeBSD__)
119 #define DRIVER_SOFTC(unit) \
120 ((drm_device_t *) devclass_get_softc(DRM(devclass), unit))
122 #if __REALLY_HAVE_AGP
123 MODULE_DEPEND(DRIVER_NAME
, agp
, 1, 1, 1);
125 #endif /* __FreeBSD__ */
128 #define DRIVER_SOFTC(unit) \
129 ((drm_device_t *) device_lookup(&DRM(cd), unit))
130 #endif /* __NetBSD__ */
132 static drm_ioctl_desc_t
DRM(ioctls
)[] = {
133 [DRM_IOCTL_NR(DRM_IOCTL_VERSION
)] = { DRM(version
), 0, 0 },
134 [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE
)] = { DRM(getunique
), 0, 0 },
135 [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC
)] = { DRM(getmagic
), 0, 0 },
136 [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID
)] = { DRM(irq_busid
), 0, 1 },
137 [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP
)] = { DRM(getmap
), 0, 0 },
138 [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT
)] = { DRM(getclient
), 0, 0 },
139 [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS
)] = { DRM(getstats
), 0, 0 },
141 [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE
)] = { DRM(setunique
), 1, 1 },
142 [DRM_IOCTL_NR(DRM_IOCTL_BLOCK
)] = { DRM(noop
), 1, 1 },
143 [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK
)] = { DRM(noop
), 1, 1 },
144 [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC
)] = { DRM(authmagic
), 1, 1 },
146 [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP
)] = { DRM(addmap
), 1, 1 },
147 [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP
)] = { DRM(rmmap
), 1, 0 },
149 #if __HAVE_CTX_BITMAP
150 [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX
)] = { DRM(setsareactx
), 1, 1 },
151 [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX
)] = { DRM(getsareactx
), 1, 0 },
154 [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX
)] = { DRM(addctx
), 1, 1 },
155 [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX
)] = { DRM(rmctx
), 1, 1 },
156 [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX
)] = { DRM(modctx
), 1, 1 },
157 [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX
)] = { DRM(getctx
), 1, 0 },
158 [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX
)] = { DRM(switchctx
), 1, 1 },
159 [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX
)] = { DRM(newctx
), 1, 1 },
160 [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX
)] = { DRM(resctx
), 1, 0 },
162 [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW
)] = { DRM(adddraw
), 1, 1 },
163 [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW
)] = { DRM(rmdraw
), 1, 1 },
165 [DRM_IOCTL_NR(DRM_IOCTL_LOCK
)] = { DRM(lock
), 1, 0 },
166 [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK
)] = { DRM(unlock
), 1, 0 },
167 [DRM_IOCTL_NR(DRM_IOCTL_FINISH
)] = { DRM(noop
), 1, 0 },
170 [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS
)] = { DRM(addbufs
), 1, 1 },
171 [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS
)] = { DRM(markbufs
), 1, 1 },
172 [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS
)] = { DRM(infobufs
), 1, 0 },
173 [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS
)] = { DRM(mapbufs
), 1, 0 },
174 [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS
)] = { DRM(freebufs
), 1, 0 },
176 /* The DRM_IOCTL_DMA ioctl should be defined by the driver.
178 [DRM_IOCTL_NR(DRM_IOCTL_CONTROL
)] = { DRM(control
), 1, 1 },
181 #if __REALLY_HAVE_AGP
182 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE
)] = { DRM(agp_acquire
), 1, 1 },
183 [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE
)] = { DRM(agp_release
), 1, 1 },
184 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE
)] = { DRM(agp_enable
), 1, 1 },
185 [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO
)] = { DRM(agp_info
), 1, 0 },
186 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC
)] = { DRM(agp_alloc
), 1, 1 },
187 [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE
)] = { DRM(agp_free
), 1, 1 },
188 [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND
)] = { DRM(agp_bind
), 1, 1 },
189 [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND
)] = { DRM(agp_unbind
), 1, 1 },
193 [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC
)] = { DRM(sg_alloc
), 1, 1 },
194 [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE
)] = { DRM(sg_free
), 1, 1 },
198 [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK
)] = { DRM(wait_vblank
), 0, 0 },
204 #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( DRM(ioctls) )
206 const char *DRM(find_description
)(int vendor
, int device
);
208 #if defined(__DragonFly__) || defined(__FreeBSD__)
209 static struct dev_ops
DRM(ops
) = {
210 { DRIVER_NAME
, CDEV_MAJOR
, D_TTY
| D_TRACKCLOSE
},
212 .d_close
= DRM(close
),
214 .d_ioctl
= DRM(ioctl
),
219 static int DRM(probe
)(device_t dev
)
221 const char *s
= NULL
;
223 int pciid
=pci_get_devid(dev
);
224 int vendor
= (pciid
& 0x0000ffff);
225 int device
= (pciid
& 0xffff0000) >> 16;
227 s
= DRM(find_description
)(vendor
, device
);
229 device_set_desc(dev
, s
);
236 static int DRM(attach
)(device_t dev
)
238 return DRM(init
)(dev
);
241 static int DRM(detach
)(device_t dev
)
246 static device_method_t
DRM(methods
)[] = {
247 /* Device interface */
248 DEVMETHOD(device_probe
, DRM( probe
)),
249 DEVMETHOD(device_attach
, DRM( attach
)),
250 DEVMETHOD(device_detach
, DRM( detach
)),
255 static driver_t
DRM(driver
) = {
258 sizeof(drm_device_t
),
261 static devclass_t
DRM(devclass
);
263 #elif defined(__NetBSD__)
265 static struct cdevsw
DRM(cdevsw
) = {
280 #if __NetBSD_Version__ >= 106080000
281 MOD_DEV( DRIVER_NAME
, DRIVER_NAME
, NULL
, -1, &DRM(cdevsw
), CDEV_MAJOR
);
283 MOD_DEV( DRIVER_NAME
, LM_DT_CHAR
, CDEV_MAJOR
, &DRM(cdevsw
) );
286 int DRM(lkmentry
)(struct lkm_table
*lkmtp
, int cmd
, int ver
);
287 static int DRM(lkmhandle
)(struct lkm_table
*lkmtp
, int cmd
);
290 int DRM(probe
)(struct pci_attach_args
*pa
);
291 void DRM(attach
)(struct pci_attach_args
*pa
, cdev_t kdev
);
293 int DRM(lkmentry
)(struct lkm_table
*lkmtp
, int cmd
, int ver
) {
294 DISPATCH(lkmtp
, cmd
, ver
, DRM(lkmhandle
), DRM(lkmhandle
), DRM(lkmhandle
));
297 static int DRM(lkmhandle
)(struct lkm_table
*lkmtp
, int cmd
)
300 #if defined(__NetBSD__) && (__NetBSD_Version__ > 106080000)
301 struct lkm_dev
*args
= lkmtp
->private.lkm_dev
;
306 if (lkmexists(lkmtp
))
329 int DRM(modprobe
)() {
330 struct pci_attach_args pa
;
332 if((error
= pci_find_device(&pa
, DRM(probe
))) != 0)
338 int DRM(probe
)(struct pci_attach_args
*pa
)
342 desc
= DRM(find_description
)(PCI_VENDOR(pa
->pa_id
), PCI_PRODUCT(pa
->pa_id
));
350 void DRM(attach
)(struct pci_attach_args
*pa
, cdev_t kdev
)
355 config_makeroom(kdev
, &DRM(cd
));
356 DRM(cd
).cd_devs
[(kdev
)] = DRM(alloc
)(sizeof(drm_device_t
),
358 dev
= DRIVER_SOFTC(kdev
);
360 memset(dev
, 0, sizeof(drm_device_t
));
361 memcpy(&dev
->pa
, pa
, sizeof(dev
->pa
));
363 DRM_INFO("%s", DRM(find_description
)(PCI_VENDOR(pa
->pa_id
), PCI_PRODUCT(pa
->pa_id
)));
367 int DRM(detach
)(struct device
*self
, int flags
)
369 DRM(cleanup
)((drm_device_t
*)self
);
373 int DRM(activate
)(struct device
*self
, enum devact act
)
380 case DVACT_DEACTIVATE
:
386 #endif /* __NetBSD__ */
388 const char *DRM(find_description
)(int vendor
, int device
) {
389 const char *s
= NULL
;
392 while ( !done
&& (DRM(devicelist
)[i
].vendor
!= 0 ) ) {
393 if ( (DRM(devicelist
)[i
].vendor
== vendor
) &&
394 (DRM(devicelist
)[i
].device
== device
) ) {
396 if ( DRM(devicelist
)[i
].supported
)
397 s
= DRM(devicelist
)[i
].name
;
399 DRM_INFO("%s not supported\n", DRM(devicelist
)[i
].name
);
406 static int DRM(setup
)( drm_device_t
*dev
)
415 i
= DRM(dma_setup
)( dev
);
420 dev
->counters
= 6 + __HAVE_COUNTERS
;
421 dev
->types
[0] = _DRM_STAT_LOCK
;
422 dev
->types
[1] = _DRM_STAT_OPENS
;
423 dev
->types
[2] = _DRM_STAT_CLOSES
;
424 dev
->types
[3] = _DRM_STAT_IOCTLS
;
425 dev
->types
[4] = _DRM_STAT_LOCKS
;
426 dev
->types
[5] = _DRM_STAT_UNLOCKS
;
427 #ifdef __HAVE_COUNTER6
428 dev
->types
[6] = __HAVE_COUNTER6
;
430 #ifdef __HAVE_COUNTER7
431 dev
->types
[7] = __HAVE_COUNTER7
;
433 #ifdef __HAVE_COUNTER8
434 dev
->types
[8] = __HAVE_COUNTER8
;
436 #ifdef __HAVE_COUNTER9
437 dev
->types
[9] = __HAVE_COUNTER9
;
439 #ifdef __HAVE_COUNTER10
440 dev
->types
[10] = __HAVE_COUNTER10
;
442 #ifdef __HAVE_COUNTER11
443 dev
->types
[11] = __HAVE_COUNTER11
;
445 #ifdef __HAVE_COUNTER12
446 dev
->types
[12] = __HAVE_COUNTER12
;
448 #ifdef __HAVE_COUNTER13
449 dev
->types
[13] = __HAVE_COUNTER13
;
451 #ifdef __HAVE_COUNTER14
452 dev
->types
[14] = __HAVE_COUNTER14
;
454 #ifdef __HAVE_COUNTER15
455 dev
->types
[14] = __HAVE_COUNTER14
;
458 for ( i
= 0 ; i
< DRM_ARRAY_SIZE(dev
->counts
) ; i
++ )
459 atomic_set( &dev
->counts
[i
], 0 );
461 for ( i
= 0 ; i
< DRM_HASH_SIZE
; i
++ ) {
462 dev
->magiclist
[i
].head
= NULL
;
463 dev
->magiclist
[i
].tail
= NULL
;
466 dev
->maplist
= DRM(alloc
)(sizeof(*dev
->maplist
),
468 if(dev
->maplist
== NULL
) return DRM_ERR(ENOMEM
);
469 memset(dev
->maplist
, 0, sizeof(*dev
->maplist
));
470 TAILQ_INIT(dev
->maplist
);
472 dev
->lock
.hw_lock
= NULL
;
473 dev
->lock
.lock_queue
= 0;
475 dev
->context_flag
= 0;
476 dev
->last_context
= 0;
477 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
478 callout_init( &dev
->timer
, 1 );
480 callout_init( &dev
->timer
);
483 #if defined(__DragonFly__) || defined(__FreeBSD__)
484 dev
->buf_sigio
= NULL
;
485 #elif defined(__NetBSD__)
496 static int DRM(takedown
)( drm_device_t
*dev
)
498 drm_magic_entry_t
*pt
, *next
;
499 drm_local_map_t
*map
;
500 drm_map_list_entry_t
*list
;
505 DRIVER_PRETAKEDOWN();
507 if ( dev
->irq
) DRM(irq_uninstall
)( dev
);
511 callout_stop( &dev
->timer
);
514 DRM(free
)( dev
->unique
, strlen( dev
->unique
) + 1,
520 for ( i
= 0 ; i
< DRM_HASH_SIZE
; i
++ ) {
521 for ( pt
= dev
->magiclist
[i
].head
; pt
; pt
= next
) {
523 DRM(free
)( pt
, sizeof(*pt
), DRM_MEM_MAGIC
);
525 dev
->magiclist
[i
].head
= dev
->magiclist
[i
].tail
= NULL
;
528 #if __REALLY_HAVE_AGP
529 /* Clear AGP information */
531 drm_agp_mem_t
*entry
;
532 drm_agp_mem_t
*nexte
;
534 /* Remove AGP resources, but leave dev->agp
535 intact until drv_cleanup is called. */
536 for ( entry
= dev
->agp
->memory
; entry
; entry
= nexte
) {
538 if ( entry
->bound
) DRM(unbind_agp
)( entry
->handle
);
539 DRM(free_agp
)( entry
->handle
, entry
->pages
);
540 DRM(free
)( entry
, sizeof(*entry
), DRM_MEM_AGPLISTS
);
542 dev
->agp
->memory
= NULL
;
544 if ( dev
->agp
->acquired
) DRM(agp_do_release
)();
546 dev
->agp
->acquired
= 0;
547 dev
->agp
->enabled
= 0;
552 while ((list
=TAILQ_FIRST(dev
->maplist
))) {
554 switch ( map
->type
) {
556 case _DRM_FRAME_BUFFER
:
557 #if __REALLY_HAVE_MTRR
558 if ( map
->mtrr
>= 0 ) {
560 #if defined(__DragonFly__) || defined(__FreeBSD__)
562 struct mem_range_desc mrdesc
;
563 mrdesc
.mr_base
= map
->offset
;
564 mrdesc
.mr_len
= map
->size
;
565 mrdesc
.mr_flags
= MDF_WRITECOMBINE
;
566 act
= MEMRANGE_SET_UPDATE
;
567 bcopy(DRIVER_NAME
, &mrdesc
.mr_owner
, strlen(DRIVER_NAME
));
568 retcode
= mem_range_attr_set(&mrdesc
, &act
);
570 #elif defined __NetBSD__
573 mtrrmap
.base
= map
->offset
;
574 mtrrmap
.len
= map
->size
;
575 mtrrmap
.type
= MTRR_TYPE_WC
;
577 retcode
= mtrr_set( &mtrrmap
, &one
,
578 DRM_CURPROC
, MTRR_GETSET_KERNEL
);
580 DRM_DEBUG( "mtrr_del=%d\n", retcode
);
583 DRM(ioremapfree
)( map
);
586 DRM(free
)(map
->handle
,
592 /* Do nothing here, because this is all
593 * handled in the AGP/GART driver.
596 case _DRM_SCATTER_GATHER
:
597 /* Handle it, but do nothing, if REALLY_HAVE_SG
602 DRM(sg_cleanup
)(dev
->sg
);
608 TAILQ_REMOVE(dev
->maplist
, list
, link
);
609 DRM(free
)(list
, sizeof(*list
), DRM_MEM_MAPS
);
610 DRM(free
)(map
, sizeof(*map
), DRM_MEM_MAPS
);
612 DRM(free
)(dev
->maplist
, sizeof(*dev
->maplist
), DRM_MEM_MAPS
);
617 DRM(dma_takedown
)( dev
);
619 if ( dev
->lock
.hw_lock
) {
620 dev
->lock
.hw_lock
= NULL
; /* SHM removed */
621 dev
->lock
.filp
= NULL
;
622 DRM_WAKEUP_INT((void *)&dev
->lock
.lock_queue
);
629 /* linux: drm_init is called via init_module at module load time, or via
630 * linux/init/main.c (this is not currently supported).
631 * bsd: drm_init is called via the attach function per device.
633 static int DRM(init
)( device_t nbdev
)
636 #if defined(__DragonFly__) || defined(__FreeBSD__)
638 #elif defined(__NetBSD__)
639 drm_device_t
*dev
= nbdev
;
641 #if __HAVE_CTX_BITMAP
647 #if defined(__DragonFly__) || defined(__FreeBSD__)
648 unit
= device_get_unit(nbdev
);
649 dev
= device_get_softc(nbdev
);
650 memset( (void *)dev
, 0, sizeof(*dev
) );
652 dev_ops_add(&DRM(ops
), -1, unit
);
653 dev
->devnode
= make_dev( &DRM(ops
),
658 "dri/card%d", unit
);
659 reference_dev(dev
->devnode
);
660 #elif defined(__NetBSD__)
661 unit
= minor(dev
->device
.dv_unit
);
663 DRM_SPININIT(dev
->count_lock
, "drm device");
664 lockinit(&dev
->dev_lock
, "drmlk", 0, 0);
665 dev
->name
= DRIVER_NAME
;
667 DRM(sysctl_init
)(dev
);
668 TAILQ_INIT(&dev
->files
);
670 #if __REALLY_HAVE_AGP
671 dev
->agp
= DRM(agp_init
)();
673 if ( dev
->agp
== NULL
) {
674 DRM_ERROR( "Cannot initialize the agpgart module.\n" );
675 DRM(sysctl_cleanup
)( dev
);
676 #if defined(__DragonFly__) || defined(__FreeBSD__)
677 destroy_dev(dev
->devnode
);
679 DRM(takedown
)( dev
);
680 return DRM_ERR(ENOMEM
);
682 #endif /* __MUST_HAVE_AGP */
683 #if __REALLY_HAVE_MTRR
685 #if defined(__DragonFly__) || defined(__FreeBSD__)
686 int retcode
= 0, act
;
687 struct mem_range_desc mrdesc
;
688 mrdesc
.mr_base
= dev
->agp
->info
.ai_aperture_base
;
689 mrdesc
.mr_len
= dev
->agp
->info
.ai_aperture_size
;
690 mrdesc
.mr_flags
= MDF_WRITECOMBINE
;
691 act
= MEMRANGE_SET_UPDATE
;
692 bcopy(DRIVER_NAME
, &mrdesc
.mr_owner
, strlen(DRIVER_NAME
));
693 retcode
= mem_range_attr_set(&mrdesc
, &act
);
694 dev
->agp
->agp_mtrr
=1;
695 #elif defined __NetBSD__
698 mtrrmap
.base
= dev
->agp
->info
.ai_aperture_base
;
699 mtrrmap
.len
= dev
->agp
->info
.ai_aperture_size
;
700 mtrrmap
.type
= MTRR_TYPE_WC
;
701 mtrrmap
.flags
= MTRR_VALID
;
702 dev
->agp
->agp_mtrr
= mtrr_set( &mtrrmap
, &one
, NULL
, MTRR_GETSET_KERNEL
);
703 #endif /* __NetBSD__ */
705 #endif /* __REALLY_HAVE_MTRR */
706 #endif /* __REALLY_HAVE_AGP */
708 #if __HAVE_CTX_BITMAP
709 retcode
= DRM(ctxbitmap_init
)( dev
);
711 DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
712 DRM(sysctl_cleanup
)( dev
);
713 #if defined(__DragonFly__) || defined(__FreeBSD__)
714 destroy_dev(dev
->devnode
);
716 DRM(takedown
)( dev
);
720 DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
733 /* linux: drm_cleanup is called via cleanup_module at module unload time.
734 * bsd: drm_cleanup is called per device at module unload time.
737 static void DRM(cleanup
)(device_t nbdev
)
741 #if __REALLY_HAVE_MTRR
744 #endif /* __REALLY_HAVE_MTRR */
746 #endif /* __NetBSD__ */
750 #if defined(__DragonFly__) || defined(__FreeBSD__)
751 dev
= device_get_softc(nbdev
);
753 DRM(sysctl_cleanup
)( dev
);
754 #if defined(__DragonFly__) || defined(__FreeBSD__)
755 destroy_dev(dev
->devnode
);
757 #if __HAVE_CTX_BITMAP
758 DRM(ctxbitmap_cleanup
)( dev
);
761 #if __REALLY_HAVE_AGP && __REALLY_HAVE_MTRR
762 if ( dev
->agp
&& dev
->agp
->agp_mtrr
>= 0) {
763 #if defined(__NetBSD__)
764 mtrrmap
.base
= dev
->agp
->info
.ai_aperture_base
;
765 mtrrmap
.len
= dev
->agp
->info
.ai_aperture_size
;
768 mtrr_set( &mtrrmap
, &one
, NULL
, MTRR_GETSET_KERNEL
);
772 dev_ops_remove(&DRM(ops
), -1, device_get_unit(nbdev
));
774 DRM(takedown
)( dev
);
776 #if __REALLY_HAVE_AGP
779 DRM(free
)( dev
->agp
, sizeof(*dev
->agp
), DRM_MEM_AGPLISTS
);
783 DRIVER_POSTCLEANUP();
785 DRM_SPINUNINIT(dev
->count_lock
);
789 int DRM(version
)( DRM_IOCTL_ARGS
)
791 drm_version_t version
;
794 DRM_COPY_FROM_USER_IOCTL( version
, (drm_version_t
*)data
, sizeof(version
) );
796 #define DRM_COPY( name, value ) \
797 len = strlen( value ); \
798 if ( len > name##_len ) len = name##_len; \
799 name##_len = strlen( value ); \
800 if ( len && name ) { \
801 if ( DRM_COPY_TO_USER( name, value, len ) ) \
802 return DRM_ERR(EFAULT); \
805 version
.version_major
= DRIVER_MAJOR
;
806 version
.version_minor
= DRIVER_MINOR
;
807 version
.version_patchlevel
= DRIVER_PATCHLEVEL
;
809 DRM_COPY( version
.name
, DRIVER_NAME
);
810 DRM_COPY( version
.date
, DRIVER_DATE
);
811 DRM_COPY( version
.desc
, DRIVER_DESC
);
813 DRM_COPY_TO_USER_IOCTL( (drm_version_t
*)data
, version
, sizeof(version
) );
818 int DRM(open
)(struct dev_open_args
*ap
)
820 cdev_t kdev
= ap
->a_head
.a_dev
;
821 drm_device_t
*dev
= NULL
;
824 dev
= DRIVER_SOFTC(minor(kdev
));
826 DRM_DEBUG( "open_count = %d\n", dev
->open_count
);
828 retcode
= DRM(open_helper
)(kdev
, ap
->a_oflags
, ap
->a_devtype
,
832 atomic_inc( &dev
->counts
[_DRM_STAT_OPENS
] );
833 DRM_SPINLOCK( &dev
->count_lock
);
834 #if defined(__DragonFly__) || defined(__FreeBSD__)
835 device_busy(dev
->device
);
837 if ( !dev
->open_count
++ )
838 retcode
= DRM(setup
)( dev
);
839 DRM_SPINUNLOCK( &dev
->count_lock
);
845 int DRM(close
)(struct dev_close_args
*ap
)
847 cdev_t kdev
= ap
->a_head
.a_dev
;
851 DRMFILE __unused filp
= (void *)(DRM_CURRENTPID
);
853 DRM_DEBUG( "open_count = %d\n", dev
->open_count
);
854 priv
= DRM(find_file_by_proc
)(dev
, curthread
);
856 DRM_DEBUG("can't find authenticator\n");
862 /* ========================================================
863 * Begin inline drm_release
866 #if defined(__DragonFly__) || defined(__FreeBSD__)
867 DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
868 DRM_CURRENTPID
, (long)dev
->device
, dev
->open_count
);
869 #elif defined(__NetBSD__)
870 DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
871 DRM_CURRENTPID
, (long)&dev
->device
, dev
->open_count
);
874 if (dev
->lock
.hw_lock
&& _DRM_LOCK_IS_HELD(dev
->lock
.hw_lock
->lock
)
875 && dev
->lock
.filp
== (void *)DRM_CURRENTPID
) {
876 DRM_DEBUG("Process %d dead, freeing lock for context %d\n",
878 _DRM_LOCKING_CONTEXT(dev
->lock
.hw_lock
->lock
));
879 #if HAVE_DRIVER_RELEASE
883 &dev
->lock
.hw_lock
->lock
,
884 _DRM_LOCKING_CONTEXT(dev
->lock
.hw_lock
->lock
));
886 /* FIXME: may require heavy-handed reset of
887 hardware at this point, possibly
888 processed via a callback to the X
892 else if ( dev
->lock
.hw_lock
) {
893 /* The lock is required to reclaim buffers */
895 if ( !dev
->lock
.hw_lock
) {
896 /* Device has been unregistered */
897 retcode
= DRM_ERR(EINTR
);
900 if ( DRM(lock_take
)( &dev
->lock
.hw_lock
->lock
,
901 DRM_KERNEL_CONTEXT
) ) {
902 dev
->lock
.pid
= DRM_CURRENTPID
;
903 dev
->lock
.lock_time
= jiffies
;
904 atomic_inc( &dev
->counts
[_DRM_STAT_LOCKS
] );
905 break; /* Got lock */
909 atomic_inc( &dev
->total_sleeps
);
911 retcode
= tsleep((void *)&dev
->lock
.lock_queue
,
912 PCATCH
, "drmlk2", 0);
918 DRM(lock_free
)( dev
, &dev
->lock
.hw_lock
->lock
,
919 DRM_KERNEL_CONTEXT
);
923 DRM(reclaim_buffers
)( dev
, (void *)priv
->pid
);
926 #if defined (__FreeBSD__) && (__FreeBSD_version >= 500000)
927 funsetown(&dev
->buf_sigio
);
928 #elif defined(__DragonFly__) || defined(__FreeBSD__)
929 funsetown(dev
->buf_sigio
);
930 #elif defined(__NetBSD__)
932 #endif /* __NetBSD__ */
935 priv
= DRM(find_file_by_proc
)(dev
, curthread
);
939 TAILQ_REMOVE(&dev
->files
, priv
, link
);
940 DRM(free
)( priv
, sizeof(*priv
), DRM_MEM_FILES
);
946 /* ========================================================
947 * End inline drm_release
950 atomic_inc( &dev
->counts
[_DRM_STAT_CLOSES
] );
951 DRM_SPINLOCK( &dev
->count_lock
);
952 #if defined(__DragonFly__) || defined(__FreeBSD__)
953 device_unbusy(dev
->device
);
955 if ( !--dev
->open_count
) {
956 DRM_SPINUNLOCK( &dev
->count_lock
);
957 return DRM(takedown
)( dev
);
959 DRM_SPINUNLOCK( &dev
->count_lock
);
964 /* DRM(ioctl) is called whenever a process performs an ioctl on /dev/drm.
966 int DRM(ioctl
)(struct dev_ioctl_args
*ap
)
968 cdev_t kdev
= ap
->a_head
.a_dev
;
971 drm_ioctl_desc_t
*ioctl
;
972 int (*func
)(DRM_IOCTL_ARGS
);
973 int nr
= DRM_IOCTL_NR(ap
->a_cmd
);
976 atomic_inc( &dev
->counts
[_DRM_STAT_IOCTLS
] );
979 #if defined(__DragonFly__) || defined(__FreeBSD__)
980 DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
981 DRM_CURRENTPID
, ap
->a_cmd
, nr
, (long)dev
->device
, priv
->authenticated
);
982 #elif defined(__NetBSD__)
983 DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
984 DRM_CURRENTPID
, ap
->a_cmd
, nr
, (long)&dev
->device
, priv
->authenticated
);
989 dev
->flags
|= FASYNC
;
992 #if defined(__DragonFly__) || defined(__FreeBSD__)
994 return fsetown(*(int *)ap
->a_data
, &dev
->buf_sigio
);
997 #if defined(__FreeBSD__) && (__FreeBSD_version >= 500000)
998 *(int *) ap
->a_data
= fgetown(&dev
->buf_sigio
);
1000 *(int *) ap
->a_data
= fgetown(dev
->buf_sigio
);
1003 #endif /* __FreeBSD__ */
1006 dev
->buf_pgid
= *(int *)ap
->a_data
;
1010 *(int *)ap
->a_data
= dev
->buf_pgid
;
1012 #endif /* __NetBSD__ */
1015 if ( nr
>= DRIVER_IOCTL_COUNT
) {
1018 ioctl
= &DRM(ioctls
)[nr
];
1022 DRM_DEBUG( "no function\n" );
1024 } else if ( ( ioctl
->root_only
&& suser_cred(ap
->a_cred
, 0) )
1025 || ( ioctl
->auth_needed
&& !priv
->authenticated
) ) {
1028 retcode
= func(kdev
, ap
->a_cmd
, ap
->a_data
, ap
->a_fflag
, curthread
, (void *)DRM_CURRENTPID
);
1032 return DRM_ERR(retcode
);
1035 int DRM(lock
)( DRM_IOCTL_ARGS
)
1041 DRM_COPY_FROM_USER_IOCTL( lock
, (drm_lock_t
*)data
, sizeof(lock
) );
1043 if ( lock
.context
== DRM_KERNEL_CONTEXT
) {
1044 DRM_ERROR( "Process %d using kernel context %d\n",
1045 DRM_CURRENTPID
, lock
.context
);
1046 return DRM_ERR(EINVAL
);
1049 DRM_DEBUG( "%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
1050 lock
.context
, DRM_CURRENTPID
,
1051 dev
->lock
.hw_lock
->lock
, lock
.flags
);
1053 #if __HAVE_DMA_QUEUE
1054 if ( lock
.context
< 0 )
1055 return DRM_ERR(EINVAL
);
1060 if ( !dev
->lock
.hw_lock
) {
1061 /* Device has been unregistered */
1065 if ( DRM(lock_take
)( &dev
->lock
.hw_lock
->lock
,
1067 dev
->lock
.filp
= (void *)DRM_CURRENTPID
;
1068 dev
->lock
.lock_time
= jiffies
;
1069 atomic_inc( &dev
->counts
[_DRM_STAT_LOCKS
] );
1070 break; /* Got lock */
1074 ret
= tsleep((void *)&dev
->lock
.lock_queue
,
1075 PCATCH
, "drmlk2", 0);
1082 /* FIXME: Add signal blocking here */
1084 #if __HAVE_DMA_QUIESCENT
1085 if ( lock
.flags
& _DRM_LOCK_QUIESCENT
) {
1086 DRIVER_DMA_QUIESCENT();
1091 DRM_DEBUG( "%d %s\n", lock
.context
, ret
? "interrupted" : "has lock" );
1093 return DRM_ERR(ret
);
1097 int DRM(unlock
)( DRM_IOCTL_ARGS
)
1102 DRM_COPY_FROM_USER_IOCTL( lock
, (drm_lock_t
*)data
, sizeof(lock
) ) ;
1104 if ( lock
.context
== DRM_KERNEL_CONTEXT
) {
1105 DRM_ERROR( "Process %d using kernel context %d\n",
1106 DRM_CURRENTPID
, lock
.context
);
1107 return DRM_ERR(EINVAL
);
1110 atomic_inc( &dev
->counts
[_DRM_STAT_UNLOCKS
] );
1112 DRM(lock_transfer
)( dev
, &dev
->lock
.hw_lock
->lock
,
1113 DRM_KERNEL_CONTEXT
);
1114 #if __HAVE_DMA_SCHEDULE
1115 DRM(dma_schedule
)( dev
, 1 );
1118 /* FIXME: Do we ever really need to check this?
1120 if ( 1 /* !dev->context_flag */ ) {
1121 if ( DRM(lock_free
)( dev
, &dev
->lock
.hw_lock
->lock
,
1122 DRM_KERNEL_CONTEXT
) ) {
1132 #include <sys/file2.h>
1133 #include <sys/mapped_ioctl.h>
1134 #include <sys/sysproto.h>
1135 #include <emulation/linux/linux_ioctl.h>
1137 MODULE_DEPEND(DRIVER_NAME
, linux
, 1, 1, 1);
1139 #define LINUX_IOCTL_DRM_MIN 0x6400
1140 #define LINUX_IOCTL_DRM_MAX 0x64ff
1142 static struct ioctl_map_range
DRM(ioctl_cmds
)[] = {
1143 MAPPED_IOCTL_MAPRANGE(LINUX_IOCTL_DRM_MIN
, LINUX_IOCTL_DRM_MAX
, LINUX_IOCTL_DRM_MIN
,
1144 LINUX_IOCTL_DRM_MAX
, NULL
, linux_gen_dirmap
),
1145 MAPPED_IOCTL_MAPF(0, 0, NULL
)
1148 static struct ioctl_map_handler
DRM(ioctl_handler
) = {
1150 __XSTRING(DRM(linux
)),
1154 SYSINIT(DRM(register), SI_BOOT2_KLD
, SI_ORDER_MIDDLE
,
1155 mapped_ioctl_register_handler
, &DRM(ioctl_handler
));
1156 SYSUNINIT(DRM(unregister
), SI_BOOT2_KLD
, SI_ORDER_MIDDLE
,
1157 mapped_ioctl_unregister_handler
, &DRM(ioctl_handler
));
1159 #endif /* DRM_LINUX */