mach64_drv.h revision 145132
1/* mach64_drv.h -- Private header for mach64 driver -*- linux-c -*- 2 * Created: Fri Nov 24 22:07:58 2000 by gareth@valinux.com 3 * 4 * Copyright 2000 Gareth Hughes 5 * Copyright 2002 Frank C. Earl 6 * Copyright 2002-2003 Leif Delgass 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 * THE COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 24 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 * Authors: 28 * Gareth Hughes <gareth@valinux.com> 29 * Frank C. Earl <fearl@airmail.net> 30 * Leif Delgass <ldelgass@retinalburn.net> 31 * Jos���Fonseca <j_r_fonseca@yahoo.co.uk> 32 * 33 * $FreeBSD: head/sys/dev/drm/mach64_drv.h 145132 2005-04-16 03:44:47Z anholt $ 34 */ 35 36#ifndef __MACH64_DRV_H__ 37#define __MACH64_DRV_H__ 38 39/* General customization: 40 */ 41 42#define DRIVER_AUTHOR "Gareth Hughes, Leif Delgass, Jos�� Fonseca" 43 44#define DRIVER_NAME "mach64" 45#define DRIVER_DESC "DRM module for the ATI Rage Pro" 46#define DRIVER_DATE "20020904" 47 48#define DRIVER_MAJOR 1 49#define DRIVER_MINOR 0 50#define DRIVER_PATCHLEVEL 0 51 52/* FIXME: remove these when not needed */ 53/* Development driver options */ 54#define MACH64_EXTRA_CHECKING 0 /* Extra sanity checks for DMA/freelist management */ 55#define MACH64_VERBOSE 0 /* Verbose debugging output */ 56 57typedef struct drm_mach64_freelist { 58 struct list_head list; /* List pointers for free_list, placeholders, or pending list */ 59 drm_buf_t *buf; /* Pointer to the buffer */ 60 int discard; /* This flag is set when we're done (re)using a buffer */ 61 u32 ring_ofs; /* dword offset in ring of last descriptor for this buffer */ 62} drm_mach64_freelist_t; 63 64typedef struct drm_mach64_descriptor_ring { 65 dma_addr_t handle; /* handle (bus address) of ring returned by pci_alloc_consistent() */ 66 void *start; /* write pointer (cpu address) to start of descriptor ring */ 67 u32 start_addr; /* bus address of beginning of descriptor ring */ 68 int size; /* size of ring in bytes */ 69 70 u32 head_addr; /* bus address of descriptor ring head */ 71 u32 head; /* dword offset of descriptor ring head */ 72 u32 tail; /* dword offset of descriptor ring tail */ 73 u32 tail_mask; /* mask used to wrap ring */ 74 int space; /* number of free bytes in ring */ 75} drm_mach64_descriptor_ring_t; 76 77typedef struct drm_mach64_private { 78 drm_mach64_sarea_t *sarea_priv; 79 80 int is_pci; 81 drm_mach64_dma_mode_t driver_mode; /* Async DMA, sync DMA, or MMIO */ 82 83 int usec_timeout; /* Timeout for the wait functions */ 84 85 drm_mach64_descriptor_ring_t ring; /* DMA descriptor table (ring buffer) */ 86 int ring_running; /* Is bus mastering is enabled */ 87 88 struct list_head free_list; /* Free-list head */ 89 struct list_head placeholders; /* Placeholder list for buffers held by clients */ 90 struct list_head pending; /* Buffers pending completion */ 91 92 u32 frame_ofs[MACH64_MAX_QUEUED_FRAMES]; /* dword ring offsets of most recent frame swaps */ 93 94 unsigned int fb_bpp; 95 unsigned int front_offset, front_pitch; 96 unsigned int back_offset, back_pitch; 97 98 unsigned int depth_bpp; 99 unsigned int depth_offset, depth_pitch; 100 101 u32 front_offset_pitch; 102 u32 back_offset_pitch; 103 u32 depth_offset_pitch; 104 105 drm_local_map_t *sarea; 106 drm_local_map_t *fb; 107 drm_local_map_t *mmio; 108 drm_local_map_t *ring_map; 109 drm_local_map_t *dev_buffers; /* this is a pointer to a structure in dev */ 110 drm_local_map_t *agp_textures; 111} drm_mach64_private_t; 112 113 /* mach64_dma.c */ 114extern int mach64_dma_init(DRM_IOCTL_ARGS); 115extern int mach64_dma_idle(DRM_IOCTL_ARGS); 116extern int mach64_dma_flush(DRM_IOCTL_ARGS); 117extern int mach64_engine_reset(DRM_IOCTL_ARGS); 118extern int mach64_dma_buffers(DRM_IOCTL_ARGS); 119extern void mach64_driver_pretakedown(drm_device_t * dev); 120 121extern int mach64_init_freelist(drm_device_t * dev); 122extern void mach64_destroy_freelist(drm_device_t * dev); 123extern drm_buf_t *mach64_freelist_get(drm_mach64_private_t * dev_priv); 124 125extern int mach64_do_wait_for_fifo(drm_mach64_private_t * dev_priv, 126 int entries); 127extern int mach64_do_wait_for_idle(drm_mach64_private_t * dev_priv); 128extern int mach64_wait_ring(drm_mach64_private_t * dev_priv, int n); 129extern int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t * dev_priv); 130extern int mach64_do_release_used_buffers(drm_mach64_private_t * dev_priv); 131extern void mach64_dump_engine_info(drm_mach64_private_t * dev_priv); 132extern void mach64_dump_ring_info(drm_mach64_private_t * dev_priv); 133extern int mach64_do_engine_reset(drm_mach64_private_t * dev_priv); 134 135extern int mach64_do_dma_idle(drm_mach64_private_t * dev_priv); 136extern int mach64_do_dma_flush(drm_mach64_private_t * dev_priv); 137extern int mach64_do_cleanup_dma(drm_device_t * dev); 138 139 /* mach64_state.c */ 140extern int mach64_dma_clear(DRM_IOCTL_ARGS); 141extern int mach64_dma_swap(DRM_IOCTL_ARGS); 142extern int mach64_dma_vertex(DRM_IOCTL_ARGS); 143extern int mach64_dma_blit(DRM_IOCTL_ARGS); 144extern int mach64_get_param(DRM_IOCTL_ARGS); 145extern int mach64_driver_vblank_wait(drm_device_t * dev, 146 unsigned int *sequence); 147 148extern irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS); 149extern void mach64_driver_irq_preinstall(drm_device_t * dev); 150extern void mach64_driver_irq_postinstall(drm_device_t * dev); 151extern void mach64_driver_irq_uninstall(drm_device_t * dev); 152 153/* ================================================================ 154 * Registers 155 */ 156 157#define MACH64_AGP_BASE 0x0148 158#define MACH64_AGP_CNTL 0x014c 159#define MACH64_ALPHA_TST_CNTL 0x0550 160 161#define MACH64_DSP_CONFIG 0x0420 162#define MACH64_DSP_ON_OFF 0x0424 163#define MACH64_EXT_MEM_CNTL 0x04ac 164#define MACH64_GEN_TEST_CNTL 0x04d0 165#define MACH64_HW_DEBUG 0x047c 166#define MACH64_MEM_ADDR_CONFIG 0x0434 167#define MACH64_MEM_BUF_CNTL 0x042c 168#define MACH64_MEM_CNTL 0x04b0 169 170#define MACH64_BM_ADDR 0x0648 171#define MACH64_BM_COMMAND 0x0188 172#define MACH64_BM_DATA 0x0648 173#define MACH64_BM_FRAME_BUF_OFFSET 0x0180 174#define MACH64_BM_GUI_TABLE 0x01b8 175#define MACH64_BM_GUI_TABLE_CMD 0x064c 176# define MACH64_CIRCULAR_BUF_SIZE_16KB (0 << 0) 177# define MACH64_CIRCULAR_BUF_SIZE_32KB (1 << 0) 178# define MACH64_CIRCULAR_BUF_SIZE_64KB (2 << 0) 179# define MACH64_CIRCULAR_BUF_SIZE_128KB (3 << 0) 180# define MACH64_LAST_DESCRIPTOR (1 << 31) 181#define MACH64_BM_HOSTDATA 0x0644 182#define MACH64_BM_STATUS 0x018c 183#define MACH64_BM_SYSTEM_MEM_ADDR 0x0184 184#define MACH64_BM_SYSTEM_TABLE 0x01bc 185#define MACH64_BUS_CNTL 0x04a0 186# define MACH64_BUS_MSTR_RESET (1 << 1) 187# define MACH64_BUS_APER_REG_DIS (1 << 4) 188# define MACH64_BUS_FLUSH_BUF (1 << 2) 189# define MACH64_BUS_MASTER_DIS (1 << 6) 190# define MACH64_BUS_EXT_REG_EN (1 << 27) 191 192#define MACH64_CLR_CMP_CLR 0x0700 193#define MACH64_CLR_CMP_CNTL 0x0708 194#define MACH64_CLR_CMP_MASK 0x0704 195#define MACH64_CONFIG_CHIP_ID 0x04e0 196#define MACH64_CONFIG_CNTL 0x04dc 197#define MACH64_CONFIG_STAT0 0x04e4 198#define MACH64_CONFIG_STAT1 0x0494 199#define MACH64_CONFIG_STAT2 0x0498 200#define MACH64_CONTEXT_LOAD_CNTL 0x072c 201#define MACH64_CONTEXT_MASK 0x0720 202#define MACH64_COMPOSITE_SHADOW_ID 0x0798 203#define MACH64_CRC_SIG 0x04e8 204#define MACH64_CUSTOM_MACRO_CNTL 0x04d4 205 206#define MACH64_DP_BKGD_CLR 0x06c0 207#define MACH64_DP_FOG_CLR 0x06c4 208#define MACH64_DP_FGRD_BKGD_CLR 0x06e0 209#define MACH64_DP_FRGD_CLR 0x06c4 210#define MACH64_DP_FGRD_CLR_MIX 0x06dc 211 212#define MACH64_DP_MIX 0x06d4 213# define BKGD_MIX_NOT_D (0 << 0) 214# define BKGD_MIX_ZERO (1 << 0) 215# define BKGD_MIX_ONE (2 << 0) 216# define MACH64_BKGD_MIX_D (3 << 0) 217# define BKGD_MIX_NOT_S (4 << 0) 218# define BKGD_MIX_D_XOR_S (5 << 0) 219# define BKGD_MIX_NOT_D_XOR_S (6 << 0) 220# define MACH64_BKGD_MIX_S (7 << 0) 221# define BKGD_MIX_NOT_D_OR_NOT_S (8 << 0) 222# define BKGD_MIX_D_OR_NOT_S (9 << 0) 223# define BKGD_MIX_NOT_D_OR_S (10 << 0) 224# define BKGD_MIX_D_OR_S (11 << 0) 225# define BKGD_MIX_D_AND_S (12 << 0) 226# define BKGD_MIX_NOT_D_AND_S (13 << 0) 227# define BKGD_MIX_D_AND_NOT_S (14 << 0) 228# define BKGD_MIX_NOT_D_AND_NOT_S (15 << 0) 229# define BKGD_MIX_D_PLUS_S_DIV2 (23 << 0) 230# define FRGD_MIX_NOT_D (0 << 16) 231# define FRGD_MIX_ZERO (1 << 16) 232# define FRGD_MIX_ONE (2 << 16) 233# define FRGD_MIX_D (3 << 16) 234# define FRGD_MIX_NOT_S (4 << 16) 235# define FRGD_MIX_D_XOR_S (5 << 16) 236# define FRGD_MIX_NOT_D_XOR_S (6 << 16) 237# define MACH64_FRGD_MIX_S (7 << 16) 238# define FRGD_MIX_NOT_D_OR_NOT_S (8 << 16) 239# define FRGD_MIX_D_OR_NOT_S (9 << 16) 240# define FRGD_MIX_NOT_D_OR_S (10 << 16) 241# define FRGD_MIX_D_OR_S (11 << 16) 242# define FRGD_MIX_D_AND_S (12 << 16) 243# define FRGD_MIX_NOT_D_AND_S (13 << 16) 244# define FRGD_MIX_D_AND_NOT_S (14 << 16) 245# define FRGD_MIX_NOT_D_AND_NOT_S (15 << 16) 246# define FRGD_MIX_D_PLUS_S_DIV2 (23 << 16) 247 248#define MACH64_DP_PIX_WIDTH 0x06d0 249# define MACH64_HOST_TRIPLE_ENABLE (1 << 13) 250# define MACH64_BYTE_ORDER_MSB_TO_LSB (0 << 24) 251# define MACH64_BYTE_ORDER_LSB_TO_MSB (1 << 24) 252 253#define MACH64_DP_SRC 0x06d8 254# define MACH64_BKGD_SRC_BKGD_CLR (0 << 0) 255# define MACH64_BKGD_SRC_FRGD_CLR (1 << 0) 256# define MACH64_BKGD_SRC_HOST (2 << 0) 257# define MACH64_BKGD_SRC_BLIT (3 << 0) 258# define MACH64_BKGD_SRC_PATTERN (4 << 0) 259# define MACH64_BKGD_SRC_3D (5 << 0) 260# define MACH64_FRGD_SRC_BKGD_CLR (0 << 8) 261# define MACH64_FRGD_SRC_FRGD_CLR (1 << 8) 262# define MACH64_FRGD_SRC_HOST (2 << 8) 263# define MACH64_FRGD_SRC_BLIT (3 << 8) 264# define MACH64_FRGD_SRC_PATTERN (4 << 8) 265# define MACH64_FRGD_SRC_3D (5 << 8) 266# define MACH64_MONO_SRC_ONE (0 << 16) 267# define MACH64_MONO_SRC_PATTERN (1 << 16) 268# define MACH64_MONO_SRC_HOST (2 << 16) 269# define MACH64_MONO_SRC_BLIT (3 << 16) 270 271#define MACH64_DP_WRITE_MASK 0x06c8 272 273#define MACH64_DST_CNTL 0x0530 274# define MACH64_DST_X_RIGHT_TO_LEFT (0 << 0) 275# define MACH64_DST_X_LEFT_TO_RIGHT (1 << 0) 276# define MACH64_DST_Y_BOTTOM_TO_TOP (0 << 1) 277# define MACH64_DST_Y_TOP_TO_BOTTOM (1 << 1) 278# define MACH64_DST_X_MAJOR (0 << 2) 279# define MACH64_DST_Y_MAJOR (1 << 2) 280# define MACH64_DST_X_TILE (1 << 3) 281# define MACH64_DST_Y_TILE (1 << 4) 282# define MACH64_DST_LAST_PEL (1 << 5) 283# define MACH64_DST_POLYGON_ENABLE (1 << 6) 284# define MACH64_DST_24_ROTATION_ENABLE (1 << 7) 285 286#define MACH64_DST_HEIGHT_WIDTH 0x0518 287#define MACH64_DST_OFF_PITCH 0x0500 288#define MACH64_DST_WIDTH_HEIGHT 0x06ec 289#define MACH64_DST_X_Y 0x06e8 290#define MACH64_DST_Y_X 0x050c 291 292#define MACH64_FIFO_STAT 0x0710 293# define MACH64_FIFO_SLOT_MASK 0x0000ffff 294# define MACH64_FIFO_ERR (1 << 31) 295 296#define MACH64_GEN_TEST_CNTL 0x04d0 297# define MACH64_GUI_ENGINE_ENABLE (1 << 8) 298#define MACH64_GUI_CMDFIFO_DEBUG 0x0170 299#define MACH64_GUI_CMDFIFO_DATA 0x0174 300#define MACH64_GUI_CNTL 0x0178 301# define MACH64_CMDFIFO_SIZE_MASK 0x00000003ul 302# define MACH64_CMDFIFO_SIZE_192 0x00000000ul 303# define MACH64_CMDFIFO_SIZE_128 0x00000001ul 304# define MACH64_CMDFIFO_SIZE_64 0x00000002ul 305#define MACH64_GUI_STAT 0x0738 306# define MACH64_GUI_ACTIVE (1 << 0) 307#define MACH64_GUI_TRAJ_CNTL 0x0730 308 309#define MACH64_HOST_CNTL 0x0640 310#define MACH64_HOST_DATA0 0x0600 311 312#define MACH64_ONE_OVER_AREA 0x029c 313#define MACH64_ONE_OVER_AREA_UC 0x0300 314 315#define MACH64_PAT_REG0 0x0680 316#define MACH64_PAT_REG1 0x0684 317 318#define MACH64_SC_LEFT 0x06a0 319#define MACH64_SC_RIGHT 0x06a4 320#define MACH64_SC_LEFT_RIGHT 0x06a8 321#define MACH64_SC_TOP 0x06ac 322#define MACH64_SC_BOTTOM 0x06b0 323#define MACH64_SC_TOP_BOTTOM 0x06b4 324 325#define MACH64_SCALE_3D_CNTL 0x05fc 326#define MACH64_SCRATCH_REG0 0x0480 327#define MACH64_SCRATCH_REG1 0x0484 328#define MACH64_SECONDARY_TEX_OFF 0x0778 329#define MACH64_SETUP_CNTL 0x0304 330#define MACH64_SRC_CNTL 0x05b4 331# define MACH64_SRC_BM_ENABLE (1 << 8) 332# define MACH64_SRC_BM_SYNC (1 << 9) 333# define MACH64_SRC_BM_OP_FRAME_TO_SYSTEM (0 << 10) 334# define MACH64_SRC_BM_OP_SYSTEM_TO_FRAME (1 << 10) 335# define MACH64_SRC_BM_OP_REG_TO_SYSTEM (2 << 10) 336# define MACH64_SRC_BM_OP_SYSTEM_TO_REG (3 << 10) 337#define MACH64_SRC_HEIGHT1 0x0594 338#define MACH64_SRC_HEIGHT2 0x05ac 339#define MACH64_SRC_HEIGHT1_WIDTH1 0x0598 340#define MACH64_SRC_HEIGHT2_WIDTH2 0x05b0 341#define MACH64_SRC_OFF_PITCH 0x0580 342#define MACH64_SRC_WIDTH1 0x0590 343#define MACH64_SRC_Y_X 0x058c 344 345#define MACH64_TEX_0_OFF 0x05c0 346#define MACH64_TEX_CNTL 0x0774 347#define MACH64_TEX_SIZE_PITCH 0x0770 348#define MACH64_TIMER_CONFIG 0x0428 349 350#define MACH64_VERTEX_1_ARGB 0x0254 351#define MACH64_VERTEX_1_S 0x0240 352#define MACH64_VERTEX_1_SECONDARY_S 0x0328 353#define MACH64_VERTEX_1_SECONDARY_T 0x032c 354#define MACH64_VERTEX_1_SECONDARY_W 0x0330 355#define MACH64_VERTEX_1_SPEC_ARGB 0x024c 356#define MACH64_VERTEX_1_T 0x0244 357#define MACH64_VERTEX_1_W 0x0248 358#define MACH64_VERTEX_1_X_Y 0x0258 359#define MACH64_VERTEX_1_Z 0x0250 360#define MACH64_VERTEX_2_ARGB 0x0274 361#define MACH64_VERTEX_2_S 0x0260 362#define MACH64_VERTEX_2_SECONDARY_S 0x0334 363#define MACH64_VERTEX_2_SECONDARY_T 0x0338 364#define MACH64_VERTEX_2_SECONDARY_W 0x033c 365#define MACH64_VERTEX_2_SPEC_ARGB 0x026c 366#define MACH64_VERTEX_2_T 0x0264 367#define MACH64_VERTEX_2_W 0x0268 368#define MACH64_VERTEX_2_X_Y 0x0278 369#define MACH64_VERTEX_2_Z 0x0270 370#define MACH64_VERTEX_3_ARGB 0x0294 371#define MACH64_VERTEX_3_S 0x0280 372#define MACH64_VERTEX_3_SECONDARY_S 0x02a0 373#define MACH64_VERTEX_3_SECONDARY_T 0x02a4 374#define MACH64_VERTEX_3_SECONDARY_W 0x02a8 375#define MACH64_VERTEX_3_SPEC_ARGB 0x028c 376#define MACH64_VERTEX_3_T 0x0284 377#define MACH64_VERTEX_3_W 0x0288 378#define MACH64_VERTEX_3_X_Y 0x0298 379#define MACH64_VERTEX_3_Z 0x0290 380 381#define MACH64_Z_CNTL 0x054c 382#define MACH64_Z_OFF_PITCH 0x0548 383 384#define MACH64_CRTC_VLINE_CRNT_VLINE 0x0410 385# define MACH64_CRTC_VLINE_MASK 0x000007ff 386# define MACH64_CRTC_CRNT_VLINE_MASK 0x07ff0000 387#define MACH64_CRTC_OFF_PITCH 0x0414 388#define MACH64_CRTC_INT_CNTL 0x0418 389# define MACH64_CRTC_VBLANK (1 << 0) 390# define MACH64_CRTC_VBLANK_INT_EN (1 << 1) 391# define MACH64_CRTC_VBLANK_INT (1 << 2) 392# define MACH64_CRTC_VLINE_INT_EN (1 << 3) 393# define MACH64_CRTC_VLINE_INT (1 << 4) 394# define MACH64_CRTC_VLINE_SYNC (1 << 5) /* 0=even, 1=odd */ 395# define MACH64_CRTC_FRAME (1 << 6) /* 0=even, 1=odd */ 396# define MACH64_CRTC_SNAPSHOT_INT_EN (1 << 7) 397# define MACH64_CRTC_SNAPSHOT_INT (1 << 8) 398# define MACH64_CRTC_I2C_INT_EN (1 << 9) 399# define MACH64_CRTC_I2C_INT (1 << 10) 400# define MACH64_CRTC2_VBLANK (1 << 11) /* LT Pro */ 401# define MACH64_CRTC2_VBLANK_INT_EN (1 << 12) /* LT Pro */ 402# define MACH64_CRTC2_VBLANK_INT (1 << 13) /* LT Pro */ 403# define MACH64_CRTC2_VLINE_INT_EN (1 << 14) /* LT Pro */ 404# define MACH64_CRTC2_VLINE_INT (1 << 15) /* LT Pro */ 405# define MACH64_CRTC_CAPBUF0_INT_EN (1 << 16) 406# define MACH64_CRTC_CAPBUF0_INT (1 << 17) 407# define MACH64_CRTC_CAPBUF1_INT_EN (1 << 18) 408# define MACH64_CRTC_CAPBUF1_INT (1 << 19) 409# define MACH64_CRTC_OVERLAY_EOF_INT_EN (1 << 20) 410# define MACH64_CRTC_OVERLAY_EOF_INT (1 << 21) 411# define MACH64_CRTC_ONESHOT_CAP_INT_EN (1 << 22) 412# define MACH64_CRTC_ONESHOT_CAP_INT (1 << 23) 413# define MACH64_CRTC_BUSMASTER_EOL_INT_EN (1 << 24) 414# define MACH64_CRTC_BUSMASTER_EOL_INT (1 << 25) 415# define MACH64_CRTC_GP_INT_EN (1 << 26) 416# define MACH64_CRTC_GP_INT (1 << 27) 417# define MACH64_CRTC2_VLINE_SYNC (1 << 28) /* LT Pro */ /* 0=even, 1=odd */ 418# define MACH64_CRTC_SNAPSHOT2_INT_EN (1 << 29) /* LT Pro */ 419# define MACH64_CRTC_SNAPSHOT2_INT (1 << 30) /* LT Pro */ 420# define MACH64_CRTC_VBLANK2_INT (1 << 31) 421# define MACH64_CRTC_INT_ENS \ 422 ( \ 423 MACH64_CRTC_VBLANK_INT_EN | \ 424 MACH64_CRTC_VLINE_INT_EN | \ 425 MACH64_CRTC_SNAPSHOT_INT_EN | \ 426 MACH64_CRTC_I2C_INT_EN | \ 427 MACH64_CRTC2_VBLANK_INT_EN | \ 428 MACH64_CRTC2_VLINE_INT_EN | \ 429 MACH64_CRTC_CAPBUF0_INT_EN | \ 430 MACH64_CRTC_CAPBUF1_INT_EN | \ 431 MACH64_CRTC_OVERLAY_EOF_INT_EN | \ 432 MACH64_CRTC_ONESHOT_CAP_INT_EN | \ 433 MACH64_CRTC_BUSMASTER_EOL_INT_EN | \ 434 MACH64_CRTC_GP_INT_EN | \ 435 MACH64_CRTC_SNAPSHOT2_INT_EN | \ 436 0 \ 437 ) 438# define MACH64_CRTC_INT_ACKS \ 439 ( \ 440 MACH64_CRTC_VBLANK_INT | \ 441 MACH64_CRTC_VLINE_INT | \ 442 MACH64_CRTC_SNAPSHOT_INT | \ 443 MACH64_CRTC_I2C_INT | \ 444 MACH64_CRTC2_VBLANK_INT | \ 445 MACH64_CRTC2_VLINE_INT | \ 446 MACH64_CRTC_CAPBUF0_INT | \ 447 MACH64_CRTC_CAPBUF1_INT | \ 448 MACH64_CRTC_OVERLAY_EOF_INT | \ 449 MACH64_CRTC_ONESHOT_CAP_INT | \ 450 MACH64_CRTC_BUSMASTER_EOL_INT | \ 451 MACH64_CRTC_GP_INT | \ 452 MACH64_CRTC_SNAPSHOT2_INT | \ 453 MACH64_CRTC_VBLANK2_INT | \ 454 0 \ 455 ) 456 457#define MACH64_DATATYPE_CI8 2 458#define MACH64_DATATYPE_ARGB1555 3 459#define MACH64_DATATYPE_RGB565 4 460#define MACH64_DATATYPE_ARGB8888 6 461#define MACH64_DATATYPE_RGB332 7 462#define MACH64_DATATYPE_Y8 8 463#define MACH64_DATATYPE_RGB8 9 464#define MACH64_DATATYPE_VYUY422 11 465#define MACH64_DATATYPE_YVYU422 12 466#define MACH64_DATATYPE_AYUV444 14 467#define MACH64_DATATYPE_ARGB4444 15 468 469#define MACH64_READ(reg) DRM_READ32(dev_priv->mmio, (reg) ) 470#define MACH64_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio, (reg), (val) ) 471 472#define DWMREG0 0x0400 473#define DWMREG0_END 0x07ff 474#define DWMREG1 0x0000 475#define DWMREG1_END 0x03ff 476 477#define ISREG0(r) (((r) >= DWMREG0) && ((r) <= DWMREG0_END)) 478#define DMAREG0(r) (((r) - DWMREG0) >> 2) 479#define DMAREG1(r) ((((r) - DWMREG1) >> 2 ) | 0x0100) 480#define DMAREG(r) (ISREG0(r) ? DMAREG0(r) : DMAREG1(r)) 481 482#define MMREG0 0x0000 483#define MMREG0_END 0x00ff 484 485#define ISMMREG0(r) (((r) >= MMREG0) && ((r) <= MMREG0_END)) 486#define MMSELECT0(r) (((r) << 2) + DWMREG0) 487#define MMSELECT1(r) (((((r) & 0xff) << 2) + DWMREG1)) 488#define MMSELECT(r) (ISMMREG0(r) ? MMSELECT0(r) : MMSELECT1(r)) 489 490/* ================================================================ 491 * DMA constants 492 */ 493 494/* DMA descriptor field indices: 495 * The descriptor fields are loaded into the read-only 496 * BM_* system bus master registers during a bus-master operation 497 */ 498#define MACH64_DMA_FRAME_BUF_OFFSET 0 /* BM_FRAME_BUF_OFFSET */ 499#define MACH64_DMA_SYS_MEM_ADDR 1 /* BM_SYSTEM_MEM_ADDR */ 500#define MACH64_DMA_COMMAND 2 /* BM_COMMAND */ 501#define MACH64_DMA_RESERVED 3 /* BM_STATUS */ 502 503/* BM_COMMAND descriptor field flags */ 504#define MACH64_DMA_HOLD_OFFSET (1<<30) /* Don't increment DMA_FRAME_BUF_OFFSET */ 505#define MACH64_DMA_EOL (1<<31) /* End of descriptor list flag */ 506 507#define MACH64_DMA_CHUNKSIZE 0x1000 /* 4kB per DMA descriptor */ 508#define MACH64_APERTURE_OFFSET 0x7ff800 /* frame-buffer offset for gui-masters */ 509 510/* ================================================================ 511 * Misc helper macros 512 */ 513 514static __inline__ void mach64_set_dma_eol(volatile u32 * addr) 515{ 516#if defined(__i386__) 517 int nr = 31; 518 519 /* Taken from include/asm-i386/bitops.h linux header */ 520 __asm__ __volatile__("lock;" "btsl %1,%0":"=m"(*addr) 521 :"Ir"(nr)); 522#elif defined(__powerpc__) 523 u32 old; 524 u32 mask = cpu_to_le32(MACH64_DMA_EOL); 525 526 /* Taken from the include/asm-ppc/bitops.h linux header */ 527 __asm__ __volatile__("\n\ 5281: lwarx %0,0,%3 \n\ 529 or %0,%0,%2 \n\ 530 stwcx. %0,0,%3 \n\ 531 bne- 1b":"=&r"(old), "=m"(*addr) 532 :"r"(mask), "r"(addr), "m"(*addr) 533 :"cc"); 534#elif defined(__alpha__) 535 u32 temp; 536 u32 mask = MACH64_DMA_EOL; 537 538 /* Taken from the include/asm-alpha/bitops.h linux header */ 539 __asm__ __volatile__("1: ldl_l %0,%3\n" 540 " bis %0,%2,%0\n" 541 " stl_c %0,%1\n" 542 " beq %0,2f\n" 543 ".subsection 2\n" 544 "2: br 1b\n" 545 ".previous":"=&r"(temp), "=m"(*addr) 546 :"Ir"(mask), "m"(*addr)); 547#else 548 u32 mask = cpu_to_le32(MACH64_DMA_EOL); 549 550 *addr |= mask; 551#endif 552} 553 554static __inline__ void mach64_clear_dma_eol(volatile u32 * addr) 555{ 556#if defined(__i386__) 557 int nr = 31; 558 559 /* Taken from include/asm-i386/bitops.h linux header */ 560 __asm__ __volatile__("lock;" "btrl %1,%0":"=m"(*addr) 561 :"Ir"(nr)); 562#elif defined(__powerpc__) 563 u32 old; 564 u32 mask = cpu_to_le32(MACH64_DMA_EOL); 565 566 /* Taken from the include/asm-ppc/bitops.h linux header */ 567 __asm__ __volatile__("\n\ 5681: lwarx %0,0,%3 \n\ 569 andc %0,%0,%2 \n\ 570 stwcx. %0,0,%3 \n\ 571 bne- 1b":"=&r"(old), "=m"(*addr) 572 :"r"(mask), "r"(addr), "m"(*addr) 573 :"cc"); 574#elif defined(__alpha__) 575 u32 temp; 576 u32 mask = ~MACH64_DMA_EOL; 577 578 /* Taken from the include/asm-alpha/bitops.h linux header */ 579 __asm__ __volatile__("1: ldl_l %0,%3\n" 580 " and %0,%2,%0\n" 581 " stl_c %0,%1\n" 582 " beq %0,2f\n" 583 ".subsection 2\n" 584 "2: br 1b\n" 585 ".previous":"=&r"(temp), "=m"(*addr) 586 :"Ir"(mask), "m"(*addr)); 587#else 588 u32 mask = cpu_to_le32(~MACH64_DMA_EOL); 589 590 *addr &= mask; 591#endif 592} 593 594static __inline__ void mach64_ring_start(drm_mach64_private_t * dev_priv) 595{ 596 drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; 597 598 DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n", 599 __FUNCTION__, 600 ring->head_addr, ring->head, ring->tail, ring->space); 601 602 if (mach64_do_wait_for_idle(dev_priv) < 0) { 603 mach64_do_engine_reset(dev_priv); 604 } 605 606 if (dev_priv->driver_mode != MACH64_MODE_MMIO) { 607 /* enable bus mastering and block 1 registers */ 608 MACH64_WRITE(MACH64_BUS_CNTL, 609 (MACH64_READ(MACH64_BUS_CNTL) & 610 ~MACH64_BUS_MASTER_DIS) 611 | MACH64_BUS_EXT_REG_EN); 612 mach64_do_wait_for_idle(dev_priv); 613 } 614 615 /* reset descriptor table ring head */ 616 MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD, 617 ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB); 618 619 dev_priv->ring_running = 1; 620} 621 622static __inline__ void mach64_ring_resume(drm_mach64_private_t * dev_priv, 623 drm_mach64_descriptor_ring_t * ring) 624{ 625 DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n", 626 __FUNCTION__, 627 ring->head_addr, ring->head, ring->tail, ring->space); 628 629 /* reset descriptor table ring head */ 630 MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD, 631 ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB); 632 633 if (dev_priv->driver_mode == MACH64_MODE_MMIO) { 634 mach64_do_dispatch_pseudo_dma(dev_priv); 635 } else { 636 /* enable GUI bus mastering, and sync the bus master to the GUI */ 637 MACH64_WRITE(MACH64_SRC_CNTL, 638 MACH64_SRC_BM_ENABLE | MACH64_SRC_BM_SYNC | 639 MACH64_SRC_BM_OP_SYSTEM_TO_REG); 640 641 /* kick off the transfer */ 642 MACH64_WRITE(MACH64_DST_HEIGHT_WIDTH, 0); 643 if (dev_priv->driver_mode == MACH64_MODE_DMA_SYNC) { 644 if ((mach64_do_wait_for_idle(dev_priv)) < 0) { 645 DRM_ERROR("%s: idle failed, resetting engine\n", 646 __FUNCTION__); 647 mach64_dump_engine_info(dev_priv); 648 mach64_do_engine_reset(dev_priv); 649 return; 650 } 651 mach64_do_release_used_buffers(dev_priv); 652 } 653 } 654} 655 656static __inline__ void mach64_ring_tick(drm_mach64_private_t * dev_priv, 657 drm_mach64_descriptor_ring_t * ring) 658{ 659 DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n", 660 __FUNCTION__, 661 ring->head_addr, ring->head, ring->tail, ring->space); 662 663 if (!dev_priv->ring_running) { 664 mach64_ring_start(dev_priv); 665 666 if (ring->head != ring->tail) { 667 mach64_ring_resume(dev_priv, ring); 668 } 669 } else { 670 /* GUI_ACTIVE must be read before BM_GUI_TABLE to 671 * correctly determine the ring head 672 */ 673 int gui_active = 674 MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE; 675 676 ring->head_addr = MACH64_READ(MACH64_BM_GUI_TABLE) & 0xfffffff0; 677 678 if (gui_active) { 679 /* If not idle, BM_GUI_TABLE points one descriptor 680 * past the current head 681 */ 682 if (ring->head_addr == ring->start_addr) { 683 ring->head_addr += ring->size; 684 } 685 ring->head_addr -= 4 * sizeof(u32); 686 } 687 688 if (ring->head_addr < ring->start_addr || 689 ring->head_addr >= ring->start_addr + ring->size) { 690 DRM_ERROR("bad ring head address: 0x%08x\n", 691 ring->head_addr); 692 mach64_dump_ring_info(dev_priv); 693 mach64_do_engine_reset(dev_priv); 694 return; 695 } 696 697 ring->head = (ring->head_addr - ring->start_addr) / sizeof(u32); 698 699 if (!gui_active && ring->head != ring->tail) { 700 mach64_ring_resume(dev_priv, ring); 701 } 702 } 703} 704 705static __inline__ void mach64_ring_stop(drm_mach64_private_t * dev_priv) 706{ 707 DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n", 708 __FUNCTION__, 709 dev_priv->ring.head_addr, dev_priv->ring.head, 710 dev_priv->ring.tail, dev_priv->ring.space); 711 712 /* restore previous SRC_CNTL to disable busmastering */ 713 mach64_do_wait_for_fifo(dev_priv, 1); 714 MACH64_WRITE(MACH64_SRC_CNTL, 0); 715 716 /* disable busmastering but keep the block 1 registers enabled */ 717 mach64_do_wait_for_idle(dev_priv); 718 MACH64_WRITE(MACH64_BUS_CNTL, MACH64_READ(MACH64_BUS_CNTL) 719 | MACH64_BUS_MASTER_DIS | MACH64_BUS_EXT_REG_EN); 720 721 dev_priv->ring_running = 0; 722} 723 724static __inline__ void 725mach64_update_ring_snapshot(drm_mach64_private_t * dev_priv) 726{ 727 drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; 728 729 DRM_DEBUG("%s\n", __FUNCTION__); 730 731 mach64_ring_tick(dev_priv, ring); 732 733 ring->space = (ring->head - ring->tail) * sizeof(u32); 734 if (ring->space <= 0) { 735 ring->space += ring->size; 736 } 737} 738 739/* ================================================================ 740 * DMA descriptor ring macros 741 */ 742 743#define RING_LOCALS \ 744 int _ring_tail, _ring_write; unsigned int _ring_mask; volatile u32 *_ring 745 746#define RING_WRITE_OFS _ring_write 747 748#define BEGIN_RING( n ) \ 749do { \ 750 if ( MACH64_VERBOSE ) { \ 751 DRM_INFO( "BEGIN_RING( %d ) in %s\n", \ 752 (n), __FUNCTION__ ); \ 753 } \ 754 if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \ 755 int ret; \ 756 if ((ret=mach64_wait_ring( dev_priv, (n) * sizeof(u32))) < 0 ) { \ 757 DRM_ERROR( "wait_ring failed, resetting engine\n"); \ 758 mach64_dump_engine_info( dev_priv ); \ 759 mach64_do_engine_reset( dev_priv ); \ 760 return ret; \ 761 } \ 762 } \ 763 dev_priv->ring.space -= (n) * sizeof(u32); \ 764 _ring = (u32 *) dev_priv->ring.start; \ 765 _ring_tail = _ring_write = dev_priv->ring.tail; \ 766 _ring_mask = dev_priv->ring.tail_mask; \ 767} while (0) 768 769#define OUT_RING( x ) \ 770do { \ 771 if ( MACH64_VERBOSE ) { \ 772 DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \ 773 (unsigned int)(x), _ring_write ); \ 774 } \ 775 _ring[_ring_write++] = cpu_to_le32( x ); \ 776 _ring_write &= _ring_mask; \ 777} while (0) 778 779#define ADVANCE_RING() \ 780do { \ 781 if ( MACH64_VERBOSE ) { \ 782 DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \ 783 _ring_write, _ring_tail ); \ 784 } \ 785 DRM_MEMORYBARRIER(); \ 786 mach64_clear_dma_eol( &_ring[(_ring_tail - 2) & _ring_mask] ); \ 787 DRM_MEMORYBARRIER(); \ 788 dev_priv->ring.tail = _ring_write; \ 789 mach64_ring_tick( dev_priv, &(dev_priv)->ring ); \ 790} while (0) 791 792/* ================================================================ 793 * DMA macros 794 */ 795 796#define DMALOCALS \ 797 drm_mach64_freelist_t *_entry = NULL; \ 798 drm_buf_t *_buf = NULL; \ 799 u32 *_buf_wptr; int _outcount 800 801#define GETBUFPTR( __buf ) \ 802((dev_priv->is_pci) ? \ 803 ((u32 *)(__buf)->address) : \ 804 ((u32 *)((char *)dev_priv->dev_buffers->handle + (__buf)->offset))) 805 806#define GETBUFADDR( __buf ) ((u32)(__buf)->bus_address) 807 808#define GETRINGOFFSET() (_entry->ring_ofs) 809 810static __inline__ int mach64_find_pending_buf_entry(drm_mach64_private_t * 811 dev_priv, 812 drm_mach64_freelist_t ** 813 entry, drm_buf_t * buf) 814{ 815 struct list_head *ptr; 816#if MACH64_EXTRA_CHECKING 817 if (list_empty(&dev_priv->pending)) { 818 DRM_ERROR("Empty pending list in %s\n", __FUNCTION__); 819 return DRM_ERR(EINVAL); 820 } 821#endif 822 ptr = dev_priv->pending.prev; 823 *entry = list_entry(ptr, drm_mach64_freelist_t, list); 824 while ((*entry)->buf != buf) { 825 if (ptr == &dev_priv->pending) { 826 return DRM_ERR(EFAULT); 827 } 828 ptr = ptr->prev; 829 *entry = list_entry(ptr, drm_mach64_freelist_t, list); 830 } 831 return 0; 832} 833 834#define DMASETPTR( _p ) \ 835do { \ 836 _buf = (_p); \ 837 _outcount = 0; \ 838 _buf_wptr = GETBUFPTR( _buf ); \ 839} while(0) 840 841/* FIXME: use a private set of smaller buffers for state emits, clears, and swaps? */ 842#define DMAGETPTR( filp, dev_priv, n ) \ 843do { \ 844 if ( MACH64_VERBOSE ) { \ 845 DRM_INFO( "DMAGETPTR( %d ) in %s\n", \ 846 n, __FUNCTION__ ); \ 847 } \ 848 _buf = mach64_freelist_get( dev_priv ); \ 849 if (_buf == NULL) { \ 850 DRM_ERROR("%s: couldn't get buffer in DMAGETPTR\n", \ 851 __FUNCTION__ ); \ 852 return DRM_ERR(EAGAIN); \ 853 } \ 854 if (_buf->pending) { \ 855 DRM_ERROR("%s: pending buf in DMAGETPTR\n", \ 856 __FUNCTION__ ); \ 857 return DRM_ERR(EFAULT); \ 858 } \ 859 _buf->filp = filp; \ 860 _outcount = 0; \ 861 \ 862 _buf_wptr = GETBUFPTR( _buf ); \ 863} while (0) 864 865#define DMAOUTREG( reg, val ) \ 866do { \ 867 if ( MACH64_VERBOSE ) { \ 868 DRM_INFO( " DMAOUTREG( 0x%x = 0x%08x )\n", \ 869 reg, val ); \ 870 } \ 871 _buf_wptr[_outcount++] = cpu_to_le32(DMAREG(reg)); \ 872 _buf_wptr[_outcount++] = cpu_to_le32((val)); \ 873 _buf->used += 8; \ 874} while (0) 875 876#define DMAADVANCE( dev_priv, _discard ) \ 877do { \ 878 struct list_head *ptr; \ 879 RING_LOCALS; \ 880 \ 881 if ( MACH64_VERBOSE ) { \ 882 DRM_INFO( "DMAADVANCE() in %s\n", __FUNCTION__ ); \ 883 } \ 884 \ 885 if (_buf->used <= 0) { \ 886 DRM_ERROR( "DMAADVANCE() in %s: sending empty buf %d\n", \ 887 __FUNCTION__, _buf->idx ); \ 888 return DRM_ERR(EFAULT); \ 889 } \ 890 if (_buf->pending) { \ 891 /* This is a resued buffer, so we need to find it in the pending list */ \ 892 int ret; \ 893 if ( (ret=mach64_find_pending_buf_entry(dev_priv, &_entry, _buf)) ) { \ 894 DRM_ERROR( "DMAADVANCE() in %s: couldn't find pending buf %d\n", \ 895 __FUNCTION__, _buf->idx ); \ 896 return ret; \ 897 } \ 898 if (_entry->discard) { \ 899 DRM_ERROR( "DMAADVANCE() in %s: sending discarded pending buf %d\n", \ 900 __FUNCTION__, _buf->idx ); \ 901 return DRM_ERR(EFAULT); \ 902 } \ 903 } else { \ 904 if (list_empty(&dev_priv->placeholders)) { \ 905 DRM_ERROR( "DMAADVANCE() in %s: empty placeholder list\n", \ 906 __FUNCTION__ ); \ 907 return DRM_ERR(EFAULT); \ 908 } \ 909 ptr = dev_priv->placeholders.next; \ 910 list_del(ptr); \ 911 _entry = list_entry(ptr, drm_mach64_freelist_t, list); \ 912 _buf->pending = 1; \ 913 _entry->buf = _buf; \ 914 list_add_tail(ptr, &dev_priv->pending); \ 915 } \ 916 _entry->discard = (_discard); \ 917 ADD_BUF_TO_RING( dev_priv ); \ 918} while (0) 919 920#define DMADISCARDBUF() \ 921do { \ 922 if (_entry == NULL) { \ 923 int ret; \ 924 if ( (ret=mach64_find_pending_buf_entry(dev_priv, &_entry, _buf)) ) { \ 925 DRM_ERROR( "%s: couldn't find pending buf %d\n", \ 926 __FUNCTION__, _buf->idx ); \ 927 return ret; \ 928 } \ 929 } \ 930 _entry->discard = 1; \ 931} while(0) 932 933#define ADD_BUF_TO_RING( dev_priv ) \ 934do { \ 935 int bytes, pages, remainder; \ 936 u32 address, page; \ 937 int i; \ 938 \ 939 bytes = _buf->used; \ 940 address = GETBUFADDR( _buf ); \ 941 \ 942 pages = (bytes + MACH64_DMA_CHUNKSIZE - 1) / MACH64_DMA_CHUNKSIZE; \ 943 \ 944 BEGIN_RING( pages * 4 ); \ 945 \ 946 for ( i = 0 ; i < pages-1 ; i++ ) { \ 947 page = address + i * MACH64_DMA_CHUNKSIZE; \ 948 OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR ); \ 949 OUT_RING( page ); \ 950 OUT_RING( MACH64_DMA_CHUNKSIZE | MACH64_DMA_HOLD_OFFSET ); \ 951 OUT_RING( 0 ); \ 952 } \ 953 \ 954 /* generate the final descriptor for any remaining commands in this buffer */ \ 955 page = address + i * MACH64_DMA_CHUNKSIZE; \ 956 remainder = bytes - i * MACH64_DMA_CHUNKSIZE; \ 957 \ 958 /* Save dword offset of last descriptor for this buffer. \ 959 * This is needed to check for completion of the buffer in freelist_get \ 960 */ \ 961 _entry->ring_ofs = RING_WRITE_OFS; \ 962 \ 963 OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR ); \ 964 OUT_RING( page ); \ 965 OUT_RING( remainder | MACH64_DMA_HOLD_OFFSET | MACH64_DMA_EOL ); \ 966 OUT_RING( 0 ); \ 967 \ 968 ADVANCE_RING(); \ 969} while(0) 970 971#define DMAADVANCEHOSTDATA( dev_priv ) \ 972do { \ 973 struct list_head *ptr; \ 974 RING_LOCALS; \ 975 \ 976 if ( MACH64_VERBOSE ) { \ 977 DRM_INFO( "DMAADVANCEHOSTDATA() in %s\n", __FUNCTION__ ); \ 978 } \ 979 \ 980 if (_buf->used <= 0) { \ 981 DRM_ERROR( "DMAADVANCEHOSTDATA() in %s: sending empty buf %d\n", \ 982 __FUNCTION__, _buf->idx ); \ 983 return DRM_ERR(EFAULT); \ 984 } \ 985 if (list_empty(&dev_priv->placeholders)) { \ 986 DRM_ERROR( "%s: empty placeholder list in DMAADVANCEHOSTDATA()\n", \ 987 __FUNCTION__ ); \ 988 return DRM_ERR(EFAULT); \ 989 } \ 990 \ 991 ptr = dev_priv->placeholders.next; \ 992 list_del(ptr); \ 993 _entry = list_entry(ptr, drm_mach64_freelist_t, list); \ 994 _entry->buf = _buf; \ 995 _entry->buf->pending = 1; \ 996 list_add_tail(ptr, &dev_priv->pending); \ 997 _entry->discard = 1; \ 998 ADD_HOSTDATA_BUF_TO_RING( dev_priv ); \ 999} while (0) 1000 1001#define ADD_HOSTDATA_BUF_TO_RING( dev_priv ) \ 1002do { \ 1003 int bytes, pages, remainder; \ 1004 u32 address, page; \ 1005 int i; \ 1006 \ 1007 bytes = _buf->used - MACH64_HOSTDATA_BLIT_OFFSET; \ 1008 pages = (bytes + MACH64_DMA_CHUNKSIZE - 1) / MACH64_DMA_CHUNKSIZE; \ 1009 address = GETBUFADDR( _buf ); \ 1010 \ 1011 BEGIN_RING( 4 + pages * 4 ); \ 1012 \ 1013 OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR ); \ 1014 OUT_RING( address ); \ 1015 OUT_RING( MACH64_HOSTDATA_BLIT_OFFSET | MACH64_DMA_HOLD_OFFSET ); \ 1016 OUT_RING( 0 ); \ 1017 \ 1018 address += MACH64_HOSTDATA_BLIT_OFFSET; \ 1019 \ 1020 for ( i = 0 ; i < pages-1 ; i++ ) { \ 1021 page = address + i * MACH64_DMA_CHUNKSIZE; \ 1022 OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_HOSTDATA ); \ 1023 OUT_RING( page ); \ 1024 OUT_RING( MACH64_DMA_CHUNKSIZE | MACH64_DMA_HOLD_OFFSET ); \ 1025 OUT_RING( 0 ); \ 1026 } \ 1027 \ 1028 /* generate the final descriptor for any remaining commands in this buffer */ \ 1029 page = address + i * MACH64_DMA_CHUNKSIZE; \ 1030 remainder = bytes - i * MACH64_DMA_CHUNKSIZE; \ 1031 \ 1032 /* Save dword offset of last descriptor for this buffer. \ 1033 * This is needed to check for completion of the buffer in freelist_get \ 1034 */ \ 1035 _entry->ring_ofs = RING_WRITE_OFS; \ 1036 \ 1037 OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_HOSTDATA ); \ 1038 OUT_RING( page ); \ 1039 OUT_RING( remainder | MACH64_DMA_HOLD_OFFSET | MACH64_DMA_EOL ); \ 1040 OUT_RING( 0 ); \ 1041 \ 1042 ADVANCE_RING(); \ 1043} while(0) 1044 1045#endif /* __MACH64_DRV_H__ */ 1046