The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/drm/mga_state.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 4c94790946f4bcb60075afc124f87965


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.