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