1 /* $Id: ffb_context.c,v 1.5 2001/08/09 17:47:51 davem Exp $
2  * ffb_context.c: Creator/Creator3D DRI/DRM context switching.
3  *
4  * Copyright (C) 2000 David S. Miller (davem@redhat.com)
5  *
6  * Almost entirely stolen from tdfx_context.c, see there
7  * for authors.
8  */
9 
10 #include <linux/sched.h>
11 #include <asm/upa.h>
12 
13 #include "ffb.h"
14 #include "drmP.h"
15 
16 #include "ffb_drv.h"
17 
DRM(alloc_queue)18 static int DRM(alloc_queue)(drm_device_t *dev, int is_2d_only)
19 {
20 	ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
21 	int i;
22 
23 	for (i = 0; i < FFB_MAX_CTXS; i++) {
24 		if (fpriv->hw_state[i] == NULL)
25 			break;
26 	}
27 	if (i == FFB_MAX_CTXS)
28 		return -1;
29 
30 	fpriv->hw_state[i] = kmalloc(sizeof(struct ffb_hw_context), GFP_KERNEL);
31 	if (fpriv->hw_state[i] == NULL)
32 		return -1;
33 
34 	fpriv->hw_state[i]->is_2d_only = is_2d_only;
35 
36 	/* Plus one because 0 is the special DRM_KERNEL_CONTEXT. */
37 	return i + 1;
38 }
39 
ffb_save_context(ffb_dev_priv_t * fpriv,int idx)40 static void ffb_save_context(ffb_dev_priv_t *fpriv, int idx)
41 {
42 	ffb_fbcPtr ffb = fpriv->regs;
43 	struct ffb_hw_context *ctx;
44 	int i;
45 
46 	ctx = fpriv->hw_state[idx - 1];
47 	if (idx == 0 || ctx == NULL)
48 		return;
49 
50 	if (ctx->is_2d_only) {
51 		/* 2D applications only care about certain pieces
52 		 * of state.
53 		 */
54 		ctx->drawop = upa_readl(&ffb->drawop);
55 		ctx->ppc = upa_readl(&ffb->ppc);
56 		ctx->wid = upa_readl(&ffb->wid);
57 		ctx->fg = upa_readl(&ffb->fg);
58 		ctx->bg = upa_readl(&ffb->bg);
59 		ctx->xclip = upa_readl(&ffb->xclip);
60 		ctx->fbc = upa_readl(&ffb->fbc);
61 		ctx->rop = upa_readl(&ffb->rop);
62 		ctx->cmp = upa_readl(&ffb->cmp);
63 		ctx->matchab = upa_readl(&ffb->matchab);
64 		ctx->magnab = upa_readl(&ffb->magnab);
65 		ctx->pmask = upa_readl(&ffb->pmask);
66 		ctx->xpmask = upa_readl(&ffb->xpmask);
67 		ctx->lpat = upa_readl(&ffb->lpat);
68 		ctx->fontxy = upa_readl(&ffb->fontxy);
69 		ctx->fontw = upa_readl(&ffb->fontw);
70 		ctx->fontinc = upa_readl(&ffb->fontinc);
71 
72 		/* stencil/stencilctl only exists on FFB2+ and later
73 		 * due to the introduction of 3DRAM-III.
74 		 */
75 		if (fpriv->ffb_type == ffb2_vertical_plus ||
76 		    fpriv->ffb_type == ffb2_horizontal_plus) {
77 			ctx->stencil = upa_readl(&ffb->stencil);
78 			ctx->stencilctl = upa_readl(&ffb->stencilctl);
79 		}
80 
81 		for (i = 0; i < 32; i++)
82 			ctx->area_pattern[i] = upa_readl(&ffb->pattern[i]);
83 		ctx->ucsr = upa_readl(&ffb->ucsr);
84 		return;
85 	}
86 
87 	/* Fetch drawop. */
88 	ctx->drawop = upa_readl(&ffb->drawop);
89 
90 	/* If we were saving the vertex registers, this is where
91 	 * we would do it.  We would save 32 32-bit words starting
92 	 * at ffb->suvtx.
93 	 */
94 
95 	/* Capture rendering attributes. */
96 
97 	ctx->ppc = upa_readl(&ffb->ppc);		/* Pixel Processor Control */
98 	ctx->wid = upa_readl(&ffb->wid);		/* Current WID */
99 	ctx->fg = upa_readl(&ffb->fg);			/* Constant FG color */
100 	ctx->bg = upa_readl(&ffb->bg);			/* Constant BG color */
101 	ctx->consty = upa_readl(&ffb->consty);		/* Constant Y */
102 	ctx->constz = upa_readl(&ffb->constz);		/* Constant Z */
103 	ctx->xclip = upa_readl(&ffb->xclip);		/* X plane clip */
104 	ctx->dcss = upa_readl(&ffb->dcss);		/* Depth Cue Scale Slope */
105 	ctx->vclipmin = upa_readl(&ffb->vclipmin);	/* Primary XY clip, minimum */
106 	ctx->vclipmax = upa_readl(&ffb->vclipmax);	/* Primary XY clip, maximum */
107 	ctx->vclipzmin = upa_readl(&ffb->vclipzmin);	/* Primary Z clip, minimum */
108 	ctx->vclipzmax = upa_readl(&ffb->vclipzmax);	/* Primary Z clip, maximum */
109 	ctx->dcsf = upa_readl(&ffb->dcsf);		/* Depth Cue Scale Front Bound */
110 	ctx->dcsb = upa_readl(&ffb->dcsb);		/* Depth Cue Scale Back Bound */
111 	ctx->dczf = upa_readl(&ffb->dczf);		/* Depth Cue Scale Z Front */
112 	ctx->dczb = upa_readl(&ffb->dczb);		/* Depth Cue Scale Z Back */
113 	ctx->blendc = upa_readl(&ffb->blendc);		/* Alpha Blend Control */
114 	ctx->blendc1 = upa_readl(&ffb->blendc1);	/* Alpha Blend Color 1 */
115 	ctx->blendc2 = upa_readl(&ffb->blendc2);	/* Alpha Blend Color 2 */
116 	ctx->fbc = upa_readl(&ffb->fbc);		/* Frame Buffer Control */
117 	ctx->rop = upa_readl(&ffb->rop);		/* Raster Operation */
118 	ctx->cmp = upa_readl(&ffb->cmp);		/* Compare Controls */
119 	ctx->matchab = upa_readl(&ffb->matchab);	/* Buffer A/B Match Ops */
120 	ctx->matchc = upa_readl(&ffb->matchc);		/* Buffer C Match Ops */
121 	ctx->magnab = upa_readl(&ffb->magnab);		/* Buffer A/B Magnitude Ops */
122 	ctx->magnc = upa_readl(&ffb->magnc);		/* Buffer C Magnitude Ops */
123 	ctx->pmask = upa_readl(&ffb->pmask);		/* RGB Plane Mask */
124 	ctx->xpmask = upa_readl(&ffb->xpmask);		/* X Plane Mask */
125 	ctx->ypmask = upa_readl(&ffb->ypmask);		/* Y Plane Mask */
126 	ctx->zpmask = upa_readl(&ffb->zpmask);		/* Z Plane Mask */
127 
128 	/* Auxiliary Clips. */
129 	ctx->auxclip0min = upa_readl(&ffb->auxclip[0].min);
130 	ctx->auxclip0max = upa_readl(&ffb->auxclip[0].max);
131 	ctx->auxclip1min = upa_readl(&ffb->auxclip[1].min);
132 	ctx->auxclip1max = upa_readl(&ffb->auxclip[1].max);
133 	ctx->auxclip2min = upa_readl(&ffb->auxclip[2].min);
134 	ctx->auxclip2max = upa_readl(&ffb->auxclip[2].max);
135 	ctx->auxclip3min = upa_readl(&ffb->auxclip[3].min);
136 	ctx->auxclip3max = upa_readl(&ffb->auxclip[3].max);
137 
138 	ctx->lpat = upa_readl(&ffb->lpat);		/* Line Pattern */
139 	ctx->fontxy = upa_readl(&ffb->fontxy);		/* XY Font Coordinate */
140 	ctx->fontw = upa_readl(&ffb->fontw);		/* Font Width */
141 	ctx->fontinc = upa_readl(&ffb->fontinc);	/* Font X/Y Increment */
142 
143 	/* These registers/features only exist on FFB2 and later chips. */
144 	if (fpriv->ffb_type >= ffb2_prototype) {
145 		ctx->dcss1 = upa_readl(&ffb->dcss1);	/* Depth Cue Scale Slope 1 */
146 		ctx->dcss2 = upa_readl(&ffb->dcss2);	/* Depth Cue Scale Slope 2 */
147 		ctx->dcss2 = upa_readl(&ffb->dcss3);	/* Depth Cue Scale Slope 3 */
148 		ctx->dcs2  = upa_readl(&ffb->dcs2);	/* Depth Cue Scale 2 */
149 		ctx->dcs3  = upa_readl(&ffb->dcs3);	/* Depth Cue Scale 3 */
150 		ctx->dcs4  = upa_readl(&ffb->dcs4);	/* Depth Cue Scale 4 */
151 		ctx->dcd2  = upa_readl(&ffb->dcd2);	/* Depth Cue Depth 2 */
152 		ctx->dcd3  = upa_readl(&ffb->dcd3);	/* Depth Cue Depth 3 */
153 		ctx->dcd4  = upa_readl(&ffb->dcd4);	/* Depth Cue Depth 4 */
154 
155 		/* And stencil/stencilctl only exists on FFB2+ and later
156 		 * due to the introduction of 3DRAM-III.
157 		 */
158 		if (fpriv->ffb_type == ffb2_vertical_plus ||
159 		    fpriv->ffb_type == ffb2_horizontal_plus) {
160 			ctx->stencil = upa_readl(&ffb->stencil);
161 			ctx->stencilctl = upa_readl(&ffb->stencilctl);
162 		}
163 	}
164 
165 	/* Save the 32x32 area pattern. */
166 	for (i = 0; i < 32; i++)
167 		ctx->area_pattern[i] = upa_readl(&ffb->pattern[i]);
168 
169 	/* Finally, stash away the User Constol/Status Register. */
170 	ctx->ucsr = upa_readl(&ffb->ucsr);
171 }
172 
ffb_restore_context(ffb_dev_priv_t * fpriv,int old,int idx)173 static void ffb_restore_context(ffb_dev_priv_t *fpriv, int old, int idx)
174 {
175 	ffb_fbcPtr ffb = fpriv->regs;
176 	struct ffb_hw_context *ctx;
177 	int i;
178 
179 	ctx = fpriv->hw_state[idx - 1];
180 	if (idx == 0 || ctx == NULL)
181 		return;
182 
183 	if (ctx->is_2d_only) {
184 		/* 2D applications only care about certain pieces
185 		 * of state.
186 		 */
187 		upa_writel(ctx->drawop, &ffb->drawop);
188 
189 		/* If we were restoring the vertex registers, this is where
190 		 * we would do it.  We would restore 32 32-bit words starting
191 		 * at ffb->suvtx.
192 		 */
193 
194 		upa_writel(ctx->ppc, &ffb->ppc);
195 		upa_writel(ctx->wid, &ffb->wid);
196 		upa_writel(ctx->fg,  &ffb->fg);
197 		upa_writel(ctx->bg, &ffb->bg);
198 		upa_writel(ctx->xclip, &ffb->xclip);
199 		upa_writel(ctx->fbc, &ffb->fbc);
200 		upa_writel(ctx->rop, &ffb->rop);
201 		upa_writel(ctx->cmp, &ffb->cmp);
202 		upa_writel(ctx->matchab, &ffb->matchab);
203 		upa_writel(ctx->magnab, &ffb->magnab);
204 		upa_writel(ctx->pmask, &ffb->pmask);
205 		upa_writel(ctx->xpmask, &ffb->xpmask);
206 		upa_writel(ctx->lpat, &ffb->lpat);
207 		upa_writel(ctx->fontxy, &ffb->fontxy);
208 		upa_writel(ctx->fontw, &ffb->fontw);
209 		upa_writel(ctx->fontinc, &ffb->fontinc);
210 
211 		/* stencil/stencilctl only exists on FFB2+ and later
212 		 * due to the introduction of 3DRAM-III.
213 		 */
214 		if (fpriv->ffb_type == ffb2_vertical_plus ||
215 		    fpriv->ffb_type == ffb2_horizontal_plus) {
216 			upa_writel(ctx->stencil, &ffb->stencil);
217 			upa_writel(ctx->stencilctl, &ffb->stencilctl);
218 			upa_writel(0x80000000, &ffb->fbc);
219 			upa_writel((ctx->stencilctl | 0x80000),
220 				   &ffb->rawstencilctl);
221 			upa_writel(ctx->fbc, &ffb->fbc);
222 		}
223 
224 		for (i = 0; i < 32; i++)
225 			upa_writel(ctx->area_pattern[i], &ffb->pattern[i]);
226 		upa_writel((ctx->ucsr & 0xf0000), &ffb->ucsr);
227 		return;
228 	}
229 
230 	/* Restore drawop. */
231 	upa_writel(ctx->drawop, &ffb->drawop);
232 
233 	/* If we were restoring the vertex registers, this is where
234 	 * we would do it.  We would restore 32 32-bit words starting
235 	 * at ffb->suvtx.
236 	 */
237 
238 	/* Restore rendering attributes. */
239 
240 	upa_writel(ctx->ppc, &ffb->ppc);		/* Pixel Processor Control */
241 	upa_writel(ctx->wid, &ffb->wid);		/* Current WID */
242 	upa_writel(ctx->fg, &ffb->fg);			/* Constant FG color */
243 	upa_writel(ctx->bg, &ffb->bg);			/* Constant BG color */
244 	upa_writel(ctx->consty, &ffb->consty);		/* Constant Y */
245 	upa_writel(ctx->constz, &ffb->constz);		/* Constant Z */
246 	upa_writel(ctx->xclip, &ffb->xclip);		/* X plane clip */
247 	upa_writel(ctx->dcss, &ffb->dcss);		/* Depth Cue Scale Slope */
248 	upa_writel(ctx->vclipmin, &ffb->vclipmin);	/* Primary XY clip, minimum */
249 	upa_writel(ctx->vclipmax, &ffb->vclipmax);	/* Primary XY clip, maximum */
250 	upa_writel(ctx->vclipzmin, &ffb->vclipzmin);	/* Primary Z clip, minimum */
251 	upa_writel(ctx->vclipzmax, &ffb->vclipzmax);	/* Primary Z clip, maximum */
252 	upa_writel(ctx->dcsf, &ffb->dcsf);		/* Depth Cue Scale Front Bound */
253 	upa_writel(ctx->dcsb, &ffb->dcsb);		/* Depth Cue Scale Back Bound */
254 	upa_writel(ctx->dczf, &ffb->dczf);		/* Depth Cue Scale Z Front */
255 	upa_writel(ctx->dczb, &ffb->dczb);		/* Depth Cue Scale Z Back */
256 	upa_writel(ctx->blendc, &ffb->blendc);		/* Alpha Blend Control */
257 	upa_writel(ctx->blendc1, &ffb->blendc1);	/* Alpha Blend Color 1 */
258 	upa_writel(ctx->blendc2, &ffb->blendc2);	/* Alpha Blend Color 2 */
259 	upa_writel(ctx->fbc, &ffb->fbc);		/* Frame Buffer Control */
260 	upa_writel(ctx->rop, &ffb->rop);		/* Raster Operation */
261 	upa_writel(ctx->cmp, &ffb->cmp);		/* Compare Controls */
262 	upa_writel(ctx->matchab, &ffb->matchab);	/* Buffer A/B Match Ops */
263 	upa_writel(ctx->matchc, &ffb->matchc);		/* Buffer C Match Ops */
264 	upa_writel(ctx->magnab, &ffb->magnab);		/* Buffer A/B Magnitude Ops */
265 	upa_writel(ctx->magnc, &ffb->magnc);		/* Buffer C Magnitude Ops */
266 	upa_writel(ctx->pmask, &ffb->pmask);		/* RGB Plane Mask */
267 	upa_writel(ctx->xpmask, &ffb->xpmask);		/* X Plane Mask */
268 	upa_writel(ctx->ypmask, &ffb->ypmask);		/* Y Plane Mask */
269 	upa_writel(ctx->zpmask, &ffb->zpmask);		/* Z Plane Mask */
270 
271 	/* Auxiliary Clips. */
272 	upa_writel(ctx->auxclip0min, &ffb->auxclip[0].min);
273 	upa_writel(ctx->auxclip0max, &ffb->auxclip[0].max);
274 	upa_writel(ctx->auxclip1min, &ffb->auxclip[1].min);
275 	upa_writel(ctx->auxclip1max, &ffb->auxclip[1].max);
276 	upa_writel(ctx->auxclip2min, &ffb->auxclip[2].min);
277 	upa_writel(ctx->auxclip2max, &ffb->auxclip[2].max);
278 	upa_writel(ctx->auxclip3min, &ffb->auxclip[3].min);
279 	upa_writel(ctx->auxclip3max, &ffb->auxclip[3].max);
280 
281 	upa_writel(ctx->lpat, &ffb->lpat);		/* Line Pattern */
282 	upa_writel(ctx->fontxy, &ffb->fontxy);		/* XY Font Coordinate */
283 	upa_writel(ctx->fontw, &ffb->fontw);		/* Font Width */
284 	upa_writel(ctx->fontinc, &ffb->fontinc);	/* Font X/Y Increment */
285 
286 	/* These registers/features only exist on FFB2 and later chips. */
287 	if (fpriv->ffb_type >= ffb2_prototype) {
288 		upa_writel(ctx->dcss1, &ffb->dcss1);	/* Depth Cue Scale Slope 1 */
289 		upa_writel(ctx->dcss2, &ffb->dcss2);	/* Depth Cue Scale Slope 2 */
290 		upa_writel(ctx->dcss3, &ffb->dcss2);	/* Depth Cue Scale Slope 3 */
291 		upa_writel(ctx->dcs2, &ffb->dcs2);	/* Depth Cue Scale 2 */
292 		upa_writel(ctx->dcs3, &ffb->dcs3);	/* Depth Cue Scale 3 */
293 		upa_writel(ctx->dcs4, &ffb->dcs4);	/* Depth Cue Scale 4 */
294 		upa_writel(ctx->dcd2, &ffb->dcd2);	/* Depth Cue Depth 2 */
295 		upa_writel(ctx->dcd3, &ffb->dcd3);	/* Depth Cue Depth 3 */
296 		upa_writel(ctx->dcd4, &ffb->dcd4);	/* Depth Cue Depth 4 */
297 
298 		/* And stencil/stencilctl only exists on FFB2+ and later
299 		 * due to the introduction of 3DRAM-III.
300 		 */
301 		if (fpriv->ffb_type == ffb2_vertical_plus ||
302 		    fpriv->ffb_type == ffb2_horizontal_plus) {
303 			/* Unfortunately, there is a hardware bug on
304 			 * the FFB2+ chips which prevents a normal write
305 			 * to the stencil control register from working
306 			 * as it should.
307 			 *
308 			 * The state controlled by the FFB stencilctl register
309 			 * really gets transferred to the per-buffer instances
310 			 * of the stencilctl register in the 3DRAM chips.
311 			 *
312 			 * The bug is that FFB does not update buffer C correctly,
313 			 * so we have to do it by hand for them.
314 			 */
315 
316 			/* This will update buffers A and B. */
317 			upa_writel(ctx->stencil, &ffb->stencil);
318 			upa_writel(ctx->stencilctl, &ffb->stencilctl);
319 
320 			/* Force FFB to use buffer C 3dram regs. */
321 			upa_writel(0x80000000, &ffb->fbc);
322 			upa_writel((ctx->stencilctl | 0x80000),
323 				   &ffb->rawstencilctl);
324 
325 			/* Now restore the correct FBC controls. */
326 			upa_writel(ctx->fbc, &ffb->fbc);
327 		}
328 	}
329 
330 	/* Restore the 32x32 area pattern. */
331 	for (i = 0; i < 32; i++)
332 		upa_writel(ctx->area_pattern[i], &ffb->pattern[i]);
333 
334 	/* Finally, stash away the User Constol/Status Register.
335 	 * The only state we really preserve here is the picking
336 	 * control.
337 	 */
338 	upa_writel((ctx->ucsr & 0xf0000), &ffb->ucsr);
339 }
340 
341 #define FFB_UCSR_FB_BUSY       0x01000000
342 #define FFB_UCSR_RP_BUSY       0x02000000
343 #define FFB_UCSR_ALL_BUSY      (FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY)
344 
FFBWait(ffb_fbcPtr ffb)345 static void FFBWait(ffb_fbcPtr ffb)
346 {
347 	int limit = 100000;
348 
349 	do {
350 		u32 regval = upa_readl(&ffb->ucsr);
351 
352 		if ((regval & FFB_UCSR_ALL_BUSY) == 0)
353 			break;
354 	} while (--limit);
355 }
356 
DRM(context_switch)357 int DRM(context_switch)(drm_device_t *dev, int old, int new)
358 {
359 	ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
360 
361 #if DRM_DMA_HISTOGRAM
362         dev->ctx_start = get_cycles();
363 #endif
364 
365         DRM_DEBUG("Context switch from %d to %d\n", old, new);
366 
367         if (new == dev->last_context ||
368 	    dev->last_context == 0) {
369 		dev->last_context = new;
370                 return 0;
371 	}
372 
373 	FFBWait(fpriv->regs);
374 	ffb_save_context(fpriv, old);
375 	ffb_restore_context(fpriv, old, new);
376 	FFBWait(fpriv->regs);
377 
378 	dev->last_context = new;
379 
380         return 0;
381 }
382 
DRM(resctx)383 int DRM(resctx)(struct inode *inode, struct file *filp, unsigned int cmd,
384 		unsigned long arg)
385 {
386 	drm_ctx_res_t	res;
387 	drm_ctx_t	ctx;
388 	int		i;
389 
390 	DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
391 	if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res)))
392 		return -EFAULT;
393 	if (res.count >= DRM_RESERVED_CONTEXTS) {
394 		memset(&ctx, 0, sizeof(ctx));
395 		for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
396 			ctx.handle = i;
397 			if (copy_to_user(&res.contexts[i],
398 					 &i,
399 					 sizeof(i)))
400 				return -EFAULT;
401 		}
402 	}
403 	res.count = DRM_RESERVED_CONTEXTS;
404 	if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res)))
405 		return -EFAULT;
406 	return 0;
407 }
408 
409 
DRM(addctx)410 int DRM(addctx)(struct inode *inode, struct file *filp, unsigned int cmd,
411 		unsigned long arg)
412 {
413 	drm_file_t	*priv	= filp->private_data;
414 	drm_device_t	*dev	= priv->dev;
415 	drm_ctx_t	ctx;
416 	int idx;
417 
418 	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
419 		return -EFAULT;
420 	idx = DRM(alloc_queue)(dev, (ctx.flags & _DRM_CONTEXT_2DONLY));
421 	if (idx < 0)
422 		return -ENFILE;
423 
424 	DRM_DEBUG("%d\n", ctx.handle);
425 	ctx.handle = idx;
426 	if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
427 		return -EFAULT;
428 	return 0;
429 }
430 
DRM(modctx)431 int DRM(modctx)(struct inode *inode, struct file *filp, unsigned int cmd,
432 		unsigned long arg)
433 {
434 	drm_file_t	*priv	= filp->private_data;
435 	drm_device_t	*dev	= priv->dev;
436 	ffb_dev_priv_t	*fpriv	= (ffb_dev_priv_t *) dev->dev_private;
437 	struct ffb_hw_context *hwctx;
438 	drm_ctx_t ctx;
439 	int idx;
440 
441 	if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
442 		return -EFAULT;
443 
444 	idx = ctx.handle;
445 	if (idx <= 0 || idx >= FFB_MAX_CTXS)
446 		return -EINVAL;
447 
448 	hwctx = fpriv->hw_state[idx - 1];
449 	if (hwctx == NULL)
450 		return -EINVAL;
451 
452 	if ((ctx.flags & _DRM_CONTEXT_2DONLY) == 0)
453 		hwctx->is_2d_only = 0;
454 	else
455 		hwctx->is_2d_only = 1;
456 
457 	return 0;
458 }
459 
DRM(getctx)460 int DRM(getctx)(struct inode *inode, struct file *filp, unsigned int cmd,
461 		unsigned long arg)
462 {
463 	drm_file_t	*priv	= filp->private_data;
464 	drm_device_t	*dev	= priv->dev;
465 	ffb_dev_priv_t	*fpriv	= (ffb_dev_priv_t *) dev->dev_private;
466 	struct ffb_hw_context *hwctx;
467 	drm_ctx_t ctx;
468 	int idx;
469 
470 	if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
471 		return -EFAULT;
472 
473 	idx = ctx.handle;
474 	if (idx <= 0 || idx >= FFB_MAX_CTXS)
475 		return -EINVAL;
476 
477 	hwctx = fpriv->hw_state[idx - 1];
478 	if (hwctx == NULL)
479 		return -EINVAL;
480 
481 	if (hwctx->is_2d_only != 0)
482 		ctx.flags = _DRM_CONTEXT_2DONLY;
483 	else
484 		ctx.flags = 0;
485 
486 	if (copy_to_user((drm_ctx_t*)arg, &ctx, sizeof(ctx)))
487 		return -EFAULT;
488 
489 	return 0;
490 }
491 
DRM(switchctx)492 int DRM(switchctx)(struct inode *inode, struct file *filp, unsigned int cmd,
493 		   unsigned long arg)
494 {
495 	drm_file_t	*priv	= filp->private_data;
496 	drm_device_t	*dev	= priv->dev;
497 	drm_ctx_t	ctx;
498 
499 	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
500 		return -EFAULT;
501 	DRM_DEBUG("%d\n", ctx.handle);
502 	return DRM(context_switch)(dev, dev->last_context, ctx.handle);
503 }
504 
DRM(newctx)505 int DRM(newctx)(struct inode *inode, struct file *filp, unsigned int cmd,
506 		unsigned long arg)
507 {
508 	drm_ctx_t	ctx;
509 
510 	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
511 		return -EFAULT;
512 	DRM_DEBUG("%d\n", ctx.handle);
513 
514 	return 0;
515 }
516 
DRM(rmctx)517 int DRM(rmctx)(struct inode *inode, struct file *filp, unsigned int cmd,
518 	       unsigned long arg)
519 {
520 	drm_ctx_t	ctx;
521 	drm_file_t	*priv	= filp->private_data;
522 	drm_device_t	*dev	= priv->dev;
523 	ffb_dev_priv_t	*fpriv	= (ffb_dev_priv_t *) dev->dev_private;
524 	int idx;
525 
526 	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
527 		return -EFAULT;
528 	DRM_DEBUG("%d\n", ctx.handle);
529 
530 	idx = ctx.handle - 1;
531 	if (idx < 0 || idx >= FFB_MAX_CTXS)
532 		return -EINVAL;
533 
534 	if (fpriv->hw_state[idx] != NULL) {
535 		kfree(fpriv->hw_state[idx]);
536 		fpriv->hw_state[idx] = NULL;
537 	}
538 	return 0;
539 }
540