mach64_state.c revision 198332
1145132Sanholt/* mach64_state.c -- State support for mach64 (Rage Pro) driver -*- linux-c -*- 2145132Sanholt * Created: Sun Dec 03 19:20:26 2000 by gareth@valinux.com 3152909Sanholt */ 4152909Sanholt/*- 5145132Sanholt * Copyright 2000 Gareth Hughes 6145132Sanholt * Copyright 2002-2003 Leif Delgass 7145132Sanholt * All Rights Reserved. 8145132Sanholt * 9145132Sanholt * Permission is hereby granted, free of charge, to any person obtaining a 10145132Sanholt * copy of this software and associated documentation files (the "Software"), 11145132Sanholt * to deal in the Software without restriction, including without limitation 12145132Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13145132Sanholt * and/or sell copies of the Software, and to permit persons to whom the 14145132Sanholt * Software is furnished to do so, subject to the following conditions: 15145132Sanholt * 16145132Sanholt * The above copyright notice and this permission notice (including the next 17145132Sanholt * paragraph) shall be included in all copies or substantial portions of the 18145132Sanholt * Software. 19145132Sanholt * 20145132Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21145132Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22145132Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23145132Sanholt * THE COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 24145132Sanholt * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25145132Sanholt * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26145132Sanholt * 27145132Sanholt * Authors: 28145132Sanholt * Gareth Hughes <gareth@valinux.com> 29145132Sanholt * Leif Delgass <ldelgass@retinalburn.net> 30182080Srnoland * Jos�� Fonseca <j_r_fonseca@yahoo.co.uk> 31145132Sanholt */ 32145132Sanholt 33152909Sanholt#include <sys/cdefs.h> 34152909Sanholt__FBSDID("$FreeBSD: head/sys/dev/drm/mach64_state.c 198332 2009-10-21 15:54:45Z brueffer $"); 35152909Sanholt 36145132Sanholt#include "dev/drm/drmP.h" 37145132Sanholt#include "dev/drm/drm.h" 38145132Sanholt#include "dev/drm/mach64_drm.h" 39145132Sanholt#include "dev/drm/mach64_drv.h" 40145132Sanholt 41145132Sanholt/* Interface history: 42145132Sanholt * 43145132Sanholt * 1.0 - Initial mach64 DRM 44145132Sanholt * 45145132Sanholt */ 46182080Srnolandstruct drm_ioctl_desc mach64_ioctls[] = { 47182080Srnoland DRM_IOCTL_DEF(DRM_MACH64_INIT, mach64_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 48182080Srnoland DRM_IOCTL_DEF(DRM_MACH64_CLEAR, mach64_dma_clear, DRM_AUTH), 49182080Srnoland DRM_IOCTL_DEF(DRM_MACH64_SWAP, mach64_dma_swap, DRM_AUTH), 50182080Srnoland DRM_IOCTL_DEF(DRM_MACH64_IDLE, mach64_dma_idle, DRM_AUTH), 51182080Srnoland DRM_IOCTL_DEF(DRM_MACH64_RESET, mach64_engine_reset, DRM_AUTH), 52182080Srnoland DRM_IOCTL_DEF(DRM_MACH64_VERTEX, mach64_dma_vertex, DRM_AUTH), 53182080Srnoland DRM_IOCTL_DEF(DRM_MACH64_BLIT, mach64_dma_blit, DRM_AUTH), 54182080Srnoland DRM_IOCTL_DEF(DRM_MACH64_FLUSH, mach64_dma_flush, DRM_AUTH), 55182080Srnoland DRM_IOCTL_DEF(DRM_MACH64_GETPARAM, mach64_get_param, DRM_AUTH), 56145132Sanholt}; 57145132Sanholt 58145132Sanholtint mach64_max_ioctl = DRM_ARRAY_SIZE(mach64_ioctls); 59145132Sanholt 60145132Sanholt/* ================================================================ 61145132Sanholt * DMA hardware state programming functions 62145132Sanholt */ 63145132Sanholt 64145132Sanholtstatic void mach64_print_dirty(const char *msg, unsigned int flags) 65145132Sanholt{ 66145132Sanholt DRM_DEBUG("%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s\n", 67145132Sanholt msg, 68145132Sanholt flags, 69145132Sanholt (flags & MACH64_UPLOAD_DST_OFF_PITCH) ? "dst_off_pitch, " : 70145132Sanholt "", 71145132Sanholt (flags & MACH64_UPLOAD_Z_ALPHA_CNTL) ? "z_alpha_cntl, " : "", 72145132Sanholt (flags & MACH64_UPLOAD_SCALE_3D_CNTL) ? "scale_3d_cntl, " : 73145132Sanholt "", (flags & MACH64_UPLOAD_DP_FOG_CLR) ? "dp_fog_clr, " : "", 74145132Sanholt (flags & MACH64_UPLOAD_DP_WRITE_MASK) ? "dp_write_mask, " : 75145132Sanholt "", 76145132Sanholt (flags & MACH64_UPLOAD_DP_PIX_WIDTH) ? "dp_pix_width, " : "", 77145132Sanholt (flags & MACH64_UPLOAD_SETUP_CNTL) ? "setup_cntl, " : "", 78145132Sanholt (flags & MACH64_UPLOAD_MISC) ? "misc, " : "", 79145132Sanholt (flags & MACH64_UPLOAD_TEXTURE) ? "texture, " : "", 80145132Sanholt (flags & MACH64_UPLOAD_TEX0IMAGE) ? "tex0 image, " : "", 81145132Sanholt (flags & MACH64_UPLOAD_TEX1IMAGE) ? "tex1 image, " : "", 82145132Sanholt (flags & MACH64_UPLOAD_CLIPRECTS) ? "cliprects, " : ""); 83145132Sanholt} 84145132Sanholt 85145132Sanholt/* Mach64 doesn't have hardware cliprects, just one hardware scissor, 86145132Sanholt * so the GL scissor is intersected with each cliprect here 87145132Sanholt */ 88145132Sanholt/* This function returns 0 on success, 1 for no intersection, and 89145132Sanholt * negative for an error 90145132Sanholt */ 91182080Srnolandstatic int mach64_emit_cliprect(struct drm_file *file_priv, 92182080Srnoland drm_mach64_private_t * dev_priv, 93182080Srnoland struct drm_clip_rect * box) 94145132Sanholt{ 95145132Sanholt u32 sc_left_right, sc_top_bottom; 96182080Srnoland struct drm_clip_rect scissor; 97145132Sanholt drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 98145132Sanholt drm_mach64_context_regs_t *regs = &sarea_priv->context_state; 99145132Sanholt DMALOCALS; 100145132Sanholt 101182080Srnoland DRM_DEBUG("box=%p\n", box); 102145132Sanholt 103145132Sanholt /* Get GL scissor */ 104145132Sanholt /* FIXME: store scissor in SAREA as a cliprect instead of in 105145132Sanholt * hardware format, or do intersection client-side 106145132Sanholt */ 107145132Sanholt scissor.x1 = regs->sc_left_right & 0xffff; 108145132Sanholt scissor.x2 = (regs->sc_left_right & 0xffff0000) >> 16; 109145132Sanholt scissor.y1 = regs->sc_top_bottom & 0xffff; 110145132Sanholt scissor.y2 = (regs->sc_top_bottom & 0xffff0000) >> 16; 111145132Sanholt 112145132Sanholt /* Intersect GL scissor with cliprect */ 113145132Sanholt if (box->x1 > scissor.x1) 114145132Sanholt scissor.x1 = box->x1; 115145132Sanholt if (box->y1 > scissor.y1) 116145132Sanholt scissor.y1 = box->y1; 117145132Sanholt if (box->x2 < scissor.x2) 118145132Sanholt scissor.x2 = box->x2; 119145132Sanholt if (box->y2 < scissor.y2) 120145132Sanholt scissor.y2 = box->y2; 121145132Sanholt /* positive return means skip */ 122145132Sanholt if (scissor.x1 >= scissor.x2) 123145132Sanholt return 1; 124145132Sanholt if (scissor.y1 >= scissor.y2) 125145132Sanholt return 1; 126145132Sanholt 127182080Srnoland DMAGETPTR(file_priv, dev_priv, 2); /* returns on failure to get buffer */ 128145132Sanholt 129145132Sanholt sc_left_right = ((scissor.x1 << 0) | (scissor.x2 << 16)); 130145132Sanholt sc_top_bottom = ((scissor.y1 << 0) | (scissor.y2 << 16)); 131145132Sanholt 132145132Sanholt DMAOUTREG(MACH64_SC_LEFT_RIGHT, sc_left_right); 133145132Sanholt DMAOUTREG(MACH64_SC_TOP_BOTTOM, sc_top_bottom); 134145132Sanholt 135145132Sanholt DMAADVANCE(dev_priv, 1); 136145132Sanholt 137145132Sanholt return 0; 138145132Sanholt} 139145132Sanholt 140182080Srnolandstatic __inline__ int mach64_emit_state(struct drm_file *file_priv, 141145132Sanholt drm_mach64_private_t * dev_priv) 142145132Sanholt{ 143145132Sanholt drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 144145132Sanholt drm_mach64_context_regs_t *regs = &sarea_priv->context_state; 145145132Sanholt unsigned int dirty = sarea_priv->dirty; 146145132Sanholt u32 offset = ((regs->tex_size_pitch & 0xf0) >> 2); 147145132Sanholt DMALOCALS; 148145132Sanholt 149145132Sanholt if (MACH64_VERBOSE) { 150145132Sanholt mach64_print_dirty(__FUNCTION__, dirty); 151145132Sanholt } else { 152182080Srnoland DRM_DEBUG("dirty=0x%08x\n", dirty); 153145132Sanholt } 154145132Sanholt 155182080Srnoland DMAGETPTR(file_priv, dev_priv, 17); /* returns on failure to get buffer */ 156145132Sanholt 157145132Sanholt if (dirty & MACH64_UPLOAD_MISC) { 158145132Sanholt DMAOUTREG(MACH64_DP_MIX, regs->dp_mix); 159145132Sanholt DMAOUTREG(MACH64_DP_SRC, regs->dp_src); 160145132Sanholt DMAOUTREG(MACH64_CLR_CMP_CNTL, regs->clr_cmp_cntl); 161145132Sanholt DMAOUTREG(MACH64_GUI_TRAJ_CNTL, regs->gui_traj_cntl); 162145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_MISC; 163145132Sanholt } 164145132Sanholt 165145132Sanholt if (dirty & MACH64_UPLOAD_DST_OFF_PITCH) { 166145132Sanholt DMAOUTREG(MACH64_DST_OFF_PITCH, regs->dst_off_pitch); 167145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_DST_OFF_PITCH; 168145132Sanholt } 169145132Sanholt if (dirty & MACH64_UPLOAD_Z_OFF_PITCH) { 170145132Sanholt DMAOUTREG(MACH64_Z_OFF_PITCH, regs->z_off_pitch); 171145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_Z_OFF_PITCH; 172145132Sanholt } 173145132Sanholt if (dirty & MACH64_UPLOAD_Z_ALPHA_CNTL) { 174145132Sanholt DMAOUTREG(MACH64_Z_CNTL, regs->z_cntl); 175145132Sanholt DMAOUTREG(MACH64_ALPHA_TST_CNTL, regs->alpha_tst_cntl); 176145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_Z_ALPHA_CNTL; 177145132Sanholt } 178145132Sanholt if (dirty & MACH64_UPLOAD_SCALE_3D_CNTL) { 179145132Sanholt DMAOUTREG(MACH64_SCALE_3D_CNTL, regs->scale_3d_cntl); 180145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_SCALE_3D_CNTL; 181145132Sanholt } 182145132Sanholt if (dirty & MACH64_UPLOAD_DP_FOG_CLR) { 183145132Sanholt DMAOUTREG(MACH64_DP_FOG_CLR, regs->dp_fog_clr); 184145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_DP_FOG_CLR; 185145132Sanholt } 186145132Sanholt if (dirty & MACH64_UPLOAD_DP_WRITE_MASK) { 187145132Sanholt DMAOUTREG(MACH64_DP_WRITE_MASK, regs->dp_write_mask); 188145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_DP_WRITE_MASK; 189145132Sanholt } 190145132Sanholt if (dirty & MACH64_UPLOAD_DP_PIX_WIDTH) { 191145132Sanholt DMAOUTREG(MACH64_DP_PIX_WIDTH, regs->dp_pix_width); 192145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_DP_PIX_WIDTH; 193145132Sanholt } 194145132Sanholt if (dirty & MACH64_UPLOAD_SETUP_CNTL) { 195145132Sanholt DMAOUTREG(MACH64_SETUP_CNTL, regs->setup_cntl); 196145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_SETUP_CNTL; 197145132Sanholt } 198145132Sanholt 199145132Sanholt if (dirty & MACH64_UPLOAD_TEXTURE) { 200145132Sanholt DMAOUTREG(MACH64_TEX_SIZE_PITCH, regs->tex_size_pitch); 201145132Sanholt DMAOUTREG(MACH64_TEX_CNTL, regs->tex_cntl); 202145132Sanholt DMAOUTREG(MACH64_SECONDARY_TEX_OFF, regs->secondary_tex_off); 203145132Sanholt DMAOUTREG(MACH64_TEX_0_OFF + offset, regs->tex_offset); 204145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_TEXTURE; 205145132Sanholt } 206145132Sanholt 207145132Sanholt DMAADVANCE(dev_priv, 1); 208145132Sanholt 209145132Sanholt sarea_priv->dirty &= MACH64_UPLOAD_CLIPRECTS; 210145132Sanholt 211145132Sanholt return 0; 212145132Sanholt 213145132Sanholt} 214145132Sanholt 215145132Sanholt/* ================================================================ 216145132Sanholt * DMA command dispatch functions 217145132Sanholt */ 218145132Sanholt 219182080Srnolandstatic int mach64_dma_dispatch_clear(struct drm_device * dev, 220182080Srnoland struct drm_file *file_priv, 221145132Sanholt unsigned int flags, 222145132Sanholt int cx, int cy, int cw, int ch, 223145132Sanholt unsigned int clear_color, 224145132Sanholt unsigned int clear_depth) 225145132Sanholt{ 226145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 227145132Sanholt drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 228145132Sanholt drm_mach64_context_regs_t *ctx = &sarea_priv->context_state; 229145132Sanholt int nbox = sarea_priv->nbox; 230182080Srnoland struct drm_clip_rect *pbox = sarea_priv->boxes; 231145132Sanholt u32 fb_bpp, depth_bpp; 232145132Sanholt int i; 233145132Sanholt DMALOCALS; 234145132Sanholt 235182080Srnoland DRM_DEBUG("\n"); 236145132Sanholt 237145132Sanholt switch (dev_priv->fb_bpp) { 238145132Sanholt case 16: 239145132Sanholt fb_bpp = MACH64_DATATYPE_RGB565; 240145132Sanholt break; 241145132Sanholt case 32: 242145132Sanholt fb_bpp = MACH64_DATATYPE_ARGB8888; 243145132Sanholt break; 244145132Sanholt default: 245182080Srnoland return -EINVAL; 246145132Sanholt } 247145132Sanholt switch (dev_priv->depth_bpp) { 248145132Sanholt case 16: 249145132Sanholt depth_bpp = MACH64_DATATYPE_RGB565; 250145132Sanholt break; 251145132Sanholt case 24: 252145132Sanholt case 32: 253145132Sanholt depth_bpp = MACH64_DATATYPE_ARGB8888; 254145132Sanholt break; 255145132Sanholt default: 256182080Srnoland return -EINVAL; 257145132Sanholt } 258145132Sanholt 259145132Sanholt if (!nbox) 260145132Sanholt return 0; 261145132Sanholt 262182080Srnoland DMAGETPTR(file_priv, dev_priv, nbox * 31); /* returns on failure to get buffer */ 263145132Sanholt 264145132Sanholt for (i = 0; i < nbox; i++) { 265145132Sanholt int x = pbox[i].x1; 266145132Sanholt int y = pbox[i].y1; 267145132Sanholt int w = pbox[i].x2 - x; 268145132Sanholt int h = pbox[i].y2 - y; 269145132Sanholt 270145132Sanholt DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n", 271145132Sanholt pbox[i].x1, pbox[i].y1, 272145132Sanholt pbox[i].x2, pbox[i].y2, flags); 273145132Sanholt 274145132Sanholt if (flags & (MACH64_FRONT | MACH64_BACK)) { 275145132Sanholt /* Setup for color buffer clears 276145132Sanholt */ 277145132Sanholt 278145132Sanholt DMAOUTREG(MACH64_Z_CNTL, 0); 279145132Sanholt DMAOUTREG(MACH64_SCALE_3D_CNTL, 0); 280145132Sanholt 281145132Sanholt DMAOUTREG(MACH64_SC_LEFT_RIGHT, ctx->sc_left_right); 282145132Sanholt DMAOUTREG(MACH64_SC_TOP_BOTTOM, ctx->sc_top_bottom); 283145132Sanholt 284145132Sanholt DMAOUTREG(MACH64_CLR_CMP_CNTL, 0); 285145132Sanholt DMAOUTREG(MACH64_GUI_TRAJ_CNTL, 286145132Sanholt (MACH64_DST_X_LEFT_TO_RIGHT | 287145132Sanholt MACH64_DST_Y_TOP_TO_BOTTOM)); 288145132Sanholt 289145132Sanholt DMAOUTREG(MACH64_DP_PIX_WIDTH, ((fb_bpp << 0) | 290145132Sanholt (fb_bpp << 4) | 291145132Sanholt (fb_bpp << 8) | 292145132Sanholt (fb_bpp << 16) | 293145132Sanholt (fb_bpp << 28))); 294145132Sanholt 295145132Sanholt DMAOUTREG(MACH64_DP_FRGD_CLR, clear_color); 296145132Sanholt DMAOUTREG(MACH64_DP_WRITE_MASK, ctx->dp_write_mask); 297145132Sanholt DMAOUTREG(MACH64_DP_MIX, (MACH64_BKGD_MIX_D | 298145132Sanholt MACH64_FRGD_MIX_S)); 299145132Sanholt DMAOUTREG(MACH64_DP_SRC, (MACH64_BKGD_SRC_FRGD_CLR | 300145132Sanholt MACH64_FRGD_SRC_FRGD_CLR | 301145132Sanholt MACH64_MONO_SRC_ONE)); 302145132Sanholt 303145132Sanholt } 304145132Sanholt 305145132Sanholt if (flags & MACH64_FRONT) { 306145132Sanholt 307145132Sanholt DMAOUTREG(MACH64_DST_OFF_PITCH, 308145132Sanholt dev_priv->front_offset_pitch); 309145132Sanholt DMAOUTREG(MACH64_DST_X_Y, (y << 16) | x); 310145132Sanholt DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w); 311145132Sanholt 312145132Sanholt } 313145132Sanholt 314145132Sanholt if (flags & MACH64_BACK) { 315145132Sanholt 316145132Sanholt DMAOUTREG(MACH64_DST_OFF_PITCH, 317145132Sanholt dev_priv->back_offset_pitch); 318145132Sanholt DMAOUTREG(MACH64_DST_X_Y, (y << 16) | x); 319145132Sanholt DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w); 320145132Sanholt 321145132Sanholt } 322145132Sanholt 323145132Sanholt if (flags & MACH64_DEPTH) { 324145132Sanholt /* Setup for depth buffer clear 325145132Sanholt */ 326145132Sanholt DMAOUTREG(MACH64_Z_CNTL, 0); 327145132Sanholt DMAOUTREG(MACH64_SCALE_3D_CNTL, 0); 328145132Sanholt 329145132Sanholt DMAOUTREG(MACH64_SC_LEFT_RIGHT, ctx->sc_left_right); 330145132Sanholt DMAOUTREG(MACH64_SC_TOP_BOTTOM, ctx->sc_top_bottom); 331145132Sanholt 332145132Sanholt DMAOUTREG(MACH64_CLR_CMP_CNTL, 0); 333145132Sanholt DMAOUTREG(MACH64_GUI_TRAJ_CNTL, 334145132Sanholt (MACH64_DST_X_LEFT_TO_RIGHT | 335145132Sanholt MACH64_DST_Y_TOP_TO_BOTTOM)); 336145132Sanholt 337145132Sanholt DMAOUTREG(MACH64_DP_PIX_WIDTH, ((depth_bpp << 0) | 338145132Sanholt (depth_bpp << 4) | 339145132Sanholt (depth_bpp << 8) | 340145132Sanholt (depth_bpp << 16) | 341145132Sanholt (depth_bpp << 28))); 342145132Sanholt 343145132Sanholt DMAOUTREG(MACH64_DP_FRGD_CLR, clear_depth); 344145132Sanholt DMAOUTREG(MACH64_DP_WRITE_MASK, 0xffffffff); 345145132Sanholt DMAOUTREG(MACH64_DP_MIX, (MACH64_BKGD_MIX_D | 346145132Sanholt MACH64_FRGD_MIX_S)); 347145132Sanholt DMAOUTREG(MACH64_DP_SRC, (MACH64_BKGD_SRC_FRGD_CLR | 348145132Sanholt MACH64_FRGD_SRC_FRGD_CLR | 349145132Sanholt MACH64_MONO_SRC_ONE)); 350145132Sanholt 351145132Sanholt DMAOUTREG(MACH64_DST_OFF_PITCH, 352145132Sanholt dev_priv->depth_offset_pitch); 353145132Sanholt DMAOUTREG(MACH64_DST_X_Y, (y << 16) | x); 354145132Sanholt DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w); 355145132Sanholt } 356145132Sanholt } 357145132Sanholt 358145132Sanholt DMAADVANCE(dev_priv, 1); 359145132Sanholt 360145132Sanholt return 0; 361145132Sanholt} 362145132Sanholt 363182080Srnolandstatic int mach64_dma_dispatch_swap(struct drm_device * dev, 364182080Srnoland struct drm_file *file_priv) 365145132Sanholt{ 366145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 367145132Sanholt drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 368145132Sanholt int nbox = sarea_priv->nbox; 369182080Srnoland struct drm_clip_rect *pbox = sarea_priv->boxes; 370145132Sanholt u32 fb_bpp; 371145132Sanholt int i; 372145132Sanholt DMALOCALS; 373145132Sanholt 374182080Srnoland DRM_DEBUG("\n"); 375145132Sanholt 376145132Sanholt switch (dev_priv->fb_bpp) { 377145132Sanholt case 16: 378145132Sanholt fb_bpp = MACH64_DATATYPE_RGB565; 379145132Sanholt break; 380145132Sanholt case 32: 381145132Sanholt default: 382145132Sanholt fb_bpp = MACH64_DATATYPE_ARGB8888; 383145132Sanholt break; 384145132Sanholt } 385145132Sanholt 386145132Sanholt if (!nbox) 387145132Sanholt return 0; 388145132Sanholt 389182080Srnoland DMAGETPTR(file_priv, dev_priv, 13 + nbox * 4); /* returns on failure to get buffer */ 390145132Sanholt 391145132Sanholt DMAOUTREG(MACH64_Z_CNTL, 0); 392145132Sanholt DMAOUTREG(MACH64_SCALE_3D_CNTL, 0); 393145132Sanholt 394145132Sanholt DMAOUTREG(MACH64_SC_LEFT_RIGHT, 0 | (8191 << 16)); /* no scissor */ 395145132Sanholt DMAOUTREG(MACH64_SC_TOP_BOTTOM, 0 | (16383 << 16)); 396145132Sanholt 397145132Sanholt DMAOUTREG(MACH64_CLR_CMP_CNTL, 0); 398145132Sanholt DMAOUTREG(MACH64_GUI_TRAJ_CNTL, (MACH64_DST_X_LEFT_TO_RIGHT | 399145132Sanholt MACH64_DST_Y_TOP_TO_BOTTOM)); 400145132Sanholt 401145132Sanholt DMAOUTREG(MACH64_DP_PIX_WIDTH, ((fb_bpp << 0) | 402145132Sanholt (fb_bpp << 4) | 403145132Sanholt (fb_bpp << 8) | 404145132Sanholt (fb_bpp << 16) | (fb_bpp << 28))); 405145132Sanholt 406145132Sanholt DMAOUTREG(MACH64_DP_WRITE_MASK, 0xffffffff); 407145132Sanholt DMAOUTREG(MACH64_DP_MIX, (MACH64_BKGD_MIX_D | MACH64_FRGD_MIX_S)); 408145132Sanholt DMAOUTREG(MACH64_DP_SRC, (MACH64_BKGD_SRC_BKGD_CLR | 409145132Sanholt MACH64_FRGD_SRC_BLIT | MACH64_MONO_SRC_ONE)); 410145132Sanholt 411145132Sanholt DMAOUTREG(MACH64_SRC_OFF_PITCH, dev_priv->back_offset_pitch); 412145132Sanholt DMAOUTREG(MACH64_DST_OFF_PITCH, dev_priv->front_offset_pitch); 413145132Sanholt 414145132Sanholt for (i = 0; i < nbox; i++) { 415145132Sanholt int x = pbox[i].x1; 416145132Sanholt int y = pbox[i].y1; 417145132Sanholt int w = pbox[i].x2 - x; 418145132Sanholt int h = pbox[i].y2 - y; 419145132Sanholt 420145132Sanholt DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", 421145132Sanholt pbox[i].x1, pbox[i].y1, pbox[i].x2, pbox[i].y2); 422145132Sanholt 423145132Sanholt DMAOUTREG(MACH64_SRC_WIDTH1, w); 424145132Sanholt DMAOUTREG(MACH64_SRC_Y_X, (x << 16) | y); 425145132Sanholt DMAOUTREG(MACH64_DST_Y_X, (x << 16) | y); 426145132Sanholt DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w); 427145132Sanholt 428145132Sanholt } 429145132Sanholt 430145132Sanholt DMAADVANCE(dev_priv, 1); 431145132Sanholt 432145132Sanholt if (dev_priv->driver_mode == MACH64_MODE_DMA_ASYNC) { 433145132Sanholt for (i = 0; i < MACH64_MAX_QUEUED_FRAMES - 1; i++) { 434145132Sanholt dev_priv->frame_ofs[i] = dev_priv->frame_ofs[i + 1]; 435145132Sanholt } 436145132Sanholt dev_priv->frame_ofs[i] = GETRINGOFFSET(); 437145132Sanholt 438145132Sanholt dev_priv->sarea_priv->frames_queued++; 439145132Sanholt } 440145132Sanholt 441145132Sanholt return 0; 442145132Sanholt} 443145132Sanholt 444145132Sanholtstatic int mach64_do_get_frames_queued(drm_mach64_private_t * dev_priv) 445145132Sanholt{ 446145132Sanholt drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; 447145132Sanholt drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 448145132Sanholt int i, start; 449145132Sanholt u32 head, tail, ofs; 450145132Sanholt 451182080Srnoland DRM_DEBUG("\n"); 452145132Sanholt 453145132Sanholt if (sarea_priv->frames_queued == 0) 454145132Sanholt return 0; 455145132Sanholt 456145132Sanholt tail = ring->tail; 457145132Sanholt mach64_ring_tick(dev_priv, ring); 458145132Sanholt head = ring->head; 459145132Sanholt 460145132Sanholt start = (MACH64_MAX_QUEUED_FRAMES - 461145132Sanholt DRM_MIN(MACH64_MAX_QUEUED_FRAMES, sarea_priv->frames_queued)); 462145132Sanholt 463145132Sanholt if (head == tail) { 464145132Sanholt sarea_priv->frames_queued = 0; 465145132Sanholt for (i = start; i < MACH64_MAX_QUEUED_FRAMES; i++) { 466145132Sanholt dev_priv->frame_ofs[i] = ~0; 467145132Sanholt } 468145132Sanholt return 0; 469145132Sanholt } 470145132Sanholt 471145132Sanholt for (i = start; i < MACH64_MAX_QUEUED_FRAMES; i++) { 472145132Sanholt ofs = dev_priv->frame_ofs[i]; 473145132Sanholt DRM_DEBUG("frame_ofs[%d] ofs: %d\n", i, ofs); 474145132Sanholt if (ofs == ~0 || 475145132Sanholt (head < tail && (ofs < head || ofs >= tail)) || 476145132Sanholt (head > tail && (ofs < head && ofs >= tail))) { 477145132Sanholt sarea_priv->frames_queued = 478145132Sanholt (MACH64_MAX_QUEUED_FRAMES - 1) - i; 479145132Sanholt dev_priv->frame_ofs[i] = ~0; 480145132Sanholt } 481145132Sanholt } 482145132Sanholt 483145132Sanholt return sarea_priv->frames_queued; 484145132Sanholt} 485145132Sanholt 486145132Sanholt/* Copy and verify a client submited buffer. 487145132Sanholt * FIXME: Make an assembly optimized version 488145132Sanholt */ 489182080Srnolandstatic __inline__ int copy_from_user_vertex(u32 *to, 490182080Srnoland const u32 __user *ufrom, 491182080Srnoland unsigned long bytes) 492145132Sanholt{ 493145132Sanholt unsigned long n = bytes; /* dwords remaining in buffer */ 494152909Sanholt u32 *from, *orig_from; 495145132Sanholt 496152909Sanholt from = drm_alloc(bytes, DRM_MEM_DRIVER); 497152909Sanholt if (from == NULL) 498182080Srnoland return -ENOMEM; 499152909Sanholt 500152909Sanholt if (DRM_COPY_FROM_USER(from, ufrom, bytes)) { 501152909Sanholt drm_free(from, bytes, DRM_MEM_DRIVER); 502182080Srnoland return -EFAULT; 503145132Sanholt } 504152909Sanholt orig_from = from; /* we'll be modifying the "from" ptr, so save it */ 505145132Sanholt 506145132Sanholt n >>= 2; 507145132Sanholt 508145132Sanholt while (n > 1) { 509145132Sanholt u32 data, reg, count; 510145132Sanholt 511152909Sanholt data = *from++; 512145132Sanholt 513145132Sanholt n--; 514145132Sanholt 515145132Sanholt reg = le32_to_cpu(data); 516145132Sanholt count = (reg >> 16) + 1; 517145132Sanholt if (count <= n) { 518145132Sanholt n -= count; 519145132Sanholt reg &= 0xffff; 520145132Sanholt 521145132Sanholt /* This is an exact match of Mach64's Setup Engine registers, 522145132Sanholt * excluding SETUP_CNTL (1_C1). 523145132Sanholt */ 524145132Sanholt if ((reg >= 0x0190 && reg < 0x01c1) || 525145132Sanholt (reg >= 0x01ca && reg <= 0x01cf)) { 526145132Sanholt *to++ = data; 527152909Sanholt memcpy(to, from, count << 2); 528152909Sanholt from += count; 529145132Sanholt to += count; 530145132Sanholt } else { 531182080Srnoland DRM_ERROR("Got bad command: 0x%04x\n", reg); 532152909Sanholt drm_free(orig_from, bytes, DRM_MEM_DRIVER); 533182080Srnoland return -EACCES; 534145132Sanholt } 535145132Sanholt } else { 536145132Sanholt DRM_ERROR 537182080Srnoland ("Got bad command count(=%u) dwords remaining=%lu\n", 538182080Srnoland count, n); 539152909Sanholt drm_free(orig_from, bytes, DRM_MEM_DRIVER); 540182080Srnoland return -EINVAL; 541145132Sanholt } 542145132Sanholt } 543145132Sanholt 544152909Sanholt drm_free(orig_from, bytes, DRM_MEM_DRIVER); 545145132Sanholt if (n == 0) 546145132Sanholt return 0; 547145132Sanholt else { 548182080Srnoland DRM_ERROR("Bad buf->used(=%lu)\n", bytes); 549182080Srnoland return -EINVAL; 550145132Sanholt } 551145132Sanholt} 552145132Sanholt 553182080Srnolandstatic int mach64_dma_dispatch_vertex(struct drm_device * dev, 554182080Srnoland struct drm_file *file_priv, 555182080Srnoland drm_mach64_vertex_t * vertex) 556145132Sanholt{ 557145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 558145132Sanholt drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 559182080Srnoland struct drm_buf *copy_buf; 560182080Srnoland void *buf = vertex->buf; 561182080Srnoland unsigned long used = vertex->used; 562182080Srnoland int ret = 0; 563182080Srnoland int i = 0; 564145132Sanholt int done = 0; 565145132Sanholt int verify_ret = 0; 566145132Sanholt DMALOCALS; 567145132Sanholt 568182080Srnoland DRM_DEBUG("buf=%p used=%lu nbox=%d\n", 569182080Srnoland buf, used, sarea_priv->nbox); 570145132Sanholt 571182080Srnoland if (!used) 572182080Srnoland goto _vertex_done; 573145132Sanholt 574182080Srnoland copy_buf = mach64_freelist_get(dev_priv); 575182080Srnoland if (copy_buf == NULL) { 576182080Srnoland DRM_ERROR("couldn't get buffer\n"); 577182080Srnoland return -EAGAIN; 578182080Srnoland } 579145132Sanholt 580182080Srnoland /* Mach64's vertex data is actually register writes. To avoid security 581182080Srnoland * compromises these register writes have to be verified and copied from 582182080Srnoland * user space into a private DMA buffer. 583182080Srnoland */ 584182080Srnoland verify_ret = copy_from_user_vertex(GETBUFPTR(copy_buf), buf, used); 585145132Sanholt 586182080Srnoland if (verify_ret != 0) { 587182080Srnoland mach64_freelist_put(dev_priv, copy_buf); 588182080Srnoland goto _vertex_done; 589182080Srnoland } 590145132Sanholt 591182080Srnoland copy_buf->used = used; 592145132Sanholt 593182080Srnoland DMASETPTR(copy_buf); 594182080Srnoland 595182080Srnoland if (sarea_priv->dirty & ~MACH64_UPLOAD_CLIPRECTS) { 596182080Srnoland ret = mach64_emit_state(file_priv, dev_priv); 597182080Srnoland if (ret < 0) 598182080Srnoland return ret; 599182080Srnoland } 600182080Srnoland 601182080Srnoland do { 602182080Srnoland /* Emit the next cliprect */ 603182080Srnoland if (i < sarea_priv->nbox) { 604182080Srnoland ret = mach64_emit_cliprect(file_priv, dev_priv, 605182080Srnoland &sarea_priv->boxes[i]); 606182080Srnoland if (ret < 0) { 607182080Srnoland /* failed to get buffer */ 608182080Srnoland return ret; 609182080Srnoland } else if (ret != 0) { 610182080Srnoland /* null intersection with scissor */ 611182080Srnoland continue; 612145132Sanholt } 613182080Srnoland } 614182080Srnoland if ((i >= sarea_priv->nbox - 1)) 615182080Srnoland done = 1; 616145132Sanholt 617182080Srnoland /* Add the buffer to the DMA queue */ 618182080Srnoland DMAADVANCE(dev_priv, done); 619145132Sanholt 620182080Srnoland } while (++i < sarea_priv->nbox); 621145132Sanholt 622182080Srnoland if (!done) { 623182080Srnoland if (copy_buf->pending) { 624145132Sanholt DMADISCARDBUF(); 625182080Srnoland } else { 626182080Srnoland /* This buffer wasn't used (no cliprects), so place it 627182080Srnoland * back on the free list 628145132Sanholt */ 629182080Srnoland mach64_freelist_put(dev_priv, copy_buf); 630145132Sanholt } 631145132Sanholt } 632145132Sanholt 633182080Srnoland_vertex_done: 634145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_CLIPRECTS; 635145132Sanholt sarea_priv->nbox = 0; 636145132Sanholt 637145132Sanholt return verify_ret; 638145132Sanholt} 639145132Sanholt 640182080Srnolandstatic __inline__ int copy_from_user_blit(u32 *to, 641182080Srnoland const u32 __user *ufrom, 642182080Srnoland unsigned long bytes) 643182080Srnoland{ 644182080Srnoland to = (u32 *)((char *)to + MACH64_HOSTDATA_BLIT_OFFSET); 645182080Srnoland 646182080Srnoland if (DRM_COPY_FROM_USER(to, ufrom, bytes)) { 647182080Srnoland return -EFAULT; 648182080Srnoland } 649182080Srnoland 650182080Srnoland return 0; 651182080Srnoland} 652182080Srnoland 653182080Srnolandstatic int mach64_dma_dispatch_blit(struct drm_device * dev, 654182080Srnoland struct drm_file *file_priv, 655145132Sanholt drm_mach64_blit_t * blit) 656145132Sanholt{ 657145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 658145132Sanholt int dword_shift, dwords; 659182080Srnoland unsigned long used; 660182080Srnoland struct drm_buf *copy_buf; 661182080Srnoland int verify_ret = 0; 662145132Sanholt DMALOCALS; 663145132Sanholt 664145132Sanholt /* The compiler won't optimize away a division by a variable, 665145132Sanholt * even if the only legal values are powers of two. Thus, we'll 666145132Sanholt * use a shift instead. 667145132Sanholt */ 668145132Sanholt switch (blit->format) { 669145132Sanholt case MACH64_DATATYPE_ARGB8888: 670145132Sanholt dword_shift = 0; 671145132Sanholt break; 672145132Sanholt case MACH64_DATATYPE_ARGB1555: 673145132Sanholt case MACH64_DATATYPE_RGB565: 674145132Sanholt case MACH64_DATATYPE_VYUY422: 675145132Sanholt case MACH64_DATATYPE_YVYU422: 676145132Sanholt case MACH64_DATATYPE_ARGB4444: 677145132Sanholt dword_shift = 1; 678145132Sanholt break; 679145132Sanholt case MACH64_DATATYPE_CI8: 680145132Sanholt case MACH64_DATATYPE_RGB8: 681145132Sanholt dword_shift = 2; 682145132Sanholt break; 683145132Sanholt default: 684145132Sanholt DRM_ERROR("invalid blit format %d\n", blit->format); 685182080Srnoland return -EINVAL; 686145132Sanholt } 687145132Sanholt 688145132Sanholt /* Set buf->used to the bytes of blit data based on the blit dimensions 689145132Sanholt * and verify the size. When the setup is emitted to the buffer with 690145132Sanholt * the DMA* macros below, buf->used is incremented to include the bytes 691145132Sanholt * used for setup as well as the blit data. 692145132Sanholt */ 693145132Sanholt dwords = (blit->width * blit->height) >> dword_shift; 694182080Srnoland used = dwords << 2; 695182080Srnoland if (used <= 0 || 696182080Srnoland used > MACH64_BUFFER_SIZE - MACH64_HOSTDATA_BLIT_OFFSET) { 697182080Srnoland DRM_ERROR("Invalid blit size: %lu bytes\n", used); 698182080Srnoland return -EINVAL; 699145132Sanholt } 700145132Sanholt 701182080Srnoland copy_buf = mach64_freelist_get(dev_priv); 702182080Srnoland if (copy_buf == NULL) { 703182080Srnoland DRM_ERROR("couldn't get buffer\n"); 704182080Srnoland return -EAGAIN; 705182080Srnoland } 706182080Srnoland 707182080Srnoland /* Copy the blit data from userspace. 708182080Srnoland * 709182080Srnoland * XXX: This is overkill. The most efficient solution would be having 710182080Srnoland * two sets of buffers (one set private for vertex data, the other set 711182080Srnoland * client-writable for blits). However that would bring more complexity 712182080Srnoland * and would break backward compatability. The solution currently 713182080Srnoland * implemented is keeping all buffers private, allowing to secure the 714182080Srnoland * driver, without increasing complexity at the expense of some speed 715182080Srnoland * transfering data. 716182080Srnoland */ 717182080Srnoland verify_ret = copy_from_user_blit(GETBUFPTR(copy_buf), blit->buf, used); 718182080Srnoland 719182080Srnoland if (verify_ret != 0) { 720182080Srnoland mach64_freelist_put(dev_priv, copy_buf); 721182080Srnoland goto _blit_done; 722182080Srnoland } 723182080Srnoland 724182080Srnoland copy_buf->used = used; 725182080Srnoland 726145132Sanholt /* FIXME: Use a last buffer flag and reduce the state emitted for subsequent, 727145132Sanholt * continuation buffers? 728145132Sanholt */ 729145132Sanholt 730145132Sanholt /* Blit via BM_HOSTDATA (gui-master) - like HOST_DATA[0-15], but doesn't require 731145132Sanholt * a register command every 16 dwords. State setup is added at the start of the 732145132Sanholt * buffer -- the client leaves space for this based on MACH64_HOSTDATA_BLIT_OFFSET 733145132Sanholt */ 734182080Srnoland DMASETPTR(copy_buf); 735145132Sanholt 736145132Sanholt DMAOUTREG(MACH64_Z_CNTL, 0); 737145132Sanholt DMAOUTREG(MACH64_SCALE_3D_CNTL, 0); 738145132Sanholt 739145132Sanholt DMAOUTREG(MACH64_SC_LEFT_RIGHT, 0 | (8191 << 16)); /* no scissor */ 740145132Sanholt DMAOUTREG(MACH64_SC_TOP_BOTTOM, 0 | (16383 << 16)); 741145132Sanholt 742145132Sanholt DMAOUTREG(MACH64_CLR_CMP_CNTL, 0); /* disable */ 743145132Sanholt DMAOUTREG(MACH64_GUI_TRAJ_CNTL, 744145132Sanholt MACH64_DST_X_LEFT_TO_RIGHT | MACH64_DST_Y_TOP_TO_BOTTOM); 745145132Sanholt 746145132Sanholt DMAOUTREG(MACH64_DP_PIX_WIDTH, (blit->format << 0) /* dst pix width */ 747145132Sanholt |(blit->format << 4) /* composite pix width */ 748145132Sanholt |(blit->format << 8) /* src pix width */ 749145132Sanholt |(blit->format << 16) /* host data pix width */ 750145132Sanholt |(blit->format << 28) /* scaler/3D pix width */ 751145132Sanholt ); 752145132Sanholt 753145132Sanholt DMAOUTREG(MACH64_DP_WRITE_MASK, 0xffffffff); /* enable all planes */ 754145132Sanholt DMAOUTREG(MACH64_DP_MIX, MACH64_BKGD_MIX_D | MACH64_FRGD_MIX_S); 755145132Sanholt DMAOUTREG(MACH64_DP_SRC, 756145132Sanholt MACH64_BKGD_SRC_BKGD_CLR 757145132Sanholt | MACH64_FRGD_SRC_HOST | MACH64_MONO_SRC_ONE); 758145132Sanholt 759145132Sanholt DMAOUTREG(MACH64_DST_OFF_PITCH, 760145132Sanholt (blit->pitch << 22) | (blit->offset >> 3)); 761145132Sanholt DMAOUTREG(MACH64_DST_X_Y, (blit->y << 16) | blit->x); 762145132Sanholt DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (blit->height << 16) | blit->width); 763145132Sanholt 764182080Srnoland DRM_DEBUG("%lu bytes\n", used); 765145132Sanholt 766145132Sanholt /* Add the buffer to the queue */ 767145132Sanholt DMAADVANCEHOSTDATA(dev_priv); 768145132Sanholt 769182080Srnoland_blit_done: 770182080Srnoland return verify_ret; 771145132Sanholt} 772145132Sanholt 773145132Sanholt/* ================================================================ 774145132Sanholt * IOCTL functions 775145132Sanholt */ 776145132Sanholt 777182080Srnolandint mach64_dma_clear(struct drm_device *dev, void *data, 778182080Srnoland struct drm_file *file_priv) 779145132Sanholt{ 780145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 781145132Sanholt drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 782182080Srnoland drm_mach64_clear_t *clear = data; 783145132Sanholt int ret; 784145132Sanholt 785182080Srnoland DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); 786145132Sanholt 787182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 788145132Sanholt 789145132Sanholt if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS) 790145132Sanholt sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS; 791145132Sanholt 792182080Srnoland ret = mach64_dma_dispatch_clear(dev, file_priv, clear->flags, 793182080Srnoland clear->x, clear->y, clear->w, clear->h, 794182080Srnoland clear->clear_color, 795182080Srnoland clear->clear_depth); 796145132Sanholt 797145132Sanholt /* Make sure we restore the 3D state next time. 798145132Sanholt */ 799145132Sanholt sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT | MACH64_UPLOAD_MISC); 800145132Sanholt return ret; 801145132Sanholt} 802145132Sanholt 803182080Srnolandint mach64_dma_swap(struct drm_device *dev, void *data, 804182080Srnoland struct drm_file *file_priv) 805145132Sanholt{ 806145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 807145132Sanholt drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 808145132Sanholt int ret; 809145132Sanholt 810182080Srnoland DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); 811145132Sanholt 812182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 813145132Sanholt 814145132Sanholt if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS) 815145132Sanholt sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS; 816145132Sanholt 817182080Srnoland ret = mach64_dma_dispatch_swap(dev, file_priv); 818145132Sanholt 819145132Sanholt /* Make sure we restore the 3D state next time. 820145132Sanholt */ 821145132Sanholt sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT | MACH64_UPLOAD_MISC); 822145132Sanholt return ret; 823145132Sanholt} 824145132Sanholt 825182080Srnolandint mach64_dma_vertex(struct drm_device *dev, void *data, 826182080Srnoland struct drm_file *file_priv) 827145132Sanholt{ 828145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 829198332Sbrueffer drm_mach64_sarea_t *sarea_priv; 830182080Srnoland drm_mach64_vertex_t *vertex = data; 831145132Sanholt 832182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 833145132Sanholt 834145132Sanholt if (!dev_priv) { 835182080Srnoland DRM_ERROR("called with no initialization\n"); 836182080Srnoland return -EINVAL; 837145132Sanholt } 838198332Sbrueffer sarea_priv = dev_priv->sarea_priv; 839145132Sanholt 840182080Srnoland DRM_DEBUG("pid=%d buf=%p used=%lu discard=%d\n", 841182080Srnoland DRM_CURRENTPID, 842182080Srnoland vertex->buf, vertex->used, vertex->discard); 843145132Sanholt 844182080Srnoland if (vertex->prim < 0 || vertex->prim > MACH64_PRIM_POLYGON) { 845182080Srnoland DRM_ERROR("buffer prim %d\n", vertex->prim); 846182080Srnoland return -EINVAL; 847145132Sanholt } 848145132Sanholt 849182080Srnoland if (vertex->used > MACH64_BUFFER_SIZE || (vertex->used & 3) != 0) { 850145132Sanholt DRM_ERROR("Invalid vertex buffer size: %lu bytes\n", 851182080Srnoland vertex->used); 852182080Srnoland return -EINVAL; 853145132Sanholt } 854145132Sanholt 855145132Sanholt if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS) 856145132Sanholt sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS; 857145132Sanholt 858182080Srnoland return mach64_dma_dispatch_vertex(dev, file_priv, vertex); 859145132Sanholt} 860145132Sanholt 861182080Srnolandint mach64_dma_blit(struct drm_device *dev, void *data, 862182080Srnoland struct drm_file *file_priv) 863145132Sanholt{ 864145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 865145132Sanholt drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 866182080Srnoland drm_mach64_blit_t *blit = data; 867145132Sanholt int ret; 868145132Sanholt 869182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 870145132Sanholt 871182080Srnoland ret = mach64_dma_dispatch_blit(dev, file_priv, blit); 872145132Sanholt 873145132Sanholt /* Make sure we restore the 3D state next time. 874145132Sanholt */ 875145132Sanholt sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT | 876145132Sanholt MACH64_UPLOAD_MISC | MACH64_UPLOAD_CLIPRECTS); 877145132Sanholt 878145132Sanholt return ret; 879145132Sanholt} 880145132Sanholt 881182080Srnolandint mach64_get_param(struct drm_device *dev, void *data, 882182080Srnoland struct drm_file *file_priv) 883145132Sanholt{ 884145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 885182080Srnoland drm_mach64_getparam_t *param = data; 886145132Sanholt int value; 887145132Sanholt 888182080Srnoland DRM_DEBUG("\n"); 889145132Sanholt 890145132Sanholt if (!dev_priv) { 891182080Srnoland DRM_ERROR("called with no initialization\n"); 892182080Srnoland return -EINVAL; 893145132Sanholt } 894145132Sanholt 895182080Srnoland switch (param->param) { 896145132Sanholt case MACH64_PARAM_FRAMES_QUEUED: 897145132Sanholt /* Needs lock since it calls mach64_ring_tick() */ 898182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 899145132Sanholt value = mach64_do_get_frames_queued(dev_priv); 900145132Sanholt break; 901145132Sanholt case MACH64_PARAM_IRQ_NR: 902145132Sanholt value = dev->irq; 903145132Sanholt break; 904145132Sanholt default: 905182080Srnoland return -EINVAL; 906145132Sanholt } 907145132Sanholt 908182080Srnoland if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { 909145132Sanholt DRM_ERROR("copy_to_user\n"); 910182080Srnoland return -EFAULT; 911145132Sanholt } 912145132Sanholt 913145132Sanholt return 0; 914145132Sanholt} 915