Style(9) cleanup to src/sys/vfs, stage 20/21: umapfs.
[dragonfly.git] / 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: 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/Attic/drm_drv.h,v 1.7 2004/05/13 23:49:16 dillon Exp $
33  */
34
35 /*
36  * To use this template, you must at least define the following (samples
37  * given for the MGA driver):
38  *
39  * #define DRIVER_AUTHOR        "VA Linux Systems, Inc."
40  *
41  * #define DRIVER_NAME          "mga"
42  * #define DRIVER_DESC          "Matrox G200/G400"
43  * #define DRIVER_DATE          "20001127"
44  *
45  * #define DRIVER_MAJOR         2
46  * #define DRIVER_MINOR         0
47  * #define DRIVER_PATCHLEVEL    2
48  *
49  * #define DRIVER_IOCTL_COUNT   DRM_ARRAY_SIZE( mga_ioctls )
50  *
51  * #define DRM(x)               mga_##x
52  */
53
54 #ifndef __MUST_HAVE_AGP
55 #define __MUST_HAVE_AGP                 0
56 #endif
57 #ifndef __HAVE_CTX_BITMAP
58 #define __HAVE_CTX_BITMAP               0
59 #endif
60 #ifndef __HAVE_DMA_IRQ
61 #define __HAVE_DMA_IRQ                  0
62 #endif
63 #ifndef __HAVE_DMA_QUEUE
64 #define __HAVE_DMA_QUEUE                0
65 #endif
66 #ifndef __HAVE_DMA_SCHEDULE
67 #define __HAVE_DMA_SCHEDULE             0
68 #endif
69 #ifndef __HAVE_DMA_QUIESCENT
70 #define __HAVE_DMA_QUIESCENT            0
71 #endif
72 #ifndef __HAVE_RELEASE
73 #define __HAVE_RELEASE                  0
74 #endif
75 #ifndef __HAVE_COUNTERS
76 #define __HAVE_COUNTERS                 0
77 #endif
78 #ifndef __HAVE_SG
79 #define __HAVE_SG                       0
80 #endif
81
82 #ifndef DRIVER_PREINIT
83 #define DRIVER_PREINIT()
84 #endif
85 #ifndef DRIVER_POSTINIT
86 #define DRIVER_POSTINIT()
87 #endif
88 #ifndef DRIVER_PRERELEASE
89 #define DRIVER_PRERELEASE()
90 #endif
91 #ifndef DRIVER_PRETAKEDOWN
92 #define DRIVER_PRETAKEDOWN()
93 #endif
94 #ifndef DRIVER_POSTCLEANUP
95 #define DRIVER_POSTCLEANUP()
96 #endif
97 #ifndef DRIVER_PRESETUP
98 #define DRIVER_PRESETUP()
99 #endif
100 #ifndef DRIVER_POSTSETUP
101 #define DRIVER_POSTSETUP()
102 #endif
103 #ifndef DRIVER_IOCTLS
104 #define DRIVER_IOCTLS
105 #endif
106 #ifndef DRIVER_FOPS
107 #endif
108
109 #if 1 && DRM_DEBUG_CODE
110 int DRM(flags) = DRM_FLAG_DEBUG;
111 #else
112 int DRM(flags) = 0;
113 #endif
114
115 static int DRM(init)(device_t nbdev);
116 static void DRM(cleanup)(device_t nbdev);
117
118 #if defined(__DragonFly__) || defined(__FreeBSD__)
119 #define DRIVER_SOFTC(unit) \
120         ((drm_device_t *) devclass_get_softc(DRM(devclass), unit))
121
122 #if __REALLY_HAVE_AGP
123 MODULE_DEPEND(DRIVER_NAME, agp, 1, 1, 1);
124 #endif
125 #endif /* __FreeBSD__ */
126
127 #ifdef __NetBSD__
128 #define DRIVER_SOFTC(unit) \
129         ((drm_device_t *) device_lookup(&DRM(cd), unit))
130 #endif /* __NetBSD__ */
131
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 },
140
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 },
145
146         [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)]       = { DRM(addmap),      1, 1 },
147         [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)]        = { DRM(rmmap),       1, 0 },
148
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 },
152 #endif
153
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 },
161
162         [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)]      = { DRM(adddraw),     1, 1 },
163         [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)]       = { DRM(rmdraw),      1, 1 },
164
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 },
168
169 #if __HAVE_DMA
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 },
175
176         /* The DRM_IOCTL_DMA ioctl should be defined by the driver.
177          */
178         [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)]       = { DRM(control),     1, 1 },
179 #endif
180
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 },
190 #endif
191
192 #if __HAVE_SG
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 },
195 #endif
196
197 #if __HAVE_VBL_IRQ
198         [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)]   = { DRM(wait_vblank), 0, 0 },
199 #endif
200
201         DRIVER_IOCTLS
202 };
203
204 #define DRIVER_IOCTL_COUNT      DRM_ARRAY_SIZE( DRM(ioctls) )
205
206 const char *DRM(find_description)(int vendor, int device);
207
208 #if defined(__DragonFly__) || defined(__FreeBSD__)
209 static struct cdevsw DRM(cdevsw) = {
210         .d_name =       DRIVER_NAME,
211         .d_maj =        CDEV_MAJOR,
212         .d_flags =      D_TTY | D_TRACKCLOSE,
213         .d_port =       NULL,
214         .d_clone =      NULL,
215
216         .old_open =     DRM( open ),
217         .old_close =    DRM( close ),
218         .old_read =     DRM( read ),
219         .old_ioctl =    DRM( ioctl ),
220         .old_poll =     DRM( poll ),
221         .old_mmap =     DRM( mmap )
222 };
223
224 static int DRM(probe)(device_t dev)
225 {
226         const char *s = NULL;
227
228         int pciid=pci_get_devid(dev);
229         int vendor = (pciid & 0x0000ffff);
230         int device = (pciid & 0xffff0000) >> 16;
231         
232         s = DRM(find_description)(vendor, device);
233         if (s) {
234                 device_set_desc(dev, s);
235                 return 0;
236         }
237
238         return ENXIO;
239 }
240
241 static int DRM(attach)(device_t dev)
242 {
243         return DRM(init)(dev);
244 }
245
246 static int DRM(detach)(device_t dev)
247 {
248         DRM(cleanup)(dev);
249         return 0;
250 }
251 static device_method_t DRM(methods)[] = {
252         /* Device interface */
253         DEVMETHOD(device_probe,         DRM( probe)),
254         DEVMETHOD(device_attach,        DRM( attach)),
255         DEVMETHOD(device_detach,        DRM( detach)),
256
257         { 0, 0 }
258 };
259
260 static driver_t DRM(driver) = {
261         "drm",
262         DRM(methods),
263         sizeof(drm_device_t),
264 };
265
266 static devclass_t DRM(devclass);
267
268 #elif defined(__NetBSD__)
269
270 static struct cdevsw DRM(cdevsw) = {
271         DRM(open),
272         DRM(close),
273         DRM(read),
274         nowrite,
275         DRM(ioctl),
276         nostop,
277         notty,
278         DRM(poll),
279         DRM(mmap),
280         nokqfilter,
281         D_TTY
282 };
283
284 int DRM(refcnt) = 0;
285 #if __NetBSD_Version__ >= 106080000
286 MOD_DEV( DRIVER_NAME, DRIVER_NAME, NULL, -1, &DRM(cdevsw), CDEV_MAJOR);
287 #else
288 MOD_DEV( DRIVER_NAME, LM_DT_CHAR, CDEV_MAJOR, &DRM(cdevsw) );
289 #endif
290
291 int DRM(lkmentry)(struct lkm_table *lkmtp, int cmd, int ver);
292 static int DRM(lkmhandle)(struct lkm_table *lkmtp, int cmd);
293
294 int DRM(modprobe)();
295 int DRM(probe)(struct pci_attach_args *pa);
296 void DRM(attach)(struct pci_attach_args *pa, dev_t kdev);
297
298 int DRM(lkmentry)(struct lkm_table *lkmtp, int cmd, int ver) {
299         DISPATCH(lkmtp, cmd, ver, DRM(lkmhandle), DRM(lkmhandle), DRM(lkmhandle));
300 }
301
302 static int DRM(lkmhandle)(struct lkm_table *lkmtp, int cmd)
303 {
304         int j, error = 0;
305 #if defined(__NetBSD__) && (__NetBSD_Version__ > 106080000)
306         struct lkm_dev *args = lkmtp->private.lkm_dev;
307 #endif
308
309         switch(cmd) {
310         case LKM_E_LOAD:
311                 if (lkmexists(lkmtp))
312                         return EEXIST;
313
314                 if(DRM(modprobe)())
315                         return 0;
316
317                 return 1;
318
319         case LKM_E_UNLOAD:
320                 if (DRM(refcnt) > 0)
321                         return (EBUSY);
322                 break;
323         case LKM_E_STAT:
324                 break;
325
326         default:
327                 error = EIO;
328                 break;
329         }
330         
331         return error;
332 }
333
334 int DRM(modprobe)() {
335         struct pci_attach_args pa;
336         int error = 0;
337         if((error = pci_find_device(&pa, DRM(probe))) != 0)
338                 DRM(attach)(&pa, 0);
339
340         return error;
341 }
342
343 int DRM(probe)(struct pci_attach_args *pa)
344 {
345         const char *desc;
346
347         desc = DRM(find_description)(PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id));
348         if (desc != NULL) {
349                 return 1;
350         }
351
352         return 0;
353 }
354
355 void DRM(attach)(struct pci_attach_args *pa, dev_t kdev)
356 {
357         int i;
358         drm_device_t *dev;
359
360         config_makeroom(kdev, &DRM(cd));
361         DRM(cd).cd_devs[(kdev)] = DRM(alloc)(sizeof(drm_device_t),
362             DRM_MEM_DRIVER);
363         dev = DRIVER_SOFTC(kdev);
364
365         memset(dev, 0, sizeof(drm_device_t));
366         memcpy(&dev->pa, pa, sizeof(dev->pa));
367
368         DRM_INFO("%s", DRM(find_description)(PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id)));
369         DRM(init)(dev);
370 }
371
372 int DRM(detach)(struct device *self, int flags)
373 {
374         DRM(cleanup)((drm_device_t *)self);
375         return 0;
376 }
377
378 int DRM(activate)(struct device *self, enum devact act)
379 {
380         switch (act) {
381         case DVACT_ACTIVATE:
382                 return (EOPNOTSUPP);
383                 break;
384
385         case DVACT_DEACTIVATE:
386                 /* FIXME */
387                 break;
388         }
389         return (0);
390 }
391 #endif /* __NetBSD__ */
392
393 const char *DRM(find_description)(int vendor, int device) {
394         const char *s = NULL;
395         int i=0, done=0;
396         
397         while ( !done && (DRM(devicelist)[i].vendor != 0 ) ) {
398                 if ( (DRM(devicelist)[i].vendor == vendor) &&
399                      (DRM(devicelist)[i].device == device) ) {
400                         done=1;
401                         if ( DRM(devicelist)[i].supported )
402                                 s = DRM(devicelist)[i].name;
403                         else
404                                 DRM_INFO("%s not supported\n", DRM(devicelist)[i].name);
405                 }
406                 i++;
407         }
408         return s;
409 }
410
411 static int DRM(setup)( drm_device_t *dev )
412 {
413         int i;
414
415         DRIVER_PRESETUP();
416         dev->buf_use = 0;
417         dev->buf_alloc = 0;
418
419 #if __HAVE_DMA
420         i = DRM(dma_setup)( dev );
421         if ( i < 0 )
422                 return i;
423 #endif
424
425         dev->counters  = 6 + __HAVE_COUNTERS;
426         dev->types[0]  = _DRM_STAT_LOCK;
427         dev->types[1]  = _DRM_STAT_OPENS;
428         dev->types[2]  = _DRM_STAT_CLOSES;
429         dev->types[3]  = _DRM_STAT_IOCTLS;
430         dev->types[4]  = _DRM_STAT_LOCKS;
431         dev->types[5]  = _DRM_STAT_UNLOCKS;
432 #ifdef __HAVE_COUNTER6
433         dev->types[6]  = __HAVE_COUNTER6;
434 #endif
435 #ifdef __HAVE_COUNTER7
436         dev->types[7]  = __HAVE_COUNTER7;
437 #endif
438 #ifdef __HAVE_COUNTER8
439         dev->types[8]  = __HAVE_COUNTER8;
440 #endif
441 #ifdef __HAVE_COUNTER9
442         dev->types[9]  = __HAVE_COUNTER9;
443 #endif
444 #ifdef __HAVE_COUNTER10
445         dev->types[10] = __HAVE_COUNTER10;
446 #endif
447 #ifdef __HAVE_COUNTER11
448         dev->types[11] = __HAVE_COUNTER11;
449 #endif
450 #ifdef __HAVE_COUNTER12
451         dev->types[12] = __HAVE_COUNTER12;
452 #endif
453 #ifdef __HAVE_COUNTER13
454         dev->types[13] = __HAVE_COUNTER13;
455 #endif
456 #ifdef __HAVE_COUNTER14
457         dev->types[14] = __HAVE_COUNTER14;
458 #endif
459 #ifdef __HAVE_COUNTER15
460         dev->types[14] = __HAVE_COUNTER14;
461 #endif
462
463         for ( i = 0 ; i < DRM_ARRAY_SIZE(dev->counts) ; i++ )
464                 atomic_set( &dev->counts[i], 0 );
465
466         for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
467                 dev->magiclist[i].head = NULL;
468                 dev->magiclist[i].tail = NULL;
469         }
470
471         dev->maplist = DRM(alloc)(sizeof(*dev->maplist),
472                                   DRM_MEM_MAPS);
473         if(dev->maplist == NULL) return DRM_ERR(ENOMEM);
474         memset(dev->maplist, 0, sizeof(*dev->maplist));
475         TAILQ_INIT(dev->maplist);
476
477         dev->lock.hw_lock = NULL;
478         dev->lock.lock_queue = 0;
479         dev->irq = 0;
480         dev->context_flag = 0;
481         dev->last_context = 0;
482 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
483         callout_init( &dev->timer, 1 );
484 #else
485         callout_init( &dev->timer );
486 #endif
487
488 #if defined(__DragonFly__) || defined(__FreeBSD__)
489         dev->buf_sigio = NULL;
490 #elif defined(__NetBSD__)
491         dev->buf_pgid = 0;
492 #endif
493
494         DRM_DEBUG( "\n" );
495
496         DRIVER_POSTSETUP();
497         return 0;
498 }
499
500
501 static int DRM(takedown)( drm_device_t *dev )
502 {
503         drm_magic_entry_t *pt, *next;
504         drm_local_map_t *map;
505         drm_map_list_entry_t *list;
506         int i;
507
508         DRM_DEBUG( "\n" );
509
510         DRIVER_PRETAKEDOWN();
511 #if __HAVE_DMA_IRQ
512         if ( dev->irq ) DRM(irq_uninstall)( dev );
513 #endif
514
515         DRM_LOCK;
516         callout_stop( &dev->timer );
517
518         if ( dev->unique ) {
519                 DRM(free)( dev->unique, strlen( dev->unique ) + 1,
520                            DRM_MEM_DRIVER );
521                 dev->unique = NULL;
522                 dev->unique_len = 0;
523         }
524                                 /* Clear pid list */
525         for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
526                 for ( pt = dev->magiclist[i].head ; pt ; pt = next ) {
527                         next = pt->next;
528                         DRM(free)( pt, sizeof(*pt), DRM_MEM_MAGIC );
529                 }
530                 dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
531         }
532
533 #if __REALLY_HAVE_AGP
534                                 /* Clear AGP information */
535         if ( dev->agp ) {
536                 drm_agp_mem_t *entry;
537                 drm_agp_mem_t *nexte;
538
539                                 /* Remove AGP resources, but leave dev->agp
540                                    intact until drv_cleanup is called. */
541                 for ( entry = dev->agp->memory ; entry ; entry = nexte ) {
542                         nexte = entry->next;
543                         if ( entry->bound ) DRM(unbind_agp)( entry->handle );
544                         DRM(free_agp)( entry->handle, entry->pages );
545                         DRM(free)( entry, sizeof(*entry), DRM_MEM_AGPLISTS );
546                 }
547                 dev->agp->memory = NULL;
548
549                 if ( dev->agp->acquired ) DRM(agp_do_release)();
550
551                 dev->agp->acquired = 0;
552                 dev->agp->enabled  = 0;
553         }
554 #endif
555
556         if( dev->maplist ) {
557                 while ((list=TAILQ_FIRST(dev->maplist))) {
558                         map = list->map;
559                         switch ( map->type ) {
560                         case _DRM_REGISTERS:
561                         case _DRM_FRAME_BUFFER:
562 #if __REALLY_HAVE_MTRR
563                                 if ( map->mtrr >= 0 ) {
564                                         int retcode;
565 #if defined(__DragonFly__) || defined(__FreeBSD__)
566                                         int act;
567                                         struct mem_range_desc mrdesc;
568                                         mrdesc.mr_base = map->offset;
569                                         mrdesc.mr_len = map->size;
570                                         mrdesc.mr_flags = MDF_WRITECOMBINE;
571                                         act = MEMRANGE_SET_UPDATE;
572                                         bcopy(DRIVER_NAME, &mrdesc.mr_owner, strlen(DRIVER_NAME));
573                                         retcode = mem_range_attr_set(&mrdesc, &act);
574                                         map->mtrr=1;
575 #elif defined __NetBSD__
576                                         struct mtrr mtrrmap;
577                                         int one = 1;
578                                         mtrrmap.base = map->offset;
579                                         mtrrmap.len = map->size;
580                                         mtrrmap.type = MTRR_TYPE_WC;
581                                         mtrrmap.flags = 0;
582                                         retcode = mtrr_set( &mtrrmap, &one, 
583                                                 DRM_CURPROC, MTRR_GETSET_KERNEL);
584 #endif
585                                         DRM_DEBUG( "mtrr_del=%d\n", retcode );
586                                 }
587 #endif
588                                 DRM(ioremapfree)( map );
589                                 break;
590                         case _DRM_SHM:
591                                 DRM(free)(map->handle,
592                                                map->size,
593                                                DRM_MEM_SAREA);
594                                 break;
595
596                         case _DRM_AGP:
597                                 /* Do nothing here, because this is all
598                                  * handled in the AGP/GART driver.
599                                  */
600                                 break;
601                        case _DRM_SCATTER_GATHER:
602                                 /* Handle it, but do nothing, if REALLY_HAVE_SG
603                                  * isn't defined.
604                                  */
605 #if __REALLY_HAVE_SG
606                                 if(dev->sg) {
607                                         DRM(sg_cleanup)(dev->sg);
608                                         dev->sg = NULL;
609                                 }
610 #endif
611                                 break;
612                         }
613                         TAILQ_REMOVE(dev->maplist, list, link);
614                         DRM(free)(list, sizeof(*list), DRM_MEM_MAPS);
615                         DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
616                 }
617                 DRM(free)(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
618                 dev->maplist   = NULL;
619         }
620
621 #if __HAVE_DMA
622         DRM(dma_takedown)( dev );
623 #endif
624         if ( dev->lock.hw_lock ) {
625                 dev->lock.hw_lock = NULL; /* SHM removed */
626                 dev->lock.filp = NULL;
627                 DRM_WAKEUP_INT((void *)&dev->lock.lock_queue);
628         }
629         DRM_UNLOCK;
630
631         return 0;
632 }
633
634 /* linux: drm_init is called via init_module at module load time, or via
635  *        linux/init/main.c (this is not currently supported).
636  * bsd:   drm_init is called via the attach function per device.
637  */
638 static int DRM(init)( device_t nbdev )
639 {
640         int unit;
641 #if defined(__DragonFly__) || defined(__FreeBSD__)
642         drm_device_t *dev;
643 #elif defined(__NetBSD__)
644         drm_device_t *dev = nbdev;
645 #endif
646 #if __HAVE_CTX_BITMAP
647         int retcode;
648 #endif
649         DRM_DEBUG( "\n" );
650         DRIVER_PREINIT();
651
652 #if defined(__DragonFly__) || defined(__FreeBSD__)
653         unit = device_get_unit(nbdev);
654         dev = device_get_softc(nbdev);
655         memset( (void *)dev, 0, sizeof(*dev) );
656         dev->device = nbdev;
657         dev->devnode = make_dev( &DRM(cdevsw),
658                         unit,
659                         DRM_DEV_UID,
660                         DRM_DEV_GID,
661                         DRM_DEV_MODE,
662                         "dri/card%d", unit );
663 #elif defined(__NetBSD__)
664         unit = minor(dev->device.dv_unit);
665 #endif
666         DRM_SPININIT(dev->count_lock, "drm device");
667         lockinit(&dev->dev_lock, 0, "drmlk", 0, 0);
668         dev->name = DRIVER_NAME;
669         DRM(mem_init)();
670         DRM(sysctl_init)(dev);
671         TAILQ_INIT(&dev->files);
672
673 #if __REALLY_HAVE_AGP
674         dev->agp = DRM(agp_init)();
675 #if __MUST_HAVE_AGP
676         if ( dev->agp == NULL ) {
677                 DRM_ERROR( "Cannot initialize the agpgart module.\n" );
678                 DRM(sysctl_cleanup)( dev );
679 #if defined(__DragonFly__) || defined(__FreeBSD__)
680                 destroy_dev(dev->devnode);
681 #endif
682                 DRM(takedown)( dev );
683                 return DRM_ERR(ENOMEM);
684         }
685 #endif /* __MUST_HAVE_AGP */
686 #if __REALLY_HAVE_MTRR
687         if (dev->agp) {
688 #if defined(__DragonFly__) || defined(__FreeBSD__)
689                 int retcode = 0, act;
690                 struct mem_range_desc mrdesc;
691                 mrdesc.mr_base = dev->agp->info.ai_aperture_base;
692                 mrdesc.mr_len = dev->agp->info.ai_aperture_size;
693                 mrdesc.mr_flags = MDF_WRITECOMBINE;
694                 act = MEMRANGE_SET_UPDATE;
695                 bcopy(DRIVER_NAME, &mrdesc.mr_owner, strlen(DRIVER_NAME));
696                 retcode = mem_range_attr_set(&mrdesc, &act);
697                 dev->agp->agp_mtrr=1;
698 #elif defined __NetBSD__
699                 struct mtrr mtrrmap;
700                 int one = 1;
701                 mtrrmap.base = dev->agp->info.ai_aperture_base;
702                 mtrrmap.len = dev->agp->info.ai_aperture_size;
703                 mtrrmap.type = MTRR_TYPE_WC;
704                 mtrrmap.flags = MTRR_VALID;
705                 dev->agp->agp_mtrr = mtrr_set( &mtrrmap, &one, NULL, MTRR_GETSET_KERNEL);
706 #endif /* __NetBSD__ */
707         }
708 #endif /* __REALLY_HAVE_MTRR */
709 #endif /* __REALLY_HAVE_AGP */
710
711 #if __HAVE_CTX_BITMAP
712         retcode = DRM(ctxbitmap_init)( dev );
713         if( retcode ) {
714                 DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
715                 DRM(sysctl_cleanup)( dev );
716 #if defined(__DragonFly__) || defined(__FreeBSD__)
717                 destroy_dev(dev->devnode);
718 #endif
719                 DRM(takedown)( dev );
720                 return retcode;
721         }
722 #endif
723         DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
724                 DRIVER_NAME,
725                 DRIVER_MAJOR,
726                 DRIVER_MINOR,
727                 DRIVER_PATCHLEVEL,
728                 DRIVER_DATE,
729                 unit );
730
731         DRIVER_POSTINIT();
732
733         return 0;
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)(device_t nbdev)
741 {
742         drm_device_t *dev;
743 #ifdef __NetBSD__
744 #if __REALLY_HAVE_MTRR
745         struct mtrr mtrrmap;
746         int one = 1;
747 #endif /* __REALLY_HAVE_MTRR */
748         dev = nbdev;
749 #endif /* __NetBSD__ */
750
751         DRM_DEBUG( "\n" );
752
753 #if defined(__DragonFly__) || defined(__FreeBSD__)
754         dev = device_get_softc(nbdev);
755 #endif
756         DRM(sysctl_cleanup)( dev );
757 #if defined(__DragonFly__) || defined(__FreeBSD__)
758         destroy_dev(dev->devnode);
759 #endif
760 #if __HAVE_CTX_BITMAP
761         DRM(ctxbitmap_cleanup)( dev );
762 #endif
763
764 #if __REALLY_HAVE_AGP && __REALLY_HAVE_MTRR
765         if ( dev->agp && dev->agp->agp_mtrr >= 0) {
766 #if defined(__NetBSD__)
767                 mtrrmap.base = dev->agp->info.ai_aperture_base;
768                 mtrrmap.len = dev->agp->info.ai_aperture_size;
769                 mtrrmap.type = 0;
770                 mtrrmap.flags = 0;
771                 mtrr_set( &mtrrmap, &one, NULL, MTRR_GETSET_KERNEL);
772 #endif
773         }
774 #endif
775
776         DRM(takedown)( dev );
777
778 #if __REALLY_HAVE_AGP
779         if ( dev->agp ) {
780                 DRM(agp_uninit)();
781                 DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
782                 dev->agp = NULL;
783         }
784 #endif
785         DRIVER_POSTCLEANUP();
786         DRM(mem_uninit)();
787         DRM_SPINUNINIT(dev->count_lock);
788 }
789
790
791 int DRM(version)( DRM_IOCTL_ARGS )
792 {
793         drm_version_t version;
794         int len;
795
796         DRM_COPY_FROM_USER_IOCTL( version, (drm_version_t *)data, sizeof(version) );
797
798 #define DRM_COPY( name, value )                                         \
799         len = strlen( value );                                          \
800         if ( len > name##_len ) len = name##_len;                       \
801         name##_len = strlen( value );                                   \
802         if ( len && name ) {                                            \
803                 if ( DRM_COPY_TO_USER( name, value, len ) )             \
804                         return DRM_ERR(EFAULT);                         \
805         }
806
807         version.version_major = DRIVER_MAJOR;
808         version.version_minor = DRIVER_MINOR;
809         version.version_patchlevel = DRIVER_PATCHLEVEL;
810
811         DRM_COPY( version.name, DRIVER_NAME );
812         DRM_COPY( version.date, DRIVER_DATE );
813         DRM_COPY( version.desc, DRIVER_DESC );
814
815         DRM_COPY_TO_USER_IOCTL( (drm_version_t *)data, version, sizeof(version) );
816
817         return 0;
818 }
819
820 int DRM(open)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
821 {
822         drm_device_t *dev = NULL;
823         int retcode = 0;
824
825         dev = DRIVER_SOFTC(minor(kdev));
826
827         DRM_DEBUG( "open_count = %d\n", dev->open_count );
828
829         retcode = DRM(open_helper)(kdev, flags, fmt, p, dev);
830
831         if ( !retcode ) {
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);
836 #endif
837                 if ( !dev->open_count++ )
838                         retcode = DRM(setup)( dev );
839                 DRM_SPINUNLOCK( &dev->count_lock );
840         }
841
842         return retcode;
843 }
844
845 int DRM(close)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
846 {
847         drm_file_t *priv;
848         DRM_DEVICE;
849         int retcode = 0;
850         DRMFILE __unused filp = (void *)(DRM_CURRENTPID);
851         
852         DRM_DEBUG( "open_count = %d\n", dev->open_count );
853         priv = DRM(find_file_by_proc)(dev, p);
854         if (!priv) {
855                 DRM_DEBUG("can't find authenticator\n");
856                 return EINVAL;
857         }
858
859         DRIVER_PRERELEASE();
860
861         /* ========================================================
862          * Begin inline drm_release
863          */
864
865 #if defined(__DragonFly__) || defined(__FreeBSD__)
866         DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
867                    DRM_CURRENTPID, (long)dev->device, dev->open_count );
868 #elif defined(__NetBSD__)
869         DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
870                    DRM_CURRENTPID, (long)&dev->device, dev->open_count);
871 #endif
872
873         if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
874             && dev->lock.filp == (void *)DRM_CURRENTPID) {
875                 DRM_DEBUG("Process %d dead, freeing lock for context %d\n",
876                           DRM_CURRENTPID,
877                           _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
878 #if HAVE_DRIVER_RELEASE
879                 DRIVER_RELEASE();
880 #endif
881                 DRM(lock_free)(dev,
882                               &dev->lock.hw_lock->lock,
883                               _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
884                 
885                                 /* FIXME: may require heavy-handed reset of
886                                    hardware at this point, possibly
887                                    processed via a callback to the X
888                                    server. */
889         }
890 #if __HAVE_RELEASE
891         else if ( dev->lock.hw_lock ) {
892                 /* The lock is required to reclaim buffers */
893                 for (;;) {
894                         if ( !dev->lock.hw_lock ) {
895                                 /* Device has been unregistered */
896                                 retcode = DRM_ERR(EINTR);
897                                 break;
898                         }
899                         if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
900                                              DRM_KERNEL_CONTEXT ) ) {
901                                 dev->lock.pid       = DRM_CURRENTPID;
902                                 dev->lock.lock_time = jiffies;
903                                 atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
904                                 break;  /* Got lock */
905                         }
906                                 /* Contention */
907 #if 0
908                         atomic_inc( &dev->total_sleeps );
909 #endif
910                         retcode = tsleep((void *)&dev->lock.lock_queue,
911                                         PCATCH, "drmlk2", 0);
912                         if (retcode)
913                                 break;
914                 }
915                 if( !retcode ) {
916                         DRIVER_RELEASE();
917                         DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
918                                         DRM_KERNEL_CONTEXT );
919                 }
920         }
921 #elif __HAVE_DMA
922         DRM(reclaim_buffers)( dev, (void *)priv->pid );
923 #endif
924
925 #if defined (__FreeBSD__) && (__FreeBSD_version >= 500000)
926         funsetown(&dev->buf_sigio);
927 #elif defined(__DragonFly__) || defined(__FreeBSD__)
928         funsetown(dev->buf_sigio);
929 #elif defined(__NetBSD__)
930         dev->buf_pgid = 0;
931 #endif /* __NetBSD__ */
932
933         DRM_LOCK;
934         priv = DRM(find_file_by_proc)(dev, p);
935         if (priv) {
936                 priv->refs--;
937                 if (!priv->refs) {
938                         TAILQ_REMOVE(&dev->files, priv, link);
939                         DRM(free)( priv, sizeof(*priv), DRM_MEM_FILES );
940                 }
941         }
942         DRM_UNLOCK;
943
944
945         /* ========================================================
946          * End inline drm_release
947          */
948
949         atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
950         DRM_SPINLOCK( &dev->count_lock );
951 #if defined(__DragonFly__) || defined(__FreeBSD__)
952         device_unbusy(dev->device);
953 #endif
954         if ( !--dev->open_count ) {
955                 DRM_SPINUNLOCK( &dev->count_lock );
956                 return DRM(takedown)( dev );
957         }
958         DRM_SPINUNLOCK( &dev->count_lock );
959         
960         return retcode;
961 }
962
963 /* DRM(ioctl) is called whenever a process performs an ioctl on /dev/drm.
964  */
965 int DRM(ioctl)(dev_t kdev, u_long cmd, caddr_t data, int flags, 
966     DRM_STRUCTPROC *p)
967 {
968         DRM_DEVICE;
969         int retcode = 0;
970         drm_ioctl_desc_t *ioctl;
971         int (*func)(DRM_IOCTL_ARGS);
972         int nr = DRM_IOCTL_NR(cmd);
973         DRM_PRIV;
974
975         atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
976         ++priv->ioctl_count;
977
978 #if defined(__DragonFly__) || defined(__FreeBSD__)
979         DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
980                  DRM_CURRENTPID, cmd, nr, (long)dev->device, priv->authenticated );
981 #elif defined(__NetBSD__)
982         DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
983                  DRM_CURRENTPID, cmd, nr, (long)&dev->device, priv->authenticated );
984 #endif
985
986         switch (cmd) {
987         case FIONBIO:
988                 return 0;
989
990         case FIOASYNC:
991                 dev->flags |= FASYNC;
992                 return 0;
993
994 #if defined(__DragonFly__) || defined(__FreeBSD__)
995         case FIOSETOWN:
996                 return fsetown(*(int *)data, &dev->buf_sigio);
997
998         case FIOGETOWN:
999 #if defined(__FreeBSD__) && (__FreeBSD_version >= 500000)
1000                 *(int *) data = fgetown(&dev->buf_sigio);
1001 #else
1002                 *(int *) data = fgetown(dev->buf_sigio);
1003 #endif
1004                 return 0;
1005 #endif /* __FreeBSD__ */
1006 #ifdef __NetBSD__
1007         case TIOCSPGRP:
1008                 dev->buf_pgid = *(int *)data;
1009                 return 0;
1010
1011         case TIOCGPGRP:
1012                 *(int *)data = dev->buf_pgid;
1013                 return 0;
1014 #endif /* __NetBSD__ */
1015         }
1016
1017         if ( nr >= DRIVER_IOCTL_COUNT ) {
1018                 retcode = EINVAL;
1019         } else {
1020                 ioctl = &DRM(ioctls)[nr];
1021                 func = ioctl->func;
1022
1023                 if ( !func ) {
1024                         DRM_DEBUG( "no function\n" );
1025                         retcode = EINVAL;
1026                 } else if ( ( ioctl->root_only && DRM_SUSER(p) ) 
1027                          || ( ioctl->auth_needed && !priv->authenticated ) ) {
1028                         retcode = EACCES;
1029                 } else {
1030                         retcode = func(kdev, cmd, data, flags, p, (void *)DRM_CURRENTPID);
1031                 }
1032         }
1033
1034         return DRM_ERR(retcode);
1035 }
1036
1037 int DRM(lock)( DRM_IOCTL_ARGS )
1038 {
1039         DRM_DEVICE;
1040         drm_lock_t lock;
1041         int ret = 0;
1042
1043         DRM_COPY_FROM_USER_IOCTL( lock, (drm_lock_t *)data, sizeof(lock) );
1044
1045         if ( lock.context == DRM_KERNEL_CONTEXT ) {
1046                 DRM_ERROR( "Process %d using kernel context %d\n",
1047                            DRM_CURRENTPID, lock.context );
1048                 return DRM_ERR(EINVAL);
1049         }
1050
1051         DRM_DEBUG( "%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
1052                    lock.context, DRM_CURRENTPID,
1053                    dev->lock.hw_lock->lock, lock.flags );
1054
1055 #if __HAVE_DMA_QUEUE
1056         if ( lock.context < 0 )
1057                 return DRM_ERR(EINVAL);
1058 #endif
1059
1060         if ( !ret ) {
1061                 for (;;) {
1062                         if ( !dev->lock.hw_lock ) {
1063                                 /* Device has been unregistered */
1064                                 ret = EINTR;
1065                                 break;
1066                         }
1067                         if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
1068                                              lock.context ) ) {
1069                                 dev->lock.filp = (void *)DRM_CURRENTPID;
1070                                 dev->lock.lock_time = jiffies;
1071                                 atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
1072                                 break;  /* Got lock */
1073                         }
1074
1075                                 /* Contention */
1076                         ret = tsleep((void *)&dev->lock.lock_queue,
1077                                         PCATCH, "drmlk2", 0);
1078                         if (ret)
1079                                 break;
1080                 }
1081         }
1082
1083         if ( !ret ) {
1084                 /* FIXME: Add signal blocking here */
1085
1086 #if __HAVE_DMA_QUIESCENT
1087                 if ( lock.flags & _DRM_LOCK_QUIESCENT ) {
1088                         DRIVER_DMA_QUIESCENT();
1089                 }
1090 #endif
1091         }
1092
1093         DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
1094
1095         return DRM_ERR(ret);
1096 }
1097
1098
1099 int DRM(unlock)( DRM_IOCTL_ARGS )
1100 {
1101         DRM_DEVICE;
1102         drm_lock_t lock;
1103
1104         DRM_COPY_FROM_USER_IOCTL( lock, (drm_lock_t *)data, sizeof(lock) ) ;
1105
1106         if ( lock.context == DRM_KERNEL_CONTEXT ) {
1107                 DRM_ERROR( "Process %d using kernel context %d\n",
1108                            DRM_CURRENTPID, lock.context );
1109                 return DRM_ERR(EINVAL);
1110         }
1111
1112         atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
1113
1114         DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock,
1115                             DRM_KERNEL_CONTEXT );
1116 #if __HAVE_DMA_SCHEDULE
1117         DRM(dma_schedule)( dev, 1 );
1118 #endif
1119
1120         /* FIXME: Do we ever really need to check this?
1121          */
1122         if ( 1 /* !dev->context_flag */ ) {
1123                 if ( DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
1124                                      DRM_KERNEL_CONTEXT ) ) {
1125                         DRM_ERROR( "\n" );
1126                 }
1127         }
1128
1129         return 0;
1130 }
1131
1132 #if DRM_LINUX
1133
1134 #include <sys/sysproto.h>
1135
1136 MODULE_DEPEND(DRIVER_NAME, linux, 1, 1, 1);
1137
1138 #define LINUX_IOCTL_DRM_MIN             0x6400
1139 #define LINUX_IOCTL_DRM_MAX             0x64ff
1140
1141 static linux_ioctl_function_t DRM(linux_ioctl);
1142 static struct linux_ioctl_handler DRM(handler) = {DRM(linux_ioctl), 
1143     LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX};
1144
1145 SYSINIT(DRM(register), SI_SUB_KLD, SI_ORDER_MIDDLE, 
1146     linux_ioctl_register_handler, &DRM(handler));
1147 SYSUNINIT(DRM(unregister), SI_SUB_KLD, SI_ORDER_MIDDLE, 
1148     linux_ioctl_unregister_handler, &DRM(handler));
1149
1150 /* The bits for in/out are switched on Linux */
1151 #define LINUX_IOC_IN    IOC_OUT
1152 #define LINUX_IOC_OUT   IOC_IN
1153
1154 static int
1155 DRM(linux_ioctl)(DRM_STRUCTPROC *p, struct linux_ioctl_args* args)
1156 {
1157         int error;
1158         int cmd = args->cmd;
1159
1160         args->cmd &= ~(LINUX_IOC_IN | LINUX_IOC_OUT);
1161         if (cmd & LINUX_IOC_IN)
1162                 args->cmd |= IOC_IN;
1163         if (cmd & LINUX_IOC_OUT)
1164                 args->cmd |= IOC_OUT;
1165         
1166         error = ioctl(p, (struct ioctl_args *)args);
1167
1168         return error;
1169 }
1170 #endif /* DRM_LINUX */