1/* r128_state.c -- State support for r128 -*- linux-c -*- 2 * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com 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 a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the next 15 * paragraph) shall be included in all copies or substantial portions of the 16 * Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 22 * 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 OTHER 24 * DEALINGS IN THE SOFTWARE. 25 * 26 * Authors: 27 * Gareth Hughes <gareth@valinux.com> 28 */ 29 30#include "r128.h" 31#include "drmP.h" 32#include "r128_drv.h" 33#include "drm.h" 34#include <linux/delay.h> 35 36 37/* ================================================================ 38 * CCE hardware state programming functions 39 */ 40 41static void r128_emit_clip_rects( drm_r128_private_t *dev_priv, 42 drm_clip_rect_t *boxes, int count ) 43{ 44 u32 aux_sc_cntl = 0x00000000; 45 RING_LOCALS; 46 DRM_DEBUG( " %s\n", __FUNCTION__ ); 47 48 BEGIN_RING( 17 ); 49 50 if ( count >= 1 ) { 51 OUT_RING( CCE_PACKET0( R128_AUX1_SC_LEFT, 3 ) ); 52 OUT_RING( boxes[0].x1 ); 53 OUT_RING( boxes[0].x2 - 1 ); 54 OUT_RING( boxes[0].y1 ); 55 OUT_RING( boxes[0].y2 - 1 ); 56 57 aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR); 58 } 59 if ( count >= 2 ) { 60 OUT_RING( CCE_PACKET0( R128_AUX2_SC_LEFT, 3 ) ); 61 OUT_RING( boxes[1].x1 ); 62 OUT_RING( boxes[1].x2 - 1 ); 63 OUT_RING( boxes[1].y1 ); 64 OUT_RING( boxes[1].y2 - 1 ); 65 66 aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR); 67 } 68 if ( count >= 3 ) { 69 OUT_RING( CCE_PACKET0( R128_AUX3_SC_LEFT, 3 ) ); 70 OUT_RING( boxes[2].x1 ); 71 OUT_RING( boxes[2].x2 - 1 ); 72 OUT_RING( boxes[2].y1 ); 73 OUT_RING( boxes[2].y2 - 1 ); 74 75 aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR); 76 } 77 78 OUT_RING( CCE_PACKET0( R128_AUX_SC_CNTL, 0 ) ); 79 OUT_RING( aux_sc_cntl ); 80 81 ADVANCE_RING(); 82} 83 84static inline void r128_emit_core( drm_r128_private_t *dev_priv ) 85{ 86 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 87 drm_r128_context_regs_t *ctx = &sarea_priv->context_state; 88 RING_LOCALS; 89 DRM_DEBUG( " %s\n", __FUNCTION__ ); 90 91 BEGIN_RING( 2 ); 92 93 OUT_RING( CCE_PACKET0( R128_SCALE_3D_CNTL, 0 ) ); 94 OUT_RING( ctx->scale_3d_cntl ); 95 96 ADVANCE_RING(); 97} 98 99static inline void r128_emit_context( drm_r128_private_t *dev_priv ) 100{ 101 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 102 drm_r128_context_regs_t *ctx = &sarea_priv->context_state; 103 RING_LOCALS; 104 DRM_DEBUG( " %s\n", __FUNCTION__ ); 105 106 BEGIN_RING( 13 ); 107 108 OUT_RING( CCE_PACKET0( R128_DST_PITCH_OFFSET_C, 11 ) ); 109 OUT_RING( ctx->dst_pitch_offset_c ); 110 OUT_RING( ctx->dp_gui_master_cntl_c ); 111 OUT_RING( ctx->sc_top_left_c ); 112 OUT_RING( ctx->sc_bottom_right_c ); 113 OUT_RING( ctx->z_offset_c ); 114 OUT_RING( ctx->z_pitch_c ); 115 OUT_RING( ctx->z_sten_cntl_c ); 116 OUT_RING( ctx->tex_cntl_c ); 117 OUT_RING( ctx->misc_3d_state_cntl_reg ); 118 OUT_RING( ctx->texture_clr_cmp_clr_c ); 119 OUT_RING( ctx->texture_clr_cmp_msk_c ); 120 OUT_RING( ctx->fog_color_c ); 121 122 ADVANCE_RING(); 123} 124 125static inline void r128_emit_setup( drm_r128_private_t *dev_priv ) 126{ 127 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 128 drm_r128_context_regs_t *ctx = &sarea_priv->context_state; 129 RING_LOCALS; 130 DRM_DEBUG( " %s\n", __FUNCTION__ ); 131 132 BEGIN_RING( 3 ); 133 134 OUT_RING( CCE_PACKET1( R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP ) ); 135 OUT_RING( ctx->setup_cntl ); 136 OUT_RING( ctx->pm4_vc_fpu_setup ); 137 138 ADVANCE_RING(); 139} 140 141static inline void r128_emit_masks( drm_r128_private_t *dev_priv ) 142{ 143 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 144 drm_r128_context_regs_t *ctx = &sarea_priv->context_state; 145 RING_LOCALS; 146 DRM_DEBUG( " %s\n", __FUNCTION__ ); 147 148 BEGIN_RING( 5 ); 149 150 OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) ); 151 OUT_RING( ctx->dp_write_mask ); 152 153 OUT_RING( CCE_PACKET0( R128_STEN_REF_MASK_C, 1 ) ); 154 OUT_RING( ctx->sten_ref_mask_c ); 155 OUT_RING( ctx->plane_3d_mask_c ); 156 157 ADVANCE_RING(); 158} 159 160static inline void r128_emit_window( drm_r128_private_t *dev_priv ) 161{ 162 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 163 drm_r128_context_regs_t *ctx = &sarea_priv->context_state; 164 RING_LOCALS; 165 DRM_DEBUG( " %s\n", __FUNCTION__ ); 166 167 BEGIN_RING( 2 ); 168 169 OUT_RING( CCE_PACKET0( R128_WINDOW_XY_OFFSET, 0 ) ); 170 OUT_RING( ctx->window_xy_offset ); 171 172 ADVANCE_RING(); 173} 174 175static inline void r128_emit_tex0( drm_r128_private_t *dev_priv ) 176{ 177 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 178 drm_r128_context_regs_t *ctx = &sarea_priv->context_state; 179 drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0]; 180 int i; 181 RING_LOCALS; 182 DRM_DEBUG( " %s\n", __FUNCTION__ ); 183 184 BEGIN_RING( 7 + R128_MAX_TEXTURE_LEVELS ); 185 186 OUT_RING( CCE_PACKET0( R128_PRIM_TEX_CNTL_C, 187 2 + R128_MAX_TEXTURE_LEVELS ) ); 188 OUT_RING( tex->tex_cntl ); 189 OUT_RING( tex->tex_combine_cntl ); 190 OUT_RING( ctx->tex_size_pitch_c ); 191 for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) { 192 OUT_RING( tex->tex_offset[i] ); 193 } 194 195 OUT_RING( CCE_PACKET0( R128_CONSTANT_COLOR_C, 1 ) ); 196 OUT_RING( ctx->constant_color_c ); 197 OUT_RING( tex->tex_border_color ); 198 199 ADVANCE_RING(); 200} 201 202static inline void r128_emit_tex1( drm_r128_private_t *dev_priv ) 203{ 204 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 205 drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1]; 206 int i; 207 RING_LOCALS; 208 DRM_DEBUG( " %s\n", __FUNCTION__ ); 209 210 BEGIN_RING( 5 + R128_MAX_TEXTURE_LEVELS ); 211 212 OUT_RING( CCE_PACKET0( R128_SEC_TEX_CNTL_C, 213 1 + R128_MAX_TEXTURE_LEVELS ) ); 214 OUT_RING( tex->tex_cntl ); 215 OUT_RING( tex->tex_combine_cntl ); 216 for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) { 217 OUT_RING( tex->tex_offset[i] ); 218 } 219 220 OUT_RING( CCE_PACKET0( R128_SEC_TEXTURE_BORDER_COLOR_C, 0 ) ); 221 OUT_RING( tex->tex_border_color ); 222 223 ADVANCE_RING(); 224} 225 226static inline void r128_emit_state( drm_r128_private_t *dev_priv ) 227{ 228 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 229 unsigned int dirty = sarea_priv->dirty; 230 231 DRM_DEBUG( "%s: dirty=0x%08x\n", __FUNCTION__, dirty ); 232 233 if ( dirty & R128_UPLOAD_CORE ) { 234 r128_emit_core( dev_priv ); 235 sarea_priv->dirty &= ~R128_UPLOAD_CORE; 236 } 237 238 if ( dirty & R128_UPLOAD_CONTEXT ) { 239 r128_emit_context( dev_priv ); 240 sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT; 241 } 242 243 if ( dirty & R128_UPLOAD_SETUP ) { 244 r128_emit_setup( dev_priv ); 245 sarea_priv->dirty &= ~R128_UPLOAD_SETUP; 246 } 247 248 if ( dirty & R128_UPLOAD_MASKS ) { 249 r128_emit_masks( dev_priv ); 250 sarea_priv->dirty &= ~R128_UPLOAD_MASKS; 251 } 252 253 if ( dirty & R128_UPLOAD_WINDOW ) { 254 r128_emit_window( dev_priv ); 255 sarea_priv->dirty &= ~R128_UPLOAD_WINDOW; 256 } 257 258 if ( dirty & R128_UPLOAD_TEX0 ) { 259 r128_emit_tex0( dev_priv ); 260 sarea_priv->dirty &= ~R128_UPLOAD_TEX0; 261 } 262 263 if ( dirty & R128_UPLOAD_TEX1 ) { 264 r128_emit_tex1( dev_priv ); 265 sarea_priv->dirty &= ~R128_UPLOAD_TEX1; 266 } 267 268 /* Turn off the texture cache flushing */ 269 sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH; 270 271 sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE; 272} 273 274 275#if R128_PERFORMANCE_BOXES 276/* ================================================================ 277 * Performance monitoring functions 278 */ 279 280static void r128_clear_box( drm_r128_private_t *dev_priv, 281 int x, int y, int w, int h, 282 int r, int g, int b ) 283{ 284 u32 pitch, offset; 285 u32 fb_bpp, color; 286 RING_LOCALS; 287 288 switch ( dev_priv->fb_bpp ) { 289 case 16: 290 fb_bpp = R128_GMC_DST_16BPP; 291 color = (((r & 0xf8) << 8) | 292 ((g & 0xfc) << 3) | 293 ((b & 0xf8) >> 3)); 294 break; 295 case 24: 296 fb_bpp = R128_GMC_DST_24BPP; 297 color = ((r << 16) | (g << 8) | b); 298 break; 299 case 32: 300 fb_bpp = R128_GMC_DST_32BPP; 301 color = (((0xff) << 24) | (r << 16) | (g << 8) | b); 302 break; 303 default: 304 return; 305 } 306 307 offset = dev_priv->back_offset; 308 pitch = dev_priv->back_pitch >> 3; 309 310 BEGIN_RING( 6 ); 311 312 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); 313 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL | 314 R128_GMC_BRUSH_SOLID_COLOR | 315 fb_bpp | 316 R128_GMC_SRC_DATATYPE_COLOR | 317 R128_ROP3_P | 318 R128_GMC_CLR_CMP_CNTL_DIS | 319 R128_GMC_AUX_CLIP_DIS ); 320 321 OUT_RING( (pitch << 21) | (offset >> 5) ); 322 OUT_RING( color ); 323 324 OUT_RING( (x << 16) | y ); 325 OUT_RING( (w << 16) | h ); 326 327 ADVANCE_RING(); 328} 329 330static void r128_cce_performance_boxes( drm_r128_private_t *dev_priv ) 331{ 332 if ( atomic_read( &dev_priv->idle_count ) == 0 ) { 333 r128_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 ); 334 } else { 335 atomic_set( &dev_priv->idle_count, 0 ); 336 } 337} 338 339#endif 340 341 342/* ================================================================ 343 * CCE command dispatch functions 344 */ 345 346static void r128_print_dirty( const char *msg, unsigned int flags ) 347{ 348 DRM_INFO( "%s: (0x%x) %s%s%s%s%s%s%s%s%s\n", 349 msg, 350 flags, 351 (flags & R128_UPLOAD_CORE) ? "core, " : "", 352 (flags & R128_UPLOAD_CONTEXT) ? "context, " : "", 353 (flags & R128_UPLOAD_SETUP) ? "setup, " : "", 354 (flags & R128_UPLOAD_TEX0) ? "tex0, " : "", 355 (flags & R128_UPLOAD_TEX1) ? "tex1, " : "", 356 (flags & R128_UPLOAD_MASKS) ? "masks, " : "", 357 (flags & R128_UPLOAD_WINDOW) ? "window, " : "", 358 (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "", 359 (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "" ); 360} 361 362static void r128_cce_dispatch_clear( drm_device_t *dev, 363 drm_r128_clear_t *clear ) 364{ 365 drm_r128_private_t *dev_priv = dev->dev_private; 366 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 367 int nbox = sarea_priv->nbox; 368 drm_clip_rect_t *pbox = sarea_priv->boxes; 369 unsigned int flags = clear->flags; 370 int i; 371 RING_LOCALS; 372 DRM_DEBUG( "%s\n", __FUNCTION__ ); 373 374 if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) { 375 unsigned int tmp = flags; 376 377 flags &= ~(R128_FRONT | R128_BACK); 378 if ( tmp & R128_FRONT ) flags |= R128_BACK; 379 if ( tmp & R128_BACK ) flags |= R128_FRONT; 380 } 381 382 for ( i = 0 ; i < nbox ; i++ ) { 383 int x = pbox[i].x1; 384 int y = pbox[i].y1; 385 int w = pbox[i].x2 - x; 386 int h = pbox[i].y2 - y; 387 388 DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n", 389 pbox[i].x1, pbox[i].y1, pbox[i].x2, 390 pbox[i].y2, flags ); 391 392 if ( flags & (R128_FRONT | R128_BACK) ) { 393 BEGIN_RING( 2 ); 394 395 OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) ); 396 OUT_RING( clear->color_mask ); 397 398 ADVANCE_RING(); 399 } 400 401 if ( flags & R128_FRONT ) { 402 BEGIN_RING( 6 ); 403 404 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); 405 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL | 406 R128_GMC_BRUSH_SOLID_COLOR | 407 (dev_priv->color_fmt << 8) | 408 R128_GMC_SRC_DATATYPE_COLOR | 409 R128_ROP3_P | 410 R128_GMC_CLR_CMP_CNTL_DIS | 411 R128_GMC_AUX_CLIP_DIS ); 412 413 OUT_RING( dev_priv->front_pitch_offset_c ); 414 OUT_RING( clear->clear_color ); 415 416 OUT_RING( (x << 16) | y ); 417 OUT_RING( (w << 16) | h ); 418 419 ADVANCE_RING(); 420 } 421 422 if ( flags & R128_BACK ) { 423 BEGIN_RING( 6 ); 424 425 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); 426 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL | 427 R128_GMC_BRUSH_SOLID_COLOR | 428 (dev_priv->color_fmt << 8) | 429 R128_GMC_SRC_DATATYPE_COLOR | 430 R128_ROP3_P | 431 R128_GMC_CLR_CMP_CNTL_DIS | 432 R128_GMC_AUX_CLIP_DIS ); 433 434 OUT_RING( dev_priv->back_pitch_offset_c ); 435 OUT_RING( clear->clear_color ); 436 437 OUT_RING( (x << 16) | y ); 438 OUT_RING( (w << 16) | h ); 439 440 ADVANCE_RING(); 441 } 442 443 if ( flags & R128_DEPTH ) { 444 BEGIN_RING( 6 ); 445 446 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); 447 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL | 448 R128_GMC_BRUSH_SOLID_COLOR | 449 (dev_priv->depth_fmt << 8) | 450 R128_GMC_SRC_DATATYPE_COLOR | 451 R128_ROP3_P | 452 R128_GMC_CLR_CMP_CNTL_DIS | 453 R128_GMC_AUX_CLIP_DIS | 454 R128_GMC_WR_MSK_DIS ); 455 456 OUT_RING( dev_priv->depth_pitch_offset_c ); 457 OUT_RING( clear->clear_depth ); 458 459 OUT_RING( (x << 16) | y ); 460 OUT_RING( (w << 16) | h ); 461 462 ADVANCE_RING(); 463 } 464 } 465} 466 467static void r128_cce_dispatch_swap( drm_device_t *dev ) 468{ 469 drm_r128_private_t *dev_priv = dev->dev_private; 470 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 471 int nbox = sarea_priv->nbox; 472 drm_clip_rect_t *pbox = sarea_priv->boxes; 473 int i; 474 RING_LOCALS; 475 DRM_DEBUG( "%s\n", __FUNCTION__ ); 476 477#if R128_PERFORMANCE_BOXES 478 /* Do some trivial performance monitoring... 479 */ 480 r128_cce_performance_boxes( dev_priv ); 481#endif 482 483 for ( i = 0 ; i < nbox ; i++ ) { 484 int x = pbox[i].x1; 485 int y = pbox[i].y1; 486 int w = pbox[i].x2 - x; 487 int h = pbox[i].y2 - y; 488 489 BEGIN_RING( 7 ); 490 491 OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) ); 492 OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL | 493 R128_GMC_DST_PITCH_OFFSET_CNTL | 494 R128_GMC_BRUSH_NONE | 495 (dev_priv->color_fmt << 8) | 496 R128_GMC_SRC_DATATYPE_COLOR | 497 R128_ROP3_S | 498 R128_DP_SRC_SOURCE_MEMORY | 499 R128_GMC_CLR_CMP_CNTL_DIS | 500 R128_GMC_AUX_CLIP_DIS | 501 R128_GMC_WR_MSK_DIS ); 502 503 OUT_RING( dev_priv->back_pitch_offset_c ); 504 OUT_RING( dev_priv->front_pitch_offset_c ); 505 506 OUT_RING( (x << 16) | y ); 507 OUT_RING( (x << 16) | y ); 508 OUT_RING( (w << 16) | h ); 509 510 ADVANCE_RING(); 511 } 512 513 /* Increment the frame counter. The client-side 3D driver must 514 * throttle the framerate by waiting for this value before 515 * performing the swapbuffer ioctl. 516 */ 517 dev_priv->sarea_priv->last_frame++; 518 519 BEGIN_RING( 2 ); 520 521 OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) ); 522 OUT_RING( dev_priv->sarea_priv->last_frame ); 523 524 ADVANCE_RING(); 525} 526 527static void r128_cce_dispatch_flip( drm_device_t *dev ) 528{ 529 drm_r128_private_t *dev_priv = dev->dev_private; 530 RING_LOCALS; 531 DRM_DEBUG( "%s: page=%d\n", __FUNCTION__, dev_priv->current_page ); 532 533#if R128_PERFORMANCE_BOXES 534 /* Do some trivial performance monitoring... 535 */ 536 r128_cce_performance_boxes( dev_priv ); 537#endif 538 539 BEGIN_RING( 4 ); 540 541 R128_WAIT_UNTIL_PAGE_FLIPPED(); 542 OUT_RING( CCE_PACKET0( R128_CRTC_OFFSET, 0 ) ); 543 544 if ( dev_priv->current_page == 0 ) { 545 OUT_RING( dev_priv->back_offset ); 546 dev_priv->current_page = 1; 547 } else { 548 OUT_RING( dev_priv->front_offset ); 549 dev_priv->current_page = 0; 550 } 551 552 ADVANCE_RING(); 553 554 /* Increment the frame counter. The client-side 3D driver must 555 * throttle the framerate by waiting for this value before 556 * performing the swapbuffer ioctl. 557 */ 558 dev_priv->sarea_priv->last_frame++; 559 560 BEGIN_RING( 2 ); 561 562 OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) ); 563 OUT_RING( dev_priv->sarea_priv->last_frame ); 564 565 ADVANCE_RING(); 566} 567 568static void r128_cce_dispatch_vertex( drm_device_t *dev, 569 drm_buf_t *buf ) 570{ 571 drm_r128_private_t *dev_priv = dev->dev_private; 572 drm_r128_buf_priv_t *buf_priv = buf->dev_private; 573 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 574 int format = sarea_priv->vc_format; 575 int offset = buf->bus_address; 576 int size = buf->used; 577 int prim = buf_priv->prim; 578 int i = 0; 579 RING_LOCALS; 580 DRM_DEBUG( "%s: buf=%d nbox=%d\n", 581 __FUNCTION__, buf->idx, sarea_priv->nbox ); 582 583 if ( 0 ) 584 r128_print_dirty( "dispatch_vertex", sarea_priv->dirty ); 585 586 if ( buf->used ) { 587 buf_priv->dispatched = 1; 588 589 if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) { 590 r128_emit_state( dev_priv ); 591 } 592 593 do { 594 /* Emit the next set of up to three cliprects */ 595 if ( i < sarea_priv->nbox ) { 596 r128_emit_clip_rects( dev_priv, 597 &sarea_priv->boxes[i], 598 sarea_priv->nbox - i ); 599 } 600 601 /* Emit the vertex buffer rendering commands */ 602 BEGIN_RING( 5 ); 603 604 OUT_RING( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM, 3 ) ); 605 OUT_RING( offset ); 606 OUT_RING( size ); 607 OUT_RING( format ); 608 OUT_RING( prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST | 609 (size << R128_CCE_VC_CNTL_NUM_SHIFT) ); 610 611 ADVANCE_RING(); 612 613 i += 3; 614 } while ( i < sarea_priv->nbox ); 615 } 616 617 if ( buf_priv->discard ) { 618 buf_priv->age = dev_priv->sarea_priv->last_dispatch; 619 620 /* Emit the vertex buffer age */ 621 BEGIN_RING( 2 ); 622 623 OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) ); 624 OUT_RING( buf_priv->age ); 625 626 ADVANCE_RING(); 627 628 buf->pending = 1; 629 buf->used = 0; 630 buf_priv->dispatched = 0; 631 } 632 633 dev_priv->sarea_priv->last_dispatch++; 634 635 sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS; 636 sarea_priv->nbox = 0; 637} 638 639static void r128_cce_dispatch_indirect( drm_device_t *dev, 640 drm_buf_t *buf, 641 int start, int end ) 642{ 643 drm_r128_private_t *dev_priv = dev->dev_private; 644 drm_r128_buf_priv_t *buf_priv = buf->dev_private; 645 RING_LOCALS; 646 DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n", 647 buf->idx, start, end ); 648 649 if ( start != end ) { 650 int offset = buf->bus_address + start; 651 int dwords = (end - start + 3) / sizeof(u32); 652 653 /* Indirect buffer data must be an even number of 654 * dwords, so if we've been given an odd number we must 655 * pad the data with a Type-2 CCE packet. 656 */ 657 if ( dwords & 1 ) { 658 u32 *data = (u32 *) 659 ((char *)dev_priv->buffers->handle 660 + buf->offset + start); 661 data[dwords++] = cpu_to_le32( R128_CCE_PACKET2 ); 662 } 663 664 buf_priv->dispatched = 1; 665 666 /* Fire off the indirect buffer */ 667 BEGIN_RING( 3 ); 668 669 OUT_RING( CCE_PACKET0( R128_PM4_IW_INDOFF, 1 ) ); 670 OUT_RING( offset ); 671 OUT_RING( dwords ); 672 673 ADVANCE_RING(); 674 } 675 676 if ( buf_priv->discard ) { 677 buf_priv->age = dev_priv->sarea_priv->last_dispatch; 678 679 /* Emit the indirect buffer age */ 680 BEGIN_RING( 2 ); 681 682 OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) ); 683 OUT_RING( buf_priv->age ); 684 685 ADVANCE_RING(); 686 687 buf->pending = 1; 688 buf->used = 0; 689 buf_priv->dispatched = 0; 690 } 691 692 dev_priv->sarea_priv->last_dispatch++; 693} 694 695static void r128_cce_dispatch_indices( drm_device_t *dev, 696 drm_buf_t *buf, 697 int start, int end, 698 int count ) 699{ 700 drm_r128_private_t *dev_priv = dev->dev_private; 701 drm_r128_buf_priv_t *buf_priv = buf->dev_private; 702 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 703 int format = sarea_priv->vc_format; 704 int offset = dev_priv->buffers->offset - dev_priv->cce_buffers_offset; 705 int prim = buf_priv->prim; 706 u32 *data; 707 int dwords; 708 int i = 0; 709 RING_LOCALS; 710 DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count ); 711 712 if ( 0 ) 713 r128_print_dirty( "dispatch_indices", sarea_priv->dirty ); 714 715 if ( start != end ) { 716 buf_priv->dispatched = 1; 717 718 if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) { 719 r128_emit_state( dev_priv ); 720 } 721 722 dwords = (end - start + 3) / sizeof(u32); 723 724 data = (u32 *)((char *)dev_priv->buffers->handle 725 + buf->offset + start); 726 727 data[0] = cpu_to_le32( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM, 728 dwords-2 ) ); 729 730 data[1] = cpu_to_le32( offset ); 731 data[2] = cpu_to_le32( R128_MAX_VB_VERTS ); 732 data[3] = cpu_to_le32( format ); 733 data[4] = cpu_to_le32( (prim | R128_CCE_VC_CNTL_PRIM_WALK_IND | 734 (count << 16)) ); 735 736 if ( count & 0x1 ) { 737#ifdef __LITTLE_ENDIAN 738 data[dwords-1] &= 0x0000ffff; 739#else 740 data[dwords-1] &= 0xffff0000; 741#endif 742 } 743 744 do { 745 /* Emit the next set of up to three cliprects */ 746 if ( i < sarea_priv->nbox ) { 747 r128_emit_clip_rects( dev_priv, 748 &sarea_priv->boxes[i], 749 sarea_priv->nbox - i ); 750 } 751 752 r128_cce_dispatch_indirect( dev, buf, start, end ); 753 754 i += 3; 755 } while ( i < sarea_priv->nbox ); 756 } 757 758 if ( buf_priv->discard ) { 759 buf_priv->age = dev_priv->sarea_priv->last_dispatch; 760 761 /* Emit the vertex buffer age */ 762 BEGIN_RING( 2 ); 763 764 OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) ); 765 OUT_RING( buf_priv->age ); 766 767 ADVANCE_RING(); 768 769 buf->pending = 1; 770 buf_priv->dispatched = 0; 771 } 772 773 dev_priv->sarea_priv->last_dispatch++; 774 775 sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS; 776 sarea_priv->nbox = 0; 777} 778 779static int r128_cce_dispatch_blit( drm_device_t *dev, 780 drm_r128_blit_t *blit ) 781{ 782 drm_r128_private_t *dev_priv = dev->dev_private; 783 drm_device_dma_t *dma = dev->dma; 784 drm_buf_t *buf; 785 drm_r128_buf_priv_t *buf_priv; 786 u32 *data; 787 int dword_shift, dwords; 788 RING_LOCALS; 789 DRM_DEBUG( "%s\n", __FUNCTION__ ); 790 791 /* The compiler won't optimize away a division by a variable, 792 * even if the only legal values are powers of two. Thus, we'll 793 * use a shift instead. 794 */ 795 switch ( blit->format ) { 796 case R128_DATATYPE_ARGB8888: 797 dword_shift = 0; 798 break; 799 case R128_DATATYPE_ARGB1555: 800 case R128_DATATYPE_RGB565: 801 case R128_DATATYPE_ARGB4444: 802 dword_shift = 1; 803 break; 804 case R128_DATATYPE_CI8: 805 case R128_DATATYPE_RGB8: 806 dword_shift = 2; 807 break; 808 default: 809 DRM_ERROR( "invalid blit format %d\n", blit->format ); 810 return -EINVAL; 811 } 812 813 /* Flush the pixel cache, and mark the contents as Read Invalid. 814 * This ensures no pixel data gets mixed up with the texture 815 * data from the host data blit, otherwise part of the texture 816 * image may be corrupted. 817 */ 818 BEGIN_RING( 2 ); 819 820 OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) ); 821 OUT_RING( R128_PC_RI_GUI | R128_PC_FLUSH_GUI ); 822 823 ADVANCE_RING(); 824 825 /* Dispatch the indirect buffer. 826 */ 827 buf = dma->buflist[blit->idx]; 828 buf_priv = buf->dev_private; 829 830 if ( buf->pid != current->pid ) { 831 DRM_ERROR( "process %d using buffer owned by %d\n", 832 current->pid, buf->pid ); 833 return -EINVAL; 834 } 835 if ( buf->pending ) { 836 DRM_ERROR( "sending pending buffer %d\n", blit->idx ); 837 return -EINVAL; 838 } 839 840 buf_priv->discard = 1; 841 842 dwords = (blit->width * blit->height) >> dword_shift; 843 844 data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset); 845 846 data[0] = cpu_to_le32( CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 ) ); 847 data[1] = cpu_to_le32( (R128_GMC_DST_PITCH_OFFSET_CNTL | 848 R128_GMC_BRUSH_NONE | 849 (blit->format << 8) | 850 R128_GMC_SRC_DATATYPE_COLOR | 851 R128_ROP3_S | 852 R128_DP_SRC_SOURCE_HOST_DATA | 853 R128_GMC_CLR_CMP_CNTL_DIS | 854 R128_GMC_AUX_CLIP_DIS | 855 R128_GMC_WR_MSK_DIS) ); 856 857 data[2] = cpu_to_le32( (blit->pitch << 21) | (blit->offset >> 5) ); 858 data[3] = cpu_to_le32( 0xffffffff ); 859 data[4] = cpu_to_le32( 0xffffffff ); 860 data[5] = cpu_to_le32( (blit->y << 16) | blit->x ); 861 data[6] = cpu_to_le32( (blit->height << 16) | blit->width ); 862 data[7] = cpu_to_le32( dwords ); 863 864 buf->used = (dwords + 8) * sizeof(u32); 865 866 r128_cce_dispatch_indirect( dev, buf, 0, buf->used ); 867 868 /* Flush the pixel cache after the blit completes. This ensures 869 * the texture data is written out to memory before rendering 870 * continues. 871 */ 872 BEGIN_RING( 2 ); 873 874 OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) ); 875 OUT_RING( R128_PC_FLUSH_GUI ); 876 877 ADVANCE_RING(); 878 879 return 0; 880} 881 882 883 884static int r128_cce_dispatch_write_span( drm_device_t *dev, 885 drm_r128_depth_t *depth ) 886{ 887 drm_r128_private_t *dev_priv = dev->dev_private; 888 int count, x, y; 889 u32 *buffer; 890 u8 *mask; 891 int i; 892 RING_LOCALS; 893 DRM_DEBUG( "%s\n", __FUNCTION__ ); 894 895 count = depth->n; 896 if ( copy_from_user( &x, depth->x, sizeof(x) ) ) { 897 return -EFAULT; 898 } 899 if ( copy_from_user( &y, depth->y, sizeof(y) ) ) { 900 return -EFAULT; 901 } 902 903 buffer = kmalloc( depth->n * sizeof(u32), GFP_KERNEL ); 904 if ( buffer == NULL ) 905 return -ENOMEM; 906 if ( copy_from_user( buffer, depth->buffer, 907 depth->n * sizeof(u32) ) ) { 908 kfree( buffer ); 909 return -EFAULT; 910 } 911 912 if ( depth->mask ) { 913 mask = kmalloc( depth->n * sizeof(u8), GFP_KERNEL ); 914 if ( mask == NULL ) { 915 kfree( buffer ); 916 return -ENOMEM; 917 } 918 if ( copy_from_user( mask, depth->mask, 919 depth->n * sizeof(u8) ) ) { 920 kfree( buffer ); 921 kfree( mask ); 922 return -EFAULT; 923 } 924 925 for ( i = 0 ; i < count ; i++, x++ ) { 926 if ( mask[i] ) { 927 BEGIN_RING( 6 ); 928 929 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); 930 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL | 931 R128_GMC_BRUSH_SOLID_COLOR | 932 (dev_priv->depth_fmt << 8) | 933 R128_GMC_SRC_DATATYPE_COLOR | 934 R128_ROP3_P | 935 R128_GMC_CLR_CMP_CNTL_DIS | 936 R128_GMC_WR_MSK_DIS ); 937 938 OUT_RING( dev_priv->depth_pitch_offset_c ); 939 OUT_RING( buffer[i] ); 940 941 OUT_RING( (x << 16) | y ); 942 OUT_RING( (1 << 16) | 1 ); 943 944 ADVANCE_RING(); 945 } 946 } 947 948 kfree( mask ); 949 } else { 950 for ( i = 0 ; i < count ; i++, x++ ) { 951 BEGIN_RING( 6 ); 952 953 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); 954 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL | 955 R128_GMC_BRUSH_SOLID_COLOR | 956 (dev_priv->depth_fmt << 8) | 957 R128_GMC_SRC_DATATYPE_COLOR | 958 R128_ROP3_P | 959 R128_GMC_CLR_CMP_CNTL_DIS | 960 R128_GMC_WR_MSK_DIS ); 961 962 OUT_RING( dev_priv->depth_pitch_offset_c ); 963 OUT_RING( buffer[i] ); 964 965 OUT_RING( (x << 16) | y ); 966 OUT_RING( (1 << 16) | 1 ); 967 968 ADVANCE_RING(); 969 } 970 } 971 972 kfree( buffer ); 973 974 return 0; 975} 976 977static int r128_cce_dispatch_write_pixels( drm_device_t *dev, 978 drm_r128_depth_t *depth ) 979{ 980 drm_r128_private_t *dev_priv = dev->dev_private; 981 int count, *x, *y; 982 u32 *buffer; 983 u8 *mask; 984 int i; 985 RING_LOCALS; 986 DRM_DEBUG( "%s\n", __FUNCTION__ ); 987 988 count = depth->n; 989 990 x = kmalloc( count * sizeof(*x), GFP_KERNEL ); 991 if ( x == NULL ) { 992 return -ENOMEM; 993 } 994 y = kmalloc( count * sizeof(*y), GFP_KERNEL ); 995 if ( y == NULL ) { 996 kfree( x ); 997 return -ENOMEM; 998 } 999 if ( copy_from_user( x, depth->x, count * sizeof(int) ) ) { 1000 kfree( x ); 1001 kfree( y ); 1002 return -EFAULT; 1003 } 1004 if ( copy_from_user( y, depth->y, count * sizeof(int) ) ) { 1005 kfree( x ); 1006 kfree( y ); 1007 return -EFAULT; 1008 } 1009 1010 buffer = kmalloc( depth->n * sizeof(u32), GFP_KERNEL ); 1011 if ( buffer == NULL ) { 1012 kfree( x ); 1013 kfree( y ); 1014 return -ENOMEM; 1015 } 1016 if ( copy_from_user( buffer, depth->buffer, 1017 depth->n * sizeof(u32) ) ) { 1018 kfree( x ); 1019 kfree( y ); 1020 kfree( buffer ); 1021 return -EFAULT; 1022 } 1023 1024 if ( depth->mask ) { 1025 mask = kmalloc( depth->n * sizeof(u8), GFP_KERNEL ); 1026 if ( mask == NULL ) { 1027 kfree( x ); 1028 kfree( y ); 1029 kfree( buffer ); 1030 return -ENOMEM; 1031 } 1032 if ( copy_from_user( mask, depth->mask, 1033 depth->n * sizeof(u8) ) ) { 1034 kfree( x ); 1035 kfree( y ); 1036 kfree( buffer ); 1037 kfree( mask ); 1038 return -EFAULT; 1039 } 1040 1041 for ( i = 0 ; i < count ; i++ ) { 1042 if ( mask[i] ) { 1043 BEGIN_RING( 6 ); 1044 1045 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); 1046 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL | 1047 R128_GMC_BRUSH_SOLID_COLOR | 1048 (dev_priv->depth_fmt << 8) | 1049 R128_GMC_SRC_DATATYPE_COLOR | 1050 R128_ROP3_P | 1051 R128_GMC_CLR_CMP_CNTL_DIS | 1052 R128_GMC_WR_MSK_DIS ); 1053 1054 OUT_RING( dev_priv->depth_pitch_offset_c ); 1055 OUT_RING( buffer[i] ); 1056 1057 OUT_RING( (x[i] << 16) | y[i] ); 1058 OUT_RING( (1 << 16) | 1 ); 1059 1060 ADVANCE_RING(); 1061 } 1062 } 1063 1064 kfree( mask ); 1065 } else { 1066 for ( i = 0 ; i < count ; i++ ) { 1067 BEGIN_RING( 6 ); 1068 1069 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); 1070 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL | 1071 R128_GMC_BRUSH_SOLID_COLOR | 1072 (dev_priv->depth_fmt << 8) | 1073 R128_GMC_SRC_DATATYPE_COLOR | 1074 R128_ROP3_P | 1075 R128_GMC_CLR_CMP_CNTL_DIS | 1076 R128_GMC_WR_MSK_DIS ); 1077 1078 OUT_RING( dev_priv->depth_pitch_offset_c ); 1079 OUT_RING( buffer[i] ); 1080 1081 OUT_RING( (x[i] << 16) | y[i] ); 1082 OUT_RING( (1 << 16) | 1 ); 1083 1084 ADVANCE_RING(); 1085 } 1086 } 1087 1088 kfree( x ); 1089 kfree( y ); 1090 kfree( buffer ); 1091 1092 return 0; 1093} 1094 1095static int r128_cce_dispatch_read_span( drm_device_t *dev, 1096 drm_r128_depth_t *depth ) 1097{ 1098 drm_r128_private_t *dev_priv = dev->dev_private; 1099 int count, x, y; 1100 RING_LOCALS; 1101 DRM_DEBUG( "%s\n", __FUNCTION__ ); 1102 1103 count = depth->n; 1104 if ( copy_from_user( &x, depth->x, sizeof(x) ) ) { 1105 return -EFAULT; 1106 } 1107 if ( copy_from_user( &y, depth->y, sizeof(y) ) ) { 1108 return -EFAULT; 1109 } 1110 1111 BEGIN_RING( 7 ); 1112 1113 OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) ); 1114 OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL | 1115 R128_GMC_DST_PITCH_OFFSET_CNTL | 1116 R128_GMC_BRUSH_NONE | 1117 (dev_priv->depth_fmt << 8) | 1118 R128_GMC_SRC_DATATYPE_COLOR | 1119 R128_ROP3_S | 1120 R128_DP_SRC_SOURCE_MEMORY | 1121 R128_GMC_CLR_CMP_CNTL_DIS | 1122 R128_GMC_WR_MSK_DIS ); 1123 1124 OUT_RING( dev_priv->depth_pitch_offset_c ); 1125 OUT_RING( dev_priv->span_pitch_offset_c ); 1126 1127 OUT_RING( (x << 16) | y ); 1128 OUT_RING( (0 << 16) | 0 ); 1129 OUT_RING( (count << 16) | 1 ); 1130 1131 ADVANCE_RING(); 1132 1133 return 0; 1134} 1135 1136static int r128_cce_dispatch_read_pixels( drm_device_t *dev, 1137 drm_r128_depth_t *depth ) 1138{ 1139 drm_r128_private_t *dev_priv = dev->dev_private; 1140 int count, *x, *y; 1141 int i; 1142 RING_LOCALS; 1143 DRM_DEBUG( "%s\n", __FUNCTION__ ); 1144 1145 count = depth->n; 1146 if ( count > dev_priv->depth_pitch ) { 1147 count = dev_priv->depth_pitch; 1148 } 1149 1150 x = kmalloc( count * sizeof(*x), GFP_KERNEL ); 1151 if ( x == NULL ) { 1152 return -ENOMEM; 1153 } 1154 y = kmalloc( count * sizeof(*y), GFP_KERNEL ); 1155 if ( y == NULL ) { 1156 kfree( x ); 1157 return -ENOMEM; 1158 } 1159 if ( copy_from_user( x, depth->x, count * sizeof(int) ) ) { 1160 kfree( x ); 1161 kfree( y ); 1162 return -EFAULT; 1163 } 1164 if ( copy_from_user( y, depth->y, count * sizeof(int) ) ) { 1165 kfree( x ); 1166 kfree( y ); 1167 return -EFAULT; 1168 } 1169 1170 for ( i = 0 ; i < count ; i++ ) { 1171 BEGIN_RING( 7 ); 1172 1173 OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) ); 1174 OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL | 1175 R128_GMC_DST_PITCH_OFFSET_CNTL | 1176 R128_GMC_BRUSH_NONE | 1177 (dev_priv->depth_fmt << 8) | 1178 R128_GMC_SRC_DATATYPE_COLOR | 1179 R128_ROP3_S | 1180 R128_DP_SRC_SOURCE_MEMORY | 1181 R128_GMC_CLR_CMP_CNTL_DIS | 1182 R128_GMC_WR_MSK_DIS ); 1183 1184 OUT_RING( dev_priv->depth_pitch_offset_c ); 1185 OUT_RING( dev_priv->span_pitch_offset_c ); 1186 1187 OUT_RING( (x[i] << 16) | y[i] ); 1188 OUT_RING( (i << 16) | 0 ); 1189 OUT_RING( (1 << 16) | 1 ); 1190 1191 ADVANCE_RING(); 1192 } 1193 1194 kfree( x ); 1195 kfree( y ); 1196 1197 return 0; 1198} 1199 1200 1201/* ================================================================ 1202 * Polygon stipple 1203 */ 1204 1205static void r128_cce_dispatch_stipple( drm_device_t *dev, u32 *stipple ) 1206{ 1207 drm_r128_private_t *dev_priv = dev->dev_private; 1208 int i; 1209 RING_LOCALS; 1210 DRM_DEBUG( "%s\n", __FUNCTION__ ); 1211 1212 BEGIN_RING( 33 ); 1213 1214 OUT_RING( CCE_PACKET0( R128_BRUSH_DATA0, 31 ) ); 1215 for ( i = 0 ; i < 32 ; i++ ) { 1216 OUT_RING( stipple[i] ); 1217 } 1218 1219 ADVANCE_RING(); 1220} 1221 1222 1223/* ================================================================ 1224 * IOCTL functions 1225 */ 1226 1227int r128_cce_clear( struct inode *inode, struct file *filp, 1228 unsigned int cmd, unsigned long arg ) 1229{ 1230 drm_file_t *priv = filp->private_data; 1231 drm_device_t *dev = priv->dev; 1232 drm_r128_private_t *dev_priv = dev->dev_private; 1233 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 1234 drm_r128_clear_t clear; 1235 DRM_DEBUG( "%s\n", __FUNCTION__ ); 1236 1237 LOCK_TEST_WITH_RETURN( dev ); 1238 1239 if ( copy_from_user( &clear, (drm_r128_clear_t *) arg, 1240 sizeof(clear) ) ) 1241 return -EFAULT; 1242 1243 RING_SPACE_TEST_WITH_RETURN( dev_priv ); 1244 1245 if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS ) 1246 sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; 1247 1248 r128_cce_dispatch_clear( dev, &clear ); 1249 1250 /* Make sure we restore the 3D state next time. 1251 */ 1252 dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS; 1253 1254 return 0; 1255} 1256 1257int r128_cce_swap( struct inode *inode, struct file *filp, 1258 unsigned int cmd, unsigned long arg ) 1259{ 1260 drm_file_t *priv = filp->private_data; 1261 drm_device_t *dev = priv->dev; 1262 drm_r128_private_t *dev_priv = dev->dev_private; 1263 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 1264 DRM_DEBUG( "%s\n", __FUNCTION__ ); 1265 1266 LOCK_TEST_WITH_RETURN( dev ); 1267 1268 RING_SPACE_TEST_WITH_RETURN( dev_priv ); 1269 1270 if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS ) 1271 sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; 1272 1273 if ( !dev_priv->page_flipping ) { 1274 r128_cce_dispatch_swap( dev ); 1275 dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT | 1276 R128_UPLOAD_MASKS); 1277 } else { 1278 r128_cce_dispatch_flip( dev ); 1279 } 1280 1281 return 0; 1282} 1283 1284int r128_cce_vertex( struct inode *inode, struct file *filp, 1285 unsigned int cmd, unsigned long arg ) 1286{ 1287 drm_file_t *priv = filp->private_data; 1288 drm_device_t *dev = priv->dev; 1289 drm_r128_private_t *dev_priv = dev->dev_private; 1290 drm_device_dma_t *dma = dev->dma; 1291 drm_buf_t *buf; 1292 drm_r128_buf_priv_t *buf_priv; 1293 drm_r128_vertex_t vertex; 1294 1295 LOCK_TEST_WITH_RETURN( dev ); 1296 1297 if ( !dev_priv ) { 1298 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); 1299 return -EINVAL; 1300 } 1301 1302 if ( copy_from_user( &vertex, (drm_r128_vertex_t *)arg, 1303 sizeof(vertex) ) ) 1304 return -EFAULT; 1305 1306 DRM_DEBUG( "%s: pid=%d index=%d count=%d discard=%d\n", 1307 __FUNCTION__, current->pid, 1308 vertex.idx, vertex.count, vertex.discard ); 1309 1310 if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) { 1311 DRM_ERROR( "buffer index %d (of %d max)\n", 1312 vertex.idx, dma->buf_count - 1 ); 1313 return -EINVAL; 1314 } 1315 if ( vertex.prim < 0 || 1316 vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) { 1317 DRM_ERROR( "buffer prim %d\n", vertex.prim ); 1318 return -EINVAL; 1319 } 1320 1321 RING_SPACE_TEST_WITH_RETURN( dev_priv ); 1322 VB_AGE_TEST_WITH_RETURN( dev_priv ); 1323 1324 buf = dma->buflist[vertex.idx]; 1325 buf_priv = buf->dev_private; 1326 1327 if ( buf->pid != current->pid ) { 1328 DRM_ERROR( "process %d using buffer owned by %d\n", 1329 current->pid, buf->pid ); 1330 return -EINVAL; 1331 } 1332 if ( buf->pending ) { 1333 DRM_ERROR( "sending pending buffer %d\n", vertex.idx ); 1334 return -EINVAL; 1335 } 1336 1337 buf->used = vertex.count; 1338 buf_priv->prim = vertex.prim; 1339 buf_priv->discard = vertex.discard; 1340 1341 r128_cce_dispatch_vertex( dev, buf ); 1342 1343 return 0; 1344} 1345 1346int r128_cce_indices( struct inode *inode, struct file *filp, 1347 unsigned int cmd, unsigned long arg ) 1348{ 1349 drm_file_t *priv = filp->private_data; 1350 drm_device_t *dev = priv->dev; 1351 drm_r128_private_t *dev_priv = dev->dev_private; 1352 drm_device_dma_t *dma = dev->dma; 1353 drm_buf_t *buf; 1354 drm_r128_buf_priv_t *buf_priv; 1355 drm_r128_indices_t elts; 1356 int count; 1357 1358 LOCK_TEST_WITH_RETURN( dev ); 1359 1360 if ( !dev_priv ) { 1361 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); 1362 return -EINVAL; 1363 } 1364 1365 if ( copy_from_user( &elts, (drm_r128_indices_t *)arg, 1366 sizeof(elts) ) ) 1367 return -EFAULT; 1368 1369 DRM_DEBUG( "%s: pid=%d buf=%d s=%d e=%d d=%d\n", 1370 __FUNCTION__, current->pid, 1371 elts.idx, elts.start, elts.end, elts.discard ); 1372 1373 if ( elts.idx < 0 || elts.idx >= dma->buf_count ) { 1374 DRM_ERROR( "buffer index %d (of %d max)\n", 1375 elts.idx, dma->buf_count - 1 ); 1376 return -EINVAL; 1377 } 1378 if ( elts.prim < 0 || 1379 elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) { 1380 DRM_ERROR( "buffer prim %d\n", elts.prim ); 1381 return -EINVAL; 1382 } 1383 1384 RING_SPACE_TEST_WITH_RETURN( dev_priv ); 1385 VB_AGE_TEST_WITH_RETURN( dev_priv ); 1386 1387 buf = dma->buflist[elts.idx]; 1388 buf_priv = buf->dev_private; 1389 1390 if ( buf->pid != current->pid ) { 1391 DRM_ERROR( "process %d using buffer owned by %d\n", 1392 current->pid, buf->pid ); 1393 return -EINVAL; 1394 } 1395 if ( buf->pending ) { 1396 DRM_ERROR( "sending pending buffer %d\n", elts.idx ); 1397 return -EINVAL; 1398 } 1399 1400 count = (elts.end - elts.start) / sizeof(u16); 1401 elts.start -= R128_INDEX_PRIM_OFFSET; 1402 1403 if ( elts.start & 0x7 ) { 1404 DRM_ERROR( "misaligned buffer 0x%x\n", elts.start ); 1405 return -EINVAL; 1406 } 1407 if ( elts.start < buf->used ) { 1408 DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used ); 1409 return -EINVAL; 1410 } 1411 1412 buf->used = elts.end; 1413 buf_priv->prim = elts.prim; 1414 buf_priv->discard = elts.discard; 1415 1416 r128_cce_dispatch_indices( dev, buf, elts.start, elts.end, count ); 1417 1418 return 0; 1419} 1420 1421int r128_cce_blit( struct inode *inode, struct file *filp, 1422 unsigned int cmd, unsigned long arg ) 1423{ 1424 drm_file_t *priv = filp->private_data; 1425 drm_device_t *dev = priv->dev; 1426 drm_device_dma_t *dma = dev->dma; 1427 drm_r128_private_t *dev_priv = dev->dev_private; 1428 drm_r128_blit_t blit; 1429 1430 LOCK_TEST_WITH_RETURN( dev ); 1431 1432 if ( copy_from_user( &blit, (drm_r128_blit_t *)arg, 1433 sizeof(blit) ) ) 1434 return -EFAULT; 1435 1436 DRM_DEBUG( "%s: pid=%d index=%d\n", 1437 __FUNCTION__, current->pid, blit.idx ); 1438 1439 if ( blit.idx < 0 || blit.idx >= dma->buf_count ) { 1440 DRM_ERROR( "buffer index %d (of %d max)\n", 1441 blit.idx, dma->buf_count - 1 ); 1442 return -EINVAL; 1443 } 1444 1445 RING_SPACE_TEST_WITH_RETURN( dev_priv ); 1446 VB_AGE_TEST_WITH_RETURN( dev_priv ); 1447 1448 return r128_cce_dispatch_blit( dev, &blit ); 1449} 1450 1451int r128_cce_depth( struct inode *inode, struct file *filp, 1452 unsigned int cmd, unsigned long arg ) 1453{ 1454 drm_file_t *priv = filp->private_data; 1455 drm_device_t *dev = priv->dev; 1456 drm_r128_private_t *dev_priv = dev->dev_private; 1457 drm_r128_depth_t depth; 1458 1459 LOCK_TEST_WITH_RETURN( dev ); 1460 1461 if ( copy_from_user( &depth, (drm_r128_depth_t *)arg, 1462 sizeof(depth) ) ) 1463 return -EFAULT; 1464 1465 RING_SPACE_TEST_WITH_RETURN( dev_priv ); 1466 1467 switch ( depth.func ) { 1468 case R128_WRITE_SPAN: 1469 return r128_cce_dispatch_write_span( dev, &depth ); 1470 case R128_WRITE_PIXELS: 1471 return r128_cce_dispatch_write_pixels( dev, &depth ); 1472 case R128_READ_SPAN: 1473 return r128_cce_dispatch_read_span( dev, &depth ); 1474 case R128_READ_PIXELS: 1475 return r128_cce_dispatch_read_pixels( dev, &depth ); 1476 } 1477 1478 return -EINVAL; 1479} 1480 1481int r128_cce_stipple( struct inode *inode, struct file *filp, 1482 unsigned int cmd, unsigned long arg ) 1483{ 1484 drm_file_t *priv = filp->private_data; 1485 drm_device_t *dev = priv->dev; 1486 drm_r128_private_t *dev_priv = dev->dev_private; 1487 drm_r128_stipple_t stipple; 1488 u32 mask[32]; 1489 1490 LOCK_TEST_WITH_RETURN( dev ); 1491 1492 if ( copy_from_user( &stipple, (drm_r128_stipple_t *)arg, 1493 sizeof(stipple) ) ) 1494 return -EFAULT; 1495 1496 if ( copy_from_user( &mask, stipple.mask, 1497 32 * sizeof(u32) ) ) 1498 return -EFAULT; 1499 1500 RING_SPACE_TEST_WITH_RETURN( dev_priv ); 1501 1502 r128_cce_dispatch_stipple( dev, mask ); 1503 1504 return 0; 1505} 1506 1507int r128_cce_indirect( struct inode *inode, struct file *filp, 1508 unsigned int cmd, unsigned long arg ) 1509{ 1510 drm_file_t *priv = filp->private_data; 1511 drm_device_t *dev = priv->dev; 1512 drm_r128_private_t *dev_priv = dev->dev_private; 1513 drm_device_dma_t *dma = dev->dma; 1514 drm_buf_t *buf; 1515 drm_r128_buf_priv_t *buf_priv; 1516 drm_r128_indirect_t indirect; 1517 1518 LOCK_TEST_WITH_RETURN( dev ); 1519 1520 if ( !dev_priv ) { 1521 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); 1522 return -EINVAL; 1523 } 1524 1525 if ( copy_from_user( &indirect, (drm_r128_indirect_t *)arg, 1526 sizeof(indirect) ) ) 1527 return -EFAULT; 1528 1529 DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n", 1530 indirect.idx, indirect.start, 1531 indirect.end, indirect.discard ); 1532 1533 if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) { 1534 DRM_ERROR( "buffer index %d (of %d max)\n", 1535 indirect.idx, dma->buf_count - 1 ); 1536 return -EINVAL; 1537 } 1538 1539 buf = dma->buflist[indirect.idx]; 1540 buf_priv = buf->dev_private; 1541 1542 if ( buf->pid != current->pid ) { 1543 DRM_ERROR( "process %d using buffer owned by %d\n", 1544 current->pid, buf->pid ); 1545 return -EINVAL; 1546 } 1547 if ( buf->pending ) { 1548 DRM_ERROR( "sending pending buffer %d\n", indirect.idx ); 1549 return -EINVAL; 1550 } 1551 1552 if ( indirect.start < buf->used ) { 1553 DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n", 1554 indirect.start, buf->used ); 1555 return -EINVAL; 1556 } 1557 1558 RING_SPACE_TEST_WITH_RETURN( dev_priv ); 1559 VB_AGE_TEST_WITH_RETURN( dev_priv ); 1560 1561 buf->used = indirect.end; 1562 buf_priv->discard = indirect.discard; 1563 1564 1565 /* Dispatch the indirect buffer full of commands from the 1566 * X server. This is insecure and is thus only available to 1567 * privileged clients. 1568 */ 1569 r128_cce_dispatch_indirect( dev, buf, indirect.start, indirect.end ); 1570 1571 return 0; 1572} 1573