at v2.6.17 545 lines 18 kB view raw
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 18static int DRM(alloc_queue) (drm_device_t * dev, int is_2d_only) { 19 ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private; 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 39static 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 172static 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 344static 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 356int ffb_driver_context_switch(drm_device_t * dev, int old, int new) 357{ 358 ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private; 359 360#ifdef DRM_DMA_HISTOGRAM 361 dev->ctx_start = get_cycles(); 362#endif 363 364 DRM_DEBUG("Context switch from %d to %d\n", old, new); 365 366 if (new == dev->last_context || dev->last_context == 0) { 367 dev->last_context = new; 368 return 0; 369 } 370 371 FFBWait(fpriv->regs); 372 ffb_save_context(fpriv, old); 373 ffb_restore_context(fpriv, old, new); 374 FFBWait(fpriv->regs); 375 376 dev->last_context = new; 377 378 return 0; 379} 380 381int ffb_driver_resctx(struct inode *inode, struct file *filp, unsigned int cmd, 382 unsigned long arg) 383{ 384 drm_ctx_res_t res; 385 drm_ctx_t ctx; 386 int i; 387 388 DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS); 389 if (copy_from_user(&res, (drm_ctx_res_t __user *) arg, sizeof(res))) 390 return -EFAULT; 391 if (res.count >= DRM_RESERVED_CONTEXTS) { 392 memset(&ctx, 0, sizeof(ctx)); 393 for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { 394 ctx.handle = i; 395 if (copy_to_user(&res.contexts[i], &i, sizeof(i))) 396 return -EFAULT; 397 } 398 } 399 res.count = DRM_RESERVED_CONTEXTS; 400 if (copy_to_user((drm_ctx_res_t __user *) arg, &res, sizeof(res))) 401 return -EFAULT; 402 return 0; 403} 404 405int ffb_driver_addctx(struct inode *inode, struct file *filp, unsigned int cmd, 406 unsigned long arg) 407{ 408 drm_file_t *priv = filp->private_data; 409 drm_device_t *dev = priv->dev; 410 drm_ctx_t ctx; 411 int idx; 412 413 if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx))) 414 return -EFAULT; 415 idx = DRM(alloc_queue) (dev, (ctx.flags & _DRM_CONTEXT_2DONLY)); 416 if (idx < 0) 417 return -ENFILE; 418 419 DRM_DEBUG("%d\n", ctx.handle); 420 ctx.handle = idx; 421 if (copy_to_user((drm_ctx_t __user *) arg, &ctx, sizeof(ctx))) 422 return -EFAULT; 423 return 0; 424} 425 426int ffb_driver_modctx(struct inode *inode, struct file *filp, unsigned int cmd, 427 unsigned long arg) 428{ 429 drm_file_t *priv = filp->private_data; 430 drm_device_t *dev = priv->dev; 431 ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private; 432 struct ffb_hw_context *hwctx; 433 drm_ctx_t ctx; 434 int idx; 435 436 if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx))) 437 return -EFAULT; 438 439 idx = ctx.handle; 440 if (idx <= 0 || idx >= FFB_MAX_CTXS) 441 return -EINVAL; 442 443 hwctx = fpriv->hw_state[idx - 1]; 444 if (hwctx == NULL) 445 return -EINVAL; 446 447 if ((ctx.flags & _DRM_CONTEXT_2DONLY) == 0) 448 hwctx->is_2d_only = 0; 449 else 450 hwctx->is_2d_only = 1; 451 452 return 0; 453} 454 455int ffb_driver_getctx(struct inode *inode, struct file *filp, unsigned int cmd, 456 unsigned long arg) 457{ 458 drm_file_t *priv = filp->private_data; 459 drm_device_t *dev = priv->dev; 460 ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private; 461 struct ffb_hw_context *hwctx; 462 drm_ctx_t ctx; 463 int idx; 464 465 if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx))) 466 return -EFAULT; 467 468 idx = ctx.handle; 469 if (idx <= 0 || idx >= FFB_MAX_CTXS) 470 return -EINVAL; 471 472 hwctx = fpriv->hw_state[idx - 1]; 473 if (hwctx == NULL) 474 return -EINVAL; 475 476 if (hwctx->is_2d_only != 0) 477 ctx.flags = _DRM_CONTEXT_2DONLY; 478 else 479 ctx.flags = 0; 480 481 if (copy_to_user((drm_ctx_t __user *) arg, &ctx, sizeof(ctx))) 482 return -EFAULT; 483 484 return 0; 485} 486 487int ffb_driver_switchctx(struct inode *inode, struct file *filp, 488 unsigned int cmd, unsigned long arg) 489{ 490 drm_file_t *priv = filp->private_data; 491 drm_device_t *dev = priv->dev; 492 drm_ctx_t ctx; 493 494 if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx))) 495 return -EFAULT; 496 DRM_DEBUG("%d\n", ctx.handle); 497 return ffb_driver_context_switch(dev, dev->last_context, ctx.handle); 498} 499 500int ffb_driver_newctx(struct inode *inode, struct file *filp, unsigned int cmd, 501 unsigned long arg) 502{ 503 drm_ctx_t ctx; 504 505 if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx))) 506 return -EFAULT; 507 DRM_DEBUG("%d\n", ctx.handle); 508 509 return 0; 510} 511 512int ffb_driver_rmctx(struct inode *inode, struct file *filp, unsigned int cmd, 513 unsigned long arg) 514{ 515 drm_ctx_t ctx; 516 drm_file_t *priv = filp->private_data; 517 drm_device_t *dev = priv->dev; 518 ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private; 519 int idx; 520 521 if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx))) 522 return -EFAULT; 523 DRM_DEBUG("%d\n", ctx.handle); 524 525 idx = ctx.handle - 1; 526 if (idx < 0 || idx >= FFB_MAX_CTXS) 527 return -EINVAL; 528 529 kfree(fpriv->hw_state[idx]); 530 fpriv->hw_state[idx] = NULL; 531 return 0; 532} 533 534void ffb_set_context_ioctls(void) 535{ 536 DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)].func = ffb_driver_addctx; 537 DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)].func = ffb_driver_rmctx; 538 DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)].func = ffb_driver_modctx; 539 DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)].func = ffb_driver_getctx; 540 DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)].func = 541 ffb_driver_switchctx; 542 DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)].func = ffb_driver_newctx; 543 DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)].func = ffb_driver_resctx; 544 545}