2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
7 * drm_context.h -- IOCTLs for generic contexts -*- linux-c -*-
8 * Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
11 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
12 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
13 * All Rights Reserved.
15 * Permission is hereby granted, free of charge, to any person obtaining a
16 * copy of this software and associated documentation files (the "Software"),
17 * to deal in the Software without restriction, including without limitation
18 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
19 * and/or sell copies of the Software, and to permit persons to whom the
20 * Software is furnished to do so, subject to the following conditions:
22 * The above copyright notice and this permission notice (including the next
23 * paragraph) shall be included in all copies or substantial portions of the
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
29 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
30 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
31 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
32 * OTHER DEALINGS IN THE SOFTWARE.
35 * Rickard E. (Rik) Faith <faith@valinux.com>
36 * Gareth Hughes <gareth@valinux.com>
40 #pragma ident "%Z%%M% %I% %E% SMI"
46 find_first_zero_bit(volatile void *p
, int max
)
49 volatile int *ptr
= (volatile int *)p
;
51 for (b
= 0; b
< max
; b
+= 32) {
52 if (ptr
[b
>> 5] != ~0) {
54 if ((ptr
[b
>> 5] & (1 << (b
& 0x1f))) == 0)
64 * Context bitmap support
67 drm_ctxbitmap_free(drm_device_t
*dev
, int ctx_handle
)
69 if (ctx_handle
< 0 || ctx_handle
>= DRM_MAX_CTXBITMAP
||
70 dev
->ctx_bitmap
== NULL
) {
71 DRM_ERROR("drm_ctxbitmap_free: Attempt to free\
72 invalid context handle: %d\n",
78 clear_bit(ctx_handle
, dev
->ctx_bitmap
);
79 dev
->context_sareas
[ctx_handle
] = NULL
;
83 /* Is supposed to return -1 if any error by calling functions */
85 drm_ctxbitmap_next(drm_device_t
*dev
)
89 if (dev
->ctx_bitmap
== NULL
)
93 bit
= find_first_zero_bit(dev
->ctx_bitmap
, DRM_MAX_CTXBITMAP
);
94 if (bit
>= DRM_MAX_CTXBITMAP
) {
99 set_bit(bit
, dev
->ctx_bitmap
);
100 DRM_DEBUG("drm_ctxbitmap_next: bit : %d", bit
);
101 if ((bit
+1) > dev
->max_context
) {
102 dev
->max_context
= (bit
+1);
103 if (dev
->context_sareas
!= NULL
) {
104 drm_local_map_t
**ctx_sareas
;
105 ctx_sareas
= drm_realloc(dev
->context_sareas
,
106 (dev
->max_context
- 1) *
107 sizeof (*dev
->context_sareas
),
109 sizeof (*dev
->context_sareas
),
111 if (ctx_sareas
== NULL
) {
112 clear_bit(bit
, dev
->ctx_bitmap
);
116 dev
->context_sareas
= ctx_sareas
;
117 dev
->context_sareas
[bit
] = NULL
;
119 /* max_context == 1 at this point */
120 dev
->context_sareas
= drm_alloc(dev
->max_context
*
121 sizeof (*dev
->context_sareas
), KM_NOSLEEP
);
122 if (dev
->context_sareas
== NULL
) {
123 clear_bit(bit
, dev
->ctx_bitmap
);
127 dev
->context_sareas
[bit
] = NULL
;
131 DRM_DEBUG("drm_ctxbitmap_next: return %d", bit
);
136 drm_ctxbitmap_init(drm_device_t
*dev
)
142 dev
->ctx_bitmap
= drm_calloc(1, DRM_PAGE_SIZE
, DRM_MEM_CTXBITMAP
);
143 if (dev
->ctx_bitmap
== NULL
) {
147 dev
->context_sareas
= NULL
;
148 dev
->max_context
= -1;
151 for (i
= 0; i
< DRM_RESERVED_CONTEXTS
; i
++) {
152 temp
= drm_ctxbitmap_next(dev
);
153 DRM_DEBUG("drm_ctxbitmap_init : %d", temp
);
159 drm_ctxbitmap_cleanup(drm_device_t
*dev
)
162 if (dev
->context_sareas
!= NULL
)
163 drm_free(dev
->context_sareas
,
164 sizeof (*dev
->context_sareas
) *
167 drm_free(dev
->ctx_bitmap
, DRM_PAGE_SIZE
, DRM_MEM_CTXBITMAP
);
172 * Per Context SAREA Support
176 drm_getsareactx(DRM_IOCTL_ARGS
)
179 drm_ctx_priv_map_t request
;
180 drm_local_map_t
*map
;
182 #ifdef _MULTI_DATAMODEL
183 if (ddi_model_convert_from(mode
& FMODELS
) == DDI_MODEL_ILP32
) {
184 drm_ctx_priv_map_32_t request32
;
185 DRM_COPYFROM_WITH_RETURN(&request32
, (void *)data
,
186 sizeof (drm_ctx_priv_map_32_t
));
187 request
.ctx_id
= request32
.ctx_id
;
188 request
.handle
= (void *)(uintptr_t)request32
.handle
;
191 DRM_COPYFROM_WITH_RETURN(&request
, (void *)data
,
195 if (dev
->max_context
< 0 || request
.ctx_id
>= (unsigned)
201 map
= dev
->context_sareas
[request
.ctx_id
];
207 request
.handle
= map
->handle
;
209 #ifdef _MULTI_DATAMODEL
210 if (ddi_model_convert_from(mode
& FMODELS
) == DDI_MODEL_ILP32
) {
211 drm_ctx_priv_map_32_t request32
;
212 request32
.ctx_id
= request
.ctx_id
;
213 request32
.handle
= (caddr32_t
)(uintptr_t)request
.handle
;
214 DRM_COPYTO_WITH_RETURN((void *)data
, &request32
,
215 sizeof (drm_ctx_priv_map_32_t
));
218 DRM_COPYTO_WITH_RETURN((void *)data
,
219 &request
, sizeof (request
));
226 drm_setsareactx(DRM_IOCTL_ARGS
)
229 drm_ctx_priv_map_t request
;
230 drm_local_map_t
*map
= NULL
;
232 #ifdef _MULTI_DATAMODEL
233 if (ddi_model_convert_from(mode
& FMODELS
) == DDI_MODEL_ILP32
) {
234 drm_ctx_priv_map_32_t request32
;
236 DRM_COPYFROM_WITH_RETURN(&request32
, (void *)data
,
237 sizeof (drm_ctx_priv_map_32_t
));
238 request
.ctx_id
= request32
.ctx_id
;
239 request
.handle
= (void *)(uintptr_t)request32
.handle
;
242 DRM_COPYFROM_WITH_RETURN(&request
,
243 (void *)data
, sizeof (request
));
246 TAILQ_FOREACH(map
, &dev
->maplist
, link
) {
247 if (map
->handle
== request
.handle
) {
248 if (dev
->max_context
< 0)
250 if (request
.ctx_id
>= (unsigned)dev
->max_context
)
252 dev
->context_sareas
[request
.ctx_id
] = map
;
264 * The actual DRM context handling routines
267 drm_context_switch(drm_device_t
*dev
, int old
, int new)
269 if (test_and_set_bit(0, &dev
->context_flag
)) {
270 DRM_ERROR("drm_context_switch: Reentering -- FIXME");
274 DRM_DEBUG("drm_context_switch: Context switch from %d to %d",
277 if (new == dev
->last_context
) {
278 clear_bit(0, &dev
->context_flag
);
286 drm_context_switch_complete(drm_device_t
*dev
, int new)
288 dev
->last_context
= new; /* PRE/POST: This is the _only_ writer. */
290 if (!_DRM_LOCK_IS_HELD(dev
->lock
.hw_lock
->lock
)) {
292 "drm_context_switch_complete: Lock not held");
295 * If a context switch is ever initiated
296 * when the kernel holds the lock, release
299 clear_bit(0, &dev
->context_flag
);
306 drm_resctx(DRM_IOCTL_ARGS
)
312 #ifdef _MULTI_DATAMODEL
313 if (ddi_model_convert_from(mode
& FMODELS
) == DDI_MODEL_ILP32
) {
314 drm_ctx_res_32_t res32
;
315 DRM_COPYFROM_WITH_RETURN(&res32
, (void *)data
, sizeof (res32
));
316 res
.count
= res32
.count
;
317 res
.contexts
= (drm_ctx_t
*)(uintptr_t)res32
.contexts
;
320 DRM_COPYFROM_WITH_RETURN(&res
, (void *)data
, sizeof (res
));
322 if (res
.count
>= DRM_RESERVED_CONTEXTS
) {
323 bzero(&ctx
, sizeof (ctx
));
324 for (i
= 0; i
< DRM_RESERVED_CONTEXTS
; i
++) {
326 DRM_COPYTO_WITH_RETURN(&res
.contexts
[i
],
330 res
.count
= DRM_RESERVED_CONTEXTS
;
332 #ifdef _MULTI_DATAMODEL
333 if (ddi_model_convert_from(mode
& FMODELS
) == DDI_MODEL_ILP32
) {
334 drm_ctx_res_32_t res32
;
335 res32
.count
= res
.count
;
336 res32
.contexts
= (caddr32_t
)(uintptr_t)res
.contexts
;
338 DRM_COPYTO_WITH_RETURN((void *)data
, &res32
,
339 sizeof (drm_ctx_res_32_t
));
342 DRM_COPYTO_WITH_RETURN((void *)data
, &res
, sizeof (res
));
349 drm_addctx(DRM_IOCTL_ARGS
)
354 DRM_COPYFROM_WITH_RETURN(&ctx
, (void *)data
, sizeof (ctx
));
356 ctx
.handle
= drm_ctxbitmap_next(dev
);
357 if (ctx
.handle
== DRM_KERNEL_CONTEXT
) {
358 /* Skip kernel's context and get a new one. */
359 ctx
.handle
= drm_ctxbitmap_next(dev
);
361 if (ctx
.handle
== (drm_context_t
)-1) {
365 if (dev
->driver
->context_ctor
&& ctx
.handle
!= DRM_KERNEL_CONTEXT
) {
366 dev
->driver
->context_ctor(dev
, ctx
.handle
);
369 DRM_COPYTO_WITH_RETURN((void *)data
, &ctx
, sizeof (ctx
));
376 drm_modctx(DRM_IOCTL_ARGS
)
378 /* This does nothing */
384 drm_getctx(DRM_IOCTL_ARGS
)
388 DRM_COPYFROM_WITH_RETURN(&ctx
, (void *)data
, sizeof (ctx
));
390 /* This is 0, because we don't handle any context flags */
393 DRM_COPYTO_WITH_RETURN((void *)data
, &ctx
, sizeof (ctx
));
400 drm_switchctx(DRM_IOCTL_ARGS
)
405 DRM_COPYFROM_WITH_RETURN(&ctx
, (void *)data
, sizeof (ctx
));
407 DRM_DEBUG("drm_switchctx: %d", ctx
.handle
);
408 return (drm_context_switch(dev
, dev
->last_context
, ctx
.handle
));
413 drm_newctx(DRM_IOCTL_ARGS
)
418 DRM_COPYFROM_WITH_RETURN(&ctx
, (void *)data
, sizeof (ctx
));
420 DRM_DEBUG("drm_newctx: %d", ctx
.handle
);
421 (void) drm_context_switch_complete(dev
, ctx
.handle
);
428 drm_rmctx(DRM_IOCTL_ARGS
)
433 DRM_COPYFROM_WITH_RETURN(&ctx
, (void *)data
, sizeof (ctx
));
435 DRM_DEBUG("drm_rmctx : %d", ctx
.handle
);
436 if (ctx
.handle
!= DRM_KERNEL_CONTEXT
) {
437 if (dev
->driver
->context_dtor
) {
439 dev
->driver
->context_dtor(dev
, ctx
.handle
);
443 drm_ctxbitmap_free(dev
, ctx
.handle
);