Back to home page

OSCL-LXR

 
 

    


0001 /* r128_drv.h -- Private header for r128 driver -*- linux-c -*-
0002  * Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com
0003  */
0004 /*
0005  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
0006  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
0007  * All rights reserved.
0008  *
0009  * Permission is hereby granted, free of charge, to any person obtaining a
0010  * copy of this software and associated documentation files (the "Software"),
0011  * to deal in the Software without restriction, including without limitation
0012  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0013  * and/or sell copies of the Software, and to permit persons to whom the
0014  * Software is furnished to do so, subject to the following conditions:
0015  *
0016  * The above copyright notice and this permission notice (including the next
0017  * paragraph) shall be included in all copies or substantial portions of the
0018  * Software.
0019  *
0020  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0021  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0022  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0023  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
0024  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0025  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
0026  * DEALINGS IN THE SOFTWARE.
0027  *
0028  * Authors:
0029  *    Rickard E. (Rik) Faith <faith@valinux.com>
0030  *    Kevin E. Martin <martin@valinux.com>
0031  *    Gareth Hughes <gareth@valinux.com>
0032  *    Michel Dänzer <daenzerm@student.ethz.ch>
0033  */
0034 
0035 #ifndef __R128_DRV_H__
0036 #define __R128_DRV_H__
0037 
0038 #include <linux/delay.h>
0039 #include <linux/io.h>
0040 #include <linux/irqreturn.h>
0041 
0042 #include <drm/drm_ioctl.h>
0043 #include <drm/drm_legacy.h>
0044 #include <drm/r128_drm.h>
0045 
0046 #include "ati_pcigart.h"
0047 
0048 /* General customization:
0049  */
0050 #define DRIVER_AUTHOR       "Gareth Hughes, VA Linux Systems Inc."
0051 
0052 #define DRIVER_NAME     "r128"
0053 #define DRIVER_DESC     "ATI Rage 128"
0054 #define DRIVER_DATE     "20030725"
0055 
0056 /* Interface history:
0057  *
0058  * ??  - ??
0059  * 2.4 - Add support for ycbcr textures (no new ioctls)
0060  * 2.5 - Add FLIP ioctl, disable FULLSCREEN.
0061  */
0062 #define DRIVER_MAJOR        2
0063 #define DRIVER_MINOR        5
0064 #define DRIVER_PATCHLEVEL   0
0065 
0066 #define GET_RING_HEAD(dev_priv)     R128_READ(R128_PM4_BUFFER_DL_RPTR)
0067 
0068 typedef struct drm_r128_freelist {
0069     unsigned int age;
0070     struct drm_buf *buf;
0071     struct drm_r128_freelist *next;
0072     struct drm_r128_freelist *prev;
0073 } drm_r128_freelist_t;
0074 
0075 typedef struct drm_r128_ring_buffer {
0076     u32 *start;
0077     u32 *end;
0078     int size;
0079     int size_l2qw;
0080 
0081     u32 tail;
0082     u32 tail_mask;
0083     int space;
0084 
0085     int high_mark;
0086 } drm_r128_ring_buffer_t;
0087 
0088 typedef struct drm_r128_private {
0089     drm_r128_ring_buffer_t ring;
0090     drm_r128_sarea_t *sarea_priv;
0091 
0092     int cce_mode;
0093     int cce_fifo_size;
0094     int cce_running;
0095 
0096     drm_r128_freelist_t *head;
0097     drm_r128_freelist_t *tail;
0098 
0099     int usec_timeout;
0100     int is_pci;
0101     unsigned long cce_buffers_offset;
0102 
0103     atomic_t idle_count;
0104 
0105     int page_flipping;
0106     int current_page;
0107     u32 crtc_offset;
0108     u32 crtc_offset_cntl;
0109 
0110     atomic_t vbl_received;
0111 
0112     u32 color_fmt;
0113     unsigned int front_offset;
0114     unsigned int front_pitch;
0115     unsigned int back_offset;
0116     unsigned int back_pitch;
0117 
0118     u32 depth_fmt;
0119     unsigned int depth_offset;
0120     unsigned int depth_pitch;
0121     unsigned int span_offset;
0122 
0123     u32 front_pitch_offset_c;
0124     u32 back_pitch_offset_c;
0125     u32 depth_pitch_offset_c;
0126     u32 span_pitch_offset_c;
0127 
0128     drm_local_map_t *sarea;
0129     drm_local_map_t *mmio;
0130     drm_local_map_t *cce_ring;
0131     drm_local_map_t *ring_rptr;
0132     drm_local_map_t *agp_textures;
0133     struct drm_ati_pcigart_info gart_info;
0134 } drm_r128_private_t;
0135 
0136 typedef struct drm_r128_buf_priv {
0137     u32 age;
0138     int prim;
0139     int discard;
0140     int dispatched;
0141     drm_r128_freelist_t *list_entry;
0142 } drm_r128_buf_priv_t;
0143 
0144 extern const struct drm_ioctl_desc r128_ioctls[];
0145 extern int r128_max_ioctl;
0146 
0147                 /* r128_cce.c */
0148 extern int r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
0149 extern int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv);
0150 extern int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv);
0151 extern int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_priv);
0152 extern int r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv);
0153 extern int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv);
0154 extern int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv);
0155 extern int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv);
0156 
0157 extern int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv);
0158 extern int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv);
0159 extern int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv);
0160 
0161 extern void r128_freelist_reset(struct drm_device *dev);
0162 
0163 extern int r128_wait_ring(drm_r128_private_t *dev_priv, int n);
0164 
0165 extern int r128_do_cce_idle(drm_r128_private_t *dev_priv);
0166 extern int r128_do_cleanup_cce(struct drm_device *dev);
0167 
0168 extern int r128_enable_vblank(struct drm_device *dev, unsigned int pipe);
0169 extern void r128_disable_vblank(struct drm_device *dev, unsigned int pipe);
0170 extern u32 r128_get_vblank_counter(struct drm_device *dev, unsigned int pipe);
0171 extern irqreturn_t r128_driver_irq_handler(int irq, void *arg);
0172 extern void r128_driver_irq_preinstall(struct drm_device *dev);
0173 extern int r128_driver_irq_postinstall(struct drm_device *dev);
0174 extern void r128_driver_irq_uninstall(struct drm_device *dev);
0175 extern void r128_driver_lastclose(struct drm_device *dev);
0176 extern int r128_driver_load(struct drm_device *dev, unsigned long flags);
0177 extern void r128_driver_preclose(struct drm_device *dev,
0178                  struct drm_file *file_priv);
0179 
0180 extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
0181                   unsigned long arg);
0182 
0183 /* Register definitions, register access macros and drmAddMap constants
0184  * for Rage 128 kernel driver.
0185  */
0186 
0187 #define R128_AUX_SC_CNTL        0x1660
0188 #   define R128_AUX1_SC_EN          (1 << 0)
0189 #   define R128_AUX1_SC_MODE_OR     (0 << 1)
0190 #   define R128_AUX1_SC_MODE_NAND       (1 << 1)
0191 #   define R128_AUX2_SC_EN          (1 << 2)
0192 #   define R128_AUX2_SC_MODE_OR     (0 << 3)
0193 #   define R128_AUX2_SC_MODE_NAND       (1 << 3)
0194 #   define R128_AUX3_SC_EN          (1 << 4)
0195 #   define R128_AUX3_SC_MODE_OR     (0 << 5)
0196 #   define R128_AUX3_SC_MODE_NAND       (1 << 5)
0197 #define R128_AUX1_SC_LEFT       0x1664
0198 #define R128_AUX1_SC_RIGHT      0x1668
0199 #define R128_AUX1_SC_TOP        0x166c
0200 #define R128_AUX1_SC_BOTTOM     0x1670
0201 #define R128_AUX2_SC_LEFT       0x1674
0202 #define R128_AUX2_SC_RIGHT      0x1678
0203 #define R128_AUX2_SC_TOP        0x167c
0204 #define R128_AUX2_SC_BOTTOM     0x1680
0205 #define R128_AUX3_SC_LEFT       0x1684
0206 #define R128_AUX3_SC_RIGHT      0x1688
0207 #define R128_AUX3_SC_TOP        0x168c
0208 #define R128_AUX3_SC_BOTTOM     0x1690
0209 
0210 #define R128_BRUSH_DATA0        0x1480
0211 #define R128_BUS_CNTL           0x0030
0212 #   define R128_BUS_MASTER_DIS      (1 << 6)
0213 
0214 #define R128_CLOCK_CNTL_INDEX       0x0008
0215 #define R128_CLOCK_CNTL_DATA        0x000c
0216 #   define R128_PLL_WR_EN           (1 << 7)
0217 #define R128_CONSTANT_COLOR_C       0x1d34
0218 #define R128_CRTC_OFFSET        0x0224
0219 #define R128_CRTC_OFFSET_CNTL       0x0228
0220 #   define R128_CRTC_OFFSET_FLIP_CNTL   (1 << 16)
0221 
0222 #define R128_DP_GUI_MASTER_CNTL     0x146c
0223 #       define R128_GMC_SRC_PITCH_OFFSET_CNTL   (1    <<  0)
0224 #       define R128_GMC_DST_PITCH_OFFSET_CNTL   (1    <<  1)
0225 #   define R128_GMC_BRUSH_SOLID_COLOR   (13   <<  4)
0226 #   define R128_GMC_BRUSH_NONE      (15   <<  4)
0227 #   define R128_GMC_DST_16BPP       (4    <<  8)
0228 #   define R128_GMC_DST_24BPP       (5    <<  8)
0229 #   define R128_GMC_DST_32BPP       (6    <<  8)
0230 #       define R128_GMC_DST_DATATYPE_SHIFT  8
0231 #   define R128_GMC_SRC_DATATYPE_COLOR  (3    << 12)
0232 #   define R128_DP_SRC_SOURCE_MEMORY    (2    << 24)
0233 #   define R128_DP_SRC_SOURCE_HOST_DATA (3    << 24)
0234 #   define R128_GMC_CLR_CMP_CNTL_DIS    (1    << 28)
0235 #   define R128_GMC_AUX_CLIP_DIS        (1    << 29)
0236 #   define R128_GMC_WR_MSK_DIS      (1    << 30)
0237 #   define R128_ROP3_S          0x00cc0000
0238 #   define R128_ROP3_P          0x00f00000
0239 #define R128_DP_WRITE_MASK      0x16cc
0240 #define R128_DST_PITCH_OFFSET_C     0x1c80
0241 #   define R128_DST_TILE            (1 << 31)
0242 
0243 #define R128_GEN_INT_CNTL       0x0040
0244 #   define R128_CRTC_VBLANK_INT_EN      (1 <<  0)
0245 #define R128_GEN_INT_STATUS     0x0044
0246 #   define R128_CRTC_VBLANK_INT     (1 <<  0)
0247 #   define R128_CRTC_VBLANK_INT_AK      (1 <<  0)
0248 #define R128_GEN_RESET_CNTL     0x00f0
0249 #   define R128_SOFT_RESET_GUI      (1 <<  0)
0250 
0251 #define R128_GUI_SCRATCH_REG0       0x15e0
0252 #define R128_GUI_SCRATCH_REG1       0x15e4
0253 #define R128_GUI_SCRATCH_REG2       0x15e8
0254 #define R128_GUI_SCRATCH_REG3       0x15ec
0255 #define R128_GUI_SCRATCH_REG4       0x15f0
0256 #define R128_GUI_SCRATCH_REG5       0x15f4
0257 
0258 #define R128_GUI_STAT           0x1740
0259 #   define R128_GUI_FIFOCNT_MASK        0x0fff
0260 #   define R128_GUI_ACTIVE          (1 << 31)
0261 
0262 #define R128_MCLK_CNTL          0x000f
0263 #   define R128_FORCE_GCP           (1 << 16)
0264 #   define R128_FORCE_PIPE3D_CP     (1 << 17)
0265 #   define R128_FORCE_RCP           (1 << 18)
0266 
0267 #define R128_PC_GUI_CTLSTAT     0x1748
0268 #define R128_PC_NGUI_CTLSTAT        0x0184
0269 #   define R128_PC_FLUSH_GUI        (3 << 0)
0270 #   define R128_PC_RI_GUI           (1 << 2)
0271 #   define R128_PC_FLUSH_ALL        0x00ff
0272 #   define R128_PC_BUSY         (1 << 31)
0273 
0274 #define R128_PCI_GART_PAGE      0x017c
0275 #define R128_PRIM_TEX_CNTL_C        0x1cb0
0276 
0277 #define R128_SCALE_3D_CNTL      0x1a00
0278 #define R128_SEC_TEX_CNTL_C     0x1d00
0279 #define R128_SEC_TEXTURE_BORDER_COLOR_C 0x1d3c
0280 #define R128_SETUP_CNTL         0x1bc4
0281 #define R128_STEN_REF_MASK_C        0x1d40
0282 
0283 #define R128_TEX_CNTL_C         0x1c9c
0284 #   define R128_TEX_CACHE_FLUSH     (1 << 23)
0285 
0286 #define R128_WAIT_UNTIL         0x1720
0287 #   define R128_EVENT_CRTC_OFFSET       (1 << 0)
0288 #define R128_WINDOW_XY_OFFSET       0x1bcc
0289 
0290 /* CCE registers
0291  */
0292 #define R128_PM4_BUFFER_OFFSET      0x0700
0293 #define R128_PM4_BUFFER_CNTL        0x0704
0294 #   define R128_PM4_MASK            (15 << 28)
0295 #   define R128_PM4_NONPM4          (0  << 28)
0296 #   define R128_PM4_192PIO          (1  << 28)
0297 #   define R128_PM4_192BM           (2  << 28)
0298 #   define R128_PM4_128PIO_64INDBM      (3  << 28)
0299 #   define R128_PM4_128BM_64INDBM       (4  << 28)
0300 #   define R128_PM4_64PIO_128INDBM      (5  << 28)
0301 #   define R128_PM4_64BM_128INDBM       (6  << 28)
0302 #   define R128_PM4_64PIO_64VCBM_64INDBM    (7  << 28)
0303 #   define R128_PM4_64BM_64VCBM_64INDBM (8U  << 28)
0304 #   define R128_PM4_64PIO_64VCPIO_64INDPIO  (15U << 28)
0305 #   define R128_PM4_BUFFER_CNTL_NOUPDATE    (1  << 27)
0306 
0307 #define R128_PM4_BUFFER_WM_CNTL     0x0708
0308 #   define R128_WMA_SHIFT           0
0309 #   define R128_WMB_SHIFT           8
0310 #   define R128_WMC_SHIFT           16
0311 #   define R128_WB_WM_SHIFT         24
0312 
0313 #define R128_PM4_BUFFER_DL_RPTR_ADDR    0x070c
0314 #define R128_PM4_BUFFER_DL_RPTR     0x0710
0315 #define R128_PM4_BUFFER_DL_WPTR     0x0714
0316 #   define R128_PM4_BUFFER_DL_DONE      (1 << 31)
0317 
0318 #define R128_PM4_VC_FPU_SETUP       0x071c
0319 
0320 #define R128_PM4_IW_INDOFF      0x0738
0321 #define R128_PM4_IW_INDSIZE     0x073c
0322 
0323 #define R128_PM4_STAT           0x07b8
0324 #   define R128_PM4_FIFOCNT_MASK        0x0fff
0325 #   define R128_PM4_BUSY            (1 << 16)
0326 #   define R128_PM4_GUI_ACTIVE      (1 << 31)
0327 
0328 #define R128_PM4_MICROCODE_ADDR     0x07d4
0329 #define R128_PM4_MICROCODE_RADDR    0x07d8
0330 #define R128_PM4_MICROCODE_DATAH    0x07dc
0331 #define R128_PM4_MICROCODE_DATAL    0x07e0
0332 
0333 #define R128_PM4_BUFFER_ADDR        0x07f0
0334 #define R128_PM4_MICRO_CNTL     0x07fc
0335 #   define R128_PM4_MICRO_FREERUN       (1 << 30)
0336 
0337 #define R128_PM4_FIFO_DATA_EVEN     0x1000
0338 #define R128_PM4_FIFO_DATA_ODD      0x1004
0339 
0340 /* CCE command packets
0341  */
0342 #define R128_CCE_PACKET0        0x00000000
0343 #define R128_CCE_PACKET1        0x40000000
0344 #define R128_CCE_PACKET2        0x80000000
0345 #define R128_CCE_PACKET3        0xC0000000
0346 #   define R128_CNTL_HOSTDATA_BLT       0x00009400
0347 #   define R128_CNTL_PAINT_MULTI        0x00009A00
0348 #   define R128_CNTL_BITBLT_MULTI       0x00009B00
0349 #   define R128_3D_RNDR_GEN_INDX_PRIM   0x00002300
0350 
0351 #define R128_CCE_PACKET_MASK        0xC0000000
0352 #define R128_CCE_PACKET_COUNT_MASK  0x3fff0000
0353 #define R128_CCE_PACKET0_REG_MASK   0x000007ff
0354 #define R128_CCE_PACKET1_REG0_MASK  0x000007ff
0355 #define R128_CCE_PACKET1_REG1_MASK  0x003ff800
0356 
0357 #define R128_CCE_VC_CNTL_PRIM_TYPE_NONE     0x00000000
0358 #define R128_CCE_VC_CNTL_PRIM_TYPE_POINT    0x00000001
0359 #define R128_CCE_VC_CNTL_PRIM_TYPE_LINE     0x00000002
0360 #define R128_CCE_VC_CNTL_PRIM_TYPE_POLY_LINE    0x00000003
0361 #define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST 0x00000004
0362 #define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN  0x00000005
0363 #define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_STRIP    0x00000006
0364 #define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2    0x00000007
0365 #define R128_CCE_VC_CNTL_PRIM_WALK_IND      0x00000010
0366 #define R128_CCE_VC_CNTL_PRIM_WALK_LIST     0x00000020
0367 #define R128_CCE_VC_CNTL_PRIM_WALK_RING     0x00000030
0368 #define R128_CCE_VC_CNTL_NUM_SHIFT      16
0369 
0370 #define R128_DATATYPE_VQ        0
0371 #define R128_DATATYPE_CI4       1
0372 #define R128_DATATYPE_CI8       2
0373 #define R128_DATATYPE_ARGB1555      3
0374 #define R128_DATATYPE_RGB565        4
0375 #define R128_DATATYPE_RGB888        5
0376 #define R128_DATATYPE_ARGB8888      6
0377 #define R128_DATATYPE_RGB332        7
0378 #define R128_DATATYPE_Y8        8
0379 #define R128_DATATYPE_RGB8      9
0380 #define R128_DATATYPE_CI16      10
0381 #define R128_DATATYPE_YVYU422       11
0382 #define R128_DATATYPE_VYUY422       12
0383 #define R128_DATATYPE_AYUV444       14
0384 #define R128_DATATYPE_ARGB4444      15
0385 
0386 /* Constants */
0387 #define R128_AGP_OFFSET         0x02000000
0388 
0389 #define R128_WATERMARK_L        16
0390 #define R128_WATERMARK_M        8
0391 #define R128_WATERMARK_N        8
0392 #define R128_WATERMARK_K        128
0393 
0394 #define R128_MAX_USEC_TIMEOUT       100000  /* 100 ms */
0395 
0396 #define R128_LAST_FRAME_REG     R128_GUI_SCRATCH_REG0
0397 #define R128_LAST_DISPATCH_REG      R128_GUI_SCRATCH_REG1
0398 #define R128_MAX_VB_AGE         0x7fffffff
0399 #define R128_MAX_VB_VERTS       (0xffff)
0400 
0401 #define R128_RING_HIGH_MARK     128
0402 
0403 #define R128_PERFORMANCE_BOXES      0
0404 
0405 #define R128_PCIGART_TABLE_SIZE         32768
0406 
0407 #define R128_READ(reg)      readl(((void __iomem *)dev_priv->mmio->handle) + (reg))
0408 #define R128_WRITE(reg, val)    writel(val, ((void __iomem *)dev_priv->mmio->handle) + (reg))
0409 #define R128_READ8(reg)     readb(((void __iomem *)dev_priv->mmio->handle) + (reg))
0410 #define R128_WRITE8(reg, val)   writeb(val, ((void __iomem *)dev_priv->mmio->handle) + (reg))
0411 
0412 #define R128_WRITE_PLL(addr, val)                   \
0413 do {                                    \
0414     R128_WRITE8(R128_CLOCK_CNTL_INDEX,              \
0415             ((addr) & 0x1f) | R128_PLL_WR_EN);          \
0416     R128_WRITE(R128_CLOCK_CNTL_DATA, (val));            \
0417 } while (0)
0418 
0419 #define CCE_PACKET0(reg, n)     (R128_CCE_PACKET0 |     \
0420                      ((n) << 16) | ((reg) >> 2))
0421 #define CCE_PACKET1(reg0, reg1)     (R128_CCE_PACKET1 |     \
0422                      (((reg1) >> 2) << 11) | ((reg0) >> 2))
0423 #define CCE_PACKET2()           (R128_CCE_PACKET2)
0424 #define CCE_PACKET3(pkt, n)     (R128_CCE_PACKET3 |     \
0425                      (pkt) | ((n) << 16))
0426 
0427 static __inline__ void r128_update_ring_snapshot(drm_r128_private_t *dev_priv)
0428 {
0429     drm_r128_ring_buffer_t *ring = &dev_priv->ring;
0430     ring->space = (GET_RING_HEAD(dev_priv) - ring->tail) * sizeof(u32);
0431     if (ring->space <= 0)
0432         ring->space += ring->size;
0433 }
0434 
0435 /* ================================================================
0436  * Misc helper macros
0437  */
0438 
0439 #define DEV_INIT_TEST_WITH_RETURN(_dev_priv)                \
0440 do {                                    \
0441     if (!_dev_priv) {                       \
0442         DRM_ERROR("called with no initialization\n");       \
0443         return -EINVAL;                     \
0444     }                               \
0445 } while (0)
0446 
0447 #define RING_SPACE_TEST_WITH_RETURN(dev_priv)               \
0448 do {                                    \
0449     drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i;      \
0450     if (ring->space < ring->high_mark) {                \
0451         for (i = 0 ; i < dev_priv->usec_timeout ; i++) {    \
0452             r128_update_ring_snapshot(dev_priv);        \
0453             if (ring->space >= ring->high_mark)     \
0454                 goto __ring_space_done;         \
0455             udelay(1);                  \
0456         }                           \
0457         DRM_ERROR("ring space check failed!\n");        \
0458         return -EBUSY;                      \
0459     }                               \
0460  __ring_space_done:                         \
0461     ;                               \
0462 } while (0)
0463 
0464 #define VB_AGE_TEST_WITH_RETURN(dev_priv)               \
0465 do {                                    \
0466     drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;        \
0467     if (sarea_priv->last_dispatch >= R128_MAX_VB_AGE) {     \
0468         int __ret = r128_do_cce_idle(dev_priv);         \
0469         if (__ret)                      \
0470             return __ret;                   \
0471         sarea_priv->last_dispatch = 0;              \
0472         r128_freelist_reset(dev);               \
0473     }                               \
0474 } while (0)
0475 
0476 #define R128_WAIT_UNTIL_PAGE_FLIPPED() do {             \
0477     OUT_RING(CCE_PACKET0(R128_WAIT_UNTIL, 0));          \
0478     OUT_RING(R128_EVENT_CRTC_OFFSET);               \
0479 } while (0)
0480 
0481 /* ================================================================
0482  * Ring control
0483  */
0484 
0485 #define R128_VERBOSE    0
0486 
0487 #define RING_LOCALS                         \
0488     int write, _nr; unsigned int tail_mask; volatile u32 *ring;
0489 
0490 #define BEGIN_RING(n) do {                      \
0491     if (R128_VERBOSE)                       \
0492         DRM_INFO("BEGIN_RING(%d)\n", (n));          \
0493     if (dev_priv->ring.space <= (n) * sizeof(u32)) {        \
0494         COMMIT_RING();                      \
0495         r128_wait_ring(dev_priv, (n) * sizeof(u32));        \
0496     }                               \
0497     _nr = n; dev_priv->ring.space -= (n) * sizeof(u32);     \
0498     ring = dev_priv->ring.start;                    \
0499     write = dev_priv->ring.tail;                    \
0500     tail_mask = dev_priv->ring.tail_mask;               \
0501 } while (0)
0502 
0503 /* You can set this to zero if you want.  If the card locks up, you'll
0504  * need to keep this set.  It works around a bug in early revs of the
0505  * Rage 128 chipset, where the CCE would read 32 dwords past the end of
0506  * the ring buffer before wrapping around.
0507  */
0508 #define R128_BROKEN_CCE 1
0509 
0510 #define ADVANCE_RING() do {                     \
0511     if (R128_VERBOSE)                       \
0512         DRM_INFO("ADVANCE_RING() wr=0x%06x tail=0x%06x\n",  \
0513              write, dev_priv->ring.tail);           \
0514     if (R128_BROKEN_CCE && write < 32)              \
0515         memcpy(dev_priv->ring.end,              \
0516                dev_priv->ring.start,                \
0517                write * sizeof(u32));                \
0518     if (((dev_priv->ring.tail + _nr) & tail_mask) != write)     \
0519         DRM_ERROR(                      \
0520             "ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n",    \
0521             ((dev_priv->ring.tail + _nr) & tail_mask),  \
0522             write, __LINE__);               \
0523     else                                \
0524         dev_priv->ring.tail = write;                \
0525 } while (0)
0526 
0527 #define COMMIT_RING() do {                      \
0528     if (R128_VERBOSE)                       \
0529         DRM_INFO("COMMIT_RING() tail=0x%06x\n",         \
0530              dev_priv->ring.tail);              \
0531     mb();                       \
0532     R128_WRITE(R128_PM4_BUFFER_DL_WPTR, dev_priv->ring.tail);   \
0533     R128_READ(R128_PM4_BUFFER_DL_WPTR);             \
0534 } while (0)
0535 
0536 #define OUT_RING(x) do {                        \
0537     if (R128_VERBOSE)                       \
0538         DRM_INFO("   OUT_RING( 0x%08x ) at 0x%x\n",     \
0539              (unsigned int)(x), write);         \
0540     ring[write++] = cpu_to_le32(x);                 \
0541     write &= tail_mask;                     \
0542 } while (0)
0543 
0544 #endif              /* __R128_DRV_H__ */