2 * drm_drv.h -- Generic driver template -*- linux-c -*-
3 * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
6 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
7 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
8 * Copyright (c) 2009, Intel Corporation.
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
18 * The above copyright notice and this permission notice (including the next
19 * paragraph) shall be included in all copies or substantial portions of the
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
31 * Rickard E. (Rik) Faith <faith@valinux.com>
32 * Gareth Hughes <gareth@valinux.com>
37 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
38 * Use is subject to license terms.
43 #include "drm_sarea.h"
45 int drm_debug_flag
= 1;
47 #define DRIVER_IOCTL_COUNT 256
48 drm_ioctl_desc_t drm_ioctls
[DRIVER_IOCTL_COUNT
] = {
49 [DRM_IOCTL_NR(DRM_IOCTL_VERSION
)] =
51 [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE
)] =
53 [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC
)] =
55 [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID
)] =
56 {drm_irq_by_busid
, DRM_MASTER
|DRM_ROOT_ONLY
},
57 [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP
)] =
59 [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT
)] =
61 [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS
)] =
63 [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION
)] =
64 {drm_setversion
, DRM_MASTER
|DRM_ROOT_ONLY
},
65 [DRM_IOCTL_NR(DRM_IOCTL_MODESET_CTL
)] =
67 [DRM_IOCTL_NR(DRM_IOCTL_GEM_CLOSE
)] =
68 {drm_gem_close_ioctl
, 0},
69 [DRM_IOCTL_NR(DRM_IOCTL_GEM_FLINK
)] =
70 {drm_gem_flink_ioctl
, DRM_AUTH
},
71 [DRM_IOCTL_NR(DRM_IOCTL_GEM_OPEN
)] =
72 {drm_gem_open_ioctl
, DRM_AUTH
},
73 [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE
)] =
74 {drm_setunique
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
75 [DRM_IOCTL_NR(DRM_IOCTL_BLOCK
)] =
76 {drm_noop
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
77 [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK
)] =
78 {drm_noop
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
79 [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC
)] =
80 {drm_authmagic
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
81 [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP
)] =
82 {drm_addmap_ioctl
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
83 [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP
)] =
84 {drm_rmmap_ioctl
, DRM_AUTH
},
85 [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX
)] =
86 {drm_setsareactx
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
87 [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX
)] =
88 {drm_getsareactx
, DRM_AUTH
},
89 [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX
)] =
90 {drm_addctx
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
91 [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX
)] =
92 {drm_rmctx
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
93 [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX
)] =
94 {drm_modctx
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
95 [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX
)] =
96 {drm_getctx
, DRM_AUTH
},
97 [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX
)] =
98 {drm_switchctx
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
99 [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX
)] =
100 {drm_newctx
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
101 [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX
)] =
102 {drm_resctx
, DRM_AUTH
},
103 [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW
)] =
104 {drm_adddraw
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
105 [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW
)] =
106 {drm_rmdraw
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
107 [DRM_IOCTL_NR(DRM_IOCTL_LOCK
)] =
108 {drm_lock
, DRM_AUTH
},
109 [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK
)] =
110 {drm_unlock
, DRM_AUTH
},
111 [DRM_IOCTL_NR(DRM_IOCTL_FINISH
)] =
112 {drm_noop
, DRM_AUTH
},
113 [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS
)] =
114 {drm_addbufs_ioctl
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
115 [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS
)] =
116 {drm_markbufs
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
117 [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS
)] =
118 {drm_infobufs
, DRM_AUTH
},
119 [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS
)] =
120 {drm_mapbufs
, DRM_AUTH
},
121 [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS
)] =
122 {drm_freebufs
, DRM_AUTH
},
123 [DRM_IOCTL_NR(DRM_IOCTL_DMA
)] =
125 [DRM_IOCTL_NR(DRM_IOCTL_CONTROL
)] =
126 {drm_control
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
127 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE
)] =
128 {drm_agp_acquire
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
129 [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE
)] =
130 {drm_agp_release
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
131 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE
)] =
132 {drm_agp_enable
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
133 [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO
)] =
134 {drm_agp_info
, DRM_AUTH
},
135 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC
)] =
136 {drm_agp_alloc
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
137 [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE
)] =
138 {drm_agp_free
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
139 [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND
)] =
140 {drm_agp_bind
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
141 [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND
)] =
142 {drm_agp_unbind
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
143 [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC
)] =
144 {drm_sg_alloc
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
145 [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE
)] =
146 {drm_sg_free
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
147 [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK
)] =
148 {drm_wait_vblank
, 0},
149 [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW
)] =
150 {drm_update_draw
, DRM_AUTH
|DRM_MASTER
|DRM_ROOT_ONLY
},
153 extern void idr_list_free(struct idr_list
*head
);
156 drm_find_description(int vendor
, int device
, drm_pci_id_list_t
*idlist
)
159 for (i
= 0; idlist
[i
].vendor
!= 0; i
++) {
160 if ((idlist
[i
].vendor
== vendor
) &&
161 (idlist
[i
].device
== device
)) {
162 return (idlist
[i
].name
);
169 drm_firstopen(drm_device_t
*dev
)
173 drm_local_map_t
*map
;
175 /* prebuild the SAREA */
176 retval
= drm_addmap(dev
, 0, SAREA_MAX
, _DRM_SHM
,
177 _DRM_CONTAINS_LOCK
, &map
);
179 DRM_ERROR("firstopen: failed to prebuild SAREA");
183 if (dev
->driver
->use_agp
) {
184 DRM_DEBUG("drm_firstopen: use_agp=%d", dev
->driver
->use_agp
);
185 if (drm_device_is_agp(dev
))
186 dev
->agp
= drm_agp_init(dev
);
187 if (dev
->driver
->require_agp
&& dev
->agp
== NULL
) {
188 DRM_ERROR("couldn't initialize AGP");
193 if (dev
->driver
->firstopen
)
194 retval
= dev
->driver
->firstopen(dev
);
197 DRM_ERROR("drm_firstopen: driver-specific firstopen failed");
203 if (dev
->driver
->use_dma
) {
204 i
= drm_dma_setup(dev
);
209 dev
->types
[0] = _DRM_STAT_LOCK
;
210 dev
->types
[1] = _DRM_STAT_OPENS
;
211 dev
->types
[2] = _DRM_STAT_CLOSES
;
212 dev
->types
[3] = _DRM_STAT_IOCTLS
;
213 dev
->types
[4] = _DRM_STAT_LOCKS
;
214 dev
->types
[5] = _DRM_STAT_UNLOCKS
;
216 for (i
= 0; i
< DRM_ARRAY_SIZE(dev
->counts
); i
++)
217 *(&dev
->counts
[i
]) = 0;
219 for (i
= 0; i
< DRM_HASH_SIZE
; i
++) {
220 dev
->magiclist
[i
].head
= NULL
;
221 dev
->magiclist
[i
].tail
= NULL
;
224 dev
->irq_enabled
= 0;
225 dev
->context_flag
= 0;
226 dev
->last_context
= 0;
232 /* Free resources associated with the DRM on the last close. */
234 drm_lastclose(drm_device_t
*dev
)
236 drm_magic_entry_t
*pt
, *next
;
237 drm_local_map_t
*map
, *mapsave
;
240 DRM_SPINLOCK_ASSERT(&dev
->dev_lock
);
242 if (dev
->driver
->lastclose
!= NULL
)
243 dev
->driver
->lastclose(dev
);
245 if (dev
->irq_enabled
)
246 (void) drm_irq_uninstall(dev
);
249 drm_free(dev
->unique
, dev
->unique_len
+ 1, DRM_MEM_DRIVER
);
255 for (i
= 0; i
< DRM_HASH_SIZE
; i
++) {
256 for (pt
= dev
->magiclist
[i
].head
; pt
; pt
= next
) {
258 drm_free(pt
, sizeof (*pt
), DRM_MEM_MAGIC
);
260 dev
->magiclist
[i
].head
= dev
->magiclist
[i
].tail
= NULL
;
263 /* Clear AGP information */
265 drm_agp_mem_t
*entry
;
266 drm_agp_mem_t
*nexte
;
269 * Remove AGP resources, but leave dev->agp
270 * intact until drm_cleanup is called.
272 for (entry
= dev
->agp
->memory
; entry
; entry
= nexte
) {
275 (void) drm_agp_unbind_memory(
276 (unsigned long)entry
->handle
, dev
);
277 (void) drm_agp_free_memory(entry
->handle
, dev
);
278 drm_free(entry
, sizeof (*entry
), DRM_MEM_AGPLISTS
);
280 dev
->agp
->memory
= NULL
;
282 if (dev
->agp
->acquired
)
283 (void) drm_agp_do_release(dev
);
285 dev
->agp
->acquired
= 0;
286 dev
->agp
->enabled
= 0;
290 if (dev
->sg
!= NULL
) {
294 drm_sg_cleanup(dev
, entry
);
298 /* Clean up maps that weren't set up by the driver. */
299 TAILQ_FOREACH_SAFE(map
, &dev
->maplist
, link
, mapsave
) {
300 if (!map
->kernel_owned
)
304 drm_dma_takedown(dev
);
305 if (dev
->lock
.hw_lock
) {
306 dev
->lock
.hw_lock
= NULL
; /* SHM removed */
307 dev
->lock
.filp
= NULL
;
309 mutex_enter(&(dev
->lock
.lock_mutex
));
310 cv_broadcast(&(dev
->lock
.lock_cv
));
311 mutex_exit(&(dev
->lock
.lock_mutex
));
318 drm_load(drm_device_t
*dev
)
322 cv_init(&(dev
->lock
.lock_cv
), NULL
, CV_DRIVER
, NULL
);
323 mutex_init(&(dev
->lock
.lock_mutex
), NULL
, MUTEX_DRIVER
, NULL
);
324 mutex_init(&(dev
->dev_lock
), "drmdev", MUTEX_DRIVER
, NULL
);
325 mutex_init(&dev
->irq_lock
, "drmirq", MUTEX_DRIVER
,
326 (void *)dev
->intr_block
);
327 mutex_init(&dev
->drw_lock
, "drmdrw", MUTEX_DRIVER
, NULL
);
328 mutex_init(&dev
->tasklet_lock
, "drmtsk", MUTEX_DRIVER
, NULL
);
330 dev
->irq
= pci_get_irq(dev
);
331 dev
->pci_vendor
= pci_get_vendor(dev
);
332 dev
->pci_device
= pci_get_device(dev
);
334 TAILQ_INIT(&dev
->maplist
);
335 TAILQ_INIT(&dev
->minordevs
);
336 TAILQ_INIT(&dev
->files
);
337 if (dev
->driver
->load
!= NULL
) {
338 retcode
= dev
->driver
->load(dev
, 0);
340 DRM_ERROR("drm_load: failed\n");
345 retcode
= drm_ctxbitmap_init(dev
);
347 DRM_ERROR("drm_load: Cannot allocate memory for ctx bitmap");
351 if (dev
->driver
->use_gem
== 1) {
352 retcode
= drm_gem_init(dev
);
354 DRM_ERROR("Cannot initialize graphics execution "
360 if (drm_init_kstats(dev
)) {
361 DRM_ERROR("drm_attach => drm_load: init kstats error");
366 DRM_INFO("!drm: Initialized %s %d.%d.%d %s ",
367 dev
->driver
->driver_name
,
368 dev
->driver
->driver_major
,
369 dev
->driver
->driver_minor
,
370 dev
->driver
->driver_patchlevel
,
371 dev
->driver
->driver_date
);
376 (void) drm_lastclose(dev
);
378 cv_destroy(&(dev
->lock
.lock_cv
));
379 mutex_destroy(&(dev
->lock
.lock_mutex
));
380 mutex_destroy(&dev
->irq_lock
);
381 mutex_destroy(&(dev
->dev_lock
));
382 mutex_destroy(&dev
->drw_lock
);
383 mutex_destroy(&dev
->tasklet_lock
);
388 /* called when cleanup this module */
390 drm_unload(drm_device_t
*dev
)
392 drm_local_map_t
*map
;
394 drm_vblank_cleanup(dev
);
396 drm_ctxbitmap_cleanup(dev
);
398 if (dev
->driver
->use_gem
== 1) {
399 idr_list_free(&dev
->object_name_idr
);
400 mutex_destroy(&dev
->object_name_lock
);
404 (void) drm_lastclose(dev
);
407 while ((map
= TAILQ_FIRST(&dev
->maplist
)) != NULL
) {
411 if (dev
->driver
->unload
!= NULL
)
412 dev
->driver
->unload(dev
);
415 cv_destroy(&dev
->lock
.lock_cv
);
416 mutex_destroy(&dev
->lock
.lock_mutex
);
417 mutex_destroy(&dev
->irq_lock
);
418 mutex_destroy(&dev
->dev_lock
);
419 mutex_destroy(&dev
->drw_lock
);
420 mutex_destroy(&dev
->tasklet_lock
);
423 atomic_set(&dev
->pin_memory
, 0);
424 DRM_ERROR("drm_unload");
430 drm_open(drm_device_t
*dev
, drm_cminor_t
*mp
, int openflags
,
431 int otyp
, cred_t
*credp
)
435 retcode
= drm_open_helper(dev
, mp
, openflags
, otyp
, credp
);
438 atomic_inc_32(&dev
->counts
[_DRM_STAT_OPENS
]);
440 if (!dev
->open_count
++)
441 retcode
= drm_firstopen(dev
);
450 drm_close(drm_device_t
*dev
, int minor
, int flag
, int otyp
,
458 mp
= drm_find_file_by_minor(dev
, minor
);
461 DRM_ERROR("drm_close: can't find authenticator");
468 if (--fpriv
->refs
!= 0)
471 if (dev
->driver
->preclose
!= NULL
)
472 dev
->driver
->preclose(dev
, fpriv
);
475 * Begin inline drm_release
477 DRM_DEBUG("drm_close :pid = %d , open_count = %d",
478 DRM_CURRENTPID
, dev
->open_count
);
480 if (dev
->lock
.hw_lock
&&
481 _DRM_LOCK_IS_HELD(dev
->lock
.hw_lock
->lock
) &&
482 dev
->lock
.filp
== fpriv
) {
483 DRM_DEBUG("Process %d dead, freeing lock for context %d",
485 _DRM_LOCKING_CONTEXT(dev
->lock
.hw_lock
->lock
));
486 if (dev
->driver
->reclaim_buffers_locked
!= NULL
)
487 dev
->driver
->reclaim_buffers_locked(dev
, fpriv
);
488 (void) drm_lock_free(dev
, &dev
->lock
.hw_lock
->lock
,
489 _DRM_LOCKING_CONTEXT(dev
->lock
.hw_lock
->lock
));
490 } else if (dev
->driver
->reclaim_buffers_locked
!= NULL
&&
491 dev
->lock
.hw_lock
!= NULL
) {
492 DRM_ERROR("drm_close: "
493 "retake lock not implemented yet");
496 if (dev
->driver
->use_dma
) {
497 drm_reclaim_buffers(dev
, fpriv
);
500 if (dev
->driver
->use_gem
== 1) {
501 drm_gem_release(dev
, fpriv
);
504 if (dev
->driver
->postclose
!= NULL
) {
505 dev
->driver
->postclose(dev
, fpriv
);
507 TAILQ_REMOVE(&dev
->files
, fpriv
, link
);
508 drm_free(fpriv
, sizeof (*fpriv
), DRM_MEM_FILES
);
511 atomic_inc_32(&dev
->counts
[_DRM_STAT_CLOSES
]);
513 TAILQ_REMOVE(&dev
->minordevs
, mp
, link
);
514 drm_free(mp
, sizeof (*mp
), DRM_MEM_FILES
);
516 if (--dev
->open_count
== 0) {
517 retcode
= drm_lastclose(dev
);
525 drm_attach(drm_device_t
*dev
)
527 return (drm_load(dev
));
531 drm_detach(drm_device_t
*dev
)
534 drm_fini_kstats(dev
);
535 return (DDI_SUCCESS
);
539 drm_get_businfo(drm_device_t
*dev
)
541 dev
->irq
= pci_get_irq(dev
);
542 if (dev
->irq
== -1) {
543 DRM_ERROR("drm_get_businfo: get irq error");
544 return (DDI_FAILURE
);
546 /* XXX Fix domain number (alpha hoses) */
548 if (pci_get_info(dev
, &dev
->pci_bus
,
549 &dev
->pci_slot
, &dev
->pci_func
) != DDI_SUCCESS
) {
550 DRM_ERROR("drm_get_businfo: get bus slot func error ");
551 return (DDI_FAILURE
);
553 DRM_DEBUG("drm_get_businfo: pci bus: %d, pci slot :%d pci func %d",
554 dev
->pci_bus
, dev
->pci_slot
, dev
->pci_func
);
555 return (DDI_SUCCESS
);
559 drm_probe(drm_device_t
*dev
, drm_pci_id_list_t
*idlist
)
561 const char *s
= NULL
;
564 vendor
= pci_get_vendor(dev
);
565 device
= pci_get_device(dev
);
567 s
= drm_find_description(vendor
, device
, idlist
);
570 if (drm_get_businfo(dev
) != DDI_SUCCESS
) {
571 DRM_ERROR("drm_probe: drm get bus info error");
572 return (DDI_FAILURE
);
574 return (DDI_SUCCESS
);
576 return (DDI_FAILURE
);