Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / io / drm / drm_context.c
blob16c141f2557f616f60750db44565169f0862cb9f
1 /*
2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
6 /*
7 * drm_context.h -- IOCTLs for generic contexts -*- linux-c -*-
8 * Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
9 */
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
24 * Software.
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.
34 * Authors:
35 * Rickard E. (Rik) Faith <faith@valinux.com>
36 * Gareth Hughes <gareth@valinux.com>
40 #pragma ident "%Z%%M% %I% %E% SMI"
42 #include "drmP.h"
43 #include "drm_io32.h"
45 static inline int
46 find_first_zero_bit(volatile void *p, int max)
48 int b;
49 volatile int *ptr = (volatile int *)p;
51 for (b = 0; b < max; b += 32) {
52 if (ptr[b >> 5] != ~0) {
53 for (;;) {
54 if ((ptr[b >> 5] & (1 << (b & 0x1f))) == 0)
55 return (b);
56 b++;
60 return (max);
64 * Context bitmap support
66 void
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",
73 ctx_handle);
74 return;
77 DRM_LOCK();
78 clear_bit(ctx_handle, dev->ctx_bitmap);
79 dev->context_sareas[ctx_handle] = NULL;
80 DRM_UNLOCK();
83 /* Is supposed to return -1 if any error by calling functions */
84 int
85 drm_ctxbitmap_next(drm_device_t *dev)
87 int bit;
89 if (dev->ctx_bitmap == NULL)
90 return (-1);
92 DRM_LOCK();
93 bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP);
94 if (bit >= DRM_MAX_CTXBITMAP) {
95 DRM_UNLOCK();
96 return (-1);
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),
108 dev->max_context *
109 sizeof (*dev->context_sareas),
110 DRM_MEM_MAPS);
111 if (ctx_sareas == NULL) {
112 clear_bit(bit, dev->ctx_bitmap);
113 DRM_UNLOCK();
114 return (-1);
116 dev->context_sareas = ctx_sareas;
117 dev->context_sareas[bit] = NULL;
118 } else {
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);
124 DRM_UNLOCK();
125 return (-1);
127 dev->context_sareas[bit] = NULL;
130 DRM_UNLOCK();
131 DRM_DEBUG("drm_ctxbitmap_next: return %d", bit);
132 return (bit);
136 drm_ctxbitmap_init(drm_device_t *dev)
138 int i;
139 int temp;
141 DRM_LOCK();
142 dev->ctx_bitmap = drm_calloc(1, DRM_PAGE_SIZE, DRM_MEM_CTXBITMAP);
143 if (dev->ctx_bitmap == NULL) {
144 DRM_UNLOCK();
145 return (ENOMEM);
147 dev->context_sareas = NULL;
148 dev->max_context = -1;
149 DRM_UNLOCK();
151 for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
152 temp = drm_ctxbitmap_next(dev);
153 DRM_DEBUG("drm_ctxbitmap_init : %d", temp);
155 return (0);
158 void
159 drm_ctxbitmap_cleanup(drm_device_t *dev)
161 DRM_LOCK();
162 if (dev->context_sareas != NULL)
163 drm_free(dev->context_sareas,
164 sizeof (*dev->context_sareas) *
165 dev->max_context,
166 DRM_MEM_MAPS);
167 drm_free(dev->ctx_bitmap, DRM_PAGE_SIZE, DRM_MEM_CTXBITMAP);
168 DRM_UNLOCK();
172 * Per Context SAREA Support
174 /*ARGSUSED*/
176 drm_getsareactx(DRM_IOCTL_ARGS)
178 DRM_DEVICE;
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;
189 } else
190 #endif
191 DRM_COPYFROM_WITH_RETURN(&request, (void *)data,
192 sizeof (request));
194 DRM_LOCK();
195 if (dev->max_context < 0 || request.ctx_id >= (unsigned)
196 dev->max_context) {
197 DRM_UNLOCK();
198 return (EINVAL);
201 map = dev->context_sareas[request.ctx_id];
202 DRM_UNLOCK();
204 if (!map)
205 return (EINVAL);
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));
216 } else
217 #endif
218 DRM_COPYTO_WITH_RETURN((void *)data,
219 &request, sizeof (request));
221 return (0);
224 /*ARGSUSED*/
226 drm_setsareactx(DRM_IOCTL_ARGS)
228 DRM_DEVICE;
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;
240 } else
241 #endif
242 DRM_COPYFROM_WITH_RETURN(&request,
243 (void *)data, sizeof (request));
245 DRM_LOCK();
246 TAILQ_FOREACH(map, &dev->maplist, link) {
247 if (map->handle == request.handle) {
248 if (dev->max_context < 0)
249 goto bad;
250 if (request.ctx_id >= (unsigned)dev->max_context)
251 goto bad;
252 dev->context_sareas[request.ctx_id] = map;
253 DRM_UNLOCK();
254 return (0);
258 bad:
259 DRM_UNLOCK();
260 return (EINVAL);
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");
271 return (EBUSY);
274 DRM_DEBUG("drm_context_switch: Context switch from %d to %d",
275 old, new);
277 if (new == dev->last_context) {
278 clear_bit(0, &dev->context_flag);
279 return (0);
282 return (0);
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)) {
291 DRM_ERROR(
292 "drm_context_switch_complete: Lock not held");
295 * If a context switch is ever initiated
296 * when the kernel holds the lock, release
297 * that lock here.
299 clear_bit(0, &dev->context_flag);
301 return (0);
304 /*ARGSUSED*/
306 drm_resctx(DRM_IOCTL_ARGS)
308 drm_ctx_res_t res;
309 drm_ctx_t ctx;
310 int i;
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;
318 } else
319 #endif
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++) {
325 ctx.handle = i;
326 DRM_COPYTO_WITH_RETURN(&res.contexts[i],
327 &ctx, sizeof (ctx));
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));
340 } else
341 #endif
342 DRM_COPYTO_WITH_RETURN((void *)data, &res, sizeof (res));
344 return (0);
347 /*ARGSUSED*/
349 drm_addctx(DRM_IOCTL_ARGS)
351 DRM_DEVICE;
352 drm_ctx_t ctx;
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) {
362 return (ENOMEM);
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));
371 return (0);
374 /*ARGSUSED*/
376 drm_modctx(DRM_IOCTL_ARGS)
378 /* This does nothing */
379 return (0);
382 /*ARGSUSED*/
384 drm_getctx(DRM_IOCTL_ARGS)
386 drm_ctx_t ctx;
388 DRM_COPYFROM_WITH_RETURN(&ctx, (void *)data, sizeof (ctx));
390 /* This is 0, because we don't handle any context flags */
391 ctx.flags = 0;
393 DRM_COPYTO_WITH_RETURN((void *)data, &ctx, sizeof (ctx));
395 return (0);
398 /*ARGSUSED*/
400 drm_switchctx(DRM_IOCTL_ARGS)
402 DRM_DEVICE;
403 drm_ctx_t ctx;
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));
411 /*ARGSUSED*/
413 drm_newctx(DRM_IOCTL_ARGS)
415 DRM_DEVICE;
416 drm_ctx_t ctx;
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);
423 return (0);
426 /*ARGSUSED*/
428 drm_rmctx(DRM_IOCTL_ARGS)
430 DRM_DEVICE;
431 drm_ctx_t ctx;
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) {
438 DRM_LOCK();
439 dev->driver->context_dtor(dev, ctx.handle);
440 DRM_UNLOCK();
443 drm_ctxbitmap_free(dev, ctx.handle);
446 return (0);