Back to home page

OSCL-LXR

 
 

    


0001 /* r128_state.c -- State support for r128 -*- linux-c -*-
0002  * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com
0003  */
0004 /*
0005  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
0006  * All Rights Reserved.
0007  *
0008  * Permission is hereby granted, free of charge, to any person obtaining a
0009  * copy of this software and associated documentation files (the "Software"),
0010  * to deal in the Software without restriction, including without limitation
0011  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0012  * and/or sell copies of the Software, and to permit persons to whom the
0013  * Software is furnished to do so, subject to the following conditions:
0014  *
0015  * The above copyright notice and this permission notice (including the next
0016  * paragraph) shall be included in all copies or substantial portions of the
0017  * Software.
0018  *
0019  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0020  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0021  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0022  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
0023  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0024  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
0025  * DEALINGS IN THE SOFTWARE.
0026  *
0027  * Authors:
0028  *    Gareth Hughes <gareth@valinux.com>
0029  */
0030 
0031 #include <linux/pci.h>
0032 #include <linux/slab.h>
0033 #include <linux/uaccess.h>
0034 
0035 #include <drm/drm_device.h>
0036 #include <drm/drm_file.h>
0037 #include <drm/drm_print.h>
0038 #include <drm/r128_drm.h>
0039 
0040 #include "r128_drv.h"
0041 
0042 /* ================================================================
0043  * CCE hardware state programming functions
0044  */
0045 
0046 static void r128_emit_clip_rects(drm_r128_private_t *dev_priv,
0047                  struct drm_clip_rect *boxes, int count)
0048 {
0049     u32 aux_sc_cntl = 0x00000000;
0050     RING_LOCALS;
0051     DRM_DEBUG("\n");
0052 
0053     BEGIN_RING((count < 3 ? count : 3) * 5 + 2);
0054 
0055     if (count >= 1) {
0056         OUT_RING(CCE_PACKET0(R128_AUX1_SC_LEFT, 3));
0057         OUT_RING(boxes[0].x1);
0058         OUT_RING(boxes[0].x2 - 1);
0059         OUT_RING(boxes[0].y1);
0060         OUT_RING(boxes[0].y2 - 1);
0061 
0062         aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR);
0063     }
0064     if (count >= 2) {
0065         OUT_RING(CCE_PACKET0(R128_AUX2_SC_LEFT, 3));
0066         OUT_RING(boxes[1].x1);
0067         OUT_RING(boxes[1].x2 - 1);
0068         OUT_RING(boxes[1].y1);
0069         OUT_RING(boxes[1].y2 - 1);
0070 
0071         aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR);
0072     }
0073     if (count >= 3) {
0074         OUT_RING(CCE_PACKET0(R128_AUX3_SC_LEFT, 3));
0075         OUT_RING(boxes[2].x1);
0076         OUT_RING(boxes[2].x2 - 1);
0077         OUT_RING(boxes[2].y1);
0078         OUT_RING(boxes[2].y2 - 1);
0079 
0080         aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR);
0081     }
0082 
0083     OUT_RING(CCE_PACKET0(R128_AUX_SC_CNTL, 0));
0084     OUT_RING(aux_sc_cntl);
0085 
0086     ADVANCE_RING();
0087 }
0088 
0089 static __inline__ void r128_emit_core(drm_r128_private_t *dev_priv)
0090 {
0091     drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
0092     drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
0093     RING_LOCALS;
0094     DRM_DEBUG("\n");
0095 
0096     BEGIN_RING(2);
0097 
0098     OUT_RING(CCE_PACKET0(R128_SCALE_3D_CNTL, 0));
0099     OUT_RING(ctx->scale_3d_cntl);
0100 
0101     ADVANCE_RING();
0102 }
0103 
0104 static __inline__ void r128_emit_context(drm_r128_private_t *dev_priv)
0105 {
0106     drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
0107     drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
0108     RING_LOCALS;
0109     DRM_DEBUG("\n");
0110 
0111     BEGIN_RING(13);
0112 
0113     OUT_RING(CCE_PACKET0(R128_DST_PITCH_OFFSET_C, 11));
0114     OUT_RING(ctx->dst_pitch_offset_c);
0115     OUT_RING(ctx->dp_gui_master_cntl_c);
0116     OUT_RING(ctx->sc_top_left_c);
0117     OUT_RING(ctx->sc_bottom_right_c);
0118     OUT_RING(ctx->z_offset_c);
0119     OUT_RING(ctx->z_pitch_c);
0120     OUT_RING(ctx->z_sten_cntl_c);
0121     OUT_RING(ctx->tex_cntl_c);
0122     OUT_RING(ctx->misc_3d_state_cntl_reg);
0123     OUT_RING(ctx->texture_clr_cmp_clr_c);
0124     OUT_RING(ctx->texture_clr_cmp_msk_c);
0125     OUT_RING(ctx->fog_color_c);
0126 
0127     ADVANCE_RING();
0128 }
0129 
0130 static __inline__ void r128_emit_setup(drm_r128_private_t *dev_priv)
0131 {
0132     drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
0133     drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
0134     RING_LOCALS;
0135     DRM_DEBUG("\n");
0136 
0137     BEGIN_RING(3);
0138 
0139     OUT_RING(CCE_PACKET1(R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP));
0140     OUT_RING(ctx->setup_cntl);
0141     OUT_RING(ctx->pm4_vc_fpu_setup);
0142 
0143     ADVANCE_RING();
0144 }
0145 
0146 static __inline__ void r128_emit_masks(drm_r128_private_t *dev_priv)
0147 {
0148     drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
0149     drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
0150     RING_LOCALS;
0151     DRM_DEBUG("\n");
0152 
0153     BEGIN_RING(5);
0154 
0155     OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0));
0156     OUT_RING(ctx->dp_write_mask);
0157 
0158     OUT_RING(CCE_PACKET0(R128_STEN_REF_MASK_C, 1));
0159     OUT_RING(ctx->sten_ref_mask_c);
0160     OUT_RING(ctx->plane_3d_mask_c);
0161 
0162     ADVANCE_RING();
0163 }
0164 
0165 static __inline__ void r128_emit_window(drm_r128_private_t *dev_priv)
0166 {
0167     drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
0168     drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
0169     RING_LOCALS;
0170     DRM_DEBUG("\n");
0171 
0172     BEGIN_RING(2);
0173 
0174     OUT_RING(CCE_PACKET0(R128_WINDOW_XY_OFFSET, 0));
0175     OUT_RING(ctx->window_xy_offset);
0176 
0177     ADVANCE_RING();
0178 }
0179 
0180 static __inline__ void r128_emit_tex0(drm_r128_private_t *dev_priv)
0181 {
0182     drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
0183     drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
0184     drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0];
0185     int i;
0186     RING_LOCALS;
0187     DRM_DEBUG("\n");
0188 
0189     BEGIN_RING(7 + R128_MAX_TEXTURE_LEVELS);
0190 
0191     OUT_RING(CCE_PACKET0(R128_PRIM_TEX_CNTL_C,
0192                  2 + R128_MAX_TEXTURE_LEVELS));
0193     OUT_RING(tex->tex_cntl);
0194     OUT_RING(tex->tex_combine_cntl);
0195     OUT_RING(ctx->tex_size_pitch_c);
0196     for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++)
0197         OUT_RING(tex->tex_offset[i]);
0198 
0199     OUT_RING(CCE_PACKET0(R128_CONSTANT_COLOR_C, 1));
0200     OUT_RING(ctx->constant_color_c);
0201     OUT_RING(tex->tex_border_color);
0202 
0203     ADVANCE_RING();
0204 }
0205 
0206 static __inline__ void r128_emit_tex1(drm_r128_private_t *dev_priv)
0207 {
0208     drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
0209     drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1];
0210     int i;
0211     RING_LOCALS;
0212     DRM_DEBUG("\n");
0213 
0214     BEGIN_RING(5 + R128_MAX_TEXTURE_LEVELS);
0215 
0216     OUT_RING(CCE_PACKET0(R128_SEC_TEX_CNTL_C, 1 + R128_MAX_TEXTURE_LEVELS));
0217     OUT_RING(tex->tex_cntl);
0218     OUT_RING(tex->tex_combine_cntl);
0219     for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++)
0220         OUT_RING(tex->tex_offset[i]);
0221 
0222     OUT_RING(CCE_PACKET0(R128_SEC_TEXTURE_BORDER_COLOR_C, 0));
0223     OUT_RING(tex->tex_border_color);
0224 
0225     ADVANCE_RING();
0226 }
0227 
0228 static void r128_emit_state(drm_r128_private_t *dev_priv)
0229 {
0230     drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
0231     unsigned int dirty = sarea_priv->dirty;
0232 
0233     DRM_DEBUG("dirty=0x%08x\n", dirty);
0234 
0235     if (dirty & R128_UPLOAD_CORE) {
0236         r128_emit_core(dev_priv);
0237         sarea_priv->dirty &= ~R128_UPLOAD_CORE;
0238     }
0239 
0240     if (dirty & R128_UPLOAD_CONTEXT) {
0241         r128_emit_context(dev_priv);
0242         sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT;
0243     }
0244 
0245     if (dirty & R128_UPLOAD_SETUP) {
0246         r128_emit_setup(dev_priv);
0247         sarea_priv->dirty &= ~R128_UPLOAD_SETUP;
0248     }
0249 
0250     if (dirty & R128_UPLOAD_MASKS) {
0251         r128_emit_masks(dev_priv);
0252         sarea_priv->dirty &= ~R128_UPLOAD_MASKS;
0253     }
0254 
0255     if (dirty & R128_UPLOAD_WINDOW) {
0256         r128_emit_window(dev_priv);
0257         sarea_priv->dirty &= ~R128_UPLOAD_WINDOW;
0258     }
0259 
0260     if (dirty & R128_UPLOAD_TEX0) {
0261         r128_emit_tex0(dev_priv);
0262         sarea_priv->dirty &= ~R128_UPLOAD_TEX0;
0263     }
0264 
0265     if (dirty & R128_UPLOAD_TEX1) {
0266         r128_emit_tex1(dev_priv);
0267         sarea_priv->dirty &= ~R128_UPLOAD_TEX1;
0268     }
0269 
0270     /* Turn off the texture cache flushing */
0271     sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH;
0272 
0273     sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE;
0274 }
0275 
0276 #if R128_PERFORMANCE_BOXES
0277 /* ================================================================
0278  * Performance monitoring functions
0279  */
0280 
0281 static void r128_clear_box(drm_r128_private_t *dev_priv,
0282                int x, int y, int w, int h, int r, int g, int b)
0283 {
0284     u32 pitch, offset;
0285     u32 fb_bpp, color;
0286     RING_LOCALS;
0287 
0288     switch (dev_priv->fb_bpp) {
0289     case 16:
0290         fb_bpp = R128_GMC_DST_16BPP;
0291         color = (((r & 0xf8) << 8) |
0292              ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
0293         break;
0294     case 24:
0295         fb_bpp = R128_GMC_DST_24BPP;
0296         color = ((r << 16) | (g << 8) | b);
0297         break;
0298     case 32:
0299         fb_bpp = R128_GMC_DST_32BPP;
0300         color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
0301         break;
0302     default:
0303         return;
0304     }
0305 
0306     offset = dev_priv->back_offset;
0307     pitch = dev_priv->back_pitch >> 3;
0308 
0309     BEGIN_RING(6);
0310 
0311     OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
0312     OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
0313          R128_GMC_BRUSH_SOLID_COLOR |
0314          fb_bpp |
0315          R128_GMC_SRC_DATATYPE_COLOR |
0316          R128_ROP3_P |
0317          R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS);
0318 
0319     OUT_RING((pitch << 21) | (offset >> 5));
0320     OUT_RING(color);
0321 
0322     OUT_RING((x << 16) | y);
0323     OUT_RING((w << 16) | h);
0324 
0325     ADVANCE_RING();
0326 }
0327 
0328 static void r128_cce_performance_boxes(drm_r128_private_t *dev_priv)
0329 {
0330     if (atomic_read(&dev_priv->idle_count) == 0)
0331         r128_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
0332     else
0333         atomic_set(&dev_priv->idle_count, 0);
0334 }
0335 
0336 #endif
0337 
0338 /* ================================================================
0339  * CCE command dispatch functions
0340  */
0341 
0342 static void r128_print_dirty(const char *msg, unsigned int flags)
0343 {
0344     DRM_INFO("%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
0345          msg,
0346          flags,
0347          (flags & R128_UPLOAD_CORE) ? "core, " : "",
0348          (flags & R128_UPLOAD_CONTEXT) ? "context, " : "",
0349          (flags & R128_UPLOAD_SETUP) ? "setup, " : "",
0350          (flags & R128_UPLOAD_TEX0) ? "tex0, " : "",
0351          (flags & R128_UPLOAD_TEX1) ? "tex1, " : "",
0352          (flags & R128_UPLOAD_MASKS) ? "masks, " : "",
0353          (flags & R128_UPLOAD_WINDOW) ? "window, " : "",
0354          (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "",
0355          (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "");
0356 }
0357 
0358 static void r128_cce_dispatch_clear(struct drm_device *dev,
0359                     drm_r128_clear_t *clear)
0360 {
0361     drm_r128_private_t *dev_priv = dev->dev_private;
0362     drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
0363     int nbox = sarea_priv->nbox;
0364     struct drm_clip_rect *pbox = sarea_priv->boxes;
0365     unsigned int flags = clear->flags;
0366     int i;
0367     RING_LOCALS;
0368     DRM_DEBUG("\n");
0369 
0370     if (dev_priv->page_flipping && dev_priv->current_page == 1) {
0371         unsigned int tmp = flags;
0372 
0373         flags &= ~(R128_FRONT | R128_BACK);
0374         if (tmp & R128_FRONT)
0375             flags |= R128_BACK;
0376         if (tmp & R128_BACK)
0377             flags |= R128_FRONT;
0378     }
0379 
0380     for (i = 0; i < nbox; i++) {
0381         int x = pbox[i].x1;
0382         int y = pbox[i].y1;
0383         int w = pbox[i].x2 - x;
0384         int h = pbox[i].y2 - y;
0385 
0386         DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n",
0387               pbox[i].x1, pbox[i].y1, pbox[i].x2,
0388               pbox[i].y2, flags);
0389 
0390         if (flags & (R128_FRONT | R128_BACK)) {
0391             BEGIN_RING(2);
0392 
0393             OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0));
0394             OUT_RING(clear->color_mask);
0395 
0396             ADVANCE_RING();
0397         }
0398 
0399         if (flags & R128_FRONT) {
0400             BEGIN_RING(6);
0401 
0402             OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
0403             OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
0404                  R128_GMC_BRUSH_SOLID_COLOR |
0405                  (dev_priv->color_fmt << 8) |
0406                  R128_GMC_SRC_DATATYPE_COLOR |
0407                  R128_ROP3_P |
0408                  R128_GMC_CLR_CMP_CNTL_DIS |
0409                  R128_GMC_AUX_CLIP_DIS);
0410 
0411             OUT_RING(dev_priv->front_pitch_offset_c);
0412             OUT_RING(clear->clear_color);
0413 
0414             OUT_RING((x << 16) | y);
0415             OUT_RING((w << 16) | h);
0416 
0417             ADVANCE_RING();
0418         }
0419 
0420         if (flags & R128_BACK) {
0421             BEGIN_RING(6);
0422 
0423             OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
0424             OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
0425                  R128_GMC_BRUSH_SOLID_COLOR |
0426                  (dev_priv->color_fmt << 8) |
0427                  R128_GMC_SRC_DATATYPE_COLOR |
0428                  R128_ROP3_P |
0429                  R128_GMC_CLR_CMP_CNTL_DIS |
0430                  R128_GMC_AUX_CLIP_DIS);
0431 
0432             OUT_RING(dev_priv->back_pitch_offset_c);
0433             OUT_RING(clear->clear_color);
0434 
0435             OUT_RING((x << 16) | y);
0436             OUT_RING((w << 16) | h);
0437 
0438             ADVANCE_RING();
0439         }
0440 
0441         if (flags & R128_DEPTH) {
0442             BEGIN_RING(6);
0443 
0444             OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
0445             OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
0446                  R128_GMC_BRUSH_SOLID_COLOR |
0447                  (dev_priv->depth_fmt << 8) |
0448                  R128_GMC_SRC_DATATYPE_COLOR |
0449                  R128_ROP3_P |
0450                  R128_GMC_CLR_CMP_CNTL_DIS |
0451                  R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);
0452 
0453             OUT_RING(dev_priv->depth_pitch_offset_c);
0454             OUT_RING(clear->clear_depth);
0455 
0456             OUT_RING((x << 16) | y);
0457             OUT_RING((w << 16) | h);
0458 
0459             ADVANCE_RING();
0460         }
0461     }
0462 }
0463 
0464 static void r128_cce_dispatch_swap(struct drm_device *dev)
0465 {
0466     drm_r128_private_t *dev_priv = dev->dev_private;
0467     drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
0468     int nbox = sarea_priv->nbox;
0469     struct drm_clip_rect *pbox = sarea_priv->boxes;
0470     int i;
0471     RING_LOCALS;
0472     DRM_DEBUG("\n");
0473 
0474 #if R128_PERFORMANCE_BOXES
0475     /* Do some trivial performance monitoring...
0476      */
0477     r128_cce_performance_boxes(dev_priv);
0478 #endif
0479 
0480     for (i = 0; i < nbox; i++) {
0481         int x = pbox[i].x1;
0482         int y = pbox[i].y1;
0483         int w = pbox[i].x2 - x;
0484         int h = pbox[i].y2 - y;
0485 
0486         BEGIN_RING(7);
0487 
0488         OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
0489         OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
0490              R128_GMC_DST_PITCH_OFFSET_CNTL |
0491              R128_GMC_BRUSH_NONE |
0492              (dev_priv->color_fmt << 8) |
0493              R128_GMC_SRC_DATATYPE_COLOR |
0494              R128_ROP3_S |
0495              R128_DP_SRC_SOURCE_MEMORY |
0496              R128_GMC_CLR_CMP_CNTL_DIS |
0497              R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);
0498 
0499         /* Make this work even if front & back are flipped:
0500          */
0501         if (dev_priv->current_page == 0) {
0502             OUT_RING(dev_priv->back_pitch_offset_c);
0503             OUT_RING(dev_priv->front_pitch_offset_c);
0504         } else {
0505             OUT_RING(dev_priv->front_pitch_offset_c);
0506             OUT_RING(dev_priv->back_pitch_offset_c);
0507         }
0508 
0509         OUT_RING((x << 16) | y);
0510         OUT_RING((x << 16) | y);
0511         OUT_RING((w << 16) | h);
0512 
0513         ADVANCE_RING();
0514     }
0515 
0516     /* Increment the frame counter.  The client-side 3D driver must
0517      * throttle the framerate by waiting for this value before
0518      * performing the swapbuffer ioctl.
0519      */
0520     dev_priv->sarea_priv->last_frame++;
0521 
0522     BEGIN_RING(2);
0523 
0524     OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));
0525     OUT_RING(dev_priv->sarea_priv->last_frame);
0526 
0527     ADVANCE_RING();
0528 }
0529 
0530 static void r128_cce_dispatch_flip(struct drm_device *dev)
0531 {
0532     drm_r128_private_t *dev_priv = dev->dev_private;
0533     RING_LOCALS;
0534     DRM_DEBUG("page=%d pfCurrentPage=%d\n",
0535           dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
0536 
0537 #if R128_PERFORMANCE_BOXES
0538     /* Do some trivial performance monitoring...
0539      */
0540     r128_cce_performance_boxes(dev_priv);
0541 #endif
0542 
0543     BEGIN_RING(4);
0544 
0545     R128_WAIT_UNTIL_PAGE_FLIPPED();
0546     OUT_RING(CCE_PACKET0(R128_CRTC_OFFSET, 0));
0547 
0548     if (dev_priv->current_page == 0)
0549         OUT_RING(dev_priv->back_offset);
0550     else
0551         OUT_RING(dev_priv->front_offset);
0552 
0553     ADVANCE_RING();
0554 
0555     /* Increment the frame counter.  The client-side 3D driver must
0556      * throttle the framerate by waiting for this value before
0557      * performing the swapbuffer ioctl.
0558      */
0559     dev_priv->sarea_priv->last_frame++;
0560     dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
0561         1 - dev_priv->current_page;
0562 
0563     BEGIN_RING(2);
0564 
0565     OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));
0566     OUT_RING(dev_priv->sarea_priv->last_frame);
0567 
0568     ADVANCE_RING();
0569 }
0570 
0571 static void r128_cce_dispatch_vertex(struct drm_device *dev, struct drm_buf *buf)
0572 {
0573     drm_r128_private_t *dev_priv = dev->dev_private;
0574     drm_r128_buf_priv_t *buf_priv = buf->dev_private;
0575     drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
0576     int format = sarea_priv->vc_format;
0577     int offset = buf->bus_address;
0578     int size = buf->used;
0579     int prim = buf_priv->prim;
0580     int i = 0;
0581     RING_LOCALS;
0582     DRM_DEBUG("buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox);
0583 
0584     if (0)
0585         r128_print_dirty("dispatch_vertex", sarea_priv->dirty);
0586 
0587     if (buf->used) {
0588         buf_priv->dispatched = 1;
0589 
0590         if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS)
0591             r128_emit_state(dev_priv);
0592 
0593         do {
0594             /* Emit the next set of up to three cliprects */
0595             if (i < sarea_priv->nbox) {
0596                 r128_emit_clip_rects(dev_priv,
0597                              &sarea_priv->boxes[i],
0598                              sarea_priv->nbox - i);
0599             }
0600 
0601             /* Emit the vertex buffer rendering commands */
0602             BEGIN_RING(5);
0603 
0604             OUT_RING(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM, 3));
0605             OUT_RING(offset);
0606             OUT_RING(size);
0607             OUT_RING(format);
0608             OUT_RING(prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
0609                  (size << R128_CCE_VC_CNTL_NUM_SHIFT));
0610 
0611             ADVANCE_RING();
0612 
0613             i += 3;
0614         } while (i < sarea_priv->nbox);
0615     }
0616 
0617     if (buf_priv->discard) {
0618         buf_priv->age = dev_priv->sarea_priv->last_dispatch;
0619 
0620         /* Emit the vertex buffer age */
0621         BEGIN_RING(2);
0622 
0623         OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
0624         OUT_RING(buf_priv->age);
0625 
0626         ADVANCE_RING();
0627 
0628         buf->pending = 1;
0629         buf->used = 0;
0630         /* FIXME: Check dispatched field */
0631         buf_priv->dispatched = 0;
0632     }
0633 
0634     dev_priv->sarea_priv->last_dispatch++;
0635 
0636     sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
0637     sarea_priv->nbox = 0;
0638 }
0639 
0640 static void r128_cce_dispatch_indirect(struct drm_device *dev,
0641                        struct drm_buf *buf, int start, int end)
0642 {
0643     drm_r128_private_t *dev_priv = dev->dev_private;
0644     drm_r128_buf_priv_t *buf_priv = buf->dev_private;
0645     RING_LOCALS;
0646     DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
0647 
0648     if (start != end) {
0649         int offset = buf->bus_address + start;
0650         int dwords = (end - start + 3) / sizeof(u32);
0651 
0652         /* Indirect buffer data must be an even number of
0653          * dwords, so if we've been given an odd number we must
0654          * pad the data with a Type-2 CCE packet.
0655          */
0656         if (dwords & 1) {
0657             u32 *data = (u32 *)
0658                 ((char *)dev->agp_buffer_map->handle
0659                  + buf->offset + start);
0660             data[dwords++] = cpu_to_le32(R128_CCE_PACKET2);
0661         }
0662 
0663         buf_priv->dispatched = 1;
0664 
0665         /* Fire off the indirect buffer */
0666         BEGIN_RING(3);
0667 
0668         OUT_RING(CCE_PACKET0(R128_PM4_IW_INDOFF, 1));
0669         OUT_RING(offset);
0670         OUT_RING(dwords);
0671 
0672         ADVANCE_RING();
0673     }
0674 
0675     if (buf_priv->discard) {
0676         buf_priv->age = dev_priv->sarea_priv->last_dispatch;
0677 
0678         /* Emit the indirect buffer age */
0679         BEGIN_RING(2);
0680 
0681         OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
0682         OUT_RING(buf_priv->age);
0683 
0684         ADVANCE_RING();
0685 
0686         buf->pending = 1;
0687         buf->used = 0;
0688         /* FIXME: Check dispatched field */
0689         buf_priv->dispatched = 0;
0690     }
0691 
0692     dev_priv->sarea_priv->last_dispatch++;
0693 }
0694 
0695 static void r128_cce_dispatch_indices(struct drm_device *dev,
0696                       struct drm_buf *buf,
0697                       int start, int end, int count)
0698 {
0699     drm_r128_private_t *dev_priv = dev->dev_private;
0700     drm_r128_buf_priv_t *buf_priv = buf->dev_private;
0701     drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
0702     int format = sarea_priv->vc_format;
0703     int offset = dev->agp_buffer_map->offset - dev_priv->cce_buffers_offset;
0704     int prim = buf_priv->prim;
0705     u32 *data;
0706     int dwords;
0707     int i = 0;
0708     RING_LOCALS;
0709     DRM_DEBUG("indices: s=%d e=%d c=%d\n", start, end, count);
0710 
0711     if (0)
0712         r128_print_dirty("dispatch_indices", sarea_priv->dirty);
0713 
0714     if (start != end) {
0715         buf_priv->dispatched = 1;
0716 
0717         if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS)
0718             r128_emit_state(dev_priv);
0719 
0720         dwords = (end - start + 3) / sizeof(u32);
0721 
0722         data = (u32 *) ((char *)dev->agp_buffer_map->handle
0723                 + buf->offset + start);
0724 
0725         data[0] = cpu_to_le32(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM,
0726                           dwords - 2));
0727 
0728         data[1] = cpu_to_le32(offset);
0729         data[2] = cpu_to_le32(R128_MAX_VB_VERTS);
0730         data[3] = cpu_to_le32(format);
0731         data[4] = cpu_to_le32((prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
0732                        (count << 16)));
0733 
0734         if (count & 0x1) {
0735 #ifdef __LITTLE_ENDIAN
0736             data[dwords - 1] &= 0x0000ffff;
0737 #else
0738             data[dwords - 1] &= 0xffff0000;
0739 #endif
0740         }
0741 
0742         do {
0743             /* Emit the next set of up to three cliprects */
0744             if (i < sarea_priv->nbox) {
0745                 r128_emit_clip_rects(dev_priv,
0746                              &sarea_priv->boxes[i],
0747                              sarea_priv->nbox - i);
0748             }
0749 
0750             r128_cce_dispatch_indirect(dev, buf, start, end);
0751 
0752             i += 3;
0753         } while (i < sarea_priv->nbox);
0754     }
0755 
0756     if (buf_priv->discard) {
0757         buf_priv->age = dev_priv->sarea_priv->last_dispatch;
0758 
0759         /* Emit the vertex buffer age */
0760         BEGIN_RING(2);
0761 
0762         OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
0763         OUT_RING(buf_priv->age);
0764 
0765         ADVANCE_RING();
0766 
0767         buf->pending = 1;
0768         /* FIXME: Check dispatched field */
0769         buf_priv->dispatched = 0;
0770     }
0771 
0772     dev_priv->sarea_priv->last_dispatch++;
0773 
0774     sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
0775     sarea_priv->nbox = 0;
0776 }
0777 
0778 static int r128_cce_dispatch_blit(struct drm_device *dev,
0779                   struct drm_file *file_priv,
0780                   drm_r128_blit_t *blit)
0781 {
0782     drm_r128_private_t *dev_priv = dev->dev_private;
0783     struct drm_device_dma *dma = dev->dma;
0784     struct drm_buf *buf;
0785     drm_r128_buf_priv_t *buf_priv;
0786     u32 *data;
0787     int dword_shift, dwords;
0788     RING_LOCALS;
0789     DRM_DEBUG("\n");
0790 
0791     /* The compiler won't optimize away a division by a variable,
0792      * even if the only legal values are powers of two.  Thus, we'll
0793      * use a shift instead.
0794      */
0795     switch (blit->format) {
0796     case R128_DATATYPE_ARGB8888:
0797         dword_shift = 0;
0798         break;
0799     case R128_DATATYPE_ARGB1555:
0800     case R128_DATATYPE_RGB565:
0801     case R128_DATATYPE_ARGB4444:
0802     case R128_DATATYPE_YVYU422:
0803     case R128_DATATYPE_VYUY422:
0804         dword_shift = 1;
0805         break;
0806     case R128_DATATYPE_CI8:
0807     case R128_DATATYPE_RGB8:
0808         dword_shift = 2;
0809         break;
0810     default:
0811         DRM_ERROR("invalid blit format %d\n", blit->format);
0812         return -EINVAL;
0813     }
0814 
0815     /* Flush the pixel cache, and mark the contents as Read Invalid.
0816      * This ensures no pixel data gets mixed up with the texture
0817      * data from the host data blit, otherwise part of the texture
0818      * image may be corrupted.
0819      */
0820     BEGIN_RING(2);
0821 
0822     OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));
0823     OUT_RING(R128_PC_RI_GUI | R128_PC_FLUSH_GUI);
0824 
0825     ADVANCE_RING();
0826 
0827     /* Dispatch the indirect buffer.
0828      */
0829     buf = dma->buflist[blit->idx];
0830     buf_priv = buf->dev_private;
0831 
0832     if (buf->file_priv != file_priv) {
0833         DRM_ERROR("process %d using buffer owned by %p\n",
0834               task_pid_nr(current), buf->file_priv);
0835         return -EINVAL;
0836     }
0837     if (buf->pending) {
0838         DRM_ERROR("sending pending buffer %d\n", blit->idx);
0839         return -EINVAL;
0840     }
0841 
0842     buf_priv->discard = 1;
0843 
0844     dwords = (blit->width * blit->height) >> dword_shift;
0845 
0846     data = (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
0847 
0848     data[0] = cpu_to_le32(CCE_PACKET3(R128_CNTL_HOSTDATA_BLT, dwords + 6));
0849     data[1] = cpu_to_le32((R128_GMC_DST_PITCH_OFFSET_CNTL |
0850                    R128_GMC_BRUSH_NONE |
0851                    (blit->format << 8) |
0852                    R128_GMC_SRC_DATATYPE_COLOR |
0853                    R128_ROP3_S |
0854                    R128_DP_SRC_SOURCE_HOST_DATA |
0855                    R128_GMC_CLR_CMP_CNTL_DIS |
0856                    R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS));
0857 
0858     data[2] = cpu_to_le32((blit->pitch << 21) | (blit->offset >> 5));
0859     data[3] = cpu_to_le32(0xffffffff);
0860     data[4] = cpu_to_le32(0xffffffff);
0861     data[5] = cpu_to_le32((blit->y << 16) | blit->x);
0862     data[6] = cpu_to_le32((blit->height << 16) | blit->width);
0863     data[7] = cpu_to_le32(dwords);
0864 
0865     buf->used = (dwords + 8) * sizeof(u32);
0866 
0867     r128_cce_dispatch_indirect(dev, buf, 0, buf->used);
0868 
0869     /* Flush the pixel cache after the blit completes.  This ensures
0870      * the texture data is written out to memory before rendering
0871      * continues.
0872      */
0873     BEGIN_RING(2);
0874 
0875     OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));
0876     OUT_RING(R128_PC_FLUSH_GUI);
0877 
0878     ADVANCE_RING();
0879 
0880     return 0;
0881 }
0882 
0883 /* ================================================================
0884  * Tiled depth buffer management
0885  *
0886  * FIXME: These should all set the destination write mask for when we
0887  * have hardware stencil support.
0888  */
0889 
0890 static int r128_cce_dispatch_write_span(struct drm_device *dev,
0891                     drm_r128_depth_t *depth)
0892 {
0893     drm_r128_private_t *dev_priv = dev->dev_private;
0894     int count, x, y;
0895     u32 *buffer;
0896     u8 *mask;
0897     int i, buffer_size, mask_size;
0898     RING_LOCALS;
0899     DRM_DEBUG("\n");
0900 
0901     count = depth->n;
0902     if (count > 4096 || count <= 0)
0903         return -EMSGSIZE;
0904 
0905     if (copy_from_user(&x, depth->x, sizeof(x)))
0906         return -EFAULT;
0907     if (copy_from_user(&y, depth->y, sizeof(y)))
0908         return -EFAULT;
0909 
0910     buffer_size = depth->n * sizeof(u32);
0911     buffer = memdup_user(depth->buffer, buffer_size);
0912     if (IS_ERR(buffer))
0913         return PTR_ERR(buffer);
0914 
0915     mask_size = depth->n;
0916     if (depth->mask) {
0917         mask = memdup_user(depth->mask, mask_size);
0918         if (IS_ERR(mask)) {
0919             kfree(buffer);
0920             return PTR_ERR(mask);
0921         }
0922 
0923         for (i = 0; i < count; i++, x++) {
0924             if (mask[i]) {
0925                 BEGIN_RING(6);
0926 
0927                 OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
0928                 OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
0929                      R128_GMC_BRUSH_SOLID_COLOR |
0930                      (dev_priv->depth_fmt << 8) |
0931                      R128_GMC_SRC_DATATYPE_COLOR |
0932                      R128_ROP3_P |
0933                      R128_GMC_CLR_CMP_CNTL_DIS |
0934                      R128_GMC_WR_MSK_DIS);
0935 
0936                 OUT_RING(dev_priv->depth_pitch_offset_c);
0937                 OUT_RING(buffer[i]);
0938 
0939                 OUT_RING((x << 16) | y);
0940                 OUT_RING((1 << 16) | 1);
0941 
0942                 ADVANCE_RING();
0943             }
0944         }
0945 
0946         kfree(mask);
0947     } else {
0948         for (i = 0; i < count; i++, x++) {
0949             BEGIN_RING(6);
0950 
0951             OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
0952             OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
0953                  R128_GMC_BRUSH_SOLID_COLOR |
0954                  (dev_priv->depth_fmt << 8) |
0955                  R128_GMC_SRC_DATATYPE_COLOR |
0956                  R128_ROP3_P |
0957                  R128_GMC_CLR_CMP_CNTL_DIS |
0958                  R128_GMC_WR_MSK_DIS);
0959 
0960             OUT_RING(dev_priv->depth_pitch_offset_c);
0961             OUT_RING(buffer[i]);
0962 
0963             OUT_RING((x << 16) | y);
0964             OUT_RING((1 << 16) | 1);
0965 
0966             ADVANCE_RING();
0967         }
0968     }
0969 
0970     kfree(buffer);
0971 
0972     return 0;
0973 }
0974 
0975 static int r128_cce_dispatch_write_pixels(struct drm_device *dev,
0976                       drm_r128_depth_t *depth)
0977 {
0978     drm_r128_private_t *dev_priv = dev->dev_private;
0979     int count, *x, *y;
0980     u32 *buffer;
0981     u8 *mask;
0982     int i, xbuf_size, ybuf_size, buffer_size, mask_size;
0983     RING_LOCALS;
0984     DRM_DEBUG("\n");
0985 
0986     count = depth->n;
0987     if (count > 4096 || count <= 0)
0988         return -EMSGSIZE;
0989 
0990     xbuf_size = count * sizeof(*x);
0991     ybuf_size = count * sizeof(*y);
0992     x = memdup_user(depth->x, xbuf_size);
0993     if (IS_ERR(x))
0994         return PTR_ERR(x);
0995     y = memdup_user(depth->y, ybuf_size);
0996     if (IS_ERR(y)) {
0997         kfree(x);
0998         return PTR_ERR(y);
0999     }
1000     buffer_size = depth->n * sizeof(u32);
1001     buffer = memdup_user(depth->buffer, buffer_size);
1002     if (IS_ERR(buffer)) {
1003         kfree(x);
1004         kfree(y);
1005         return PTR_ERR(buffer);
1006     }
1007 
1008     if (depth->mask) {
1009         mask_size = depth->n;
1010         mask = memdup_user(depth->mask, mask_size);
1011         if (IS_ERR(mask)) {
1012             kfree(x);
1013             kfree(y);
1014             kfree(buffer);
1015             return PTR_ERR(mask);
1016         }
1017 
1018         for (i = 0; i < count; i++) {
1019             if (mask[i]) {
1020                 BEGIN_RING(6);
1021 
1022                 OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
1023                 OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
1024                      R128_GMC_BRUSH_SOLID_COLOR |
1025                      (dev_priv->depth_fmt << 8) |
1026                      R128_GMC_SRC_DATATYPE_COLOR |
1027                      R128_ROP3_P |
1028                      R128_GMC_CLR_CMP_CNTL_DIS |
1029                      R128_GMC_WR_MSK_DIS);
1030 
1031                 OUT_RING(dev_priv->depth_pitch_offset_c);
1032                 OUT_RING(buffer[i]);
1033 
1034                 OUT_RING((x[i] << 16) | y[i]);
1035                 OUT_RING((1 << 16) | 1);
1036 
1037                 ADVANCE_RING();
1038             }
1039         }
1040 
1041         kfree(mask);
1042     } else {
1043         for (i = 0; i < count; i++) {
1044             BEGIN_RING(6);
1045 
1046             OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
1047             OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
1048                  R128_GMC_BRUSH_SOLID_COLOR |
1049                  (dev_priv->depth_fmt << 8) |
1050                  R128_GMC_SRC_DATATYPE_COLOR |
1051                  R128_ROP3_P |
1052                  R128_GMC_CLR_CMP_CNTL_DIS |
1053                  R128_GMC_WR_MSK_DIS);
1054 
1055             OUT_RING(dev_priv->depth_pitch_offset_c);
1056             OUT_RING(buffer[i]);
1057 
1058             OUT_RING((x[i] << 16) | y[i]);
1059             OUT_RING((1 << 16) | 1);
1060 
1061             ADVANCE_RING();
1062         }
1063     }
1064 
1065     kfree(x);
1066     kfree(y);
1067     kfree(buffer);
1068 
1069     return 0;
1070 }
1071 
1072 static int r128_cce_dispatch_read_span(struct drm_device *dev,
1073                        drm_r128_depth_t *depth)
1074 {
1075     drm_r128_private_t *dev_priv = dev->dev_private;
1076     int count, x, y;
1077     RING_LOCALS;
1078     DRM_DEBUG("\n");
1079 
1080     count = depth->n;
1081     if (count > 4096 || count <= 0)
1082         return -EMSGSIZE;
1083 
1084     if (copy_from_user(&x, depth->x, sizeof(x)))
1085         return -EFAULT;
1086     if (copy_from_user(&y, depth->y, sizeof(y)))
1087         return -EFAULT;
1088 
1089     BEGIN_RING(7);
1090 
1091     OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
1092     OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
1093          R128_GMC_DST_PITCH_OFFSET_CNTL |
1094          R128_GMC_BRUSH_NONE |
1095          (dev_priv->depth_fmt << 8) |
1096          R128_GMC_SRC_DATATYPE_COLOR |
1097          R128_ROP3_S |
1098          R128_DP_SRC_SOURCE_MEMORY |
1099          R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);
1100 
1101     OUT_RING(dev_priv->depth_pitch_offset_c);
1102     OUT_RING(dev_priv->span_pitch_offset_c);
1103 
1104     OUT_RING((x << 16) | y);
1105     OUT_RING((0 << 16) | 0);
1106     OUT_RING((count << 16) | 1);
1107 
1108     ADVANCE_RING();
1109 
1110     return 0;
1111 }
1112 
1113 static int r128_cce_dispatch_read_pixels(struct drm_device *dev,
1114                      drm_r128_depth_t *depth)
1115 {
1116     drm_r128_private_t *dev_priv = dev->dev_private;
1117     int count, *x, *y;
1118     int i, xbuf_size, ybuf_size;
1119     RING_LOCALS;
1120     DRM_DEBUG("\n");
1121 
1122     count = depth->n;
1123     if (count > 4096 || count <= 0)
1124         return -EMSGSIZE;
1125 
1126     if (count > dev_priv->depth_pitch)
1127         count = dev_priv->depth_pitch;
1128 
1129     xbuf_size = count * sizeof(*x);
1130     ybuf_size = count * sizeof(*y);
1131     x = kmalloc(xbuf_size, GFP_KERNEL);
1132     if (x == NULL)
1133         return -ENOMEM;
1134     y = kmalloc(ybuf_size, GFP_KERNEL);
1135     if (y == NULL) {
1136         kfree(x);
1137         return -ENOMEM;
1138     }
1139     if (copy_from_user(x, depth->x, xbuf_size)) {
1140         kfree(x);
1141         kfree(y);
1142         return -EFAULT;
1143     }
1144     if (copy_from_user(y, depth->y, ybuf_size)) {
1145         kfree(x);
1146         kfree(y);
1147         return -EFAULT;
1148     }
1149 
1150     for (i = 0; i < count; i++) {
1151         BEGIN_RING(7);
1152 
1153         OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
1154         OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
1155              R128_GMC_DST_PITCH_OFFSET_CNTL |
1156              R128_GMC_BRUSH_NONE |
1157              (dev_priv->depth_fmt << 8) |
1158              R128_GMC_SRC_DATATYPE_COLOR |
1159              R128_ROP3_S |
1160              R128_DP_SRC_SOURCE_MEMORY |
1161              R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);
1162 
1163         OUT_RING(dev_priv->depth_pitch_offset_c);
1164         OUT_RING(dev_priv->span_pitch_offset_c);
1165 
1166         OUT_RING((x[i] << 16) | y[i]);
1167         OUT_RING((i << 16) | 0);
1168         OUT_RING((1 << 16) | 1);
1169 
1170         ADVANCE_RING();
1171     }
1172 
1173     kfree(x);
1174     kfree(y);
1175 
1176     return 0;
1177 }
1178 
1179 /* ================================================================
1180  * Polygon stipple
1181  */
1182 
1183 static void r128_cce_dispatch_stipple(struct drm_device *dev, u32 *stipple)
1184 {
1185     drm_r128_private_t *dev_priv = dev->dev_private;
1186     int i;
1187     RING_LOCALS;
1188     DRM_DEBUG("\n");
1189 
1190     BEGIN_RING(33);
1191 
1192     OUT_RING(CCE_PACKET0(R128_BRUSH_DATA0, 31));
1193     for (i = 0; i < 32; i++)
1194         OUT_RING(stipple[i]);
1195 
1196     ADVANCE_RING();
1197 }
1198 
1199 /* ================================================================
1200  * IOCTL functions
1201  */
1202 
1203 static int r128_cce_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
1204 {
1205     drm_r128_private_t *dev_priv = dev->dev_private;
1206     drm_r128_sarea_t *sarea_priv;
1207     drm_r128_clear_t *clear = data;
1208     DRM_DEBUG("\n");
1209 
1210     LOCK_TEST_WITH_RETURN(dev, file_priv);
1211 
1212     DEV_INIT_TEST_WITH_RETURN(dev_priv);
1213 
1214     RING_SPACE_TEST_WITH_RETURN(dev_priv);
1215 
1216     sarea_priv = dev_priv->sarea_priv;
1217 
1218     if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
1219         sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
1220 
1221     r128_cce_dispatch_clear(dev, clear);
1222     COMMIT_RING();
1223 
1224     /* Make sure we restore the 3D state next time.
1225      */
1226     dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
1227 
1228     return 0;
1229 }
1230 
1231 static int r128_do_init_pageflip(struct drm_device *dev)
1232 {
1233     drm_r128_private_t *dev_priv = dev->dev_private;
1234     DRM_DEBUG("\n");
1235 
1236     dev_priv->crtc_offset = R128_READ(R128_CRTC_OFFSET);
1237     dev_priv->crtc_offset_cntl = R128_READ(R128_CRTC_OFFSET_CNTL);
1238 
1239     R128_WRITE(R128_CRTC_OFFSET, dev_priv->front_offset);
1240     R128_WRITE(R128_CRTC_OFFSET_CNTL,
1241            dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL);
1242 
1243     dev_priv->page_flipping = 1;
1244     dev_priv->current_page = 0;
1245     dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
1246 
1247     return 0;
1248 }
1249 
1250 static int r128_do_cleanup_pageflip(struct drm_device *dev)
1251 {
1252     drm_r128_private_t *dev_priv = dev->dev_private;
1253     DRM_DEBUG("\n");
1254 
1255     R128_WRITE(R128_CRTC_OFFSET, dev_priv->crtc_offset);
1256     R128_WRITE(R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl);
1257 
1258     if (dev_priv->current_page != 0) {
1259         r128_cce_dispatch_flip(dev);
1260         COMMIT_RING();
1261     }
1262 
1263     dev_priv->page_flipping = 0;
1264     return 0;
1265 }
1266 
1267 /* Swapping and flipping are different operations, need different ioctls.
1268  * They can & should be intermixed to support multiple 3d windows.
1269  */
1270 
1271 static int r128_cce_flip(struct drm_device *dev, void *data, struct drm_file *file_priv)
1272 {
1273     drm_r128_private_t *dev_priv = dev->dev_private;
1274     DRM_DEBUG("\n");
1275 
1276     LOCK_TEST_WITH_RETURN(dev, file_priv);
1277 
1278     DEV_INIT_TEST_WITH_RETURN(dev_priv);
1279 
1280     RING_SPACE_TEST_WITH_RETURN(dev_priv);
1281 
1282     if (!dev_priv->page_flipping)
1283         r128_do_init_pageflip(dev);
1284 
1285     r128_cce_dispatch_flip(dev);
1286 
1287     COMMIT_RING();
1288     return 0;
1289 }
1290 
1291 static int r128_cce_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
1292 {
1293     drm_r128_private_t *dev_priv = dev->dev_private;
1294     drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
1295     DRM_DEBUG("\n");
1296 
1297     LOCK_TEST_WITH_RETURN(dev, file_priv);
1298 
1299     DEV_INIT_TEST_WITH_RETURN(dev_priv);
1300 
1301     RING_SPACE_TEST_WITH_RETURN(dev_priv);
1302 
1303     if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
1304         sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
1305 
1306     r128_cce_dispatch_swap(dev);
1307     dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
1308                     R128_UPLOAD_MASKS);
1309 
1310     COMMIT_RING();
1311     return 0;
1312 }
1313 
1314 static int r128_cce_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
1315 {
1316     drm_r128_private_t *dev_priv = dev->dev_private;
1317     struct drm_device_dma *dma = dev->dma;
1318     struct drm_buf *buf;
1319     drm_r128_buf_priv_t *buf_priv;
1320     drm_r128_vertex_t *vertex = data;
1321 
1322     LOCK_TEST_WITH_RETURN(dev, file_priv);
1323 
1324     DEV_INIT_TEST_WITH_RETURN(dev_priv);
1325 
1326     DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
1327           task_pid_nr(current), vertex->idx, vertex->count, vertex->discard);
1328 
1329     if (vertex->idx < 0 || vertex->idx >= dma->buf_count) {
1330         DRM_ERROR("buffer index %d (of %d max)\n",
1331               vertex->idx, dma->buf_count - 1);
1332         return -EINVAL;
1333     }
1334     if (vertex->prim < 0 ||
1335         vertex->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
1336         DRM_ERROR("buffer prim %d\n", vertex->prim);
1337         return -EINVAL;
1338     }
1339 
1340     RING_SPACE_TEST_WITH_RETURN(dev_priv);
1341     VB_AGE_TEST_WITH_RETURN(dev_priv);
1342 
1343     buf = dma->buflist[vertex->idx];
1344     buf_priv = buf->dev_private;
1345 
1346     if (buf->file_priv != file_priv) {
1347         DRM_ERROR("process %d using buffer owned by %p\n",
1348               task_pid_nr(current), buf->file_priv);
1349         return -EINVAL;
1350     }
1351     if (buf->pending) {
1352         DRM_ERROR("sending pending buffer %d\n", vertex->idx);
1353         return -EINVAL;
1354     }
1355 
1356     buf->used = vertex->count;
1357     buf_priv->prim = vertex->prim;
1358     buf_priv->discard = vertex->discard;
1359 
1360     r128_cce_dispatch_vertex(dev, buf);
1361 
1362     COMMIT_RING();
1363     return 0;
1364 }
1365 
1366 static int r128_cce_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
1367 {
1368     drm_r128_private_t *dev_priv = dev->dev_private;
1369     struct drm_device_dma *dma = dev->dma;
1370     struct drm_buf *buf;
1371     drm_r128_buf_priv_t *buf_priv;
1372     drm_r128_indices_t *elts = data;
1373     int count;
1374 
1375     LOCK_TEST_WITH_RETURN(dev, file_priv);
1376 
1377     DEV_INIT_TEST_WITH_RETURN(dev_priv);
1378 
1379     DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", task_pid_nr(current),
1380           elts->idx, elts->start, elts->end, elts->discard);
1381 
1382     if (elts->idx < 0 || elts->idx >= dma->buf_count) {
1383         DRM_ERROR("buffer index %d (of %d max)\n",
1384               elts->idx, dma->buf_count - 1);
1385         return -EINVAL;
1386     }
1387     if (elts->prim < 0 ||
1388         elts->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
1389         DRM_ERROR("buffer prim %d\n", elts->prim);
1390         return -EINVAL;
1391     }
1392 
1393     RING_SPACE_TEST_WITH_RETURN(dev_priv);
1394     VB_AGE_TEST_WITH_RETURN(dev_priv);
1395 
1396     buf = dma->buflist[elts->idx];
1397     buf_priv = buf->dev_private;
1398 
1399     if (buf->file_priv != file_priv) {
1400         DRM_ERROR("process %d using buffer owned by %p\n",
1401               task_pid_nr(current), buf->file_priv);
1402         return -EINVAL;
1403     }
1404     if (buf->pending) {
1405         DRM_ERROR("sending pending buffer %d\n", elts->idx);
1406         return -EINVAL;
1407     }
1408 
1409     count = (elts->end - elts->start) / sizeof(u16);
1410     elts->start -= R128_INDEX_PRIM_OFFSET;
1411 
1412     if (elts->start & 0x7) {
1413         DRM_ERROR("misaligned buffer 0x%x\n", elts->start);
1414         return -EINVAL;
1415     }
1416     if (elts->start < buf->used) {
1417         DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used);
1418         return -EINVAL;
1419     }
1420 
1421     buf->used = elts->end;
1422     buf_priv->prim = elts->prim;
1423     buf_priv->discard = elts->discard;
1424 
1425     r128_cce_dispatch_indices(dev, buf, elts->start, elts->end, count);
1426 
1427     COMMIT_RING();
1428     return 0;
1429 }
1430 
1431 static int r128_cce_blit(struct drm_device *dev, void *data, struct drm_file *file_priv)
1432 {
1433     struct drm_device_dma *dma = dev->dma;
1434     drm_r128_private_t *dev_priv = dev->dev_private;
1435     drm_r128_blit_t *blit = data;
1436     int ret;
1437 
1438     LOCK_TEST_WITH_RETURN(dev, file_priv);
1439 
1440     DEV_INIT_TEST_WITH_RETURN(dev_priv);
1441 
1442     DRM_DEBUG("pid=%d index=%d\n", task_pid_nr(current), blit->idx);
1443 
1444     if (blit->idx < 0 || blit->idx >= dma->buf_count) {
1445         DRM_ERROR("buffer index %d (of %d max)\n",
1446               blit->idx, dma->buf_count - 1);
1447         return -EINVAL;
1448     }
1449 
1450     RING_SPACE_TEST_WITH_RETURN(dev_priv);
1451     VB_AGE_TEST_WITH_RETURN(dev_priv);
1452 
1453     ret = r128_cce_dispatch_blit(dev, file_priv, blit);
1454 
1455     COMMIT_RING();
1456     return ret;
1457 }
1458 
1459 int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv)
1460 {
1461     drm_r128_private_t *dev_priv = dev->dev_private;
1462     drm_r128_depth_t *depth = data;
1463     int ret;
1464 
1465     LOCK_TEST_WITH_RETURN(dev, file_priv);
1466 
1467     DEV_INIT_TEST_WITH_RETURN(dev_priv);
1468 
1469     RING_SPACE_TEST_WITH_RETURN(dev_priv);
1470 
1471     ret = -EINVAL;
1472     switch (depth->func) {
1473     case R128_WRITE_SPAN:
1474         ret = r128_cce_dispatch_write_span(dev, depth);
1475         break;
1476     case R128_WRITE_PIXELS:
1477         ret = r128_cce_dispatch_write_pixels(dev, depth);
1478         break;
1479     case R128_READ_SPAN:
1480         ret = r128_cce_dispatch_read_span(dev, depth);
1481         break;
1482     case R128_READ_PIXELS:
1483         ret = r128_cce_dispatch_read_pixels(dev, depth);
1484         break;
1485     }
1486 
1487     COMMIT_RING();
1488     return ret;
1489 }
1490 
1491 int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv)
1492 {
1493     drm_r128_private_t *dev_priv = dev->dev_private;
1494     drm_r128_stipple_t *stipple = data;
1495     u32 mask[32];
1496 
1497     LOCK_TEST_WITH_RETURN(dev, file_priv);
1498 
1499     DEV_INIT_TEST_WITH_RETURN(dev_priv);
1500 
1501     if (copy_from_user(&mask, stipple->mask, 32 * sizeof(u32)))
1502         return -EFAULT;
1503 
1504     RING_SPACE_TEST_WITH_RETURN(dev_priv);
1505 
1506     r128_cce_dispatch_stipple(dev, mask);
1507 
1508     COMMIT_RING();
1509     return 0;
1510 }
1511 
1512 static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv)
1513 {
1514     drm_r128_private_t *dev_priv = dev->dev_private;
1515     struct drm_device_dma *dma = dev->dma;
1516     struct drm_buf *buf;
1517     drm_r128_buf_priv_t *buf_priv;
1518     drm_r128_indirect_t *indirect = data;
1519 #if 0
1520     RING_LOCALS;
1521 #endif
1522 
1523     LOCK_TEST_WITH_RETURN(dev, file_priv);
1524 
1525     DEV_INIT_TEST_WITH_RETURN(dev_priv);
1526 
1527     DRM_DEBUG("idx=%d s=%d e=%d d=%d\n",
1528           indirect->idx, indirect->start, indirect->end,
1529           indirect->discard);
1530 
1531     if (indirect->idx < 0 || indirect->idx >= dma->buf_count) {
1532         DRM_ERROR("buffer index %d (of %d max)\n",
1533               indirect->idx, dma->buf_count - 1);
1534         return -EINVAL;
1535     }
1536 
1537     buf = dma->buflist[indirect->idx];
1538     buf_priv = buf->dev_private;
1539 
1540     if (buf->file_priv != file_priv) {
1541         DRM_ERROR("process %d using buffer owned by %p\n",
1542               task_pid_nr(current), buf->file_priv);
1543         return -EINVAL;
1544     }
1545     if (buf->pending) {
1546         DRM_ERROR("sending pending buffer %d\n", indirect->idx);
1547         return -EINVAL;
1548     }
1549 
1550     if (indirect->start < buf->used) {
1551         DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
1552               indirect->start, buf->used);
1553         return -EINVAL;
1554     }
1555 
1556     RING_SPACE_TEST_WITH_RETURN(dev_priv);
1557     VB_AGE_TEST_WITH_RETURN(dev_priv);
1558 
1559     buf->used = indirect->end;
1560     buf_priv->discard = indirect->discard;
1561 
1562 #if 0
1563     /* Wait for the 3D stream to idle before the indirect buffer
1564      * containing 2D acceleration commands is processed.
1565      */
1566     BEGIN_RING(2);
1567     RADEON_WAIT_UNTIL_3D_IDLE();
1568     ADVANCE_RING();
1569 #endif
1570 
1571     /* Dispatch the indirect buffer full of commands from the
1572      * X server.  This is insecure and is thus only available to
1573      * privileged clients.
1574      */
1575     r128_cce_dispatch_indirect(dev, buf, indirect->start, indirect->end);
1576 
1577     COMMIT_RING();
1578     return 0;
1579 }
1580 
1581 int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
1582 {
1583     drm_r128_private_t *dev_priv = dev->dev_private;
1584     drm_r128_getparam_t *param = data;
1585     struct pci_dev *pdev = to_pci_dev(dev->dev);
1586     int value;
1587 
1588     DEV_INIT_TEST_WITH_RETURN(dev_priv);
1589 
1590     DRM_DEBUG("pid=%d\n", task_pid_nr(current));
1591 
1592     switch (param->param) {
1593     case R128_PARAM_IRQ_NR:
1594         value = pdev->irq;
1595         break;
1596     default:
1597         return -EINVAL;
1598     }
1599 
1600     if (copy_to_user(param->value, &value, sizeof(int))) {
1601         DRM_ERROR("copy_to_user\n");
1602         return -EFAULT;
1603     }
1604 
1605     return 0;
1606 }
1607 
1608 void r128_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
1609 {
1610     if (dev->dev_private) {
1611         drm_r128_private_t *dev_priv = dev->dev_private;
1612         if (dev_priv->page_flipping)
1613             r128_do_cleanup_pageflip(dev);
1614     }
1615 }
1616 void r128_driver_lastclose(struct drm_device *dev)
1617 {
1618     r128_do_cleanup_cce(dev);
1619 }
1620 
1621 const struct drm_ioctl_desc r128_ioctls[] = {
1622     DRM_IOCTL_DEF_DRV(R128_INIT, r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1623     DRM_IOCTL_DEF_DRV(R128_CCE_START, r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1624     DRM_IOCTL_DEF_DRV(R128_CCE_STOP, r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1625     DRM_IOCTL_DEF_DRV(R128_CCE_RESET, r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1626     DRM_IOCTL_DEF_DRV(R128_CCE_IDLE, r128_cce_idle, DRM_AUTH),
1627     DRM_IOCTL_DEF_DRV(R128_RESET, r128_engine_reset, DRM_AUTH),
1628     DRM_IOCTL_DEF_DRV(R128_FULLSCREEN, r128_fullscreen, DRM_AUTH),
1629     DRM_IOCTL_DEF_DRV(R128_SWAP, r128_cce_swap, DRM_AUTH),
1630     DRM_IOCTL_DEF_DRV(R128_FLIP, r128_cce_flip, DRM_AUTH),
1631     DRM_IOCTL_DEF_DRV(R128_CLEAR, r128_cce_clear, DRM_AUTH),
1632     DRM_IOCTL_DEF_DRV(R128_VERTEX, r128_cce_vertex, DRM_AUTH),
1633     DRM_IOCTL_DEF_DRV(R128_INDICES, r128_cce_indices, DRM_AUTH),
1634     DRM_IOCTL_DEF_DRV(R128_BLIT, r128_cce_blit, DRM_AUTH),
1635     DRM_IOCTL_DEF_DRV(R128_DEPTH, r128_cce_depth, DRM_AUTH),
1636     DRM_IOCTL_DEF_DRV(R128_STIPPLE, r128_cce_stipple, DRM_AUTH),
1637     DRM_IOCTL_DEF_DRV(R128_INDIRECT, r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1638     DRM_IOCTL_DEF_DRV(R128_GETPARAM, r128_getparam, DRM_AUTH),
1639 };
1640 
1641 int r128_max_ioctl = ARRAY_SIZE(r128_ioctls);