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