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 $
33 #include "dev/drm/drmP.h"
35 #if !__HAVE_CTX_BITMAP
36 #error "__HAVE_CTX_BITMAP must be defined"
39 /* ================================================================
40 * Context bitmap support
43 void DRM(ctxbitmap_free)( drm_device_t *dev, int ctx_handle )
45 if ( ctx_handle < 0 ) goto failed;
46 if ( !dev->ctx_bitmap ) goto failed;
48 if ( ctx_handle < DRM_MAX_CTXBITMAP ) {
50 clear_bit( ctx_handle, dev->ctx_bitmap );
51 dev->context_sareas[ctx_handle] = NULL;
56 DRM_ERROR( "Attempt to free invalid context handle: %d\n",
61 int DRM(ctxbitmap_next)( drm_device_t *dev )
65 if(!dev->ctx_bitmap) return -1;
68 bit = find_first_zero_bit( dev->ctx_bitmap, DRM_MAX_CTXBITMAP );
69 if ( bit < DRM_MAX_CTXBITMAP ) {
70 set_bit( bit, dev->ctx_bitmap );
71 DRM_DEBUG( "drm_ctxbitmap_next bit : %d\n", bit );
72 if((bit+1) > dev->max_context) {
73 dev->max_context = (bit+1);
74 if(dev->context_sareas) {
75 drm_local_map_t **ctx_sareas;
77 ctx_sareas = DRM(realloc)(dev->context_sareas,
78 (dev->max_context - 1) *
79 sizeof(*dev->context_sareas),
81 sizeof(*dev->context_sareas),
84 clear_bit(bit, dev->ctx_bitmap);
88 dev->context_sareas = ctx_sareas;
89 dev->context_sareas[bit] = NULL;
91 /* max_context == 1 at this point */
92 dev->context_sareas = DRM(alloc)(
94 sizeof(*dev->context_sareas),
96 if(!dev->context_sareas) {
97 clear_bit(bit, dev->ctx_bitmap);
101 dev->context_sareas[bit] = NULL;
111 int DRM(ctxbitmap_init)( drm_device_t *dev )
117 dev->ctx_bitmap = (atomic_t *) DRM(alloc)( PAGE_SIZE,
119 if ( dev->ctx_bitmap == NULL ) {
121 return DRM_ERR(ENOMEM);
123 memset( (void *)dev->ctx_bitmap, 0, PAGE_SIZE );
124 dev->context_sareas = NULL;
125 dev->max_context = -1;
128 for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
129 temp = DRM(ctxbitmap_next)( dev );
130 DRM_DEBUG( "drm_ctxbitmap_init : %d\n", temp );
136 void DRM(ctxbitmap_cleanup)( drm_device_t *dev )
139 if( dev->context_sareas ) DRM(free)( dev->context_sareas,
140 sizeof(*dev->context_sareas) *
143 DRM(free)( (void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP );
147 /* ================================================================
148 * Per Context SAREA Support
151 int DRM(getsareactx)( DRM_IOCTL_ARGS )
154 drm_ctx_priv_map_t request;
155 drm_local_map_t *map;
157 DRM_COPY_FROM_USER_IOCTL( request, (drm_ctx_priv_map_t *)data,
161 if (dev->max_context < 0 || request.ctx_id >= (unsigned) dev->max_context) {
163 return DRM_ERR(EINVAL);
166 map = dev->context_sareas[request.ctx_id];
169 request.handle = map->handle;
171 DRM_COPY_TO_USER_IOCTL( (drm_ctx_priv_map_t *)data, request, sizeof(request) );
176 int DRM(setsareactx)( DRM_IOCTL_ARGS )
179 drm_ctx_priv_map_t request;
180 drm_local_map_t *map = NULL;
181 drm_map_list_entry_t *list;
183 DRM_COPY_FROM_USER_IOCTL( request, (drm_ctx_priv_map_t *)data,
187 TAILQ_FOREACH(list, dev->maplist, link) {
189 if(map->handle == request.handle) {
190 if (dev->max_context < 0)
192 if (request.ctx_id >= (unsigned) dev->max_context)
194 dev->context_sareas[request.ctx_id] = map;
202 return DRM_ERR(EINVAL);
205 /* ================================================================
206 * The actual DRM context handling routines
209 int DRM(context_switch)( drm_device_t *dev, int old, int new )
211 if ( test_and_set_bit( 0, &dev->context_flag ) ) {
212 DRM_ERROR( "Reentering -- FIXME\n" );
213 return DRM_ERR(EBUSY);
216 DRM_DEBUG( "Context switch from %d to %d\n", old, new );
218 if ( new == dev->last_context ) {
219 clear_bit( 0, &dev->context_flag );
226 int DRM(context_switch_complete)( drm_device_t *dev, int new )
228 dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
230 if ( !_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ) {
231 DRM_ERROR( "Lock isn't held after context switch\n" );
234 /* If a context switch is ever initiated
235 when the kernel holds the lock, release
237 clear_bit( 0, &dev->context_flag );
242 int DRM(resctx)( DRM_IOCTL_ARGS )
248 DRM_COPY_FROM_USER_IOCTL( res, (drm_ctx_res_t *)data, sizeof(res) );
250 if ( res.count >= DRM_RESERVED_CONTEXTS ) {
251 memset( &ctx, 0, sizeof(ctx) );
252 for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
254 if ( DRM_COPY_TO_USER( &res.contexts[i],
256 return DRM_ERR(EFAULT);
259 res.count = DRM_RESERVED_CONTEXTS;
261 DRM_COPY_TO_USER_IOCTL( (drm_ctx_res_t *)data, res, sizeof(res) );
266 int DRM(addctx)( DRM_IOCTL_ARGS )
271 DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
273 ctx.handle = DRM(ctxbitmap_next)( dev );
274 if ( ctx.handle == DRM_KERNEL_CONTEXT ) {
275 /* Skip kernel's context and get a new one. */
276 ctx.handle = DRM(ctxbitmap_next)( dev );
278 DRM_DEBUG( "%d\n", ctx.handle );
279 if ( ctx.handle == -1 ) {
280 DRM_DEBUG( "Not enough free contexts.\n" );
281 /* Should this return -EBUSY instead? */
282 return DRM_ERR(ENOMEM);
285 DRM_COPY_TO_USER_IOCTL( (drm_ctx_t *)data, ctx, sizeof(ctx) );
290 int DRM(modctx)( DRM_IOCTL_ARGS )
292 /* This does nothing */
296 int DRM(getctx)( DRM_IOCTL_ARGS )
300 DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
302 /* This is 0, because we don't handle any context flags */
305 DRM_COPY_TO_USER_IOCTL( (drm_ctx_t *)data, ctx, sizeof(ctx) );
310 int DRM(switchctx)( DRM_IOCTL_ARGS )
315 DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
317 DRM_DEBUG( "%d\n", ctx.handle );
318 return DRM(context_switch)( dev, dev->last_context, ctx.handle );
321 int DRM(newctx)( DRM_IOCTL_ARGS )
326 DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
328 DRM_DEBUG( "%d\n", ctx.handle );
329 DRM(context_switch_complete)( dev, ctx.handle );
334 int DRM(rmctx)( DRM_IOCTL_ARGS )
339 DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
341 DRM_DEBUG( "%d\n", ctx.handle );
342 if ( ctx.handle != DRM_KERNEL_CONTEXT ) {
343 DRM(ctxbitmap_free)( dev, ctx.handle );