Path: blob/master/drivers/gpu/drm/r128/r128_state.c
15112 views
/* r128_state.c -- State support for r128 -*- linux-c -*-1* Created: Thu Jan 27 02:53:43 2000 by [email protected]2*/3/*4* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.5* All Rights Reserved.6*7* Permission is hereby granted, free of charge, to any person obtaining a8* copy of this software and associated documentation files (the "Software"),9* to deal in the Software without restriction, including without limitation10* the rights to use, copy, modify, merge, publish, distribute, sublicense,11* and/or sell copies of the Software, and to permit persons to whom the12* Software is furnished to do so, subject to the following conditions:13*14* The above copyright notice and this permission notice (including the next15* paragraph) shall be included in all copies or substantial portions of the16* Software.17*18* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR19* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,20* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL21* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR22* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,23* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER24* DEALINGS IN THE SOFTWARE.25*26* Authors:27* Gareth Hughes <[email protected]>28*/2930#include "drmP.h"31#include "drm.h"32#include "r128_drm.h"33#include "r128_drv.h"3435/* ================================================================36* CCE hardware state programming functions37*/3839static void r128_emit_clip_rects(drm_r128_private_t *dev_priv,40struct drm_clip_rect *boxes, int count)41{42u32 aux_sc_cntl = 0x00000000;43RING_LOCALS;44DRM_DEBUG("\n");4546BEGIN_RING((count < 3 ? count : 3) * 5 + 2);4748if (count >= 1) {49OUT_RING(CCE_PACKET0(R128_AUX1_SC_LEFT, 3));50OUT_RING(boxes[0].x1);51OUT_RING(boxes[0].x2 - 1);52OUT_RING(boxes[0].y1);53OUT_RING(boxes[0].y2 - 1);5455aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR);56}57if (count >= 2) {58OUT_RING(CCE_PACKET0(R128_AUX2_SC_LEFT, 3));59OUT_RING(boxes[1].x1);60OUT_RING(boxes[1].x2 - 1);61OUT_RING(boxes[1].y1);62OUT_RING(boxes[1].y2 - 1);6364aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR);65}66if (count >= 3) {67OUT_RING(CCE_PACKET0(R128_AUX3_SC_LEFT, 3));68OUT_RING(boxes[2].x1);69OUT_RING(boxes[2].x2 - 1);70OUT_RING(boxes[2].y1);71OUT_RING(boxes[2].y2 - 1);7273aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR);74}7576OUT_RING(CCE_PACKET0(R128_AUX_SC_CNTL, 0));77OUT_RING(aux_sc_cntl);7879ADVANCE_RING();80}8182static __inline__ void r128_emit_core(drm_r128_private_t *dev_priv)83{84drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;85drm_r128_context_regs_t *ctx = &sarea_priv->context_state;86RING_LOCALS;87DRM_DEBUG("\n");8889BEGIN_RING(2);9091OUT_RING(CCE_PACKET0(R128_SCALE_3D_CNTL, 0));92OUT_RING(ctx->scale_3d_cntl);9394ADVANCE_RING();95}9697static __inline__ void r128_emit_context(drm_r128_private_t *dev_priv)98{99drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;100drm_r128_context_regs_t *ctx = &sarea_priv->context_state;101RING_LOCALS;102DRM_DEBUG("\n");103104BEGIN_RING(13);105106OUT_RING(CCE_PACKET0(R128_DST_PITCH_OFFSET_C, 11));107OUT_RING(ctx->dst_pitch_offset_c);108OUT_RING(ctx->dp_gui_master_cntl_c);109OUT_RING(ctx->sc_top_left_c);110OUT_RING(ctx->sc_bottom_right_c);111OUT_RING(ctx->z_offset_c);112OUT_RING(ctx->z_pitch_c);113OUT_RING(ctx->z_sten_cntl_c);114OUT_RING(ctx->tex_cntl_c);115OUT_RING(ctx->misc_3d_state_cntl_reg);116OUT_RING(ctx->texture_clr_cmp_clr_c);117OUT_RING(ctx->texture_clr_cmp_msk_c);118OUT_RING(ctx->fog_color_c);119120ADVANCE_RING();121}122123static __inline__ void r128_emit_setup(drm_r128_private_t *dev_priv)124{125drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;126drm_r128_context_regs_t *ctx = &sarea_priv->context_state;127RING_LOCALS;128DRM_DEBUG("\n");129130BEGIN_RING(3);131132OUT_RING(CCE_PACKET1(R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP));133OUT_RING(ctx->setup_cntl);134OUT_RING(ctx->pm4_vc_fpu_setup);135136ADVANCE_RING();137}138139static __inline__ void r128_emit_masks(drm_r128_private_t *dev_priv)140{141drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;142drm_r128_context_regs_t *ctx = &sarea_priv->context_state;143RING_LOCALS;144DRM_DEBUG("\n");145146BEGIN_RING(5);147148OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0));149OUT_RING(ctx->dp_write_mask);150151OUT_RING(CCE_PACKET0(R128_STEN_REF_MASK_C, 1));152OUT_RING(ctx->sten_ref_mask_c);153OUT_RING(ctx->plane_3d_mask_c);154155ADVANCE_RING();156}157158static __inline__ void r128_emit_window(drm_r128_private_t *dev_priv)159{160drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;161drm_r128_context_regs_t *ctx = &sarea_priv->context_state;162RING_LOCALS;163DRM_DEBUG("\n");164165BEGIN_RING(2);166167OUT_RING(CCE_PACKET0(R128_WINDOW_XY_OFFSET, 0));168OUT_RING(ctx->window_xy_offset);169170ADVANCE_RING();171}172173static __inline__ void r128_emit_tex0(drm_r128_private_t *dev_priv)174{175drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;176drm_r128_context_regs_t *ctx = &sarea_priv->context_state;177drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0];178int i;179RING_LOCALS;180DRM_DEBUG("\n");181182BEGIN_RING(7 + R128_MAX_TEXTURE_LEVELS);183184OUT_RING(CCE_PACKET0(R128_PRIM_TEX_CNTL_C,1852 + R128_MAX_TEXTURE_LEVELS));186OUT_RING(tex->tex_cntl);187OUT_RING(tex->tex_combine_cntl);188OUT_RING(ctx->tex_size_pitch_c);189for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++)190OUT_RING(tex->tex_offset[i]);191192OUT_RING(CCE_PACKET0(R128_CONSTANT_COLOR_C, 1));193OUT_RING(ctx->constant_color_c);194OUT_RING(tex->tex_border_color);195196ADVANCE_RING();197}198199static __inline__ void r128_emit_tex1(drm_r128_private_t *dev_priv)200{201drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;202drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1];203int i;204RING_LOCALS;205DRM_DEBUG("\n");206207BEGIN_RING(5 + R128_MAX_TEXTURE_LEVELS);208209OUT_RING(CCE_PACKET0(R128_SEC_TEX_CNTL_C, 1 + R128_MAX_TEXTURE_LEVELS));210OUT_RING(tex->tex_cntl);211OUT_RING(tex->tex_combine_cntl);212for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++)213OUT_RING(tex->tex_offset[i]);214215OUT_RING(CCE_PACKET0(R128_SEC_TEXTURE_BORDER_COLOR_C, 0));216OUT_RING(tex->tex_border_color);217218ADVANCE_RING();219}220221static void r128_emit_state(drm_r128_private_t *dev_priv)222{223drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;224unsigned int dirty = sarea_priv->dirty;225226DRM_DEBUG("dirty=0x%08x\n", dirty);227228if (dirty & R128_UPLOAD_CORE) {229r128_emit_core(dev_priv);230sarea_priv->dirty &= ~R128_UPLOAD_CORE;231}232233if (dirty & R128_UPLOAD_CONTEXT) {234r128_emit_context(dev_priv);235sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT;236}237238if (dirty & R128_UPLOAD_SETUP) {239r128_emit_setup(dev_priv);240sarea_priv->dirty &= ~R128_UPLOAD_SETUP;241}242243if (dirty & R128_UPLOAD_MASKS) {244r128_emit_masks(dev_priv);245sarea_priv->dirty &= ~R128_UPLOAD_MASKS;246}247248if (dirty & R128_UPLOAD_WINDOW) {249r128_emit_window(dev_priv);250sarea_priv->dirty &= ~R128_UPLOAD_WINDOW;251}252253if (dirty & R128_UPLOAD_TEX0) {254r128_emit_tex0(dev_priv);255sarea_priv->dirty &= ~R128_UPLOAD_TEX0;256}257258if (dirty & R128_UPLOAD_TEX1) {259r128_emit_tex1(dev_priv);260sarea_priv->dirty &= ~R128_UPLOAD_TEX1;261}262263/* Turn off the texture cache flushing */264sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH;265266sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE;267}268269#if R128_PERFORMANCE_BOXES270/* ================================================================271* Performance monitoring functions272*/273274static void r128_clear_box(drm_r128_private_t *dev_priv,275int x, int y, int w, int h, int r, int g, int b)276{277u32 pitch, offset;278u32 fb_bpp, color;279RING_LOCALS;280281switch (dev_priv->fb_bpp) {282case 16:283fb_bpp = R128_GMC_DST_16BPP;284color = (((r & 0xf8) << 8) |285((g & 0xfc) << 3) | ((b & 0xf8) >> 3));286break;287case 24:288fb_bpp = R128_GMC_DST_24BPP;289color = ((r << 16) | (g << 8) | b);290break;291case 32:292fb_bpp = R128_GMC_DST_32BPP;293color = (((0xff) << 24) | (r << 16) | (g << 8) | b);294break;295default:296return;297}298299offset = dev_priv->back_offset;300pitch = dev_priv->back_pitch >> 3;301302BEGIN_RING(6);303304OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));305OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |306R128_GMC_BRUSH_SOLID_COLOR |307fb_bpp |308R128_GMC_SRC_DATATYPE_COLOR |309R128_ROP3_P |310R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS);311312OUT_RING((pitch << 21) | (offset >> 5));313OUT_RING(color);314315OUT_RING((x << 16) | y);316OUT_RING((w << 16) | h);317318ADVANCE_RING();319}320321static void r128_cce_performance_boxes(drm_r128_private_t *dev_priv)322{323if (atomic_read(&dev_priv->idle_count) == 0)324r128_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);325else326atomic_set(&dev_priv->idle_count, 0);327}328329#endif330331/* ================================================================332* CCE command dispatch functions333*/334335static void r128_print_dirty(const char *msg, unsigned int flags)336{337DRM_INFO("%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",338msg,339flags,340(flags & R128_UPLOAD_CORE) ? "core, " : "",341(flags & R128_UPLOAD_CONTEXT) ? "context, " : "",342(flags & R128_UPLOAD_SETUP) ? "setup, " : "",343(flags & R128_UPLOAD_TEX0) ? "tex0, " : "",344(flags & R128_UPLOAD_TEX1) ? "tex1, " : "",345(flags & R128_UPLOAD_MASKS) ? "masks, " : "",346(flags & R128_UPLOAD_WINDOW) ? "window, " : "",347(flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "",348(flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "");349}350351static void r128_cce_dispatch_clear(struct drm_device *dev,352drm_r128_clear_t *clear)353{354drm_r128_private_t *dev_priv = dev->dev_private;355drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;356int nbox = sarea_priv->nbox;357struct drm_clip_rect *pbox = sarea_priv->boxes;358unsigned int flags = clear->flags;359int i;360RING_LOCALS;361DRM_DEBUG("\n");362363if (dev_priv->page_flipping && dev_priv->current_page == 1) {364unsigned int tmp = flags;365366flags &= ~(R128_FRONT | R128_BACK);367if (tmp & R128_FRONT)368flags |= R128_BACK;369if (tmp & R128_BACK)370flags |= R128_FRONT;371}372373for (i = 0; i < nbox; i++) {374int x = pbox[i].x1;375int y = pbox[i].y1;376int w = pbox[i].x2 - x;377int h = pbox[i].y2 - y;378379DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n",380pbox[i].x1, pbox[i].y1, pbox[i].x2,381pbox[i].y2, flags);382383if (flags & (R128_FRONT | R128_BACK)) {384BEGIN_RING(2);385386OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0));387OUT_RING(clear->color_mask);388389ADVANCE_RING();390}391392if (flags & R128_FRONT) {393BEGIN_RING(6);394395OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));396OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |397R128_GMC_BRUSH_SOLID_COLOR |398(dev_priv->color_fmt << 8) |399R128_GMC_SRC_DATATYPE_COLOR |400R128_ROP3_P |401R128_GMC_CLR_CMP_CNTL_DIS |402R128_GMC_AUX_CLIP_DIS);403404OUT_RING(dev_priv->front_pitch_offset_c);405OUT_RING(clear->clear_color);406407OUT_RING((x << 16) | y);408OUT_RING((w << 16) | h);409410ADVANCE_RING();411}412413if (flags & R128_BACK) {414BEGIN_RING(6);415416OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));417OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |418R128_GMC_BRUSH_SOLID_COLOR |419(dev_priv->color_fmt << 8) |420R128_GMC_SRC_DATATYPE_COLOR |421R128_ROP3_P |422R128_GMC_CLR_CMP_CNTL_DIS |423R128_GMC_AUX_CLIP_DIS);424425OUT_RING(dev_priv->back_pitch_offset_c);426OUT_RING(clear->clear_color);427428OUT_RING((x << 16) | y);429OUT_RING((w << 16) | h);430431ADVANCE_RING();432}433434if (flags & R128_DEPTH) {435BEGIN_RING(6);436437OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));438OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |439R128_GMC_BRUSH_SOLID_COLOR |440(dev_priv->depth_fmt << 8) |441R128_GMC_SRC_DATATYPE_COLOR |442R128_ROP3_P |443R128_GMC_CLR_CMP_CNTL_DIS |444R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);445446OUT_RING(dev_priv->depth_pitch_offset_c);447OUT_RING(clear->clear_depth);448449OUT_RING((x << 16) | y);450OUT_RING((w << 16) | h);451452ADVANCE_RING();453}454}455}456457static void r128_cce_dispatch_swap(struct drm_device *dev)458{459drm_r128_private_t *dev_priv = dev->dev_private;460drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;461int nbox = sarea_priv->nbox;462struct drm_clip_rect *pbox = sarea_priv->boxes;463int i;464RING_LOCALS;465DRM_DEBUG("\n");466467#if R128_PERFORMANCE_BOXES468/* Do some trivial performance monitoring...469*/470r128_cce_performance_boxes(dev_priv);471#endif472473for (i = 0; i < nbox; i++) {474int x = pbox[i].x1;475int y = pbox[i].y1;476int w = pbox[i].x2 - x;477int h = pbox[i].y2 - y;478479BEGIN_RING(7);480481OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));482OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |483R128_GMC_DST_PITCH_OFFSET_CNTL |484R128_GMC_BRUSH_NONE |485(dev_priv->color_fmt << 8) |486R128_GMC_SRC_DATATYPE_COLOR |487R128_ROP3_S |488R128_DP_SRC_SOURCE_MEMORY |489R128_GMC_CLR_CMP_CNTL_DIS |490R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);491492/* Make this work even if front & back are flipped:493*/494if (dev_priv->current_page == 0) {495OUT_RING(dev_priv->back_pitch_offset_c);496OUT_RING(dev_priv->front_pitch_offset_c);497} else {498OUT_RING(dev_priv->front_pitch_offset_c);499OUT_RING(dev_priv->back_pitch_offset_c);500}501502OUT_RING((x << 16) | y);503OUT_RING((x << 16) | y);504OUT_RING((w << 16) | h);505506ADVANCE_RING();507}508509/* Increment the frame counter. The client-side 3D driver must510* throttle the framerate by waiting for this value before511* performing the swapbuffer ioctl.512*/513dev_priv->sarea_priv->last_frame++;514515BEGIN_RING(2);516517OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));518OUT_RING(dev_priv->sarea_priv->last_frame);519520ADVANCE_RING();521}522523static void r128_cce_dispatch_flip(struct drm_device *dev)524{525drm_r128_private_t *dev_priv = dev->dev_private;526RING_LOCALS;527DRM_DEBUG("page=%d pfCurrentPage=%d\n",528dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);529530#if R128_PERFORMANCE_BOXES531/* Do some trivial performance monitoring...532*/533r128_cce_performance_boxes(dev_priv);534#endif535536BEGIN_RING(4);537538R128_WAIT_UNTIL_PAGE_FLIPPED();539OUT_RING(CCE_PACKET0(R128_CRTC_OFFSET, 0));540541if (dev_priv->current_page == 0)542OUT_RING(dev_priv->back_offset);543else544OUT_RING(dev_priv->front_offset);545546ADVANCE_RING();547548/* Increment the frame counter. The client-side 3D driver must549* throttle the framerate by waiting for this value before550* performing the swapbuffer ioctl.551*/552dev_priv->sarea_priv->last_frame++;553dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =5541 - dev_priv->current_page;555556BEGIN_RING(2);557558OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));559OUT_RING(dev_priv->sarea_priv->last_frame);560561ADVANCE_RING();562}563564static void r128_cce_dispatch_vertex(struct drm_device *dev, struct drm_buf *buf)565{566drm_r128_private_t *dev_priv = dev->dev_private;567drm_r128_buf_priv_t *buf_priv = buf->dev_private;568drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;569int format = sarea_priv->vc_format;570int offset = buf->bus_address;571int size = buf->used;572int prim = buf_priv->prim;573int i = 0;574RING_LOCALS;575DRM_DEBUG("buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox);576577if (0)578r128_print_dirty("dispatch_vertex", sarea_priv->dirty);579580if (buf->used) {581buf_priv->dispatched = 1;582583if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS)584r128_emit_state(dev_priv);585586do {587/* Emit the next set of up to three cliprects */588if (i < sarea_priv->nbox) {589r128_emit_clip_rects(dev_priv,590&sarea_priv->boxes[i],591sarea_priv->nbox - i);592}593594/* Emit the vertex buffer rendering commands */595BEGIN_RING(5);596597OUT_RING(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM, 3));598OUT_RING(offset);599OUT_RING(size);600OUT_RING(format);601OUT_RING(prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |602(size << R128_CCE_VC_CNTL_NUM_SHIFT));603604ADVANCE_RING();605606i += 3;607} while (i < sarea_priv->nbox);608}609610if (buf_priv->discard) {611buf_priv->age = dev_priv->sarea_priv->last_dispatch;612613/* Emit the vertex buffer age */614BEGIN_RING(2);615616OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));617OUT_RING(buf_priv->age);618619ADVANCE_RING();620621buf->pending = 1;622buf->used = 0;623/* FIXME: Check dispatched field */624buf_priv->dispatched = 0;625}626627dev_priv->sarea_priv->last_dispatch++;628629sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;630sarea_priv->nbox = 0;631}632633static void r128_cce_dispatch_indirect(struct drm_device *dev,634struct drm_buf *buf, int start, int end)635{636drm_r128_private_t *dev_priv = dev->dev_private;637drm_r128_buf_priv_t *buf_priv = buf->dev_private;638RING_LOCALS;639DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);640641if (start != end) {642int offset = buf->bus_address + start;643int dwords = (end - start + 3) / sizeof(u32);644645/* Indirect buffer data must be an even number of646* dwords, so if we've been given an odd number we must647* pad the data with a Type-2 CCE packet.648*/649if (dwords & 1) {650u32 *data = (u32 *)651((char *)dev->agp_buffer_map->handle652+ buf->offset + start);653data[dwords++] = cpu_to_le32(R128_CCE_PACKET2);654}655656buf_priv->dispatched = 1;657658/* Fire off the indirect buffer */659BEGIN_RING(3);660661OUT_RING(CCE_PACKET0(R128_PM4_IW_INDOFF, 1));662OUT_RING(offset);663OUT_RING(dwords);664665ADVANCE_RING();666}667668if (buf_priv->discard) {669buf_priv->age = dev_priv->sarea_priv->last_dispatch;670671/* Emit the indirect buffer age */672BEGIN_RING(2);673674OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));675OUT_RING(buf_priv->age);676677ADVANCE_RING();678679buf->pending = 1;680buf->used = 0;681/* FIXME: Check dispatched field */682buf_priv->dispatched = 0;683}684685dev_priv->sarea_priv->last_dispatch++;686}687688static void r128_cce_dispatch_indices(struct drm_device *dev,689struct drm_buf *buf,690int start, int end, int count)691{692drm_r128_private_t *dev_priv = dev->dev_private;693drm_r128_buf_priv_t *buf_priv = buf->dev_private;694drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;695int format = sarea_priv->vc_format;696int offset = dev->agp_buffer_map->offset - dev_priv->cce_buffers_offset;697int prim = buf_priv->prim;698u32 *data;699int dwords;700int i = 0;701RING_LOCALS;702DRM_DEBUG("indices: s=%d e=%d c=%d\n", start, end, count);703704if (0)705r128_print_dirty("dispatch_indices", sarea_priv->dirty);706707if (start != end) {708buf_priv->dispatched = 1;709710if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS)711r128_emit_state(dev_priv);712713dwords = (end - start + 3) / sizeof(u32);714715data = (u32 *) ((char *)dev->agp_buffer_map->handle716+ buf->offset + start);717718data[0] = cpu_to_le32(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM,719dwords - 2));720721data[1] = cpu_to_le32(offset);722data[2] = cpu_to_le32(R128_MAX_VB_VERTS);723data[3] = cpu_to_le32(format);724data[4] = cpu_to_le32((prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |725(count << 16)));726727if (count & 0x1) {728#ifdef __LITTLE_ENDIAN729data[dwords - 1] &= 0x0000ffff;730#else731data[dwords - 1] &= 0xffff0000;732#endif733}734735do {736/* Emit the next set of up to three cliprects */737if (i < sarea_priv->nbox) {738r128_emit_clip_rects(dev_priv,739&sarea_priv->boxes[i],740sarea_priv->nbox - i);741}742743r128_cce_dispatch_indirect(dev, buf, start, end);744745i += 3;746} while (i < sarea_priv->nbox);747}748749if (buf_priv->discard) {750buf_priv->age = dev_priv->sarea_priv->last_dispatch;751752/* Emit the vertex buffer age */753BEGIN_RING(2);754755OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));756OUT_RING(buf_priv->age);757758ADVANCE_RING();759760buf->pending = 1;761/* FIXME: Check dispatched field */762buf_priv->dispatched = 0;763}764765dev_priv->sarea_priv->last_dispatch++;766767sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;768sarea_priv->nbox = 0;769}770771static int r128_cce_dispatch_blit(struct drm_device *dev,772struct drm_file *file_priv,773drm_r128_blit_t *blit)774{775drm_r128_private_t *dev_priv = dev->dev_private;776struct drm_device_dma *dma = dev->dma;777struct drm_buf *buf;778drm_r128_buf_priv_t *buf_priv;779u32 *data;780int dword_shift, dwords;781RING_LOCALS;782DRM_DEBUG("\n");783784/* The compiler won't optimize away a division by a variable,785* even if the only legal values are powers of two. Thus, we'll786* use a shift instead.787*/788switch (blit->format) {789case R128_DATATYPE_ARGB8888:790dword_shift = 0;791break;792case R128_DATATYPE_ARGB1555:793case R128_DATATYPE_RGB565:794case R128_DATATYPE_ARGB4444:795case R128_DATATYPE_YVYU422:796case R128_DATATYPE_VYUY422:797dword_shift = 1;798break;799case R128_DATATYPE_CI8:800case R128_DATATYPE_RGB8:801dword_shift = 2;802break;803default:804DRM_ERROR("invalid blit format %d\n", blit->format);805return -EINVAL;806}807808/* Flush the pixel cache, and mark the contents as Read Invalid.809* This ensures no pixel data gets mixed up with the texture810* data from the host data blit, otherwise part of the texture811* image may be corrupted.812*/813BEGIN_RING(2);814815OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));816OUT_RING(R128_PC_RI_GUI | R128_PC_FLUSH_GUI);817818ADVANCE_RING();819820/* Dispatch the indirect buffer.821*/822buf = dma->buflist[blit->idx];823buf_priv = buf->dev_private;824825if (buf->file_priv != file_priv) {826DRM_ERROR("process %d using buffer owned by %p\n",827DRM_CURRENTPID, buf->file_priv);828return -EINVAL;829}830if (buf->pending) {831DRM_ERROR("sending pending buffer %d\n", blit->idx);832return -EINVAL;833}834835buf_priv->discard = 1;836837dwords = (blit->width * blit->height) >> dword_shift;838839data = (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);840841data[0] = cpu_to_le32(CCE_PACKET3(R128_CNTL_HOSTDATA_BLT, dwords + 6));842data[1] = cpu_to_le32((R128_GMC_DST_PITCH_OFFSET_CNTL |843R128_GMC_BRUSH_NONE |844(blit->format << 8) |845R128_GMC_SRC_DATATYPE_COLOR |846R128_ROP3_S |847R128_DP_SRC_SOURCE_HOST_DATA |848R128_GMC_CLR_CMP_CNTL_DIS |849R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS));850851data[2] = cpu_to_le32((blit->pitch << 21) | (blit->offset >> 5));852data[3] = cpu_to_le32(0xffffffff);853data[4] = cpu_to_le32(0xffffffff);854data[5] = cpu_to_le32((blit->y << 16) | blit->x);855data[6] = cpu_to_le32((blit->height << 16) | blit->width);856data[7] = cpu_to_le32(dwords);857858buf->used = (dwords + 8) * sizeof(u32);859860r128_cce_dispatch_indirect(dev, buf, 0, buf->used);861862/* Flush the pixel cache after the blit completes. This ensures863* the texture data is written out to memory before rendering864* continues.865*/866BEGIN_RING(2);867868OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));869OUT_RING(R128_PC_FLUSH_GUI);870871ADVANCE_RING();872873return 0;874}875876/* ================================================================877* Tiled depth buffer management878*879* FIXME: These should all set the destination write mask for when we880* have hardware stencil support.881*/882883static int r128_cce_dispatch_write_span(struct drm_device *dev,884drm_r128_depth_t *depth)885{886drm_r128_private_t *dev_priv = dev->dev_private;887int count, x, y;888u32 *buffer;889u8 *mask;890int i, buffer_size, mask_size;891RING_LOCALS;892DRM_DEBUG("\n");893894count = depth->n;895if (count > 4096 || count <= 0)896return -EMSGSIZE;897898if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x)))899return -EFAULT;900if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y)))901return -EFAULT;902903buffer_size = depth->n * sizeof(u32);904buffer = kmalloc(buffer_size, GFP_KERNEL);905if (buffer == NULL)906return -ENOMEM;907if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {908kfree(buffer);909return -EFAULT;910}911912mask_size = depth->n * sizeof(u8);913if (depth->mask) {914mask = kmalloc(mask_size, GFP_KERNEL);915if (mask == NULL) {916kfree(buffer);917return -ENOMEM;918}919if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {920kfree(buffer);921kfree(mask);922return -EFAULT;923}924925for (i = 0; i < count; i++, x++) {926if (mask[i]) {927BEGIN_RING(6);928929OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));930OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |931R128_GMC_BRUSH_SOLID_COLOR |932(dev_priv->depth_fmt << 8) |933R128_GMC_SRC_DATATYPE_COLOR |934R128_ROP3_P |935R128_GMC_CLR_CMP_CNTL_DIS |936R128_GMC_WR_MSK_DIS);937938OUT_RING(dev_priv->depth_pitch_offset_c);939OUT_RING(buffer[i]);940941OUT_RING((x << 16) | y);942OUT_RING((1 << 16) | 1);943944ADVANCE_RING();945}946}947948kfree(mask);949} else {950for (i = 0; i < count; i++, x++) {951BEGIN_RING(6);952953OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));954OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |955R128_GMC_BRUSH_SOLID_COLOR |956(dev_priv->depth_fmt << 8) |957R128_GMC_SRC_DATATYPE_COLOR |958R128_ROP3_P |959R128_GMC_CLR_CMP_CNTL_DIS |960R128_GMC_WR_MSK_DIS);961962OUT_RING(dev_priv->depth_pitch_offset_c);963OUT_RING(buffer[i]);964965OUT_RING((x << 16) | y);966OUT_RING((1 << 16) | 1);967968ADVANCE_RING();969}970}971972kfree(buffer);973974return 0;975}976977static int r128_cce_dispatch_write_pixels(struct drm_device *dev,978drm_r128_depth_t *depth)979{980drm_r128_private_t *dev_priv = dev->dev_private;981int count, *x, *y;982u32 *buffer;983u8 *mask;984int i, xbuf_size, ybuf_size, buffer_size, mask_size;985RING_LOCALS;986DRM_DEBUG("\n");987988count = depth->n;989if (count > 4096 || count <= 0)990return -EMSGSIZE;991992xbuf_size = count * sizeof(*x);993ybuf_size = count * sizeof(*y);994x = kmalloc(xbuf_size, GFP_KERNEL);995if (x == NULL)996return -ENOMEM;997y = kmalloc(ybuf_size, GFP_KERNEL);998if (y == NULL) {999kfree(x);1000return -ENOMEM;1001}1002if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {1003kfree(x);1004kfree(y);1005return -EFAULT;1006}1007if (DRM_COPY_FROM_USER(y, depth->y, xbuf_size)) {1008kfree(x);1009kfree(y);1010return -EFAULT;1011}10121013buffer_size = depth->n * sizeof(u32);1014buffer = kmalloc(buffer_size, GFP_KERNEL);1015if (buffer == NULL) {1016kfree(x);1017kfree(y);1018return -ENOMEM;1019}1020if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {1021kfree(x);1022kfree(y);1023kfree(buffer);1024return -EFAULT;1025}10261027if (depth->mask) {1028mask_size = depth->n * sizeof(u8);1029mask = kmalloc(mask_size, GFP_KERNEL);1030if (mask == NULL) {1031kfree(x);1032kfree(y);1033kfree(buffer);1034return -ENOMEM;1035}1036if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {1037kfree(x);1038kfree(y);1039kfree(buffer);1040kfree(mask);1041return -EFAULT;1042}10431044for (i = 0; i < count; i++) {1045if (mask[i]) {1046BEGIN_RING(6);10471048OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));1049OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |1050R128_GMC_BRUSH_SOLID_COLOR |1051(dev_priv->depth_fmt << 8) |1052R128_GMC_SRC_DATATYPE_COLOR |1053R128_ROP3_P |1054R128_GMC_CLR_CMP_CNTL_DIS |1055R128_GMC_WR_MSK_DIS);10561057OUT_RING(dev_priv->depth_pitch_offset_c);1058OUT_RING(buffer[i]);10591060OUT_RING((x[i] << 16) | y[i]);1061OUT_RING((1 << 16) | 1);10621063ADVANCE_RING();1064}1065}10661067kfree(mask);1068} else {1069for (i = 0; i < count; i++) {1070BEGIN_RING(6);10711072OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));1073OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |1074R128_GMC_BRUSH_SOLID_COLOR |1075(dev_priv->depth_fmt << 8) |1076R128_GMC_SRC_DATATYPE_COLOR |1077R128_ROP3_P |1078R128_GMC_CLR_CMP_CNTL_DIS |1079R128_GMC_WR_MSK_DIS);10801081OUT_RING(dev_priv->depth_pitch_offset_c);1082OUT_RING(buffer[i]);10831084OUT_RING((x[i] << 16) | y[i]);1085OUT_RING((1 << 16) | 1);10861087ADVANCE_RING();1088}1089}10901091kfree(x);1092kfree(y);1093kfree(buffer);10941095return 0;1096}10971098static int r128_cce_dispatch_read_span(struct drm_device *dev,1099drm_r128_depth_t *depth)1100{1101drm_r128_private_t *dev_priv = dev->dev_private;1102int count, x, y;1103RING_LOCALS;1104DRM_DEBUG("\n");11051106count = depth->n;1107if (count > 4096 || count <= 0)1108return -EMSGSIZE;11091110if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x)))1111return -EFAULT;1112if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y)))1113return -EFAULT;11141115BEGIN_RING(7);11161117OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));1118OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |1119R128_GMC_DST_PITCH_OFFSET_CNTL |1120R128_GMC_BRUSH_NONE |1121(dev_priv->depth_fmt << 8) |1122R128_GMC_SRC_DATATYPE_COLOR |1123R128_ROP3_S |1124R128_DP_SRC_SOURCE_MEMORY |1125R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);11261127OUT_RING(dev_priv->depth_pitch_offset_c);1128OUT_RING(dev_priv->span_pitch_offset_c);11291130OUT_RING((x << 16) | y);1131OUT_RING((0 << 16) | 0);1132OUT_RING((count << 16) | 1);11331134ADVANCE_RING();11351136return 0;1137}11381139static int r128_cce_dispatch_read_pixels(struct drm_device *dev,1140drm_r128_depth_t *depth)1141{1142drm_r128_private_t *dev_priv = dev->dev_private;1143int count, *x, *y;1144int i, xbuf_size, ybuf_size;1145RING_LOCALS;1146DRM_DEBUG("\n");11471148count = depth->n;1149if (count > 4096 || count <= 0)1150return -EMSGSIZE;11511152if (count > dev_priv->depth_pitch)1153count = dev_priv->depth_pitch;11541155xbuf_size = count * sizeof(*x);1156ybuf_size = count * sizeof(*y);1157x = kmalloc(xbuf_size, GFP_KERNEL);1158if (x == NULL)1159return -ENOMEM;1160y = kmalloc(ybuf_size, GFP_KERNEL);1161if (y == NULL) {1162kfree(x);1163return -ENOMEM;1164}1165if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {1166kfree(x);1167kfree(y);1168return -EFAULT;1169}1170if (DRM_COPY_FROM_USER(y, depth->y, ybuf_size)) {1171kfree(x);1172kfree(y);1173return -EFAULT;1174}11751176for (i = 0; i < count; i++) {1177BEGIN_RING(7);11781179OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));1180OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |1181R128_GMC_DST_PITCH_OFFSET_CNTL |1182R128_GMC_BRUSH_NONE |1183(dev_priv->depth_fmt << 8) |1184R128_GMC_SRC_DATATYPE_COLOR |1185R128_ROP3_S |1186R128_DP_SRC_SOURCE_MEMORY |1187R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);11881189OUT_RING(dev_priv->depth_pitch_offset_c);1190OUT_RING(dev_priv->span_pitch_offset_c);11911192OUT_RING((x[i] << 16) | y[i]);1193OUT_RING((i << 16) | 0);1194OUT_RING((1 << 16) | 1);11951196ADVANCE_RING();1197}11981199kfree(x);1200kfree(y);12011202return 0;1203}12041205/* ================================================================1206* Polygon stipple1207*/12081209static void r128_cce_dispatch_stipple(struct drm_device *dev, u32 *stipple)1210{1211drm_r128_private_t *dev_priv = dev->dev_private;1212int i;1213RING_LOCALS;1214DRM_DEBUG("\n");12151216BEGIN_RING(33);12171218OUT_RING(CCE_PACKET0(R128_BRUSH_DATA0, 31));1219for (i = 0; i < 32; i++)1220OUT_RING(stipple[i]);12211222ADVANCE_RING();1223}12241225/* ================================================================1226* IOCTL functions1227*/12281229static int r128_cce_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)1230{1231drm_r128_private_t *dev_priv = dev->dev_private;1232drm_r128_sarea_t *sarea_priv;1233drm_r128_clear_t *clear = data;1234DRM_DEBUG("\n");12351236LOCK_TEST_WITH_RETURN(dev, file_priv);12371238DEV_INIT_TEST_WITH_RETURN(dev_priv);12391240RING_SPACE_TEST_WITH_RETURN(dev_priv);12411242sarea_priv = dev_priv->sarea_priv;12431244if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)1245sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;12461247r128_cce_dispatch_clear(dev, clear);1248COMMIT_RING();12491250/* Make sure we restore the 3D state next time.1251*/1252dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;12531254return 0;1255}12561257static int r128_do_init_pageflip(struct drm_device *dev)1258{1259drm_r128_private_t *dev_priv = dev->dev_private;1260DRM_DEBUG("\n");12611262dev_priv->crtc_offset = R128_READ(R128_CRTC_OFFSET);1263dev_priv->crtc_offset_cntl = R128_READ(R128_CRTC_OFFSET_CNTL);12641265R128_WRITE(R128_CRTC_OFFSET, dev_priv->front_offset);1266R128_WRITE(R128_CRTC_OFFSET_CNTL,1267dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL);12681269dev_priv->page_flipping = 1;1270dev_priv->current_page = 0;1271dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;12721273return 0;1274}12751276static int r128_do_cleanup_pageflip(struct drm_device *dev)1277{1278drm_r128_private_t *dev_priv = dev->dev_private;1279DRM_DEBUG("\n");12801281R128_WRITE(R128_CRTC_OFFSET, dev_priv->crtc_offset);1282R128_WRITE(R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl);12831284if (dev_priv->current_page != 0) {1285r128_cce_dispatch_flip(dev);1286COMMIT_RING();1287}12881289dev_priv->page_flipping = 0;1290return 0;1291}12921293/* Swapping and flipping are different operations, need different ioctls.1294* They can & should be intermixed to support multiple 3d windows.1295*/12961297static int r128_cce_flip(struct drm_device *dev, void *data, struct drm_file *file_priv)1298{1299drm_r128_private_t *dev_priv = dev->dev_private;1300DRM_DEBUG("\n");13011302LOCK_TEST_WITH_RETURN(dev, file_priv);13031304DEV_INIT_TEST_WITH_RETURN(dev_priv);13051306RING_SPACE_TEST_WITH_RETURN(dev_priv);13071308if (!dev_priv->page_flipping)1309r128_do_init_pageflip(dev);13101311r128_cce_dispatch_flip(dev);13121313COMMIT_RING();1314return 0;1315}13161317static int r128_cce_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)1318{1319drm_r128_private_t *dev_priv = dev->dev_private;1320drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;1321DRM_DEBUG("\n");13221323LOCK_TEST_WITH_RETURN(dev, file_priv);13241325DEV_INIT_TEST_WITH_RETURN(dev_priv);13261327RING_SPACE_TEST_WITH_RETURN(dev_priv);13281329if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)1330sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;13311332r128_cce_dispatch_swap(dev);1333dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |1334R128_UPLOAD_MASKS);13351336COMMIT_RING();1337return 0;1338}13391340static int r128_cce_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)1341{1342drm_r128_private_t *dev_priv = dev->dev_private;1343struct drm_device_dma *dma = dev->dma;1344struct drm_buf *buf;1345drm_r128_buf_priv_t *buf_priv;1346drm_r128_vertex_t *vertex = data;13471348LOCK_TEST_WITH_RETURN(dev, file_priv);13491350DEV_INIT_TEST_WITH_RETURN(dev_priv);13511352DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",1353DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard);13541355if (vertex->idx < 0 || vertex->idx >= dma->buf_count) {1356DRM_ERROR("buffer index %d (of %d max)\n",1357vertex->idx, dma->buf_count - 1);1358return -EINVAL;1359}1360if (vertex->prim < 0 ||1361vertex->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {1362DRM_ERROR("buffer prim %d\n", vertex->prim);1363return -EINVAL;1364}13651366RING_SPACE_TEST_WITH_RETURN(dev_priv);1367VB_AGE_TEST_WITH_RETURN(dev_priv);13681369buf = dma->buflist[vertex->idx];1370buf_priv = buf->dev_private;13711372if (buf->file_priv != file_priv) {1373DRM_ERROR("process %d using buffer owned by %p\n",1374DRM_CURRENTPID, buf->file_priv);1375return -EINVAL;1376}1377if (buf->pending) {1378DRM_ERROR("sending pending buffer %d\n", vertex->idx);1379return -EINVAL;1380}13811382buf->used = vertex->count;1383buf_priv->prim = vertex->prim;1384buf_priv->discard = vertex->discard;13851386r128_cce_dispatch_vertex(dev, buf);13871388COMMIT_RING();1389return 0;1390}13911392static int r128_cce_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)1393{1394drm_r128_private_t *dev_priv = dev->dev_private;1395struct drm_device_dma *dma = dev->dma;1396struct drm_buf *buf;1397drm_r128_buf_priv_t *buf_priv;1398drm_r128_indices_t *elts = data;1399int count;14001401LOCK_TEST_WITH_RETURN(dev, file_priv);14021403DEV_INIT_TEST_WITH_RETURN(dev_priv);14041405DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID,1406elts->idx, elts->start, elts->end, elts->discard);14071408if (elts->idx < 0 || elts->idx >= dma->buf_count) {1409DRM_ERROR("buffer index %d (of %d max)\n",1410elts->idx, dma->buf_count - 1);1411return -EINVAL;1412}1413if (elts->prim < 0 ||1414elts->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {1415DRM_ERROR("buffer prim %d\n", elts->prim);1416return -EINVAL;1417}14181419RING_SPACE_TEST_WITH_RETURN(dev_priv);1420VB_AGE_TEST_WITH_RETURN(dev_priv);14211422buf = dma->buflist[elts->idx];1423buf_priv = buf->dev_private;14241425if (buf->file_priv != file_priv) {1426DRM_ERROR("process %d using buffer owned by %p\n",1427DRM_CURRENTPID, buf->file_priv);1428return -EINVAL;1429}1430if (buf->pending) {1431DRM_ERROR("sending pending buffer %d\n", elts->idx);1432return -EINVAL;1433}14341435count = (elts->end - elts->start) / sizeof(u16);1436elts->start -= R128_INDEX_PRIM_OFFSET;14371438if (elts->start & 0x7) {1439DRM_ERROR("misaligned buffer 0x%x\n", elts->start);1440return -EINVAL;1441}1442if (elts->start < buf->used) {1443DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used);1444return -EINVAL;1445}14461447buf->used = elts->end;1448buf_priv->prim = elts->prim;1449buf_priv->discard = elts->discard;14501451r128_cce_dispatch_indices(dev, buf, elts->start, elts->end, count);14521453COMMIT_RING();1454return 0;1455}14561457static int r128_cce_blit(struct drm_device *dev, void *data, struct drm_file *file_priv)1458{1459struct drm_device_dma *dma = dev->dma;1460drm_r128_private_t *dev_priv = dev->dev_private;1461drm_r128_blit_t *blit = data;1462int ret;14631464LOCK_TEST_WITH_RETURN(dev, file_priv);14651466DEV_INIT_TEST_WITH_RETURN(dev_priv);14671468DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit->idx);14691470if (blit->idx < 0 || blit->idx >= dma->buf_count) {1471DRM_ERROR("buffer index %d (of %d max)\n",1472blit->idx, dma->buf_count - 1);1473return -EINVAL;1474}14751476RING_SPACE_TEST_WITH_RETURN(dev_priv);1477VB_AGE_TEST_WITH_RETURN(dev_priv);14781479ret = r128_cce_dispatch_blit(dev, file_priv, blit);14801481COMMIT_RING();1482return ret;1483}14841485static int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv)1486{1487drm_r128_private_t *dev_priv = dev->dev_private;1488drm_r128_depth_t *depth = data;1489int ret;14901491LOCK_TEST_WITH_RETURN(dev, file_priv);14921493DEV_INIT_TEST_WITH_RETURN(dev_priv);14941495RING_SPACE_TEST_WITH_RETURN(dev_priv);14961497ret = -EINVAL;1498switch (depth->func) {1499case R128_WRITE_SPAN:1500ret = r128_cce_dispatch_write_span(dev, depth);1501break;1502case R128_WRITE_PIXELS:1503ret = r128_cce_dispatch_write_pixels(dev, depth);1504break;1505case R128_READ_SPAN:1506ret = r128_cce_dispatch_read_span(dev, depth);1507break;1508case R128_READ_PIXELS:1509ret = r128_cce_dispatch_read_pixels(dev, depth);1510break;1511}15121513COMMIT_RING();1514return ret;1515}15161517static int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv)1518{1519drm_r128_private_t *dev_priv = dev->dev_private;1520drm_r128_stipple_t *stipple = data;1521u32 mask[32];15221523LOCK_TEST_WITH_RETURN(dev, file_priv);15241525DEV_INIT_TEST_WITH_RETURN(dev_priv);15261527if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32)))1528return -EFAULT;15291530RING_SPACE_TEST_WITH_RETURN(dev_priv);15311532r128_cce_dispatch_stipple(dev, mask);15331534COMMIT_RING();1535return 0;1536}15371538static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv)1539{1540drm_r128_private_t *dev_priv = dev->dev_private;1541struct drm_device_dma *dma = dev->dma;1542struct drm_buf *buf;1543drm_r128_buf_priv_t *buf_priv;1544drm_r128_indirect_t *indirect = data;1545#if 01546RING_LOCALS;1547#endif15481549LOCK_TEST_WITH_RETURN(dev, file_priv);15501551DEV_INIT_TEST_WITH_RETURN(dev_priv);15521553DRM_DEBUG("idx=%d s=%d e=%d d=%d\n",1554indirect->idx, indirect->start, indirect->end,1555indirect->discard);15561557if (indirect->idx < 0 || indirect->idx >= dma->buf_count) {1558DRM_ERROR("buffer index %d (of %d max)\n",1559indirect->idx, dma->buf_count - 1);1560return -EINVAL;1561}15621563buf = dma->buflist[indirect->idx];1564buf_priv = buf->dev_private;15651566if (buf->file_priv != file_priv) {1567DRM_ERROR("process %d using buffer owned by %p\n",1568DRM_CURRENTPID, buf->file_priv);1569return -EINVAL;1570}1571if (buf->pending) {1572DRM_ERROR("sending pending buffer %d\n", indirect->idx);1573return -EINVAL;1574}15751576if (indirect->start < buf->used) {1577DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",1578indirect->start, buf->used);1579return -EINVAL;1580}15811582RING_SPACE_TEST_WITH_RETURN(dev_priv);1583VB_AGE_TEST_WITH_RETURN(dev_priv);15841585buf->used = indirect->end;1586buf_priv->discard = indirect->discard;15871588#if 01589/* Wait for the 3D stream to idle before the indirect buffer1590* containing 2D acceleration commands is processed.1591*/1592BEGIN_RING(2);1593RADEON_WAIT_UNTIL_3D_IDLE();1594ADVANCE_RING();1595#endif15961597/* Dispatch the indirect buffer full of commands from the1598* X server. This is insecure and is thus only available to1599* privileged clients.1600*/1601r128_cce_dispatch_indirect(dev, buf, indirect->start, indirect->end);16021603COMMIT_RING();1604return 0;1605}16061607static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)1608{1609drm_r128_private_t *dev_priv = dev->dev_private;1610drm_r128_getparam_t *param = data;1611int value;16121613DEV_INIT_TEST_WITH_RETURN(dev_priv);16141615DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);16161617switch (param->param) {1618case R128_PARAM_IRQ_NR:1619value = drm_dev_to_irq(dev);1620break;1621default:1622return -EINVAL;1623}16241625if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {1626DRM_ERROR("copy_to_user\n");1627return -EFAULT;1628}16291630return 0;1631}16321633void r128_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)1634{1635if (dev->dev_private) {1636drm_r128_private_t *dev_priv = dev->dev_private;1637if (dev_priv->page_flipping)1638r128_do_cleanup_pageflip(dev);1639}1640}1641void r128_driver_lastclose(struct drm_device *dev)1642{1643r128_do_cleanup_cce(dev);1644}16451646struct drm_ioctl_desc r128_ioctls[] = {1647DRM_IOCTL_DEF_DRV(R128_INIT, r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),1648DRM_IOCTL_DEF_DRV(R128_CCE_START, r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),1649DRM_IOCTL_DEF_DRV(R128_CCE_STOP, r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),1650DRM_IOCTL_DEF_DRV(R128_CCE_RESET, r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),1651DRM_IOCTL_DEF_DRV(R128_CCE_IDLE, r128_cce_idle, DRM_AUTH),1652DRM_IOCTL_DEF_DRV(R128_RESET, r128_engine_reset, DRM_AUTH),1653DRM_IOCTL_DEF_DRV(R128_FULLSCREEN, r128_fullscreen, DRM_AUTH),1654DRM_IOCTL_DEF_DRV(R128_SWAP, r128_cce_swap, DRM_AUTH),1655DRM_IOCTL_DEF_DRV(R128_FLIP, r128_cce_flip, DRM_AUTH),1656DRM_IOCTL_DEF_DRV(R128_CLEAR, r128_cce_clear, DRM_AUTH),1657DRM_IOCTL_DEF_DRV(R128_VERTEX, r128_cce_vertex, DRM_AUTH),1658DRM_IOCTL_DEF_DRV(R128_INDICES, r128_cce_indices, DRM_AUTH),1659DRM_IOCTL_DEF_DRV(R128_BLIT, r128_cce_blit, DRM_AUTH),1660DRM_IOCTL_DEF_DRV(R128_DEPTH, r128_cce_depth, DRM_AUTH),1661DRM_IOCTL_DEF_DRV(R128_STIPPLE, r128_cce_stipple, DRM_AUTH),1662DRM_IOCTL_DEF_DRV(R128_INDIRECT, r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),1663DRM_IOCTL_DEF_DRV(R128_GETPARAM, r128_getparam, DRM_AUTH),1664};16651666int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls);166716681669