2 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
3 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
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:
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
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.
26 * Rickard E. (Rik) Faith <faith@valinux.com>
27 * Gareth Hughes <gareth@valinux.com>
29 * $DragonFly: src/sys/dev/drm/drm_context.c,v 1.1 2008/04/05 18:12:29 hasso Exp $
32 /** @file drm_context.c
33 * Implementation of the context management ioctls.
38 /* ================================================================
39 * Context bitmap support
42 void drm_ctxbitmap_free(drm_device_t
*dev
, int ctx_handle
)
44 if (ctx_handle
< 0 || ctx_handle
>= DRM_MAX_CTXBITMAP
||
45 dev
->ctx_bitmap
== NULL
) {
46 DRM_ERROR("Attempt to free invalid context handle: %d\n",
52 clear_bit(ctx_handle
, dev
->ctx_bitmap
);
53 dev
->context_sareas
[ctx_handle
] = NULL
;
58 int drm_ctxbitmap_next(drm_device_t
*dev
)
62 if (dev
->ctx_bitmap
== NULL
)
66 bit
= find_first_zero_bit( dev
->ctx_bitmap
, DRM_MAX_CTXBITMAP
);
67 if (bit
>= DRM_MAX_CTXBITMAP
) {
72 set_bit(bit
, dev
->ctx_bitmap
);
73 DRM_DEBUG("drm_ctxbitmap_next bit : %d\n", bit
);
74 if ((bit
+1) > dev
->max_context
) {
75 dev
->max_context
= (bit
+1);
76 if (dev
->context_sareas
!= NULL
) {
77 drm_local_map_t
**ctx_sareas
;
79 ctx_sareas
= realloc(dev
->context_sareas
,
80 dev
->max_context
* sizeof(*dev
->context_sareas
),
82 if (ctx_sareas
== NULL
) {
83 clear_bit(bit
, dev
->ctx_bitmap
);
87 dev
->context_sareas
= ctx_sareas
;
88 dev
->context_sareas
[bit
] = NULL
;
90 /* max_context == 1 at this point */
91 dev
->context_sareas
= malloc(dev
->max_context
*
92 sizeof(*dev
->context_sareas
), M_DRM
, M_NOWAIT
);
93 if (dev
->context_sareas
== NULL
) {
94 clear_bit(bit
, dev
->ctx_bitmap
);
98 dev
->context_sareas
[bit
] = NULL
;
105 int drm_ctxbitmap_init(drm_device_t
*dev
)
111 dev
->ctx_bitmap
= malloc(PAGE_SIZE
, M_DRM
, M_NOWAIT
| M_ZERO
);
112 if ( dev
->ctx_bitmap
== NULL
) {
116 dev
->context_sareas
= NULL
;
117 dev
->max_context
= -1;
120 for ( i
= 0 ; i
< DRM_RESERVED_CONTEXTS
; i
++ ) {
121 temp
= drm_ctxbitmap_next(dev
);
122 DRM_DEBUG( "drm_ctxbitmap_init : %d\n", temp
);
128 void drm_ctxbitmap_cleanup(drm_device_t
*dev
)
131 if (dev
->context_sareas
!= NULL
)
132 free(dev
->context_sareas
, M_DRM
);
133 free(dev
->ctx_bitmap
, M_DRM
);
137 /* ================================================================
138 * Per Context SAREA Support
141 int drm_getsareactx( drm_device_t
*dev
, void *data
, struct drm_file
*file_priv
)
143 drm_ctx_priv_map_t
*request
= data
;
144 drm_local_map_t
*map
;
147 if (dev
->max_context
< 0 ||
148 request
->ctx_id
>= (unsigned) dev
->max_context
) {
153 map
= dev
->context_sareas
[request
->ctx_id
];
156 request
->handle
= map
->handle
;
161 int drm_setsareactx(drm_device_t
*dev
, void *data
, struct drm_file
*file_priv
)
163 drm_ctx_priv_map_t
*request
= data
;
164 drm_local_map_t
*map
= NULL
;
167 TAILQ_FOREACH(map
, &dev
->maplist
, link
) {
168 if (map
->handle
== request
->handle
) {
169 if (dev
->max_context
< 0)
171 if (request
->ctx_id
>= (unsigned) dev
->max_context
)
173 dev
->context_sareas
[request
->ctx_id
] = map
;
184 /* ================================================================
185 * The actual DRM context handling routines
188 int drm_context_switch(drm_device_t
*dev
, int old
, int new)
190 if ( test_and_set_bit( 0, &dev
->context_flag
) ) {
191 DRM_ERROR( "Reentering -- FIXME\n" );
195 DRM_DEBUG( "Context switch from %d to %d\n", old
, new );
197 if ( new == dev
->last_context
) {
198 clear_bit( 0, &dev
->context_flag
);
205 int drm_context_switch_complete(drm_device_t
*dev
, int new)
207 dev
->last_context
= new; /* PRE/POST: This is the _only_ writer. */
209 if ( !_DRM_LOCK_IS_HELD(dev
->lock
.hw_lock
->lock
) ) {
210 DRM_ERROR( "Lock isn't held after context switch\n" );
213 /* If a context switch is ever initiated
214 when the kernel holds the lock, release
216 clear_bit( 0, &dev
->context_flag
);
221 int drm_resctx(drm_device_t
*dev
, void *data
, struct drm_file
*file_priv
)
223 drm_ctx_res_t
*res
= data
;
227 if ( res
->count
>= DRM_RESERVED_CONTEXTS
) {
228 bzero(&ctx
, sizeof(ctx
));
229 for ( i
= 0 ; i
< DRM_RESERVED_CONTEXTS
; i
++ ) {
231 if ( DRM_COPY_TO_USER( &res
->contexts
[i
],
232 &ctx
, sizeof(ctx
) ) )
236 res
->count
= DRM_RESERVED_CONTEXTS
;
241 int drm_addctx(drm_device_t
*dev
, void *data
, struct drm_file
*file_priv
)
243 drm_ctx_t
*ctx
= data
;
245 ctx
->handle
= drm_ctxbitmap_next(dev
);
246 if ( ctx
->handle
== DRM_KERNEL_CONTEXT
) {
247 /* Skip kernel's context and get a new one. */
248 ctx
->handle
= drm_ctxbitmap_next(dev
);
250 DRM_DEBUG( "%d\n", ctx
->handle
);
251 if ( ctx
->handle
== -1 ) {
252 DRM_DEBUG( "Not enough free contexts.\n" );
253 /* Should this return -EBUSY instead? */
257 if (dev
->driver
.context_ctor
&& ctx
->handle
!= DRM_KERNEL_CONTEXT
) {
259 dev
->driver
.context_ctor(dev
, ctx
->handle
);
266 int drm_modctx(drm_device_t
*dev
, void *data
, struct drm_file
*file_priv
)
268 /* This does nothing */
272 int drm_getctx(drm_device_t
*dev
, void *data
, struct drm_file
*file_priv
)
274 drm_ctx_t
*ctx
= data
;
276 /* This is 0, because we don't handle any context flags */
282 int drm_switchctx(drm_device_t
*dev
, void *data
, struct drm_file
*file_priv
)
284 drm_ctx_t
*ctx
= data
;
286 DRM_DEBUG( "%d\n", ctx
->handle
);
287 return drm_context_switch(dev
, dev
->last_context
, ctx
->handle
);
290 int drm_newctx(drm_device_t
*dev
, void *data
, struct drm_file
*file_priv
)
292 drm_ctx_t
*ctx
= data
;
294 DRM_DEBUG( "%d\n", ctx
->handle
);
295 drm_context_switch_complete(dev
, ctx
->handle
);
300 int drm_rmctx(drm_device_t
*dev
, void *data
, struct drm_file
*file_priv
)
302 drm_ctx_t
*ctx
= data
;
304 DRM_DEBUG( "%d\n", ctx
->handle
);
305 if ( ctx
->handle
!= DRM_KERNEL_CONTEXT
) {
306 if (dev
->driver
.context_dtor
) {
308 dev
->driver
.context_dtor(dev
, ctx
->handle
);
312 drm_ctxbitmap_free(dev
, ctx
->handle
);