1 /* drm_context.h -- IOCTLs for generic contexts -*- linux-c -*-
2 * Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
4 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 * Gareth Hughes <gareth@valinux.com>
30 * $FreeBSD: src/sys/dev/drm/drm_context.h,v 1.4.2.1 2003/04/26 07:05:28 anholt Exp $
31 * $DragonFly: src/sys/dev/drm/drm_context.h,v 1.2 2003/06/17 06:28:24 dillon Exp $
34 #include "dev/drm/drmP.h"
36 #if !__HAVE_CTX_BITMAP
37 #error "__HAVE_CTX_BITMAP must be defined"
40 /* ================================================================
41 * Context bitmap support
44 void DRM(ctxbitmap_free
)( drm_device_t
*dev
, int ctx_handle
)
46 if ( ctx_handle
< 0 ) goto failed
;
47 if ( !dev
->ctx_bitmap
) goto failed
;
49 if ( ctx_handle
< DRM_MAX_CTXBITMAP
) {
51 clear_bit( ctx_handle
, dev
->ctx_bitmap
);
52 dev
->context_sareas
[ctx_handle
] = NULL
;
57 DRM_ERROR( "Attempt to free invalid context handle: %d\n",
62 int DRM(ctxbitmap_next
)( drm_device_t
*dev
)
66 if(!dev
->ctx_bitmap
) return -1;
69 bit
= find_first_zero_bit( dev
->ctx_bitmap
, DRM_MAX_CTXBITMAP
);
70 if ( bit
< DRM_MAX_CTXBITMAP
) {
71 set_bit( bit
, dev
->ctx_bitmap
);
72 DRM_DEBUG( "drm_ctxbitmap_next bit : %d\n", bit
);
73 if((bit
+1) > dev
->max_context
) {
74 dev
->max_context
= (bit
+1);
75 if(dev
->context_sareas
) {
76 drm_local_map_t
**ctx_sareas
;
78 ctx_sareas
= DRM(realloc
)(dev
->context_sareas
,
79 (dev
->max_context
- 1) *
80 sizeof(*dev
->context_sareas
),
82 sizeof(*dev
->context_sareas
),
85 clear_bit(bit
, dev
->ctx_bitmap
);
89 dev
->context_sareas
= ctx_sareas
;
90 dev
->context_sareas
[bit
] = NULL
;
92 /* max_context == 1 at this point */
93 dev
->context_sareas
= DRM(alloc
)(
95 sizeof(*dev
->context_sareas
),
97 if(!dev
->context_sareas
) {
98 clear_bit(bit
, dev
->ctx_bitmap
);
102 dev
->context_sareas
[bit
] = NULL
;
112 int DRM(ctxbitmap_init
)( drm_device_t
*dev
)
118 dev
->ctx_bitmap
= (atomic_t
*) DRM(alloc
)( PAGE_SIZE
,
120 if ( dev
->ctx_bitmap
== NULL
) {
122 return DRM_ERR(ENOMEM
);
124 memset( (void *)dev
->ctx_bitmap
, 0, PAGE_SIZE
);
125 dev
->context_sareas
= NULL
;
126 dev
->max_context
= -1;
129 for ( i
= 0 ; i
< DRM_RESERVED_CONTEXTS
; i
++ ) {
130 temp
= DRM(ctxbitmap_next
)( dev
);
131 DRM_DEBUG( "drm_ctxbitmap_init : %d\n", temp
);
137 void DRM(ctxbitmap_cleanup
)( drm_device_t
*dev
)
140 if( dev
->context_sareas
) DRM(free
)( dev
->context_sareas
,
141 sizeof(*dev
->context_sareas
) *
144 DRM(free
)( (void *)dev
->ctx_bitmap
, PAGE_SIZE
, DRM_MEM_CTXBITMAP
);
148 /* ================================================================
149 * Per Context SAREA Support
152 int DRM(getsareactx
)( DRM_IOCTL_ARGS
)
155 drm_ctx_priv_map_t request
;
156 drm_local_map_t
*map
;
158 DRM_COPY_FROM_USER_IOCTL( request
, (drm_ctx_priv_map_t
*)data
,
162 if (dev
->max_context
< 0 || request
.ctx_id
>= (unsigned) dev
->max_context
) {
164 return DRM_ERR(EINVAL
);
167 map
= dev
->context_sareas
[request
.ctx_id
];
170 request
.handle
= map
->handle
;
172 DRM_COPY_TO_USER_IOCTL( (drm_ctx_priv_map_t
*)data
, request
, sizeof(request
) );
177 int DRM(setsareactx
)( DRM_IOCTL_ARGS
)
180 drm_ctx_priv_map_t request
;
181 drm_local_map_t
*map
= NULL
;
182 drm_map_list_entry_t
*list
;
184 DRM_COPY_FROM_USER_IOCTL( request
, (drm_ctx_priv_map_t
*)data
,
188 TAILQ_FOREACH(list
, dev
->maplist
, link
) {
190 if(map
->handle
== request
.handle
) {
191 if (dev
->max_context
< 0)
193 if (request
.ctx_id
>= (unsigned) dev
->max_context
)
195 dev
->context_sareas
[request
.ctx_id
] = map
;
203 return DRM_ERR(EINVAL
);
206 /* ================================================================
207 * The actual DRM context handling routines
210 int DRM(context_switch
)( drm_device_t
*dev
, int old
, int new )
212 if ( test_and_set_bit( 0, &dev
->context_flag
) ) {
213 DRM_ERROR( "Reentering -- FIXME\n" );
214 return DRM_ERR(EBUSY
);
217 DRM_DEBUG( "Context switch from %d to %d\n", old
, new );
219 if ( new == dev
->last_context
) {
220 clear_bit( 0, &dev
->context_flag
);
227 int DRM(context_switch_complete
)( drm_device_t
*dev
, int new )
229 dev
->last_context
= new; /* PRE/POST: This is the _only_ writer. */
231 if ( !_DRM_LOCK_IS_HELD(dev
->lock
.hw_lock
->lock
) ) {
232 DRM_ERROR( "Lock isn't held after context switch\n" );
235 /* If a context switch is ever initiated
236 when the kernel holds the lock, release
238 clear_bit( 0, &dev
->context_flag
);
243 int DRM(resctx
)( DRM_IOCTL_ARGS
)
249 DRM_COPY_FROM_USER_IOCTL( res
, (drm_ctx_res_t
*)data
, sizeof(res
) );
251 if ( res
.count
>= DRM_RESERVED_CONTEXTS
) {
252 memset( &ctx
, 0, sizeof(ctx
) );
253 for ( i
= 0 ; i
< DRM_RESERVED_CONTEXTS
; i
++ ) {
255 if ( DRM_COPY_TO_USER( &res
.contexts
[i
],
257 return DRM_ERR(EFAULT
);
260 res
.count
= DRM_RESERVED_CONTEXTS
;
262 DRM_COPY_TO_USER_IOCTL( (drm_ctx_res_t
*)data
, res
, sizeof(res
) );
267 int DRM(addctx
)( DRM_IOCTL_ARGS
)
272 DRM_COPY_FROM_USER_IOCTL( ctx
, (drm_ctx_t
*)data
, sizeof(ctx
) );
274 ctx
.handle
= DRM(ctxbitmap_next
)( dev
);
275 if ( ctx
.handle
== DRM_KERNEL_CONTEXT
) {
276 /* Skip kernel's context and get a new one. */
277 ctx
.handle
= DRM(ctxbitmap_next
)( dev
);
279 DRM_DEBUG( "%d\n", ctx
.handle
);
280 if ( ctx
.handle
== -1 ) {
281 DRM_DEBUG( "Not enough free contexts.\n" );
282 /* Should this return -EBUSY instead? */
283 return DRM_ERR(ENOMEM
);
286 DRM_COPY_TO_USER_IOCTL( (drm_ctx_t
*)data
, ctx
, sizeof(ctx
) );
291 int DRM(modctx
)( DRM_IOCTL_ARGS
)
293 /* This does nothing */
297 int DRM(getctx
)( DRM_IOCTL_ARGS
)
301 DRM_COPY_FROM_USER_IOCTL( ctx
, (drm_ctx_t
*)data
, sizeof(ctx
) );
303 /* This is 0, because we don't handle any context flags */
306 DRM_COPY_TO_USER_IOCTL( (drm_ctx_t
*)data
, ctx
, sizeof(ctx
) );
311 int DRM(switchctx
)( DRM_IOCTL_ARGS
)
316 DRM_COPY_FROM_USER_IOCTL( ctx
, (drm_ctx_t
*)data
, sizeof(ctx
) );
318 DRM_DEBUG( "%d\n", ctx
.handle
);
319 return DRM(context_switch
)( dev
, dev
->last_context
, ctx
.handle
);
322 int DRM(newctx
)( DRM_IOCTL_ARGS
)
327 DRM_COPY_FROM_USER_IOCTL( ctx
, (drm_ctx_t
*)data
, sizeof(ctx
) );
329 DRM_DEBUG( "%d\n", ctx
.handle
);
330 DRM(context_switch_complete
)( dev
, ctx
.handle
);
335 int DRM(rmctx
)( DRM_IOCTL_ARGS
)
340 DRM_COPY_FROM_USER_IOCTL( ctx
, (drm_ctx_t
*)data
, sizeof(ctx
) );
342 DRM_DEBUG( "%d\n", ctx
.handle
);
343 if ( ctx
.handle
!= DRM_KERNEL_CONTEXT
) {
344 DRM(ctxbitmap_free
)( dev
, ctx
.handle
);