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