linux/drivers/gpu/drm/mga/mga_state.c
<<
>>
Prefs
   1/* mga_state.c -- State support for MGA G200/G400 -*- linux-c -*-
   2 * Created: Thu Jan 27 02:53:43 2000 by jhartmann@precisioninsight.com
   3 *
   4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
   5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
   6 * All Rights Reserved.
   7 *
   8 * Permission is hereby granted, free of charge, to any person obtaining a
   9 * copy of this software and associated documentation files (the "Software"),
  10 * to deal in the Software without restriction, including without limitation
  11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  12 * and/or sell copies of the Software, and to permit persons to whom the
  13 * Software is furnished to do so, subject to the following conditions:
  14 *
  15 * The above copyright notice and this permission notice (including the next
  16 * paragraph) shall be included in all copies or substantial portions of the
  17 * Software.
  18 *
  19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  25 * OTHER DEALINGS IN THE SOFTWARE.
  26 *
  27 * Authors:
  28 *    Jeff Hartmann <jhartmann@valinux.com>
  29 *    Keith Whitwell <keith@tungstengraphics.com>
  30 *
  31 * Rewritten by:
  32 *    Gareth Hughes <gareth@valinux.com>
  33 */
  34
  35#include "drmP.h"
  36#include "drm.h"
  37#include "mga_drm.h"
  38#include "mga_drv.h"
  39
  40/* ================================================================
  41 * DMA hardware state programming functions
  42 */
  43
  44static void mga_emit_clip_rect(drm_mga_private_t *dev_priv,
  45                               struct drm_clip_rect *box)
  46{
  47        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  48        drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
  49        unsigned int pitch = dev_priv->front_pitch;
  50        DMA_LOCALS;
  51
  52        BEGIN_DMA(2);
  53
  54        /* Force reset of DWGCTL on G400 (eliminates clip disable bit).
  55         */
  56        if (dev_priv->chipset >= MGA_CARD_TYPE_G400) {
  57                DMA_BLOCK(MGA_DWGCTL, ctx->dwgctl,
  58                          MGA_LEN + MGA_EXEC, 0x80000000,
  59                          MGA_DWGCTL, ctx->dwgctl,
  60                          MGA_LEN + MGA_EXEC, 0x80000000);
  61        }
  62        DMA_BLOCK(MGA_DMAPAD, 0x00000000,
  63                  MGA_CXBNDRY, ((box->x2 - 1) << 16) | box->x1,
  64                  MGA_YTOP, box->y1 * pitch, MGA_YBOT, (box->y2 - 1) * pitch);
  65
  66        ADVANCE_DMA();
  67}
  68
  69static __inline__ void mga_g200_emit_context(drm_mga_private_t *dev_priv)
  70{
  71        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  72        drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
  73        DMA_LOCALS;
  74
  75        BEGIN_DMA(3);
  76
  77        DMA_BLOCK(MGA_DSTORG, ctx->dstorg,
  78                  MGA_MACCESS, ctx->maccess,
  79                  MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl);
  80
  81        DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl,
  82                  MGA_FOGCOL, ctx->fogcolor,
  83                  MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset);
  84
  85        DMA_BLOCK(MGA_FCOL, ctx->fcol,
  86                  MGA_DMAPAD, 0x00000000,
  87                  MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
  88
  89        ADVANCE_DMA();
  90}
  91
  92static __inline__ void mga_g400_emit_context(drm_mga_private_t *dev_priv)
  93{
  94        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  95        drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
  96        DMA_LOCALS;
  97
  98        BEGIN_DMA(4);
  99
 100        DMA_BLOCK(MGA_DSTORG, ctx->dstorg,
 101                  MGA_MACCESS, ctx->maccess,
 102                  MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl);
 103
 104        DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl,
 105                  MGA_FOGCOL, ctx->fogcolor,
 106                  MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset);
 107
 108        DMA_BLOCK(MGA_WFLAG1, ctx->wflag,
 109                  MGA_TDUALSTAGE0, ctx->tdualstage0,
 110                  MGA_TDUALSTAGE1, ctx->tdualstage1, MGA_FCOL, ctx->fcol);
 111
 112        DMA_BLOCK(MGA_STENCIL, ctx->stencil,
 113                  MGA_STENCILCTL, ctx->stencilctl,
 114                  MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
 115
 116        ADVANCE_DMA();
 117}
 118
 119static __inline__ void mga_g200_emit_tex0(drm_mga_private_t *dev_priv)
 120{
 121        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 122        drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
 123        DMA_LOCALS;
 124
 125        BEGIN_DMA(4);
 126
 127        DMA_BLOCK(MGA_TEXCTL2, tex->texctl2,
 128                  MGA_TEXCTL, tex->texctl,
 129                  MGA_TEXFILTER, tex->texfilter,
 130                  MGA_TEXBORDERCOL, tex->texbordercol);
 131
 132        DMA_BLOCK(MGA_TEXORG, tex->texorg,
 133                  MGA_TEXORG1, tex->texorg1,
 134                  MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3);
 135
 136        DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
 137                  MGA_TEXWIDTH, tex->texwidth,
 138                  MGA_TEXHEIGHT, tex->texheight, MGA_WR24, tex->texwidth);
 139
 140        DMA_BLOCK(MGA_WR34, tex->texheight,
 141                  MGA_TEXTRANS, 0x0000ffff,
 142                  MGA_TEXTRANSHIGH, 0x0000ffff, MGA_DMAPAD, 0x00000000);
 143
 144        ADVANCE_DMA();
 145}
 146
 147static __inline__ void mga_g400_emit_tex0(drm_mga_private_t *dev_priv)
 148{
 149        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 150        drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
 151        DMA_LOCALS;
 152
 153/*      printk("mga_g400_emit_tex0 %x %x %x\n", tex->texorg, */
 154/*             tex->texctl, tex->texctl2); */
 155
 156        BEGIN_DMA(6);
 157
 158        DMA_BLOCK(MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC,
 159                  MGA_TEXCTL, tex->texctl,
 160                  MGA_TEXFILTER, tex->texfilter,
 161                  MGA_TEXBORDERCOL, tex->texbordercol);
 162
 163        DMA_BLOCK(MGA_TEXORG, tex->texorg,
 164                  MGA_TEXORG1, tex->texorg1,
 165                  MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3);
 166
 167        DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
 168                  MGA_TEXWIDTH, tex->texwidth,
 169                  MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000);
 170
 171        DMA_BLOCK(MGA_WR57, 0x00000000,
 172                  MGA_WR53, 0x00000000,
 173                  MGA_WR61, 0x00000000, MGA_WR52, MGA_G400_WR_MAGIC);
 174
 175        DMA_BLOCK(MGA_WR60, MGA_G400_WR_MAGIC,
 176                  MGA_WR54, tex->texwidth | MGA_G400_WR_MAGIC,
 177                  MGA_WR62, tex->texheight | MGA_G400_WR_MAGIC,
 178                  MGA_DMAPAD, 0x00000000);
 179
 180        DMA_BLOCK(MGA_DMAPAD, 0x00000000,
 181                  MGA_DMAPAD, 0x00000000,
 182                  MGA_TEXTRANS, 0x0000ffff, MGA_TEXTRANSHIGH, 0x0000ffff);
 183
 184        ADVANCE_DMA();
 185}
 186
 187static __inline__ void mga_g400_emit_tex1(drm_mga_private_t *dev_priv)
 188{
 189        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 190        drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1];
 191        DMA_LOCALS;
 192
 193/*      printk("mga_g400_emit_tex1 %x %x %x\n", tex->texorg,  */
 194/*             tex->texctl, tex->texctl2); */
 195
 196        BEGIN_DMA(5);
 197
 198        DMA_BLOCK(MGA_TEXCTL2, (tex->texctl2 |
 199                                MGA_MAP1_ENABLE |
 200                                MGA_G400_TC2_MAGIC),
 201                  MGA_TEXCTL, tex->texctl,
 202                  MGA_TEXFILTER, tex->texfilter,
 203                  MGA_TEXBORDERCOL, tex->texbordercol);
 204
 205        DMA_BLOCK(MGA_TEXORG, tex->texorg,
 206                  MGA_TEXORG1, tex->texorg1,
 207                  MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3);
 208
 209        DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
 210                  MGA_TEXWIDTH, tex->texwidth,
 211                  MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000);
 212
 213        DMA_BLOCK(MGA_WR57, 0x00000000,
 214                  MGA_WR53, 0x00000000,
 215                  MGA_WR61, 0x00000000,
 216                  MGA_WR52, tex->texwidth | MGA_G400_WR_MAGIC);
 217
 218        DMA_BLOCK(MGA_WR60, tex->texheight | MGA_G400_WR_MAGIC,
 219                  MGA_TEXTRANS, 0x0000ffff,
 220                  MGA_TEXTRANSHIGH, 0x0000ffff,
 221                  MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC);
 222
 223        ADVANCE_DMA();
 224}
 225
 226static __inline__ void mga_g200_emit_pipe(drm_mga_private_t *dev_priv)
 227{
 228        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 229        unsigned int pipe = sarea_priv->warp_pipe;
 230        DMA_LOCALS;
 231
 232        BEGIN_DMA(3);
 233
 234        DMA_BLOCK(MGA_WIADDR, MGA_WMODE_SUSPEND,
 235                  MGA_WVRTXSZ, 0x00000007,
 236                  MGA_WFLAG, 0x00000000, MGA_WR24, 0x00000000);
 237
 238        DMA_BLOCK(MGA_WR25, 0x00000100,
 239                  MGA_WR34, 0x00000000,
 240                  MGA_WR42, 0x0000ffff, MGA_WR60, 0x0000ffff);
 241
 242        /* Padding required due to hardware bug.
 243         */
 244        DMA_BLOCK(MGA_DMAPAD, 0xffffffff,
 245                  MGA_DMAPAD, 0xffffffff,
 246                  MGA_DMAPAD, 0xffffffff,
 247                  MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] |
 248                               MGA_WMODE_START | dev_priv->wagp_enable));
 249
 250        ADVANCE_DMA();
 251}
 252
 253static __inline__ void mga_g400_emit_pipe(drm_mga_private_t *dev_priv)
 254{
 255        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 256        unsigned int pipe = sarea_priv->warp_pipe;
 257        DMA_LOCALS;
 258
 259/*      printk("mga_g400_emit_pipe %x\n", pipe); */
 260
 261        BEGIN_DMA(10);
 262
 263        DMA_BLOCK(MGA_WIADDR2, MGA_WMODE_SUSPEND,
 264                  MGA_DMAPAD, 0x00000000,
 265                  MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
 266
 267        if (pipe & MGA_T2) {
 268                DMA_BLOCK(MGA_WVRTXSZ, 0x00001e09,
 269                          MGA_DMAPAD, 0x00000000,
 270                          MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
 271
 272                DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000,
 273                          MGA_WACCEPTSEQ, 0x00000000,
 274                          MGA_WACCEPTSEQ, 0x00000000,
 275                          MGA_WACCEPTSEQ, 0x1e000000);
 276        } else {
 277                if (dev_priv->warp_pipe & MGA_T2) {
 278                        /* Flush the WARP pipe */
 279                        DMA_BLOCK(MGA_YDST, 0x00000000,
 280                                  MGA_FXLEFT, 0x00000000,
 281                                  MGA_FXRIGHT, 0x00000001,
 282                                  MGA_DWGCTL, MGA_DWGCTL_FLUSH);
 283
 284                        DMA_BLOCK(MGA_LEN + MGA_EXEC, 0x00000001,
 285                                  MGA_DWGSYNC, 0x00007000,
 286                                  MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
 287                                  MGA_LEN + MGA_EXEC, 0x00000000);
 288
 289                        DMA_BLOCK(MGA_TEXCTL2, (MGA_DUALTEX |
 290                                                MGA_G400_TC2_MAGIC),
 291                                  MGA_LEN + MGA_EXEC, 0x00000000,
 292                                  MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
 293                                  MGA_DMAPAD, 0x00000000);
 294                }
 295
 296                DMA_BLOCK(MGA_WVRTXSZ, 0x00001807,
 297                          MGA_DMAPAD, 0x00000000,
 298                          MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
 299
 300                DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000,
 301                          MGA_WACCEPTSEQ, 0x00000000,
 302                          MGA_WACCEPTSEQ, 0x00000000,
 303                          MGA_WACCEPTSEQ, 0x18000000);
 304        }
 305
 306        DMA_BLOCK(MGA_WFLAG, 0x00000000,
 307                  MGA_WFLAG1, 0x00000000,
 308                  MGA_WR56, MGA_G400_WR56_MAGIC, MGA_DMAPAD, 0x00000000);
 309
 310        DMA_BLOCK(MGA_WR49, 0x00000000, /* tex0              */
 311                  MGA_WR57, 0x00000000, /* tex0              */
 312                  MGA_WR53, 0x00000000, /* tex1              */
 313                  MGA_WR61, 0x00000000);        /* tex1              */
 314
 315        DMA_BLOCK(MGA_WR54, MGA_G400_WR_MAGIC,  /* tex0 width        */
 316                  MGA_WR62, MGA_G400_WR_MAGIC,  /* tex0 height       */
 317                  MGA_WR52, MGA_G400_WR_MAGIC,  /* tex1 width        */
 318                  MGA_WR60, MGA_G400_WR_MAGIC); /* tex1 height       */
 319
 320        /* Padding required due to hardware bug */
 321        DMA_BLOCK(MGA_DMAPAD, 0xffffffff,
 322                  MGA_DMAPAD, 0xffffffff,
 323                  MGA_DMAPAD, 0xffffffff,
 324                  MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] |
 325                                MGA_WMODE_START | dev_priv->wagp_enable));
 326
 327        ADVANCE_DMA();
 328}
 329
 330static void mga_g200_emit_state(drm_mga_private_t *dev_priv)
 331{
 332        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 333        unsigned int dirty = sarea_priv->dirty;
 334
 335        if (sarea_priv->warp_pipe != dev_priv->warp_pipe) {
 336                mga_g200_emit_pipe(dev_priv);
 337                dev_priv->warp_pipe = sarea_priv->warp_pipe;
 338        }
 339
 340        if (dirty & MGA_UPLOAD_CONTEXT) {
 341                mga_g200_emit_context(dev_priv);
 342                sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
 343        }
 344
 345        if (dirty & MGA_UPLOAD_TEX0) {
 346                mga_g200_emit_tex0(dev_priv);
 347                sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
 348        }
 349}
 350
 351static void mga_g400_emit_state(drm_mga_private_t *dev_priv)
 352{
 353        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 354        unsigned int dirty = sarea_priv->dirty;
 355        int multitex = sarea_priv->warp_pipe & MGA_T2;
 356
 357        if (sarea_priv->warp_pipe != dev_priv->warp_pipe) {
 358                mga_g400_emit_pipe(dev_priv);
 359                dev_priv->warp_pipe = sarea_priv->warp_pipe;
 360        }
 361
 362        if (dirty & MGA_UPLOAD_CONTEXT) {
 363                mga_g400_emit_context(dev_priv);
 364                sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
 365        }
 366
 367        if (dirty & MGA_UPLOAD_TEX0) {
 368                mga_g400_emit_tex0(dev_priv);
 369                sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
 370        }
 371
 372        if ((dirty & MGA_UPLOAD_TEX1) && multitex) {
 373                mga_g400_emit_tex1(dev_priv);
 374                sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
 375        }
 376}
 377
 378/* ================================================================
 379 * SAREA state verification
 380 */
 381
 382/* Disallow all write destinations except the front and backbuffer.
 383 */
 384static int mga_verify_context(drm_mga_private_t *dev_priv)
 385{
 386        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 387        drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
 388
 389        if (ctx->dstorg != dev_priv->front_offset &&
 390            ctx->dstorg != dev_priv->back_offset) {
 391                DRM_ERROR("*** bad DSTORG: %x (front %x, back %x)\n\n",
 392                          ctx->dstorg, dev_priv->front_offset,
 393                          dev_priv->back_offset);
 394                ctx->dstorg = 0;
 395                return -EINVAL;
 396        }
 397
 398        return 0;
 399}
 400
 401/* Disallow texture reads from PCI space.
 402 */
 403static int mga_verify_tex(drm_mga_private_t *dev_priv, int unit)
 404{
 405        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 406        drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit];
 407        unsigned int org;
 408
 409        org = tex->texorg & (MGA_TEXORGMAP_MASK | MGA_TEXORGACC_MASK);
 410
 411        if (org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI)) {
 412                DRM_ERROR("*** bad TEXORG: 0x%x, unit %d\n", tex->texorg, unit);
 413                tex->texorg = 0;
 414                return -EINVAL;
 415        }
 416
 417        return 0;
 418}
 419
 420static int mga_verify_state(drm_mga_private_t *dev_priv)
 421{
 422        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 423        unsigned int dirty = sarea_priv->dirty;
 424        int ret = 0;
 425
 426        if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
 427                sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
 428
 429        if (dirty & MGA_UPLOAD_CONTEXT)
 430                ret |= mga_verify_context(dev_priv);
 431
 432        if (dirty & MGA_UPLOAD_TEX0)
 433                ret |= mga_verify_tex(dev_priv, 0);
 434
 435        if (dev_priv->chipset >= MGA_CARD_TYPE_G400) {
 436                if (dirty & MGA_UPLOAD_TEX1)
 437                        ret |= mga_verify_tex(dev_priv, 1);
 438
 439                if (dirty & MGA_UPLOAD_PIPE)
 440                        ret |= (sarea_priv->warp_pipe > MGA_MAX_G400_PIPES);
 441        } else {
 442                if (dirty & MGA_UPLOAD_PIPE)
 443                        ret |= (sarea_priv->warp_pipe > MGA_MAX_G200_PIPES);
 444        }
 445
 446        return (ret == 0);
 447}
 448
 449static int mga_verify_iload(drm_mga_private_t *dev_priv,
 450                            unsigned int dstorg, unsigned int length)
 451{
 452        if (dstorg < dev_priv->texture_offset ||
 453            dstorg + length > (dev_priv->texture_offset +
 454                               dev_priv->texture_size)) {
 455                DRM_ERROR("*** bad iload DSTORG: 0x%x\n", dstorg);
 456                return -EINVAL;
 457        }
 458
 459        if (length & MGA_ILOAD_MASK) {
 460                DRM_ERROR("*** bad iload length: 0x%x\n",
 461                          length & MGA_ILOAD_MASK);
 462                return -EINVAL;
 463        }
 464
 465        return 0;
 466}
 467
 468static int mga_verify_blit(drm_mga_private_t *dev_priv,
 469                           unsigned int srcorg, unsigned int dstorg)
 470{
 471        if ((srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ||
 472            (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM)) {
 473                DRM_ERROR("*** bad blit: src=0x%x dst=0x%x\n", srcorg, dstorg);
 474                return -EINVAL;
 475        }
 476        return 0;
 477}
 478
 479/* ================================================================
 480 *
 481 */
 482
 483static void mga_dma_dispatch_clear(struct drm_device *dev, drm_mga_clear_t *clear)
 484{
 485        drm_mga_private_t *dev_priv = dev->dev_private;
 486        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 487        drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
 488        struct drm_clip_rect *pbox = sarea_priv->boxes;
 489        int nbox = sarea_priv->nbox;
 490        int i;
 491        DMA_LOCALS;
 492        DRM_DEBUG("\n");
 493
 494        BEGIN_DMA(1);
 495
 496        DMA_BLOCK(MGA_DMAPAD, 0x00000000,
 497                  MGA_DMAPAD, 0x00000000,
 498                  MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
 499
 500        ADVANCE_DMA();
 501
 502        for (i = 0; i < nbox; i++) {
 503                struct drm_clip_rect *box = &pbox[i];
 504                u32 height = box->y2 - box->y1;
 505
 506                DRM_DEBUG("   from=%d,%d to=%d,%d\n",
 507                          box->x1, box->y1, box->x2, box->y2);
 508
 509                if (clear->flags & MGA_FRONT) {
 510                        BEGIN_DMA(2);
 511
 512                        DMA_BLOCK(MGA_DMAPAD, 0x00000000,
 513                                  MGA_PLNWT, clear->color_mask,
 514                                  MGA_YDSTLEN, (box->y1 << 16) | height,
 515                                  MGA_FXBNDRY, (box->x2 << 16) | box->x1);
 516
 517                        DMA_BLOCK(MGA_DMAPAD, 0x00000000,
 518                                  MGA_FCOL, clear->clear_color,
 519                                  MGA_DSTORG, dev_priv->front_offset,
 520                                  MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
 521
 522                        ADVANCE_DMA();
 523                }
 524
 525                if (clear->flags & MGA_BACK) {
 526                        BEGIN_DMA(2);
 527
 528                        DMA_BLOCK(MGA_DMAPAD, 0x00000000,
 529                                  MGA_PLNWT, clear->color_mask,
 530                                  MGA_YDSTLEN, (box->y1 << 16) | height,
 531                                  MGA_FXBNDRY, (box->x2 << 16) | box->x1);
 532
 533                        DMA_BLOCK(MGA_DMAPAD, 0x00000000,
 534                                  MGA_FCOL, clear->clear_color,
 535                                  MGA_DSTORG, dev_priv->back_offset,
 536                                  MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
 537
 538                        ADVANCE_DMA();
 539                }
 540
 541                if (clear->flags & MGA_DEPTH) {
 542                        BEGIN_DMA(2);
 543
 544                        DMA_BLOCK(MGA_DMAPAD, 0x00000000,
 545                                  MGA_PLNWT, clear->depth_mask,
 546                                  MGA_YDSTLEN, (box->y1 << 16) | height,
 547                                  MGA_FXBNDRY, (box->x2 << 16) | box->x1);
 548
 549                        DMA_BLOCK(MGA_DMAPAD, 0x00000000,
 550                                  MGA_FCOL, clear->clear_depth,
 551                                  MGA_DSTORG, dev_priv->depth_offset,
 552                                  MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
 553
 554                        ADVANCE_DMA();
 555                }
 556
 557        }
 558
 559        BEGIN_DMA(1);
 560
 561        /* Force reset of DWGCTL */
 562        DMA_BLOCK(MGA_DMAPAD, 0x00000000,
 563                  MGA_DMAPAD, 0x00000000,
 564                  MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl);
 565
 566        ADVANCE_DMA();
 567
 568        FLUSH_DMA();
 569}
 570
 571static void mga_dma_dispatch_swap(struct drm_device *dev)
 572{
 573        drm_mga_private_t *dev_priv = dev->dev_private;
 574        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 575        drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
 576        struct drm_clip_rect *pbox = sarea_priv->boxes;
 577        int nbox = sarea_priv->nbox;
 578        int i;
 579        DMA_LOCALS;
 580        DRM_DEBUG("\n");
 581
 582        sarea_priv->last_frame.head = dev_priv->prim.tail;
 583        sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap;
 584
 585        BEGIN_DMA(4 + nbox);
 586
 587        DMA_BLOCK(MGA_DMAPAD, 0x00000000,
 588                  MGA_DMAPAD, 0x00000000,
 589                  MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
 590
 591        DMA_BLOCK(MGA_DSTORG, dev_priv->front_offset,
 592                  MGA_MACCESS, dev_priv->maccess,
 593                  MGA_SRCORG, dev_priv->back_offset,
 594                  MGA_AR5, dev_priv->front_pitch);
 595
 596        DMA_BLOCK(MGA_DMAPAD, 0x00000000,
 597                  MGA_DMAPAD, 0x00000000,
 598                  MGA_PLNWT, 0xffffffff, MGA_DWGCTL, MGA_DWGCTL_COPY);
 599
 600        for (i = 0; i < nbox; i++) {
 601                struct drm_clip_rect *box = &pbox[i];
 602                u32 height = box->y2 - box->y1;
 603                u32 start = box->y1 * dev_priv->front_pitch;
 604
 605                DRM_DEBUG("   from=%d,%d to=%d,%d\n",
 606                          box->x1, box->y1, box->x2, box->y2);
 607
 608                DMA_BLOCK(MGA_AR0, start + box->x2 - 1,
 609                          MGA_AR3, start + box->x1,
 610                          MGA_FXBNDRY, ((box->x2 - 1) << 16) | box->x1,
 611                          MGA_YDSTLEN + MGA_EXEC, (box->y1 << 16) | height);
 612        }
 613
 614        DMA_BLOCK(MGA_DMAPAD, 0x00000000,
 615                  MGA_PLNWT, ctx->plnwt,
 616                  MGA_SRCORG, dev_priv->front_offset, MGA_DWGCTL, ctx->dwgctl);
 617
 618        ADVANCE_DMA();
 619
 620        FLUSH_DMA();
 621
 622        DRM_DEBUG("... done.\n");
 623}
 624
 625static void mga_dma_dispatch_vertex(struct drm_device *dev, struct drm_buf *buf)
 626{
 627        drm_mga_private_t *dev_priv = dev->dev_private;
 628        drm_mga_buf_priv_t *buf_priv = buf->dev_private;
 629        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 630        u32 address = (u32) buf->bus_address;
 631        u32 length = (u32) buf->used;
 632        int i = 0;
 633        DMA_LOCALS;
 634        DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used);
 635
 636        if (buf->used) {
 637                buf_priv->dispatched = 1;
 638
 639                MGA_EMIT_STATE(dev_priv, sarea_priv->dirty);
 640
 641                do {
 642                        if (i < sarea_priv->nbox) {
 643                                mga_emit_clip_rect(dev_priv,
 644                                                   &sarea_priv->boxes[i]);
 645                        }
 646
 647                        BEGIN_DMA(1);
 648
 649                        DMA_BLOCK(MGA_DMAPAD, 0x00000000,
 650                                  MGA_DMAPAD, 0x00000000,
 651                                  MGA_SECADDRESS, (address |
 652                                                   MGA_DMA_VERTEX),
 653                                  MGA_SECEND, ((address + length) |
 654                                               dev_priv->dma_access));
 655
 656                        ADVANCE_DMA();
 657                } while (++i < sarea_priv->nbox);
 658        }
 659
 660        if (buf_priv->discard) {
 661                AGE_BUFFER(buf_priv);
 662                buf->pending = 0;
 663                buf->used = 0;
 664                buf_priv->dispatched = 0;
 665
 666                mga_freelist_put(dev, buf);
 667        }
 668
 669        FLUSH_DMA();
 670}
 671
 672static void mga_dma_dispatch_indices(struct drm_device *dev, struct drm_buf *buf,
 673                                     unsigned int start, unsigned int end)
 674{
 675        drm_mga_private_t *dev_priv = dev->dev_private;
 676        drm_mga_buf_priv_t *buf_priv = buf->dev_private;
 677        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 678        u32 address = (u32) buf->bus_address;
 679        int i = 0;
 680        DMA_LOCALS;
 681        DRM_DEBUG("buf=%d start=%d end=%d\n", buf->idx, start, end);
 682
 683        if (start != end) {
 684                buf_priv->dispatched = 1;
 685
 686                MGA_EMIT_STATE(dev_priv, sarea_priv->dirty);
 687
 688                do {
 689                        if (i < sarea_priv->nbox) {
 690                                mga_emit_clip_rect(dev_priv,
 691                                                   &sarea_priv->boxes[i]);
 692                        }
 693
 694                        BEGIN_DMA(1);
 695
 696                        DMA_BLOCK(MGA_DMAPAD, 0x00000000,
 697                                  MGA_DMAPAD, 0x00000000,
 698                                  MGA_SETUPADDRESS, address + start,
 699                                  MGA_SETUPEND, ((address + end) |
 700                                                 dev_priv->dma_access));
 701
 702                        ADVANCE_DMA();
 703                } while (++i < sarea_priv->nbox);
 704        }
 705
 706        if (buf_priv->discard) {
 707                AGE_BUFFER(buf_priv);
 708                buf->pending = 0;
 709                buf->used = 0;
 710                buf_priv->dispatched = 0;
 711
 712                mga_freelist_put(dev, buf);
 713        }
 714
 715        FLUSH_DMA();
 716}
 717
 718/* This copies a 64 byte aligned agp region to the frambuffer with a
 719 * standard blit, the ioctl needs to do checking.
 720 */
 721static void mga_dma_dispatch_iload(struct drm_device *dev, struct drm_buf *buf,
 722                                   unsigned int dstorg, unsigned int length)
 723{
 724        drm_mga_private_t *dev_priv = dev->dev_private;
 725        drm_mga_buf_priv_t *buf_priv = buf->dev_private;
 726        drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state;
 727        u32 srcorg =
 728            buf->bus_address | dev_priv->dma_access | MGA_SRCMAP_SYSMEM;
 729        u32 y2;
 730        DMA_LOCALS;
 731        DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used);
 732
 733        y2 = length / 64;
 734
 735        BEGIN_DMA(5);
 736
 737        DMA_BLOCK(MGA_DMAPAD, 0x00000000,
 738                  MGA_DMAPAD, 0x00000000,
 739                  MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
 740
 741        DMA_BLOCK(MGA_DSTORG, dstorg,
 742                  MGA_MACCESS, 0x00000000, MGA_SRCORG, srcorg, MGA_AR5, 64);
 743
 744        DMA_BLOCK(MGA_PITCH, 64,
 745                  MGA_PLNWT, 0xffffffff,
 746                  MGA_DMAPAD, 0x00000000, MGA_DWGCTL, MGA_DWGCTL_COPY);
 747
 748        DMA_BLOCK(MGA_AR0, 63,
 749                  MGA_AR3, 0,
 750                  MGA_FXBNDRY, (63 << 16) | 0, MGA_YDSTLEN + MGA_EXEC, y2);
 751
 752        DMA_BLOCK(MGA_PLNWT, ctx->plnwt,
 753                  MGA_SRCORG, dev_priv->front_offset,
 754                  MGA_PITCH, dev_priv->front_pitch, MGA_DWGSYNC, 0x00007000);
 755
 756        ADVANCE_DMA();
 757
 758        AGE_BUFFER(buf_priv);
 759
 760        buf->pending = 0;
 761        buf->used = 0;
 762        buf_priv->dispatched = 0;
 763
 764        mga_freelist_put(dev, buf);
 765
 766        FLUSH_DMA();
 767}
 768
 769static void mga_dma_dispatch_blit(struct drm_device *dev, drm_mga_blit_t *blit)
 770{
 771        drm_mga_private_t *dev_priv = dev->dev_private;
 772        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 773        drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
 774        struct drm_clip_rect *pbox = sarea_priv->boxes;
 775        int nbox = sarea_priv->nbox;
 776        u32 scandir = 0, i;
 777        DMA_LOCALS;
 778        DRM_DEBUG("\n");
 779
 780        BEGIN_DMA(4 + nbox);
 781
 782        DMA_BLOCK(MGA_DMAPAD, 0x00000000,
 783                  MGA_DMAPAD, 0x00000000,
 784                  MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
 785
 786        DMA_BLOCK(MGA_DWGCTL, MGA_DWGCTL_COPY,
 787                  MGA_PLNWT, blit->planemask,
 788                  MGA_SRCORG, blit->srcorg, MGA_DSTORG, blit->dstorg);
 789
 790        DMA_BLOCK(MGA_SGN, scandir,
 791                  MGA_MACCESS, dev_priv->maccess,
 792                  MGA_AR5, blit->ydir * blit->src_pitch,
 793                  MGA_PITCH, blit->dst_pitch);
 794
 795        for (i = 0; i < nbox; i++) {
 796                int srcx = pbox[i].x1 + blit->delta_sx;
 797                int srcy = pbox[i].y1 + blit->delta_sy;
 798                int dstx = pbox[i].x1 + blit->delta_dx;
 799                int dsty = pbox[i].y1 + blit->delta_dy;
 800                int h = pbox[i].y2 - pbox[i].y1;
 801                int w = pbox[i].x2 - pbox[i].x1 - 1;
 802                int start;
 803
 804                if (blit->ydir == -1)
 805                        srcy = blit->height - srcy - 1;
 806
 807                start = srcy * blit->src_pitch + srcx;
 808
 809                DMA_BLOCK(MGA_AR0, start + w,
 810                          MGA_AR3, start,
 811                          MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff),
 812                          MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h);
 813        }
 814
 815        /* Do something to flush AGP?
 816         */
 817
 818        /* Force reset of DWGCTL */
 819        DMA_BLOCK(MGA_DMAPAD, 0x00000000,
 820                  MGA_PLNWT, ctx->plnwt,
 821                  MGA_PITCH, dev_priv->front_pitch, MGA_DWGCTL, ctx->dwgctl);
 822
 823        ADVANCE_DMA();
 824}
 825
 826/* ================================================================
 827 *
 828 */
 829
 830static int mga_dma_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
 831{
 832        drm_mga_private_t *dev_priv = dev->dev_private;
 833        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 834        drm_mga_clear_t *clear = data;
 835
 836        LOCK_TEST_WITH_RETURN(dev, file_priv);
 837
 838        if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
 839                sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
 840
 841        WRAP_TEST_WITH_RETURN(dev_priv);
 842
 843        mga_dma_dispatch_clear(dev, clear);
 844
 845        /* Make sure we restore the 3D state next time.
 846         */
 847        dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
 848
 849        return 0;
 850}
 851
 852static int mga_dma_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
 853{
 854        drm_mga_private_t *dev_priv = dev->dev_private;
 855        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 856
 857        LOCK_TEST_WITH_RETURN(dev, file_priv);
 858
 859        if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
 860                sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
 861
 862        WRAP_TEST_WITH_RETURN(dev_priv);
 863
 864        mga_dma_dispatch_swap(dev);
 865
 866        /* Make sure we restore the 3D state next time.
 867         */
 868        dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
 869
 870        return 0;
 871}
 872
 873static int mga_dma_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
 874{
 875        drm_mga_private_t *dev_priv = dev->dev_private;
 876        struct drm_device_dma *dma = dev->dma;
 877        struct drm_buf *buf;
 878        drm_mga_buf_priv_t *buf_priv;
 879        drm_mga_vertex_t *vertex = data;
 880
 881        LOCK_TEST_WITH_RETURN(dev, file_priv);
 882
 883        if (vertex->idx < 0 || vertex->idx > dma->buf_count)
 884                return -EINVAL;
 885        buf = dma->buflist[vertex->idx];
 886        buf_priv = buf->dev_private;
 887
 888        buf->used = vertex->used;
 889        buf_priv->discard = vertex->discard;
 890
 891        if (!mga_verify_state(dev_priv)) {
 892                if (vertex->discard) {
 893                        if (buf_priv->dispatched == 1)
 894                                AGE_BUFFER(buf_priv);
 895                        buf_priv->dispatched = 0;
 896                        mga_freelist_put(dev, buf);
 897                }
 898                return -EINVAL;
 899        }
 900
 901        WRAP_TEST_WITH_RETURN(dev_priv);
 902
 903        mga_dma_dispatch_vertex(dev, buf);
 904
 905        return 0;
 906}
 907
 908static int mga_dma_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
 909{
 910        drm_mga_private_t *dev_priv = dev->dev_private;
 911        struct drm_device_dma *dma = dev->dma;
 912        struct drm_buf *buf;
 913        drm_mga_buf_priv_t *buf_priv;
 914        drm_mga_indices_t *indices = data;
 915
 916        LOCK_TEST_WITH_RETURN(dev, file_priv);
 917
 918        if (indices->idx < 0 || indices->idx > dma->buf_count)
 919                return -EINVAL;
 920
 921        buf = dma->buflist[indices->idx];
 922        buf_priv = buf->dev_private;
 923
 924        buf_priv->discard = indices->discard;
 925
 926        if (!mga_verify_state(dev_priv)) {
 927                if (indices->discard) {
 928                        if (buf_priv->dispatched == 1)
 929                                AGE_BUFFER(buf_priv);
 930                        buf_priv->dispatched = 0;
 931                        mga_freelist_put(dev, buf);
 932                }
 933                return -EINVAL;
 934        }
 935
 936        WRAP_TEST_WITH_RETURN(dev_priv);
 937
 938        mga_dma_dispatch_indices(dev, buf, indices->start, indices->end);
 939
 940        return 0;
 941}
 942
 943static int mga_dma_iload(struct drm_device *dev, void *data, struct drm_file *file_priv)
 944{
 945        struct drm_device_dma *dma = dev->dma;
 946        drm_mga_private_t *dev_priv = dev->dev_private;
 947        struct drm_buf *buf;
 948        drm_mga_buf_priv_t *buf_priv;
 949        drm_mga_iload_t *iload = data;
 950        DRM_DEBUG("\n");
 951
 952        LOCK_TEST_WITH_RETURN(dev, file_priv);
 953
 954#if 0
 955        if (mga_do_wait_for_idle(dev_priv) < 0) {
 956                if (MGA_DMA_DEBUG)
 957                        DRM_INFO("-EBUSY\n");
 958                return -EBUSY;
 959        }
 960#endif
 961        if (iload->idx < 0 || iload->idx > dma->buf_count)
 962                return -EINVAL;
 963
 964        buf = dma->buflist[iload->idx];
 965        buf_priv = buf->dev_private;
 966
 967        if (mga_verify_iload(dev_priv, iload->dstorg, iload->length)) {
 968                mga_freelist_put(dev, buf);
 969                return -EINVAL;
 970        }
 971
 972        WRAP_TEST_WITH_RETURN(dev_priv);
 973
 974        mga_dma_dispatch_iload(dev, buf, iload->dstorg, iload->length);
 975
 976        /* Make sure we restore the 3D state next time.
 977         */
 978        dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
 979
 980        return 0;
 981}
 982
 983static int mga_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv)
 984{
 985        drm_mga_private_t *dev_priv = dev->dev_private;
 986        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 987        drm_mga_blit_t *blit = data;
 988        DRM_DEBUG("\n");
 989
 990        LOCK_TEST_WITH_RETURN(dev, file_priv);
 991
 992        if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
 993                sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
 994
 995        if (mga_verify_blit(dev_priv, blit->srcorg, blit->dstorg))
 996                return -EINVAL;
 997
 998        WRAP_TEST_WITH_RETURN(dev_priv);
 999
1000        mga_dma_dispatch_blit(dev, blit);
1001
1002        /* Make sure we restore the 3D state next time.
1003         */
1004        dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
1005
1006        return 0;
1007}
1008
1009static int mga_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
1010{
1011        drm_mga_private_t *dev_priv = dev->dev_private;
1012        drm_mga_getparam_t *param = data;
1013        int value;
1014
1015        if (!dev_priv) {
1016                DRM_ERROR("called with no initialization\n");
1017                return -EINVAL;
1018        }
1019
1020        DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
1021
1022        switch (param->param) {
1023        case MGA_PARAM_IRQ_NR:
1024                value = drm_dev_to_irq(dev);
1025                break;
1026        case MGA_PARAM_CARD_TYPE:
1027                value = dev_priv->chipset;
1028                break;
1029        default:
1030                return -EINVAL;
1031        }
1032
1033        if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
1034                DRM_ERROR("copy_to_user\n");
1035                return -EFAULT;
1036        }
1037
1038        return 0;
1039}
1040
1041static int mga_set_fence(struct drm_device *dev, void *data, struct drm_file *file_priv)
1042{
1043        drm_mga_private_t *dev_priv = dev->dev_private;
1044        u32 *fence = data;
1045        DMA_LOCALS;
1046
1047        if (!dev_priv) {
1048                DRM_ERROR("called with no initialization\n");
1049                return -EINVAL;
1050        }
1051
1052        DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
1053
1054        /* I would normal do this assignment in the declaration of fence,
1055         * but dev_priv may be NULL.
1056         */
1057
1058        *fence = dev_priv->next_fence_to_post;
1059        dev_priv->next_fence_to_post++;
1060
1061        BEGIN_DMA(1);
1062        DMA_BLOCK(MGA_DMAPAD, 0x00000000,
1063                  MGA_DMAPAD, 0x00000000,
1064                  MGA_DMAPAD, 0x00000000, MGA_SOFTRAP, 0x00000000);
1065        ADVANCE_DMA();
1066
1067        return 0;
1068}
1069
1070static int mga_wait_fence(struct drm_device *dev, void *data, struct drm_file *
1071file_priv)
1072{
1073        drm_mga_private_t *dev_priv = dev->dev_private;
1074        u32 *fence = data;
1075
1076        if (!dev_priv) {
1077                DRM_ERROR("called with no initialization\n");
1078                return -EINVAL;
1079        }
1080
1081        DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
1082
1083        mga_driver_fence_wait(dev, fence);
1084        return 0;
1085}
1086
1087struct drm_ioctl_desc mga_ioctls[] = {
1088        DRM_IOCTL_DEF_DRV(MGA_INIT, mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1089        DRM_IOCTL_DEF_DRV(MGA_FLUSH, mga_dma_flush, DRM_AUTH),
1090        DRM_IOCTL_DEF_DRV(MGA_RESET, mga_dma_reset, DRM_AUTH),
1091        DRM_IOCTL_DEF_DRV(MGA_SWAP, mga_dma_swap, DRM_AUTH),
1092        DRM_IOCTL_DEF_DRV(MGA_CLEAR, mga_dma_clear, DRM_AUTH),
1093        DRM_IOCTL_DEF_DRV(MGA_VERTEX, mga_dma_vertex, DRM_AUTH),
1094        DRM_IOCTL_DEF_DRV(MGA_INDICES, mga_dma_indices, DRM_AUTH),
1095        DRM_IOCTL_DEF_DRV(MGA_ILOAD, mga_dma_iload, DRM_AUTH),
1096        DRM_IOCTL_DEF_DRV(MGA_BLIT, mga_dma_blit, DRM_AUTH),
1097        DRM_IOCTL_DEF_DRV(MGA_GETPARAM, mga_getparam, DRM_AUTH),
1098        DRM_IOCTL_DEF_DRV(MGA_SET_FENCE, mga_set_fence, DRM_AUTH),
1099        DRM_IOCTL_DEF_DRV(MGA_WAIT_FENCE, mga_wait_fence, DRM_AUTH),
1100        DRM_IOCTL_DEF_DRV(MGA_DMA_BOOTSTRAP, mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1101};
1102
1103int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls);
1104