mach64_state.c revision 145132
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 3145132Sanholt * 4145132Sanholt * Copyright 2000 Gareth Hughes 5145132Sanholt * Copyright 2002-2003 Leif Delgass 6145132Sanholt * All Rights Reserved. 7145132Sanholt * 8145132Sanholt * Permission is hereby granted, free of charge, to any person obtaining a 9145132Sanholt * copy of this software and associated documentation files (the "Software"), 10145132Sanholt * to deal in the Software without restriction, including without limitation 11145132Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12145132Sanholt * and/or sell copies of the Software, and to permit persons to whom the 13145132Sanholt * Software is furnished to do so, subject to the following conditions: 14145132Sanholt * 15145132Sanholt * The above copyright notice and this permission notice (including the next 16145132Sanholt * paragraph) shall be included in all copies or substantial portions of the 17145132Sanholt * Software. 18145132Sanholt * 19145132Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20145132Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21145132Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22145132Sanholt * THE COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 23145132Sanholt * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24145132Sanholt * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25145132Sanholt * 26145132Sanholt * Authors: 27145132Sanholt * Gareth Hughes <gareth@valinux.com> 28145132Sanholt * Leif Delgass <ldelgass@retinalburn.net> 29145132Sanholt * Jos���Fonseca <j_r_fonseca@yahoo.co.uk> 30145132Sanholt * 31145132Sanholt * $FreeBSD: head/sys/dev/drm/mach64_state.c 145132 2005-04-16 03:44:47Z anholt $ 32145132Sanholt */ 33145132Sanholt 34145132Sanholt#include "dev/drm/drmP.h" 35145132Sanholt#include "dev/drm/drm.h" 36145132Sanholt#include "dev/drm/mach64_drm.h" 37145132Sanholt#include "dev/drm/mach64_drv.h" 38145132Sanholt 39145132Sanholt/* Interface history: 40145132Sanholt * 41145132Sanholt * 1.0 - Initial mach64 DRM 42145132Sanholt * 43145132Sanholt */ 44145132Sanholtdrm_ioctl_desc_t mach64_ioctls[] = { 45145132Sanholt [DRM_IOCTL_NR(DRM_MACH64_INIT)] = {mach64_dma_init, 1, 1}, 46145132Sanholt [DRM_IOCTL_NR(DRM_MACH64_CLEAR)] = {mach64_dma_clear, 1, 0}, 47145132Sanholt [DRM_IOCTL_NR(DRM_MACH64_SWAP)] = {mach64_dma_swap, 1, 0}, 48145132Sanholt [DRM_IOCTL_NR(DRM_MACH64_IDLE)] = {mach64_dma_idle, 1, 0}, 49145132Sanholt [DRM_IOCTL_NR(DRM_MACH64_RESET)] = {mach64_engine_reset, 1, 0}, 50145132Sanholt [DRM_IOCTL_NR(DRM_MACH64_VERTEX)] = {mach64_dma_vertex, 1, 0}, 51145132Sanholt [DRM_IOCTL_NR(DRM_MACH64_BLIT)] = {mach64_dma_blit, 1, 0}, 52145132Sanholt [DRM_IOCTL_NR(DRM_MACH64_FLUSH)] = {mach64_dma_flush, 1, 0}, 53145132Sanholt [DRM_IOCTL_NR(DRM_MACH64_GETPARAM)] = {mach64_get_param, 1, 0}, 54145132Sanholt}; 55145132Sanholt 56145132Sanholtint mach64_max_ioctl = DRM_ARRAY_SIZE(mach64_ioctls); 57145132Sanholt 58145132Sanholt/* ================================================================ 59145132Sanholt * DMA hardware state programming functions 60145132Sanholt */ 61145132Sanholt 62145132Sanholtstatic void mach64_print_dirty(const char *msg, unsigned int flags) 63145132Sanholt{ 64145132Sanholt DRM_DEBUG("%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s\n", 65145132Sanholt msg, 66145132Sanholt flags, 67145132Sanholt (flags & MACH64_UPLOAD_DST_OFF_PITCH) ? "dst_off_pitch, " : 68145132Sanholt "", 69145132Sanholt (flags & MACH64_UPLOAD_Z_ALPHA_CNTL) ? "z_alpha_cntl, " : "", 70145132Sanholt (flags & MACH64_UPLOAD_SCALE_3D_CNTL) ? "scale_3d_cntl, " : 71145132Sanholt "", (flags & MACH64_UPLOAD_DP_FOG_CLR) ? "dp_fog_clr, " : "", 72145132Sanholt (flags & MACH64_UPLOAD_DP_WRITE_MASK) ? "dp_write_mask, " : 73145132Sanholt "", 74145132Sanholt (flags & MACH64_UPLOAD_DP_PIX_WIDTH) ? "dp_pix_width, " : "", 75145132Sanholt (flags & MACH64_UPLOAD_SETUP_CNTL) ? "setup_cntl, " : "", 76145132Sanholt (flags & MACH64_UPLOAD_MISC) ? "misc, " : "", 77145132Sanholt (flags & MACH64_UPLOAD_TEXTURE) ? "texture, " : "", 78145132Sanholt (flags & MACH64_UPLOAD_TEX0IMAGE) ? "tex0 image, " : "", 79145132Sanholt (flags & MACH64_UPLOAD_TEX1IMAGE) ? "tex1 image, " : "", 80145132Sanholt (flags & MACH64_UPLOAD_CLIPRECTS) ? "cliprects, " : ""); 81145132Sanholt} 82145132Sanholt 83145132Sanholt/* Mach64 doesn't have hardware cliprects, just one hardware scissor, 84145132Sanholt * so the GL scissor is intersected with each cliprect here 85145132Sanholt */ 86145132Sanholt/* This function returns 0 on success, 1 for no intersection, and 87145132Sanholt * negative for an error 88145132Sanholt */ 89145132Sanholtstatic int mach64_emit_cliprect(DRMFILE filp, drm_mach64_private_t * dev_priv, 90145132Sanholt drm_clip_rect_t * box) 91145132Sanholt{ 92145132Sanholt u32 sc_left_right, sc_top_bottom; 93145132Sanholt drm_clip_rect_t scissor; 94145132Sanholt drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 95145132Sanholt drm_mach64_context_regs_t *regs = &sarea_priv->context_state; 96145132Sanholt DMALOCALS; 97145132Sanholt 98145132Sanholt DRM_DEBUG("%s: box=%p\n", __FUNCTION__, box); 99145132Sanholt 100145132Sanholt /* Get GL scissor */ 101145132Sanholt /* FIXME: store scissor in SAREA as a cliprect instead of in 102145132Sanholt * hardware format, or do intersection client-side 103145132Sanholt */ 104145132Sanholt scissor.x1 = regs->sc_left_right & 0xffff; 105145132Sanholt scissor.x2 = (regs->sc_left_right & 0xffff0000) >> 16; 106145132Sanholt scissor.y1 = regs->sc_top_bottom & 0xffff; 107145132Sanholt scissor.y2 = (regs->sc_top_bottom & 0xffff0000) >> 16; 108145132Sanholt 109145132Sanholt /* Intersect GL scissor with cliprect */ 110145132Sanholt if (box->x1 > scissor.x1) 111145132Sanholt scissor.x1 = box->x1; 112145132Sanholt if (box->y1 > scissor.y1) 113145132Sanholt scissor.y1 = box->y1; 114145132Sanholt if (box->x2 < scissor.x2) 115145132Sanholt scissor.x2 = box->x2; 116145132Sanholt if (box->y2 < scissor.y2) 117145132Sanholt scissor.y2 = box->y2; 118145132Sanholt /* positive return means skip */ 119145132Sanholt if (scissor.x1 >= scissor.x2) 120145132Sanholt return 1; 121145132Sanholt if (scissor.y1 >= scissor.y2) 122145132Sanholt return 1; 123145132Sanholt 124145132Sanholt DMAGETPTR(filp, dev_priv, 2); /* returns on failure to get buffer */ 125145132Sanholt 126145132Sanholt sc_left_right = ((scissor.x1 << 0) | (scissor.x2 << 16)); 127145132Sanholt sc_top_bottom = ((scissor.y1 << 0) | (scissor.y2 << 16)); 128145132Sanholt 129145132Sanholt DMAOUTREG(MACH64_SC_LEFT_RIGHT, sc_left_right); 130145132Sanholt DMAOUTREG(MACH64_SC_TOP_BOTTOM, sc_top_bottom); 131145132Sanholt 132145132Sanholt DMAADVANCE(dev_priv, 1); 133145132Sanholt 134145132Sanholt return 0; 135145132Sanholt} 136145132Sanholt 137145132Sanholtstatic __inline__ int mach64_emit_state(DRMFILE filp, 138145132Sanholt drm_mach64_private_t * dev_priv) 139145132Sanholt{ 140145132Sanholt drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 141145132Sanholt drm_mach64_context_regs_t *regs = &sarea_priv->context_state; 142145132Sanholt unsigned int dirty = sarea_priv->dirty; 143145132Sanholt u32 offset = ((regs->tex_size_pitch & 0xf0) >> 2); 144145132Sanholt DMALOCALS; 145145132Sanholt 146145132Sanholt if (MACH64_VERBOSE) { 147145132Sanholt mach64_print_dirty(__FUNCTION__, dirty); 148145132Sanholt } else { 149145132Sanholt DRM_DEBUG("%s: dirty=0x%08x\n", __FUNCTION__, dirty); 150145132Sanholt } 151145132Sanholt 152145132Sanholt DMAGETPTR(filp, dev_priv, 17); /* returns on failure to get buffer */ 153145132Sanholt 154145132Sanholt if (dirty & MACH64_UPLOAD_MISC) { 155145132Sanholt DMAOUTREG(MACH64_DP_MIX, regs->dp_mix); 156145132Sanholt DMAOUTREG(MACH64_DP_SRC, regs->dp_src); 157145132Sanholt DMAOUTREG(MACH64_CLR_CMP_CNTL, regs->clr_cmp_cntl); 158145132Sanholt DMAOUTREG(MACH64_GUI_TRAJ_CNTL, regs->gui_traj_cntl); 159145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_MISC; 160145132Sanholt } 161145132Sanholt 162145132Sanholt if (dirty & MACH64_UPLOAD_DST_OFF_PITCH) { 163145132Sanholt DMAOUTREG(MACH64_DST_OFF_PITCH, regs->dst_off_pitch); 164145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_DST_OFF_PITCH; 165145132Sanholt } 166145132Sanholt if (dirty & MACH64_UPLOAD_Z_OFF_PITCH) { 167145132Sanholt DMAOUTREG(MACH64_Z_OFF_PITCH, regs->z_off_pitch); 168145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_Z_OFF_PITCH; 169145132Sanholt } 170145132Sanholt if (dirty & MACH64_UPLOAD_Z_ALPHA_CNTL) { 171145132Sanholt DMAOUTREG(MACH64_Z_CNTL, regs->z_cntl); 172145132Sanholt DMAOUTREG(MACH64_ALPHA_TST_CNTL, regs->alpha_tst_cntl); 173145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_Z_ALPHA_CNTL; 174145132Sanholt } 175145132Sanholt if (dirty & MACH64_UPLOAD_SCALE_3D_CNTL) { 176145132Sanholt DMAOUTREG(MACH64_SCALE_3D_CNTL, regs->scale_3d_cntl); 177145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_SCALE_3D_CNTL; 178145132Sanholt } 179145132Sanholt if (dirty & MACH64_UPLOAD_DP_FOG_CLR) { 180145132Sanholt DMAOUTREG(MACH64_DP_FOG_CLR, regs->dp_fog_clr); 181145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_DP_FOG_CLR; 182145132Sanholt } 183145132Sanholt if (dirty & MACH64_UPLOAD_DP_WRITE_MASK) { 184145132Sanholt DMAOUTREG(MACH64_DP_WRITE_MASK, regs->dp_write_mask); 185145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_DP_WRITE_MASK; 186145132Sanholt } 187145132Sanholt if (dirty & MACH64_UPLOAD_DP_PIX_WIDTH) { 188145132Sanholt DMAOUTREG(MACH64_DP_PIX_WIDTH, regs->dp_pix_width); 189145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_DP_PIX_WIDTH; 190145132Sanholt } 191145132Sanholt if (dirty & MACH64_UPLOAD_SETUP_CNTL) { 192145132Sanholt DMAOUTREG(MACH64_SETUP_CNTL, regs->setup_cntl); 193145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_SETUP_CNTL; 194145132Sanholt } 195145132Sanholt 196145132Sanholt if (dirty & MACH64_UPLOAD_TEXTURE) { 197145132Sanholt DMAOUTREG(MACH64_TEX_SIZE_PITCH, regs->tex_size_pitch); 198145132Sanholt DMAOUTREG(MACH64_TEX_CNTL, regs->tex_cntl); 199145132Sanholt DMAOUTREG(MACH64_SECONDARY_TEX_OFF, regs->secondary_tex_off); 200145132Sanholt DMAOUTREG(MACH64_TEX_0_OFF + offset, regs->tex_offset); 201145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_TEXTURE; 202145132Sanholt } 203145132Sanholt 204145132Sanholt DMAADVANCE(dev_priv, 1); 205145132Sanholt 206145132Sanholt sarea_priv->dirty &= MACH64_UPLOAD_CLIPRECTS; 207145132Sanholt 208145132Sanholt return 0; 209145132Sanholt 210145132Sanholt} 211145132Sanholt 212145132Sanholt/* ================================================================ 213145132Sanholt * DMA command dispatch functions 214145132Sanholt */ 215145132Sanholt 216145132Sanholtstatic int mach64_dma_dispatch_clear(DRMFILE filp, drm_device_t * dev, 217145132Sanholt unsigned int flags, 218145132Sanholt int cx, int cy, int cw, int ch, 219145132Sanholt unsigned int clear_color, 220145132Sanholt unsigned int clear_depth) 221145132Sanholt{ 222145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 223145132Sanholt drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 224145132Sanholt drm_mach64_context_regs_t *ctx = &sarea_priv->context_state; 225145132Sanholt int nbox = sarea_priv->nbox; 226145132Sanholt drm_clip_rect_t *pbox = sarea_priv->boxes; 227145132Sanholt u32 fb_bpp, depth_bpp; 228145132Sanholt int i; 229145132Sanholt DMALOCALS; 230145132Sanholt 231145132Sanholt DRM_DEBUG("%s\n", __FUNCTION__); 232145132Sanholt 233145132Sanholt switch (dev_priv->fb_bpp) { 234145132Sanholt case 16: 235145132Sanholt fb_bpp = MACH64_DATATYPE_RGB565; 236145132Sanholt break; 237145132Sanholt case 32: 238145132Sanholt fb_bpp = MACH64_DATATYPE_ARGB8888; 239145132Sanholt break; 240145132Sanholt default: 241145132Sanholt return DRM_ERR(EINVAL); 242145132Sanholt } 243145132Sanholt switch (dev_priv->depth_bpp) { 244145132Sanholt case 16: 245145132Sanholt depth_bpp = MACH64_DATATYPE_RGB565; 246145132Sanholt break; 247145132Sanholt case 24: 248145132Sanholt case 32: 249145132Sanholt depth_bpp = MACH64_DATATYPE_ARGB8888; 250145132Sanholt break; 251145132Sanholt default: 252145132Sanholt return DRM_ERR(EINVAL); 253145132Sanholt } 254145132Sanholt 255145132Sanholt if (!nbox) 256145132Sanholt return 0; 257145132Sanholt 258145132Sanholt DMAGETPTR(filp, dev_priv, nbox * 31); /* returns on failure to get buffer */ 259145132Sanholt 260145132Sanholt for (i = 0; i < nbox; i++) { 261145132Sanholt int x = pbox[i].x1; 262145132Sanholt int y = pbox[i].y1; 263145132Sanholt int w = pbox[i].x2 - x; 264145132Sanholt int h = pbox[i].y2 - y; 265145132Sanholt 266145132Sanholt DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n", 267145132Sanholt pbox[i].x1, pbox[i].y1, 268145132Sanholt pbox[i].x2, pbox[i].y2, flags); 269145132Sanholt 270145132Sanholt if (flags & (MACH64_FRONT | MACH64_BACK)) { 271145132Sanholt /* Setup for color buffer clears 272145132Sanholt */ 273145132Sanholt 274145132Sanholt DMAOUTREG(MACH64_Z_CNTL, 0); 275145132Sanholt DMAOUTREG(MACH64_SCALE_3D_CNTL, 0); 276145132Sanholt 277145132Sanholt DMAOUTREG(MACH64_SC_LEFT_RIGHT, ctx->sc_left_right); 278145132Sanholt DMAOUTREG(MACH64_SC_TOP_BOTTOM, ctx->sc_top_bottom); 279145132Sanholt 280145132Sanholt DMAOUTREG(MACH64_CLR_CMP_CNTL, 0); 281145132Sanholt DMAOUTREG(MACH64_GUI_TRAJ_CNTL, 282145132Sanholt (MACH64_DST_X_LEFT_TO_RIGHT | 283145132Sanholt MACH64_DST_Y_TOP_TO_BOTTOM)); 284145132Sanholt 285145132Sanholt DMAOUTREG(MACH64_DP_PIX_WIDTH, ((fb_bpp << 0) | 286145132Sanholt (fb_bpp << 4) | 287145132Sanholt (fb_bpp << 8) | 288145132Sanholt (fb_bpp << 16) | 289145132Sanholt (fb_bpp << 28))); 290145132Sanholt 291145132Sanholt DMAOUTREG(MACH64_DP_FRGD_CLR, clear_color); 292145132Sanholt DMAOUTREG(MACH64_DP_WRITE_MASK, ctx->dp_write_mask); 293145132Sanholt DMAOUTREG(MACH64_DP_MIX, (MACH64_BKGD_MIX_D | 294145132Sanholt MACH64_FRGD_MIX_S)); 295145132Sanholt DMAOUTREG(MACH64_DP_SRC, (MACH64_BKGD_SRC_FRGD_CLR | 296145132Sanholt MACH64_FRGD_SRC_FRGD_CLR | 297145132Sanholt MACH64_MONO_SRC_ONE)); 298145132Sanholt 299145132Sanholt } 300145132Sanholt 301145132Sanholt if (flags & MACH64_FRONT) { 302145132Sanholt 303145132Sanholt DMAOUTREG(MACH64_DST_OFF_PITCH, 304145132Sanholt dev_priv->front_offset_pitch); 305145132Sanholt DMAOUTREG(MACH64_DST_X_Y, (y << 16) | x); 306145132Sanholt DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w); 307145132Sanholt 308145132Sanholt } 309145132Sanholt 310145132Sanholt if (flags & MACH64_BACK) { 311145132Sanholt 312145132Sanholt DMAOUTREG(MACH64_DST_OFF_PITCH, 313145132Sanholt dev_priv->back_offset_pitch); 314145132Sanholt DMAOUTREG(MACH64_DST_X_Y, (y << 16) | x); 315145132Sanholt DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w); 316145132Sanholt 317145132Sanholt } 318145132Sanholt 319145132Sanholt if (flags & MACH64_DEPTH) { 320145132Sanholt /* Setup for depth buffer clear 321145132Sanholt */ 322145132Sanholt DMAOUTREG(MACH64_Z_CNTL, 0); 323145132Sanholt DMAOUTREG(MACH64_SCALE_3D_CNTL, 0); 324145132Sanholt 325145132Sanholt DMAOUTREG(MACH64_SC_LEFT_RIGHT, ctx->sc_left_right); 326145132Sanholt DMAOUTREG(MACH64_SC_TOP_BOTTOM, ctx->sc_top_bottom); 327145132Sanholt 328145132Sanholt DMAOUTREG(MACH64_CLR_CMP_CNTL, 0); 329145132Sanholt DMAOUTREG(MACH64_GUI_TRAJ_CNTL, 330145132Sanholt (MACH64_DST_X_LEFT_TO_RIGHT | 331145132Sanholt MACH64_DST_Y_TOP_TO_BOTTOM)); 332145132Sanholt 333145132Sanholt DMAOUTREG(MACH64_DP_PIX_WIDTH, ((depth_bpp << 0) | 334145132Sanholt (depth_bpp << 4) | 335145132Sanholt (depth_bpp << 8) | 336145132Sanholt (depth_bpp << 16) | 337145132Sanholt (depth_bpp << 28))); 338145132Sanholt 339145132Sanholt DMAOUTREG(MACH64_DP_FRGD_CLR, clear_depth); 340145132Sanholt DMAOUTREG(MACH64_DP_WRITE_MASK, 0xffffffff); 341145132Sanholt DMAOUTREG(MACH64_DP_MIX, (MACH64_BKGD_MIX_D | 342145132Sanholt MACH64_FRGD_MIX_S)); 343145132Sanholt DMAOUTREG(MACH64_DP_SRC, (MACH64_BKGD_SRC_FRGD_CLR | 344145132Sanholt MACH64_FRGD_SRC_FRGD_CLR | 345145132Sanholt MACH64_MONO_SRC_ONE)); 346145132Sanholt 347145132Sanholt DMAOUTREG(MACH64_DST_OFF_PITCH, 348145132Sanholt dev_priv->depth_offset_pitch); 349145132Sanholt DMAOUTREG(MACH64_DST_X_Y, (y << 16) | x); 350145132Sanholt DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w); 351145132Sanholt } 352145132Sanholt } 353145132Sanholt 354145132Sanholt DMAADVANCE(dev_priv, 1); 355145132Sanholt 356145132Sanholt return 0; 357145132Sanholt} 358145132Sanholt 359145132Sanholtstatic int mach64_dma_dispatch_swap(DRMFILE filp, drm_device_t * dev) 360145132Sanholt{ 361145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 362145132Sanholt drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 363145132Sanholt int nbox = sarea_priv->nbox; 364145132Sanholt drm_clip_rect_t *pbox = sarea_priv->boxes; 365145132Sanholt u32 fb_bpp; 366145132Sanholt int i; 367145132Sanholt DMALOCALS; 368145132Sanholt 369145132Sanholt DRM_DEBUG("%s\n", __FUNCTION__); 370145132Sanholt 371145132Sanholt switch (dev_priv->fb_bpp) { 372145132Sanholt case 16: 373145132Sanholt fb_bpp = MACH64_DATATYPE_RGB565; 374145132Sanholt break; 375145132Sanholt case 32: 376145132Sanholt default: 377145132Sanholt fb_bpp = MACH64_DATATYPE_ARGB8888; 378145132Sanholt break; 379145132Sanholt } 380145132Sanholt 381145132Sanholt if (!nbox) 382145132Sanholt return 0; 383145132Sanholt 384145132Sanholt DMAGETPTR(filp, dev_priv, 13 + nbox * 4); /* returns on failure to get buffer */ 385145132Sanholt 386145132Sanholt DMAOUTREG(MACH64_Z_CNTL, 0); 387145132Sanholt DMAOUTREG(MACH64_SCALE_3D_CNTL, 0); 388145132Sanholt 389145132Sanholt DMAOUTREG(MACH64_SC_LEFT_RIGHT, 0 | (8191 << 16)); /* no scissor */ 390145132Sanholt DMAOUTREG(MACH64_SC_TOP_BOTTOM, 0 | (16383 << 16)); 391145132Sanholt 392145132Sanholt DMAOUTREG(MACH64_CLR_CMP_CNTL, 0); 393145132Sanholt DMAOUTREG(MACH64_GUI_TRAJ_CNTL, (MACH64_DST_X_LEFT_TO_RIGHT | 394145132Sanholt MACH64_DST_Y_TOP_TO_BOTTOM)); 395145132Sanholt 396145132Sanholt DMAOUTREG(MACH64_DP_PIX_WIDTH, ((fb_bpp << 0) | 397145132Sanholt (fb_bpp << 4) | 398145132Sanholt (fb_bpp << 8) | 399145132Sanholt (fb_bpp << 16) | (fb_bpp << 28))); 400145132Sanholt 401145132Sanholt DMAOUTREG(MACH64_DP_WRITE_MASK, 0xffffffff); 402145132Sanholt DMAOUTREG(MACH64_DP_MIX, (MACH64_BKGD_MIX_D | MACH64_FRGD_MIX_S)); 403145132Sanholt DMAOUTREG(MACH64_DP_SRC, (MACH64_BKGD_SRC_BKGD_CLR | 404145132Sanholt MACH64_FRGD_SRC_BLIT | MACH64_MONO_SRC_ONE)); 405145132Sanholt 406145132Sanholt DMAOUTREG(MACH64_SRC_OFF_PITCH, dev_priv->back_offset_pitch); 407145132Sanholt DMAOUTREG(MACH64_DST_OFF_PITCH, dev_priv->front_offset_pitch); 408145132Sanholt 409145132Sanholt for (i = 0; i < nbox; i++) { 410145132Sanholt int x = pbox[i].x1; 411145132Sanholt int y = pbox[i].y1; 412145132Sanholt int w = pbox[i].x2 - x; 413145132Sanholt int h = pbox[i].y2 - y; 414145132Sanholt 415145132Sanholt DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", 416145132Sanholt pbox[i].x1, pbox[i].y1, pbox[i].x2, pbox[i].y2); 417145132Sanholt 418145132Sanholt DMAOUTREG(MACH64_SRC_WIDTH1, w); 419145132Sanholt DMAOUTREG(MACH64_SRC_Y_X, (x << 16) | y); 420145132Sanholt DMAOUTREG(MACH64_DST_Y_X, (x << 16) | y); 421145132Sanholt DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w); 422145132Sanholt 423145132Sanholt } 424145132Sanholt 425145132Sanholt DMAADVANCE(dev_priv, 1); 426145132Sanholt 427145132Sanholt if (dev_priv->driver_mode == MACH64_MODE_DMA_ASYNC) { 428145132Sanholt for (i = 0; i < MACH64_MAX_QUEUED_FRAMES - 1; i++) { 429145132Sanholt dev_priv->frame_ofs[i] = dev_priv->frame_ofs[i + 1]; 430145132Sanholt } 431145132Sanholt dev_priv->frame_ofs[i] = GETRINGOFFSET(); 432145132Sanholt 433145132Sanholt dev_priv->sarea_priv->frames_queued++; 434145132Sanholt } 435145132Sanholt 436145132Sanholt return 0; 437145132Sanholt} 438145132Sanholt 439145132Sanholtstatic int mach64_do_get_frames_queued(drm_mach64_private_t * dev_priv) 440145132Sanholt{ 441145132Sanholt drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; 442145132Sanholt drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 443145132Sanholt int i, start; 444145132Sanholt u32 head, tail, ofs; 445145132Sanholt 446145132Sanholt DRM_DEBUG("%s\n", __FUNCTION__); 447145132Sanholt 448145132Sanholt if (sarea_priv->frames_queued == 0) 449145132Sanholt return 0; 450145132Sanholt 451145132Sanholt tail = ring->tail; 452145132Sanholt mach64_ring_tick(dev_priv, ring); 453145132Sanholt head = ring->head; 454145132Sanholt 455145132Sanholt start = (MACH64_MAX_QUEUED_FRAMES - 456145132Sanholt DRM_MIN(MACH64_MAX_QUEUED_FRAMES, sarea_priv->frames_queued)); 457145132Sanholt 458145132Sanholt if (head == tail) { 459145132Sanholt sarea_priv->frames_queued = 0; 460145132Sanholt for (i = start; i < MACH64_MAX_QUEUED_FRAMES; i++) { 461145132Sanholt dev_priv->frame_ofs[i] = ~0; 462145132Sanholt } 463145132Sanholt return 0; 464145132Sanholt } 465145132Sanholt 466145132Sanholt for (i = start; i < MACH64_MAX_QUEUED_FRAMES; i++) { 467145132Sanholt ofs = dev_priv->frame_ofs[i]; 468145132Sanholt DRM_DEBUG("frame_ofs[%d] ofs: %d\n", i, ofs); 469145132Sanholt if (ofs == ~0 || 470145132Sanholt (head < tail && (ofs < head || ofs >= tail)) || 471145132Sanholt (head > tail && (ofs < head && ofs >= tail))) { 472145132Sanholt sarea_priv->frames_queued = 473145132Sanholt (MACH64_MAX_QUEUED_FRAMES - 1) - i; 474145132Sanholt dev_priv->frame_ofs[i] = ~0; 475145132Sanholt } 476145132Sanholt } 477145132Sanholt 478145132Sanholt return sarea_priv->frames_queued; 479145132Sanholt} 480145132Sanholt 481145132Sanholt/* Copy and verify a client submited buffer. 482145132Sanholt * FIXME: Make an assembly optimized version 483145132Sanholt */ 484145132Sanholtstatic __inline__ int copy_and_verify_from_user(u32 * to, const u32 * from, 485145132Sanholt unsigned long bytes) 486145132Sanholt{ 487145132Sanholt unsigned long n = bytes; /* dwords remaining in buffer */ 488145132Sanholt 489145132Sanholt if (DRM_VERIFYAREA_READ(from, n)) { 490145132Sanholt DRM_ERROR("%s: verify_area\n", __FUNCTION__); 491145132Sanholt return DRM_ERR(EFAULT); 492145132Sanholt } 493145132Sanholt 494145132Sanholt n >>= 2; 495145132Sanholt 496145132Sanholt while (n > 1) { 497145132Sanholt u32 data, reg, count; 498145132Sanholt 499145132Sanholt if (DRM_GET_USER_UNCHECKED(data, from++)) { 500145132Sanholt DRM_ERROR("%s: get_user\n", __FUNCTION__); 501145132Sanholt return DRM_ERR(EFAULT); 502145132Sanholt } 503145132Sanholt 504145132Sanholt n--; 505145132Sanholt 506145132Sanholt reg = le32_to_cpu(data); 507145132Sanholt count = (reg >> 16) + 1; 508145132Sanholt if (count <= n) { 509145132Sanholt n -= count; 510145132Sanholt reg &= 0xffff; 511145132Sanholt 512145132Sanholt /* This is an exact match of Mach64's Setup Engine registers, 513145132Sanholt * excluding SETUP_CNTL (1_C1). 514145132Sanholt */ 515145132Sanholt if ((reg >= 0x0190 && reg < 0x01c1) || 516145132Sanholt (reg >= 0x01ca && reg <= 0x01cf)) { 517145132Sanholt *to++ = data; 518145132Sanholt if (DRM_COPY_FROM_USER_UNCHECKED 519145132Sanholt (to, from, count << 2)) { 520145132Sanholt DRM_ERROR("%s: copy_from_user\n", 521145132Sanholt __FUNCTION__); 522145132Sanholt return DRM_ERR(EFAULT); 523145132Sanholt } 524145132Sanholt to += count; 525145132Sanholt } else { 526145132Sanholt DRM_ERROR("%s: Got bad command: 0x%04x\n", 527145132Sanholt __FUNCTION__, reg); 528145132Sanholt return DRM_ERR(EACCES); 529145132Sanholt } 530145132Sanholt 531145132Sanholt from += count; 532145132Sanholt } else { 533145132Sanholt DRM_ERROR 534145132Sanholt ("%s: Got bad command count(=%u) dwords remaining=%lu\n", 535145132Sanholt __FUNCTION__, count, n); 536145132Sanholt return DRM_ERR(EINVAL); 537145132Sanholt } 538145132Sanholt } 539145132Sanholt 540145132Sanholt if (n == 0) 541145132Sanholt return 0; 542145132Sanholt else { 543145132Sanholt DRM_ERROR("%s: Bad buf->used(=%lu)\n", __FUNCTION__, bytes); 544145132Sanholt return DRM_ERR(EINVAL); 545145132Sanholt } 546145132Sanholt} 547145132Sanholt 548145132Sanholtstatic int mach64_dma_dispatch_vertex(DRMFILE filp, drm_device_t * dev, 549145132Sanholt int prim, void *buf, unsigned long used, 550145132Sanholt int discard) 551145132Sanholt{ 552145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 553145132Sanholt drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 554145132Sanholt drm_buf_t *copy_buf; 555145132Sanholt int done = 0; 556145132Sanholt int verify_ret = 0; 557145132Sanholt DMALOCALS; 558145132Sanholt 559145132Sanholt DRM_DEBUG("%s: buf=%p used=%lu nbox=%d\n", 560145132Sanholt __FUNCTION__, buf, used, sarea_priv->nbox); 561145132Sanholt 562145132Sanholt if (used) { 563145132Sanholt int ret = 0; 564145132Sanholt int i = 0; 565145132Sanholt 566145132Sanholt copy_buf = mach64_freelist_get(dev_priv); 567145132Sanholt if (copy_buf == NULL) { 568145132Sanholt DRM_ERROR("%s: couldn't get buffer in DMAGETPTR\n", 569145132Sanholt __FUNCTION__); 570145132Sanholt return DRM_ERR(EAGAIN); 571145132Sanholt } 572145132Sanholt 573145132Sanholt if ((verify_ret = 574145132Sanholt copy_and_verify_from_user(GETBUFPTR(copy_buf), buf, 575145132Sanholt used)) == 0) { 576145132Sanholt 577145132Sanholt copy_buf->used = used; 578145132Sanholt 579145132Sanholt DMASETPTR(copy_buf); 580145132Sanholt 581145132Sanholt if (sarea_priv->dirty & ~MACH64_UPLOAD_CLIPRECTS) { 582145132Sanholt ret = mach64_emit_state(filp, dev_priv); 583145132Sanholt if (ret < 0) 584145132Sanholt return ret; 585145132Sanholt } 586145132Sanholt 587145132Sanholt do { 588145132Sanholt /* Emit the next cliprect */ 589145132Sanholt if (i < sarea_priv->nbox) { 590145132Sanholt ret = 591145132Sanholt mach64_emit_cliprect(filp, dev_priv, 592145132Sanholt &sarea_priv-> 593145132Sanholt boxes[i]); 594145132Sanholt if (ret < 0) { 595145132Sanholt /* failed to get buffer */ 596145132Sanholt return ret; 597145132Sanholt } else if (ret != 0) { 598145132Sanholt /* null intersection with scissor */ 599145132Sanholt continue; 600145132Sanholt } 601145132Sanholt } 602145132Sanholt if ((i >= sarea_priv->nbox - 1)) 603145132Sanholt done = 1; 604145132Sanholt 605145132Sanholt /* Add the buffer to the DMA queue */ 606145132Sanholt DMAADVANCE(dev_priv, done); 607145132Sanholt 608145132Sanholt } while (++i < sarea_priv->nbox); 609145132Sanholt } 610145132Sanholt 611145132Sanholt if (copy_buf->pending && !done) { 612145132Sanholt DMADISCARDBUF(); 613145132Sanholt } else if (!done) { 614145132Sanholt /* This buffer wasn't used (no cliprects or verify failed), so place it back 615145132Sanholt * on the free list 616145132Sanholt */ 617145132Sanholt struct list_head *ptr; 618145132Sanholt drm_mach64_freelist_t *entry; 619145132Sanholt#if MACH64_EXTRA_CHECKING 620145132Sanholt list_for_each(ptr, &dev_priv->pending) { 621145132Sanholt entry = 622145132Sanholt list_entry(ptr, drm_mach64_freelist_t, 623145132Sanholt list); 624145132Sanholt if (copy_buf == entry->buf) { 625145132Sanholt DRM_ERROR 626145132Sanholt ("%s: Trying to release a pending buf\n", 627145132Sanholt __FUNCTION__); 628145132Sanholt return DRM_ERR(EFAULT); 629145132Sanholt } 630145132Sanholt } 631145132Sanholt#endif 632145132Sanholt ptr = dev_priv->placeholders.next; 633145132Sanholt entry = list_entry(ptr, drm_mach64_freelist_t, list); 634145132Sanholt copy_buf->pending = 0; 635145132Sanholt copy_buf->used = 0; 636145132Sanholt entry->buf = copy_buf; 637145132Sanholt entry->discard = 1; 638145132Sanholt list_del(ptr); 639145132Sanholt list_add_tail(ptr, &dev_priv->free_list); 640145132Sanholt } 641145132Sanholt } 642145132Sanholt 643145132Sanholt sarea_priv->dirty &= ~MACH64_UPLOAD_CLIPRECTS; 644145132Sanholt sarea_priv->nbox = 0; 645145132Sanholt 646145132Sanholt return verify_ret; 647145132Sanholt} 648145132Sanholt 649145132Sanholtstatic int mach64_dma_dispatch_blit(DRMFILE filp, drm_device_t * dev, 650145132Sanholt drm_mach64_blit_t * blit) 651145132Sanholt{ 652145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 653145132Sanholt drm_device_dma_t *dma = dev->dma; 654145132Sanholt int dword_shift, dwords; 655145132Sanholt drm_buf_t *buf; 656145132Sanholt DMALOCALS; 657145132Sanholt 658145132Sanholt /* The compiler won't optimize away a division by a variable, 659145132Sanholt * even if the only legal values are powers of two. Thus, we'll 660145132Sanholt * use a shift instead. 661145132Sanholt */ 662145132Sanholt switch (blit->format) { 663145132Sanholt case MACH64_DATATYPE_ARGB8888: 664145132Sanholt dword_shift = 0; 665145132Sanholt break; 666145132Sanholt case MACH64_DATATYPE_ARGB1555: 667145132Sanholt case MACH64_DATATYPE_RGB565: 668145132Sanholt case MACH64_DATATYPE_VYUY422: 669145132Sanholt case MACH64_DATATYPE_YVYU422: 670145132Sanholt case MACH64_DATATYPE_ARGB4444: 671145132Sanholt dword_shift = 1; 672145132Sanholt break; 673145132Sanholt case MACH64_DATATYPE_CI8: 674145132Sanholt case MACH64_DATATYPE_RGB8: 675145132Sanholt dword_shift = 2; 676145132Sanholt break; 677145132Sanholt default: 678145132Sanholt DRM_ERROR("invalid blit format %d\n", blit->format); 679145132Sanholt return DRM_ERR(EINVAL); 680145132Sanholt } 681145132Sanholt 682145132Sanholt /* Dispatch the blit buffer. 683145132Sanholt */ 684145132Sanholt buf = dma->buflist[blit->idx]; 685145132Sanholt 686145132Sanholt if (buf->filp != filp) { 687145132Sanholt DRM_ERROR("process %d (filp %p) using buffer with filp %p\n", 688145132Sanholt DRM_CURRENTPID, filp, buf->filp); 689145132Sanholt return DRM_ERR(EINVAL); 690145132Sanholt } 691145132Sanholt 692145132Sanholt if (buf->pending) { 693145132Sanholt DRM_ERROR("sending pending buffer %d\n", blit->idx); 694145132Sanholt return DRM_ERR(EINVAL); 695145132Sanholt } 696145132Sanholt 697145132Sanholt /* Set buf->used to the bytes of blit data based on the blit dimensions 698145132Sanholt * and verify the size. When the setup is emitted to the buffer with 699145132Sanholt * the DMA* macros below, buf->used is incremented to include the bytes 700145132Sanholt * used for setup as well as the blit data. 701145132Sanholt */ 702145132Sanholt dwords = (blit->width * blit->height) >> dword_shift; 703145132Sanholt buf->used = dwords << 2; 704145132Sanholt if (buf->used <= 0 || 705145132Sanholt buf->used > MACH64_BUFFER_SIZE - MACH64_HOSTDATA_BLIT_OFFSET) { 706145132Sanholt DRM_ERROR("Invalid blit size: %d bytes\n", buf->used); 707145132Sanholt return DRM_ERR(EINVAL); 708145132Sanholt } 709145132Sanholt 710145132Sanholt /* FIXME: Use a last buffer flag and reduce the state emitted for subsequent, 711145132Sanholt * continuation buffers? 712145132Sanholt */ 713145132Sanholt 714145132Sanholt /* Blit via BM_HOSTDATA (gui-master) - like HOST_DATA[0-15], but doesn't require 715145132Sanholt * a register command every 16 dwords. State setup is added at the start of the 716145132Sanholt * buffer -- the client leaves space for this based on MACH64_HOSTDATA_BLIT_OFFSET 717145132Sanholt */ 718145132Sanholt DMASETPTR(buf); 719145132Sanholt 720145132Sanholt DMAOUTREG(MACH64_Z_CNTL, 0); 721145132Sanholt DMAOUTREG(MACH64_SCALE_3D_CNTL, 0); 722145132Sanholt 723145132Sanholt DMAOUTREG(MACH64_SC_LEFT_RIGHT, 0 | (8191 << 16)); /* no scissor */ 724145132Sanholt DMAOUTREG(MACH64_SC_TOP_BOTTOM, 0 | (16383 << 16)); 725145132Sanholt 726145132Sanholt DMAOUTREG(MACH64_CLR_CMP_CNTL, 0); /* disable */ 727145132Sanholt DMAOUTREG(MACH64_GUI_TRAJ_CNTL, 728145132Sanholt MACH64_DST_X_LEFT_TO_RIGHT | MACH64_DST_Y_TOP_TO_BOTTOM); 729145132Sanholt 730145132Sanholt DMAOUTREG(MACH64_DP_PIX_WIDTH, (blit->format << 0) /* dst pix width */ 731145132Sanholt |(blit->format << 4) /* composite pix width */ 732145132Sanholt |(blit->format << 8) /* src pix width */ 733145132Sanholt |(blit->format << 16) /* host data pix width */ 734145132Sanholt |(blit->format << 28) /* scaler/3D pix width */ 735145132Sanholt ); 736145132Sanholt 737145132Sanholt DMAOUTREG(MACH64_DP_WRITE_MASK, 0xffffffff); /* enable all planes */ 738145132Sanholt DMAOUTREG(MACH64_DP_MIX, MACH64_BKGD_MIX_D | MACH64_FRGD_MIX_S); 739145132Sanholt DMAOUTREG(MACH64_DP_SRC, 740145132Sanholt MACH64_BKGD_SRC_BKGD_CLR 741145132Sanholt | MACH64_FRGD_SRC_HOST | MACH64_MONO_SRC_ONE); 742145132Sanholt 743145132Sanholt DMAOUTREG(MACH64_DST_OFF_PITCH, 744145132Sanholt (blit->pitch << 22) | (blit->offset >> 3)); 745145132Sanholt DMAOUTREG(MACH64_DST_X_Y, (blit->y << 16) | blit->x); 746145132Sanholt DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (blit->height << 16) | blit->width); 747145132Sanholt 748145132Sanholt DRM_DEBUG("%s: %d bytes\n", __FUNCTION__, buf->used); 749145132Sanholt 750145132Sanholt /* Add the buffer to the queue */ 751145132Sanholt DMAADVANCEHOSTDATA(dev_priv); 752145132Sanholt 753145132Sanholt return 0; 754145132Sanholt} 755145132Sanholt 756145132Sanholt/* ================================================================ 757145132Sanholt * IOCTL functions 758145132Sanholt */ 759145132Sanholt 760145132Sanholtint mach64_dma_clear(DRM_IOCTL_ARGS) 761145132Sanholt{ 762145132Sanholt DRM_DEVICE; 763145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 764145132Sanholt drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 765145132Sanholt drm_mach64_clear_t clear; 766145132Sanholt int ret; 767145132Sanholt 768145132Sanholt DRM_DEBUG("%s: pid=%d\n", __FUNCTION__, DRM_CURRENTPID); 769145132Sanholt 770145132Sanholt LOCK_TEST_WITH_RETURN(dev, filp); 771145132Sanholt 772145132Sanholt DRM_COPY_FROM_USER_IOCTL(clear, (drm_mach64_clear_t *) data, 773145132Sanholt sizeof(clear)); 774145132Sanholt 775145132Sanholt if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS) 776145132Sanholt sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS; 777145132Sanholt 778145132Sanholt ret = mach64_dma_dispatch_clear(filp, dev, clear.flags, 779145132Sanholt clear.x, clear.y, clear.w, clear.h, 780145132Sanholt clear.clear_color, clear.clear_depth); 781145132Sanholt 782145132Sanholt /* Make sure we restore the 3D state next time. 783145132Sanholt */ 784145132Sanholt sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT | MACH64_UPLOAD_MISC); 785145132Sanholt return ret; 786145132Sanholt} 787145132Sanholt 788145132Sanholtint mach64_dma_swap(DRM_IOCTL_ARGS) 789145132Sanholt{ 790145132Sanholt DRM_DEVICE; 791145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 792145132Sanholt drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 793145132Sanholt int ret; 794145132Sanholt 795145132Sanholt DRM_DEBUG("%s: pid=%d\n", __FUNCTION__, DRM_CURRENTPID); 796145132Sanholt 797145132Sanholt LOCK_TEST_WITH_RETURN(dev, filp); 798145132Sanholt 799145132Sanholt if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS) 800145132Sanholt sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS; 801145132Sanholt 802145132Sanholt ret = mach64_dma_dispatch_swap(filp, dev); 803145132Sanholt 804145132Sanholt /* Make sure we restore the 3D state next time. 805145132Sanholt */ 806145132Sanholt sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT | MACH64_UPLOAD_MISC); 807145132Sanholt return ret; 808145132Sanholt} 809145132Sanholt 810145132Sanholtint mach64_dma_vertex(DRM_IOCTL_ARGS) 811145132Sanholt{ 812145132Sanholt DRM_DEVICE; 813145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 814145132Sanholt drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 815145132Sanholt drm_mach64_vertex_t vertex; 816145132Sanholt 817145132Sanholt LOCK_TEST_WITH_RETURN(dev, filp); 818145132Sanholt 819145132Sanholt if (!dev_priv) { 820145132Sanholt DRM_ERROR("%s called with no initialization\n", __FUNCTION__); 821145132Sanholt return DRM_ERR(EINVAL); 822145132Sanholt } 823145132Sanholt 824145132Sanholt DRM_COPY_FROM_USER_IOCTL(vertex, (drm_mach64_vertex_t *) data, 825145132Sanholt sizeof(vertex)); 826145132Sanholt 827145132Sanholt DRM_DEBUG("%s: pid=%d buf=%p used=%lu discard=%d\n", 828145132Sanholt __FUNCTION__, DRM_CURRENTPID, 829145132Sanholt vertex.buf, vertex.used, vertex.discard); 830145132Sanholt 831145132Sanholt if (vertex.prim < 0 || vertex.prim > MACH64_PRIM_POLYGON) { 832145132Sanholt DRM_ERROR("buffer prim %d\n", vertex.prim); 833145132Sanholt return DRM_ERR(EINVAL); 834145132Sanholt } 835145132Sanholt 836145132Sanholt if (vertex.used > MACH64_BUFFER_SIZE || (vertex.used & 3) != 0) { 837145132Sanholt DRM_ERROR("Invalid vertex buffer size: %lu bytes\n", 838145132Sanholt vertex.used); 839145132Sanholt return DRM_ERR(EINVAL); 840145132Sanholt } 841145132Sanholt 842145132Sanholt if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS) 843145132Sanholt sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS; 844145132Sanholt 845145132Sanholt return mach64_dma_dispatch_vertex(filp, dev, vertex.prim, vertex.buf, 846145132Sanholt vertex.used, vertex.discard); 847145132Sanholt} 848145132Sanholt 849145132Sanholtint mach64_dma_blit(DRM_IOCTL_ARGS) 850145132Sanholt{ 851145132Sanholt DRM_DEVICE; 852145132Sanholt drm_device_dma_t *dma = dev->dma; 853145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 854145132Sanholt drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 855145132Sanholt drm_mach64_blit_t blit; 856145132Sanholt int ret; 857145132Sanholt 858145132Sanholt LOCK_TEST_WITH_RETURN(dev, filp); 859145132Sanholt 860145132Sanholt DRM_COPY_FROM_USER_IOCTL(blit, (drm_mach64_blit_t *) data, 861145132Sanholt sizeof(blit)); 862145132Sanholt 863145132Sanholt DRM_DEBUG("%s: pid=%d index=%d\n", 864145132Sanholt __FUNCTION__, DRM_CURRENTPID, blit.idx); 865145132Sanholt 866145132Sanholt if (blit.idx < 0 || blit.idx >= dma->buf_count) { 867145132Sanholt DRM_ERROR("buffer index %d (of %d max)\n", 868145132Sanholt blit.idx, dma->buf_count - 1); 869145132Sanholt return DRM_ERR(EINVAL); 870145132Sanholt } 871145132Sanholt 872145132Sanholt ret = mach64_dma_dispatch_blit(filp, dev, &blit); 873145132Sanholt 874145132Sanholt /* Make sure we restore the 3D state next time. 875145132Sanholt */ 876145132Sanholt sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT | 877145132Sanholt MACH64_UPLOAD_MISC | MACH64_UPLOAD_CLIPRECTS); 878145132Sanholt 879145132Sanholt return ret; 880145132Sanholt} 881145132Sanholt 882145132Sanholtint mach64_get_param(DRM_IOCTL_ARGS) 883145132Sanholt{ 884145132Sanholt DRM_DEVICE; 885145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 886145132Sanholt drm_mach64_getparam_t param; 887145132Sanholt int value; 888145132Sanholt 889145132Sanholt DRM_DEBUG("%s\n", __FUNCTION__); 890145132Sanholt 891145132Sanholt if (!dev_priv) { 892145132Sanholt DRM_ERROR("%s called with no initialization\n", __FUNCTION__); 893145132Sanholt return DRM_ERR(EINVAL); 894145132Sanholt } 895145132Sanholt 896145132Sanholt DRM_COPY_FROM_USER_IOCTL(param, (drm_mach64_getparam_t *) data, 897145132Sanholt sizeof(param)); 898145132Sanholt 899145132Sanholt switch (param.param) { 900145132Sanholt case MACH64_PARAM_FRAMES_QUEUED: 901145132Sanholt /* Needs lock since it calls mach64_ring_tick() */ 902145132Sanholt LOCK_TEST_WITH_RETURN(dev, filp); 903145132Sanholt value = mach64_do_get_frames_queued(dev_priv); 904145132Sanholt break; 905145132Sanholt case MACH64_PARAM_IRQ_NR: 906145132Sanholt value = dev->irq; 907145132Sanholt break; 908145132Sanholt default: 909145132Sanholt return DRM_ERR(EINVAL); 910145132Sanholt } 911145132Sanholt 912145132Sanholt if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) { 913145132Sanholt DRM_ERROR("copy_to_user\n"); 914145132Sanholt return DRM_ERR(EFAULT); 915145132Sanholt } 916145132Sanholt 917145132Sanholt return 0; 918145132Sanholt} 919