OSDN Git Service

[FreeBSD] Add drm_drawable_free_all()
[android-x86/external-libdrm.git] / bsd-core / drm_drv.c
1 /*-
2  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
3  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23  * OTHER DEALINGS IN THE SOFTWARE.
24  *
25  * Authors:
26  *    Rickard E. (Rik) Faith <faith@valinux.com>
27  *    Gareth Hughes <gareth@valinux.com>
28  *
29  */
30
31 /** @file drm_drv.c
32  * The catch-all file for DRM device support, including module setup/teardown,
33  * open/close, and ioctl dispatch.
34  */
35
36
37 #include <sys/limits.h>
38 #include "drmP.h"
39 #include "drm.h"
40 #include "drm_sarea.h"
41
42 #ifdef DRM_DEBUG_DEFAULT_ON
43 int drm_debug_flag = 1;
44 #else
45 int drm_debug_flag = 0;
46 #endif
47
48 static int drm_load(struct drm_device *dev);
49 static void drm_unload(struct drm_device *dev);
50 static drm_pci_id_list_t *drm_find_description(int vendor, int device,
51     drm_pci_id_list_t *idlist);
52
53 #ifdef __FreeBSD__
54 #define DRIVER_SOFTC(unit) \
55         ((struct drm_device *)devclass_get_softc(drm_devclass, unit))
56
57 MODULE_VERSION(drm, 1);
58 MODULE_DEPEND(drm, agp, 1, 1, 1);
59 MODULE_DEPEND(drm, pci, 1, 1, 1);
60 #if __FreeBSD_version > 502127
61 MODULE_DEPEND(drm, mem, 1, 1, 1);
62 #endif
63 #endif /* __FreeBSD__ */
64
65 #if defined(__NetBSD__) || defined(__OpenBSD__)
66 #define DRIVER_SOFTC(unit) \
67         ((struct drm_device *)device_lookup(&drm_cd, unit))
68 #endif /* __NetBSD__ || __OpenBSD__ */
69
70 static drm_ioctl_desc_t           drm_ioctls[256] = {
71         DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0),
72         DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
73         DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
74         DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
75         DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0),
76         DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
77         DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
78         DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER|DRM_ROOT_ONLY),
79
80         DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
81         DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
82         DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
83         DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
84
85         DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
86         DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
87
88         DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
89         DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
90
91         DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
92         DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
93         DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
94         DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
95         DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
96         DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
97         DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
98
99         DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
100         DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
101
102         DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
103         DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
104         DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
105
106         DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
107         DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER),
108         DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
109         DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
110         DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
111         DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma, DRM_AUTH),
112
113         DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
114
115         DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
116         DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
117         DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
118         DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
119         DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
120         DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
121         DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
122         DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
123
124         DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
125         DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
126
127         DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
128         DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
129         DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_draw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
130 };
131
132 #ifdef __FreeBSD__
133 static struct cdevsw drm_cdevsw = {
134 #if __FreeBSD_version >= 502103
135         .d_version =    D_VERSION,
136 #endif
137         .d_open =       drm_open,
138         .d_close =      drm_close,
139         .d_read =       drm_read,
140         .d_ioctl =      drm_ioctl,
141         .d_poll =       drm_poll,
142         .d_mmap =       drm_mmap,
143         .d_name =       "drm",
144 #if __FreeBSD_version >= 502103
145         .d_flags =      D_TRACKCLOSE | D_NEEDGIANT,
146 #else
147         .d_maj =        145,
148         .d_flags =      D_TRACKCLOSE,
149 #endif
150 #if __FreeBSD_version < 500000
151         .d_bmaj =       -1
152 #endif
153 };
154
155 int drm_probe(device_t dev, drm_pci_id_list_t *idlist)
156 {
157         drm_pci_id_list_t *id_entry;
158         int vendor, device;
159 #if __FreeBSD_version < 700010
160         device_t realdev;
161
162         if (!strcmp(device_get_name(dev), "drmsub"))
163                 realdev = device_get_parent(dev);
164         else
165                 realdev = dev;
166         vendor = pci_get_vendor(realdev);
167         device = pci_get_device(realdev);
168 #else
169         vendor = pci_get_vendor(dev);
170         device = pci_get_device(dev);
171 #endif
172
173         id_entry = drm_find_description(vendor, device, idlist);
174         if (id_entry != NULL) {
175                 device_set_desc(dev, id_entry->name);
176                 return 0;
177         }
178
179         return ENXIO;
180 }
181
182 int drm_attach(device_t nbdev, drm_pci_id_list_t *idlist)
183 {
184         struct drm_device *dev;
185         drm_pci_id_list_t *id_entry;
186         int unit;
187
188         unit = device_get_unit(nbdev);
189         dev = device_get_softc(nbdev);
190
191 #if __FreeBSD_version < 700010
192         if (!strcmp(device_get_name(nbdev), "drmsub"))
193                 dev->device = device_get_parent(nbdev);
194         else
195                 dev->device = nbdev;
196 #else
197         dev->device = nbdev;
198 #endif
199         dev->devnode = make_dev(&drm_cdevsw,
200                         unit,
201                         DRM_DEV_UID,
202                         DRM_DEV_GID,
203                         DRM_DEV_MODE,
204                         "dri/card%d", unit);
205 #if __FreeBSD_version >= 500000
206         mtx_init(&dev->dev_lock, "drmdev", NULL, MTX_DEF);
207         mtx_init(&dev->irq_lock, "drmirq", NULL, MTX_DEF);
208         mtx_init(&dev->vbl_lock, "drmvbl", NULL, MTX_DEF);
209         mtx_init(&dev->drw_lock, "drmdrw", NULL, MTX_DEF);
210         mtx_init(&dev->tsk_lock, "drmtsk", NULL, MTX_DEF);
211 #endif
212
213         id_entry = drm_find_description(pci_get_vendor(dev->device),
214             pci_get_device(dev->device), idlist);
215         dev->id_entry = id_entry;
216
217         return drm_load(dev);
218 }
219
220 int drm_detach(device_t dev)
221 {
222         drm_unload(device_get_softc(dev));
223         return 0;
224 }
225
226 #ifndef DRM_DEV_NAME
227 #define DRM_DEV_NAME "drm"
228 #endif
229
230 devclass_t drm_devclass;
231
232 #elif defined(__NetBSD__) || defined(__OpenBSD__)
233
234 static struct cdevsw drm_cdevsw = {
235         drm_open,
236         drm_close,
237         drm_read,
238         nowrite,
239         drm_ioctl,
240         nostop,
241         notty,
242         drm_poll,
243         drm_mmap,
244         nokqfilter,
245         D_TTY
246 };
247
248 int drm_refcnt = 0;
249
250 #if defined(__NetBSD__) && __NetBSD_Version__ >= 106080000
251 MOD_DEV("drm", DRIVER_NAME, NULL, -1, &drm_cdevsw, CDEV_MAJOR);
252 #else
253 MOD_DEV("drm", LM_DT_CHAR, CDEV_MAJOR, &drm_cdevsw);
254 #endif
255
256 int drm_lkmentry(struct lkm_table *lkmtp, int cmd, int ver);
257 static int drm_lkmhandle(struct lkm_table *lkmtp, int cmd);
258
259 int drm_modprobe(void);
260 int drm_probe(struct pci_attach_args *pa);
261 void drm_attach(struct pci_attach_args *pa, dev_t kdev);
262
263 int drm_lkmentry(struct lkm_table *lkmtp, int cmd, int ver) {
264         DISPATCH(lkmtp, cmd, ver, drm_lkmhandle, drm_lkmhandle, drm_lkmhandle);
265 }
266
267 static int drm_lkmhandle(struct lkm_table *lkmtp, int cmd)
268 {
269         int error = 0;
270
271         switch(cmd) {
272         case LKM_E_LOAD:
273                 if (lkmexists(lkmtp))
274                         return EEXIST;
275
276                 if(drm_modprobe())
277                         return 0;
278
279                 return 1;
280
281         case LKM_E_UNLOAD:
282                 if (drm_refcnt > 0)
283                         return (EBUSY);
284                 break;
285         case LKM_E_STAT:
286                 break;
287
288         default:
289                 error = EIO;
290                 break;
291         }
292         
293         return error;
294 }
295
296 int drm_modprobe(void)
297 {
298         struct pci_attach_args pa;
299         int error;
300
301         error = pci_find_device(&pa, drm_probe, idlist);
302         if (error != 0)
303                 drm_attach(&pa, 0);
304
305         return error;
306 }
307
308 int drm_probe(struct pci_attach_args *pa, drm_pci_id_list_t idlist)
309 {
310         const char *desc;
311         drm_pci_id_list_t *id_entry;
312
313         id_entry = drm_find_description(PCI_VENDOR(pa->pa_id),
314             PCI_PRODUCT(pa->pa_id), idlist);
315         if (id_entry != NULL) {
316                 return 1;
317         }
318
319         return 0;
320 }
321
322 void drm_attach(struct pci_attach_args *pa, dev_t kdev, 
323     drm_pci_id_list_t *idlist)
324 {
325         int i;
326         struct drm_device *dev;
327         drm_pci_id_list_t *id_entry;
328
329         config_makeroom(kdev, &drm_cd);
330         drm_cd.cd_devs[(kdev)] = malloc(sizeof(struct drm_device),
331                                         M_DRM, M_WAITOK);
332         dev = DRIVER_SOFTC(kdev);
333
334         memset(dev, 0, sizeof(struct drm_device));
335         memcpy(&dev->pa, pa, sizeof(dev->pa));
336
337         dev->irq = pa->pa_intrline;
338         dev->pci_domain = 0;
339         dev->pci_bus = pa->pa_bus;
340         dev->pci_slot = pa->pa_device;
341         dev->pci_func = pa->pa_function;
342         dev->dma_tag = pa->pa_dmat;
343
344         id_entry = drm_find_description(PCI_VENDOR(pa->pa_id),
345             PCI_PRODUCT(pa->pa_id), idlist);
346         dev->driver.pci_id_entry = id_entry;
347
348         DRM_INFO("%s", id_entry->name);
349         drm_load(dev);
350 }
351
352 int drm_detach(struct device *self, int flags)
353 {
354         drm_unload((struct drm_device *)self);
355         return 0;
356 }
357
358 int drm_activate(struct device *self, enum devact act)
359 {
360         switch (act) {
361         case DVACT_ACTIVATE:
362                 return (EOPNOTSUPP);
363                 break;
364
365         case DVACT_DEACTIVATE:
366                 /* FIXME */
367                 break;
368         }
369         return (0);
370 }
371 #endif /* __NetBSD__ || __OpenBSD__ */
372
373 drm_pci_id_list_t *drm_find_description(int vendor, int device,
374     drm_pci_id_list_t *idlist)
375 {
376         int i = 0;
377         
378         for (i = 0; idlist[i].vendor != 0; i++) {
379                 if ((idlist[i].vendor == vendor) &&
380                     (idlist[i].device == device)) {
381                         return &idlist[i];
382                 }
383         }
384         return NULL;
385 }
386
387 static int drm_firstopen(struct drm_device *dev)
388 {
389         drm_local_map_t *map;
390         int i;
391
392         DRM_SPINLOCK_ASSERT(&dev->dev_lock);
393
394         /* prebuild the SAREA */
395         i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM,
396                        _DRM_CONTAINS_LOCK, &map);
397         if (i != 0)
398                 return i;
399
400         if (dev->driver.firstopen)
401                 dev->driver.firstopen(dev);
402
403         dev->buf_use = 0;
404
405         if (dev->driver.use_dma) {
406                 i = drm_dma_setup(dev);
407                 if (i != 0)
408                         return i;
409         }
410
411         for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
412                 dev->magiclist[i].head = NULL;
413                 dev->magiclist[i].tail = NULL;
414         }
415
416         dev->lock.lock_queue = 0;
417         dev->irq_enabled = 0;
418         dev->context_flag = 0;
419         dev->last_context = 0;
420         dev->if_version = 0;
421
422 #ifdef __FreeBSD__
423         dev->buf_sigio = NULL;
424 #elif defined(__NetBSD__) || defined(__OpenBSD__)
425         dev->buf_pgid = 0;
426 #endif
427
428         DRM_DEBUG( "\n" );
429
430         return 0;
431 }
432
433 static int drm_lastclose(struct drm_device *dev)
434 {
435         drm_magic_entry_t *pt, *next;
436         drm_local_map_t *map, *mapsave;
437         int i;
438
439         DRM_SPINLOCK_ASSERT(&dev->dev_lock);
440
441         DRM_DEBUG( "\n" );
442
443         if (dev->driver.lastclose != NULL)
444                 dev->driver.lastclose(dev);
445
446         if (dev->irq_enabled)
447                 drm_irq_uninstall(dev);
448
449         if ( dev->unique ) {
450                 free(dev->unique, M_DRM);
451                 dev->unique = NULL;
452                 dev->unique_len = 0;
453         }
454                                 /* Clear pid list */
455         for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
456                 for ( pt = dev->magiclist[i].head ; pt ; pt = next ) {
457                         next = pt->next;
458                         free(pt, M_DRM);
459                 }
460                 dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
461         }
462
463         drm_drawable_free_all(dev);
464
465                                 /* Clear AGP information */
466         if ( dev->agp ) {
467                 drm_agp_mem_t *entry;
468                 drm_agp_mem_t *nexte;
469
470                 /* Remove AGP resources, but leave dev->agp intact until
471                  * drm_unload is called.
472                  */
473                 for ( entry = dev->agp->memory ; entry ; entry = nexte ) {
474                         nexte = entry->next;
475                         if ( entry->bound )
476                                 drm_agp_unbind_memory(entry->handle);
477                         drm_agp_free_memory(entry->handle);
478                         free(entry, M_DRM);
479                 }
480                 dev->agp->memory = NULL;
481
482                 if (dev->agp->acquired)
483                         drm_agp_release(dev);
484
485                 dev->agp->acquired = 0;
486                 dev->agp->enabled  = 0;
487         }
488         if (dev->sg != NULL) {
489                 drm_sg_cleanup(dev->sg);
490                 dev->sg = NULL;
491         }
492
493         TAILQ_FOREACH_SAFE(map, &dev->maplist, link, mapsave) {
494                 if (!(map->flags & _DRM_DRIVER))
495                         drm_rmmap(dev, map);
496         }
497
498         drm_dma_takedown(dev);
499         if ( dev->lock.hw_lock ) {
500                 dev->lock.hw_lock = NULL; /* SHM removed */
501                 dev->lock.file_priv = NULL;
502                 DRM_WAKEUP_INT((void *)&dev->lock.lock_queue);
503         }
504
505         return 0;
506 }
507
508 static int drm_load(struct drm_device *dev)
509 {
510         int i, retcode;
511
512         DRM_DEBUG( "\n" );
513
514         dev->irq = pci_get_irq(dev->device);
515 #if defined(__FreeBSD__) && __FreeBSD_version >= 700053
516         dev->pci_domain = pci_get_domain(dev->device);
517 #else
518         dev->pci_domain = 0;
519 #endif
520         dev->pci_bus = pci_get_bus(dev->device);
521         dev->pci_slot = pci_get_slot(dev->device);
522         dev->pci_func = pci_get_function(dev->device);
523
524         dev->pci_vendor = pci_get_vendor(dev->device);
525         dev->pci_device = pci_get_device(dev->device);
526
527         TAILQ_INIT(&dev->maplist);
528
529         drm_mem_init();
530 #ifdef __FreeBSD__
531         drm_sysctl_init(dev);
532 #endif
533         TAILQ_INIT(&dev->files);
534
535         dev->counters  = 6;
536         dev->types[0]  = _DRM_STAT_LOCK;
537         dev->types[1]  = _DRM_STAT_OPENS;
538         dev->types[2]  = _DRM_STAT_CLOSES;
539         dev->types[3]  = _DRM_STAT_IOCTLS;
540         dev->types[4]  = _DRM_STAT_LOCKS;
541         dev->types[5]  = _DRM_STAT_UNLOCKS;
542
543         for ( i = 0 ; i < DRM_ARRAY_SIZE(dev->counts) ; i++ )
544                 atomic_set( &dev->counts[i], 0 );
545
546         if (dev->driver.load != NULL) {
547                 DRM_LOCK();
548                 /* Shared code returns -errno. */
549                 retcode = -dev->driver.load(dev,
550                     dev->id_entry->driver_private);
551                 if (pci_enable_busmaster(dev->device))
552                         DRM_ERROR("Request to enable bus-master failed.\n");
553                 DRM_UNLOCK();
554                 if (retcode != 0)
555                         goto error;
556         }
557
558         if (dev->driver.use_agp) {
559                 if (drm_device_is_agp(dev))
560                         dev->agp = drm_agp_init();
561                 if (dev->driver.require_agp && dev->agp == NULL) {
562                         DRM_ERROR("Card isn't AGP, or couldn't initialize "
563                             "AGP.\n");
564                         retcode = ENOMEM;
565                         goto error;
566                 }
567                 if (dev->agp != NULL) {
568                         if (drm_mtrr_add(dev->agp->info.ai_aperture_base,
569                             dev->agp->info.ai_aperture_size, DRM_MTRR_WC) == 0)
570                                 dev->agp->mtrr = 1;
571                 }
572         }
573
574         retcode = drm_ctxbitmap_init(dev);
575         if (retcode != 0) {
576                 DRM_ERROR("Cannot allocate memory for context bitmap.\n");
577                 goto error;
578         }
579
580         dev->drw_unrhdr = new_unrhdr(1, INT_MAX, NULL);
581         if (dev->drw_unrhdr == NULL) {
582                 DRM_ERROR("Couldn't allocate drawable number allocator\n");
583                 goto error;
584         }
585
586         DRM_INFO("Initialized %s %d.%d.%d %s\n",
587                 dev->driver.name,
588                 dev->driver.major,
589                 dev->driver.minor,
590                 dev->driver.patchlevel,
591                 dev->driver.date);
592
593         return 0;
594
595 error:
596 #ifdef __FreeBSD__
597         drm_sysctl_cleanup(dev);
598 #endif
599         DRM_LOCK();
600         drm_lastclose(dev);
601         DRM_UNLOCK();
602 #ifdef __FreeBSD__
603         destroy_dev(dev->devnode);
604 #if __FreeBSD_version >= 500000
605         mtx_destroy(&dev->tsk_lock);
606         mtx_destroy(&dev->drw_lock);
607         mtx_destroy(&dev->vbl_lock);
608         mtx_destroy(&dev->irq_lock);
609         mtx_destroy(&dev->dev_lock);
610 #endif
611 #endif
612         return retcode;
613 }
614
615 static void drm_unload(struct drm_device *dev)
616 {
617         int i;
618
619         DRM_DEBUG( "\n" );
620
621 #ifdef __FreeBSD__
622         drm_sysctl_cleanup(dev);
623         destroy_dev(dev->devnode);
624 #endif
625
626         drm_ctxbitmap_cleanup(dev);
627
628         if (dev->agp && dev->agp->mtrr) {
629                 int __unused retcode;
630
631                 retcode = drm_mtrr_del(0, dev->agp->info.ai_aperture_base,
632                     dev->agp->info.ai_aperture_size, DRM_MTRR_WC);
633                 DRM_DEBUG("mtrr_del = %d", retcode);
634         }
635
636         DRM_LOCK();
637         drm_lastclose(dev);
638         DRM_UNLOCK();
639
640         /* Clean up PCI resources allocated by drm_bufs.c.  We're not really
641          * worried about resource consumption while the DRM is inactive (between
642          * lastclose and firstopen or unload) because these aren't actually
643          * taking up KVA, just keeping the PCI resource allocated.
644          */
645         for (i = 0; i < DRM_MAX_PCI_RESOURCE; i++) {
646                 if (dev->pcir[i] == NULL)
647                         continue;
648                 bus_release_resource(dev->device, SYS_RES_MEMORY,
649                     dev->pcirid[i], dev->pcir[i]);
650                 dev->pcir[i] = NULL;
651         }
652
653         if ( dev->agp ) {
654                 free(dev->agp, M_DRM);
655                 dev->agp = NULL;
656         }
657
658         if (dev->driver.unload != NULL)
659                 dev->driver.unload(dev);
660
661         delete_unrhdr(dev->drw_unrhdr);
662
663         drm_mem_uninit();
664
665         if (pci_disable_busmaster(dev->device))
666                 DRM_ERROR("Request to disable bus-master failed.\n");
667
668 #if defined(__FreeBSD__) &&  __FreeBSD_version >= 500000
669         mtx_destroy(&dev->tsk_lock);
670         mtx_destroy(&dev->drw_lock);
671         mtx_destroy(&dev->vbl_lock);
672         mtx_destroy(&dev->irq_lock);
673         mtx_destroy(&dev->dev_lock);
674 #endif
675 }
676
677
678 int drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv)
679 {
680         drm_version_t *version = data;
681         int len;
682
683 #define DRM_COPY( name, value )                                         \
684         len = strlen( value );                                          \
685         if ( len > name##_len ) len = name##_len;                       \
686         name##_len = strlen( value );                                   \
687         if ( len && name ) {                                            \
688                 if ( DRM_COPY_TO_USER( name, value, len ) )             \
689                         return EFAULT;                          \
690         }
691
692         version->version_major          = dev->driver.major;
693         version->version_minor          = dev->driver.minor;
694         version->version_patchlevel     = dev->driver.patchlevel;
695
696         DRM_COPY(version->name, dev->driver.name);
697         DRM_COPY(version->date, dev->driver.date);
698         DRM_COPY(version->desc, dev->driver.desc);
699
700         return 0;
701 }
702
703 int drm_open(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
704 {
705         struct drm_device *dev = NULL;
706         int retcode = 0;
707
708         dev = DRIVER_SOFTC(minor(kdev));
709
710         DRM_DEBUG( "open_count = %d\n", dev->open_count );
711
712         retcode = drm_open_helper(kdev, flags, fmt, p, dev);
713
714         if ( !retcode ) {
715                 atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
716                 DRM_LOCK();
717 #ifdef __FreeBSD__
718                 device_busy(dev->device);
719 #endif
720                 if ( !dev->open_count++ )
721                         retcode = drm_firstopen(dev);
722                 DRM_UNLOCK();
723         }
724
725         return retcode;
726 }
727
728 int drm_close(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
729 {
730         struct drm_device *dev = drm_get_device_from_kdev(kdev);
731         drm_file_t *file_priv;
732         int retcode = 0;
733
734         DRM_DEBUG( "open_count = %d\n", dev->open_count );
735
736         DRM_LOCK();
737
738         file_priv = drm_find_file_by_proc(dev, p);
739         if (!file_priv) {
740                 DRM_UNLOCK();
741                 DRM_ERROR("can't find authenticator\n");
742                 return EINVAL;
743         }
744
745         if (--file_priv->refs != 0)
746                 goto done;
747
748         if (dev->driver.preclose != NULL)
749                 dev->driver.preclose(dev, file_priv);
750
751         /* ========================================================
752          * Begin inline drm_release
753          */
754
755 #ifdef __FreeBSD__
756         DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
757                    DRM_CURRENTPID, (long)dev->device, dev->open_count );
758 #elif defined(__NetBSD__) || defined(__OpenBSD__)
759         DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
760                    DRM_CURRENTPID, (long)&dev->device, dev->open_count);
761 #endif
762
763         if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
764             && dev->lock.file_priv == file_priv) {
765                 DRM_DEBUG("Process %d dead, freeing lock for context %d\n",
766                           DRM_CURRENTPID,
767                           _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
768                 if (dev->driver.reclaim_buffers_locked != NULL)
769                         dev->driver.reclaim_buffers_locked(dev, file_priv);
770
771                 drm_lock_free(dev, &dev->lock.hw_lock->lock,
772                     _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
773                 
774                                 /* FIXME: may require heavy-handed reset of
775                                    hardware at this point, possibly
776                                    processed via a callback to the X
777                                    server. */
778         } else if (dev->driver.reclaim_buffers_locked != NULL &&
779             dev->lock.hw_lock != NULL) {
780                 /* The lock is required to reclaim buffers */
781                 for (;;) {
782                         if ( !dev->lock.hw_lock ) {
783                                 /* Device has been unregistered */
784                                 retcode = EINTR;
785                                 break;
786                         }
787                         if (drm_lock_take(&dev->lock.hw_lock->lock,
788                             DRM_KERNEL_CONTEXT)) {
789                                 dev->lock.file_priv = file_priv;
790                                 dev->lock.lock_time = jiffies;
791                                 atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
792                                 break;  /* Got lock */
793                         }
794                                 /* Contention */
795 #if defined(__FreeBSD__) && __FreeBSD_version > 500000
796                         retcode = mtx_sleep((void *)&dev->lock.lock_queue,
797                             &dev->dev_lock, PZERO | PCATCH, "drmlk2", 0);
798 #else
799                         retcode = tsleep((void *)&dev->lock.lock_queue,
800                             PZERO | PCATCH, "drmlk2", 0);
801 #endif
802                         if (retcode)
803                                 break;
804                 }
805                 if (retcode == 0) {
806                         dev->driver.reclaim_buffers_locked(dev, file_priv);
807                         drm_lock_free(dev, &dev->lock.hw_lock->lock,
808                             DRM_KERNEL_CONTEXT);
809                 }
810         }
811
812         if (dev->driver.use_dma && !dev->driver.reclaim_buffers_locked)
813                 drm_reclaim_buffers(dev, file_priv);
814
815 #if defined (__FreeBSD__) && (__FreeBSD_version >= 500000)
816         funsetown(&dev->buf_sigio);
817 #elif defined(__FreeBSD__)
818         funsetown(dev->buf_sigio);
819 #elif defined(__NetBSD__) || defined(__OpenBSD__)
820         dev->buf_pgid = 0;
821 #endif /* __NetBSD__  || __OpenBSD__ */
822
823         if (dev->driver.postclose != NULL)
824                 dev->driver.postclose(dev, file_priv);
825         TAILQ_REMOVE(&dev->files, file_priv, link);
826         free(file_priv, M_DRM);
827
828         /* ========================================================
829          * End inline drm_release
830          */
831
832 done:
833         atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
834 #ifdef __FreeBSD__
835         device_unbusy(dev->device);
836 #endif
837         if (--dev->open_count == 0) {
838                 retcode = drm_lastclose(dev);
839         }
840
841         DRM_UNLOCK();
842         
843         return retcode;
844 }
845
846 /* drm_ioctl is called whenever a process performs an ioctl on /dev/drm.
847  */
848 int drm_ioctl(struct cdev *kdev, u_long cmd, caddr_t data, int flags, 
849     DRM_STRUCTPROC *p)
850 {
851         struct drm_device *dev = drm_get_device_from_kdev(kdev);
852         int retcode = 0;
853         drm_ioctl_desc_t *ioctl;
854         int (*func)(struct drm_device *dev, void *data, struct drm_file *file_priv);
855         int nr = DRM_IOCTL_NR(cmd);
856         int is_driver_ioctl = 0;
857         drm_file_t *file_priv;
858
859         DRM_LOCK();
860         file_priv = drm_find_file_by_proc(dev, p);
861         DRM_UNLOCK();
862         if (file_priv == NULL) {
863                 DRM_ERROR("can't find authenticator\n");
864                 return EINVAL;
865         }
866
867         atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
868         ++file_priv->ioctl_count;
869
870 #ifdef __FreeBSD__
871         DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
872             DRM_CURRENTPID, cmd, nr, (long)dev->device,
873             file_priv->authenticated );
874 #elif defined(__NetBSD__) || defined(__OpenBSD__)
875         DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
876             DRM_CURRENTPID, cmd, nr, (long)&dev->device,
877             file_priv->authenticated );
878 #endif
879
880         switch (cmd) {
881         case FIONBIO:
882         case FIOASYNC:
883                 return 0;
884
885 #ifdef __FreeBSD__
886         case FIOSETOWN:
887                 return fsetown(*(int *)data, &dev->buf_sigio);
888
889         case FIOGETOWN:
890 #if (__FreeBSD_version >= 500000)
891                 *(int *) data = fgetown(&dev->buf_sigio);
892 #else
893                 *(int *) data = fgetown(dev->buf_sigio);
894 #endif
895                 return 0;
896 #endif /* __FreeBSD__ */
897 #if defined(__NetBSD__) || defined(__OpenBSD__)
898         case TIOCSPGRP:
899                 dev->buf_pgid = *(int *)data;
900                 return 0;
901
902         case TIOCGPGRP:
903                 *(int *)data = dev->buf_pgid;
904                 return 0;
905 #endif /* __NetBSD__ */
906         }
907
908         if (IOCGROUP(cmd) != DRM_IOCTL_BASE) {
909                 DRM_DEBUG("Bad ioctl group 0x%x\n", (int)IOCGROUP(cmd));
910                 return EINVAL;
911         }
912
913         ioctl = &drm_ioctls[nr];
914         /* It's not a core DRM ioctl, try driver-specific. */
915         if (ioctl->func == NULL && nr >= DRM_COMMAND_BASE) {
916                 /* The array entries begin at DRM_COMMAND_BASE ioctl nr */
917                 nr -= DRM_COMMAND_BASE;
918                 if (nr > dev->driver.max_ioctl) {
919                         DRM_DEBUG("Bad driver ioctl number, 0x%x (of 0x%x)\n",
920                             nr, dev->driver.max_ioctl);
921                         return EINVAL;
922                 }
923                 ioctl = &dev->driver.ioctls[nr];
924                 is_driver_ioctl = 1;
925         }
926         func = ioctl->func;
927
928         if (func == NULL) {
929                 DRM_DEBUG( "no function\n" );
930                 return EINVAL;
931         }
932
933         if (((ioctl->flags & DRM_ROOT_ONLY) && !DRM_SUSER(p)) ||
934             ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
935             ((ioctl->flags & DRM_MASTER) && !file_priv->master))
936                 return EACCES;
937
938         if (is_driver_ioctl) {
939                 DRM_LOCK();
940                 /* shared code returns -errno */
941                 retcode = -func(dev, data, file_priv);
942                 DRM_UNLOCK();
943         } else {
944                 retcode = func(dev, data, file_priv);
945         }
946
947         if (retcode != 0)
948                 DRM_DEBUG("    returning %d\n", retcode);
949
950         return retcode;
951 }
952
953 drm_local_map_t *drm_getsarea(struct drm_device *dev)
954 {
955         drm_local_map_t *map;
956
957         DRM_SPINLOCK_ASSERT(&dev->dev_lock);
958         TAILQ_FOREACH(map, &dev->maplist, link) {
959                 if (map->type == _DRM_SHM && (map->flags & _DRM_CONTAINS_LOCK))
960                         return map;
961         }
962
963         return NULL;
964 }
965
966 #if DRM_LINUX
967
968 #include <sys/sysproto.h>
969
970 MODULE_DEPEND(DRIVER_NAME, linux, 1, 1, 1);
971
972 #define LINUX_IOCTL_DRM_MIN             0x6400
973 #define LINUX_IOCTL_DRM_MAX             0x64ff
974
975 static linux_ioctl_function_t drm_linux_ioctl;
976 static struct linux_ioctl_handler drm_handler = {drm_linux_ioctl, 
977     LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX};
978
979 SYSINIT(drm_register, SI_SUB_KLD, SI_ORDER_MIDDLE, 
980     linux_ioctl_register_handler, &drm_handler);
981 SYSUNINIT(drm_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE, 
982     linux_ioctl_unregister_handler, &drm_handler);
983
984 /* The bits for in/out are switched on Linux */
985 #define LINUX_IOC_IN    IOC_OUT
986 #define LINUX_IOC_OUT   IOC_IN
987
988 static int
989 drm_linux_ioctl(DRM_STRUCTPROC *p, struct linux_ioctl_args* args)
990 {
991         int error;
992         int cmd = args->cmd;
993
994         args->cmd &= ~(LINUX_IOC_IN | LINUX_IOC_OUT);
995         if (cmd & LINUX_IOC_IN)
996                 args->cmd |= IOC_IN;
997         if (cmd & LINUX_IOC_OUT)
998                 args->cmd |= IOC_OUT;
999         
1000         error = ioctl(p, (struct ioctl_args *)args);
1001
1002         return error;
1003 }
1004 #endif /* DRM_LINUX */