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