r128_state.c
字号:
if (count > 4096 || count <= 0) return DRM_ERR(EMSGSIZE); if ( DRM_COPY_FROM_USER( &x, depth->x, sizeof(x) ) ) { return DRM_ERR(EFAULT); } if ( DRM_COPY_FROM_USER( &y, depth->y, sizeof(y) ) ) { return DRM_ERR(EFAULT); } BEGIN_RING( 7 ); OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) ); OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL | R128_GMC_DST_PITCH_OFFSET_CNTL | R128_GMC_BRUSH_NONE | (dev_priv->depth_fmt << 8) | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP3_S | R128_DP_SRC_SOURCE_MEMORY | R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS ); OUT_RING( dev_priv->depth_pitch_offset_c ); OUT_RING( dev_priv->span_pitch_offset_c ); OUT_RING( (x << 16) | y ); OUT_RING( (0 << 16) | 0 ); OUT_RING( (count << 16) | 1 ); ADVANCE_RING(); return 0;}static int r128_cce_dispatch_read_pixels( drm_device_t *dev, drm_r128_depth_t *depth ){ drm_r128_private_t *dev_priv = dev->dev_private; int count, *x, *y; int i, xbuf_size, ybuf_size; RING_LOCALS; DRM_DEBUG( "%s\n", __FUNCTION__ ); count = depth->n; if (count > 4096 || count <= 0) return DRM_ERR(EMSGSIZE); if ( count > dev_priv->depth_pitch ) { count = dev_priv->depth_pitch; } xbuf_size = count * sizeof(*x); ybuf_size = count * sizeof(*y); x = DRM_MALLOC( xbuf_size ); if ( x == NULL ) { return DRM_ERR(ENOMEM); } y = DRM_MALLOC( ybuf_size ); if ( y == NULL ) { DRM_FREE( x, xbuf_size ); return DRM_ERR(ENOMEM); } if ( DRM_COPY_FROM_USER( x, depth->x, xbuf_size ) ) { DRM_FREE( x, xbuf_size ); DRM_FREE( y, ybuf_size ); return DRM_ERR(EFAULT); } if ( DRM_COPY_FROM_USER( y, depth->y, ybuf_size ) ) { DRM_FREE( x, xbuf_size ); DRM_FREE( y, ybuf_size ); return DRM_ERR(EFAULT); } for ( i = 0 ; i < count ; i++ ) { BEGIN_RING( 7 ); OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) ); OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL | R128_GMC_DST_PITCH_OFFSET_CNTL | R128_GMC_BRUSH_NONE | (dev_priv->depth_fmt << 8) | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP3_S | R128_DP_SRC_SOURCE_MEMORY | R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS ); OUT_RING( dev_priv->depth_pitch_offset_c ); OUT_RING( dev_priv->span_pitch_offset_c ); OUT_RING( (x[i] << 16) | y[i] ); OUT_RING( (i << 16) | 0 ); OUT_RING( (1 << 16) | 1 ); ADVANCE_RING(); } DRM_FREE( x, xbuf_size ); DRM_FREE( y, ybuf_size ); return 0;}/* ================================================================ * Polygon stipple */static void r128_cce_dispatch_stipple( drm_device_t *dev, u32 *stipple ){ drm_r128_private_t *dev_priv = dev->dev_private; int i; RING_LOCALS; DRM_DEBUG( "%s\n", __FUNCTION__ ); BEGIN_RING( 33 ); OUT_RING( CCE_PACKET0( R128_BRUSH_DATA0, 31 ) ); for ( i = 0 ; i < 32 ; i++ ) { OUT_RING( stipple[i] ); } ADVANCE_RING();}/* ================================================================ * IOCTL functions */int r128_cce_clear( DRM_IOCTL_ARGS ){ DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_r128_clear_t clear; DRM_DEBUG( "\n" ); LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( clear, (drm_r128_clear_t __user *) data, sizeof(clear) ); RING_SPACE_TEST_WITH_RETURN( dev_priv ); if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS ) sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; r128_cce_dispatch_clear( dev, &clear ); COMMIT_RING(); /* Make sure we restore the 3D state next time. */ dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS; return 0;}static int r128_do_init_pageflip( drm_device_t *dev ){ drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "\n" ); dev_priv->crtc_offset = R128_READ( R128_CRTC_OFFSET ); dev_priv->crtc_offset_cntl = R128_READ( R128_CRTC_OFFSET_CNTL ); R128_WRITE( R128_CRTC_OFFSET, dev_priv->front_offset ); R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL ); dev_priv->page_flipping = 1; dev_priv->current_page = 0; dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page; return 0;}int r128_do_cleanup_pageflip( drm_device_t *dev ){ drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "\n" ); R128_WRITE( R128_CRTC_OFFSET, dev_priv->crtc_offset ); R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl ); if (dev_priv->current_page != 0) { r128_cce_dispatch_flip( dev ); COMMIT_RING(); } dev_priv->page_flipping = 0; return 0;}/* Swapping and flipping are different operations, need different ioctls. * They can & should be intermixed to support multiple 3d windows. */int r128_cce_flip( DRM_IOCTL_ARGS ){ DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "%s\n", __FUNCTION__ ); LOCK_TEST_WITH_RETURN( dev, filp ); RING_SPACE_TEST_WITH_RETURN( dev_priv ); if (!dev_priv->page_flipping) r128_do_init_pageflip( dev ); r128_cce_dispatch_flip( dev ); COMMIT_RING(); return 0;}int r128_cce_swap( DRM_IOCTL_ARGS ){ DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; DRM_DEBUG( "%s\n", __FUNCTION__ ); LOCK_TEST_WITH_RETURN( dev, filp ); RING_SPACE_TEST_WITH_RETURN( dev_priv ); if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS ) sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; r128_cce_dispatch_swap( dev ); dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS); COMMIT_RING(); return 0;}int r128_cce_vertex( DRM_IOCTL_ARGS ){ DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_r128_buf_priv_t *buf_priv; drm_r128_vertex_t vertex; LOCK_TEST_WITH_RETURN( dev, filp ); if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL( vertex, (drm_r128_vertex_t __user *) data, sizeof(vertex) ); DRM_DEBUG( "pid=%d index=%d count=%d discard=%d\n", DRM_CURRENTPID, vertex.idx, vertex.count, vertex.discard ); if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) { DRM_ERROR( "buffer index %d (of %d max)\n", vertex.idx, dma->buf_count - 1 ); return DRM_ERR(EINVAL); } if ( vertex.prim < 0 || vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) { DRM_ERROR( "buffer prim %d\n", vertex.prim ); return DRM_ERR(EINVAL); } RING_SPACE_TEST_WITH_RETURN( dev_priv ); VB_AGE_TEST_WITH_RETURN( dev_priv ); buf = dma->buflist[vertex.idx]; buf_priv = buf->dev_private; if ( buf->filp != filp ) { DRM_ERROR( "process %d using buffer owned by %p\n", DRM_CURRENTPID, buf->filp ); return DRM_ERR(EINVAL); } if ( buf->pending ) { DRM_ERROR( "sending pending buffer %d\n", vertex.idx ); return DRM_ERR(EINVAL); } buf->used = vertex.count; buf_priv->prim = vertex.prim; buf_priv->discard = vertex.discard; r128_cce_dispatch_vertex( dev, buf ); COMMIT_RING(); return 0;}int r128_cce_indices( DRM_IOCTL_ARGS ){ DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_r128_buf_priv_t *buf_priv; drm_r128_indices_t elts; int count; LOCK_TEST_WITH_RETURN( dev, filp ); if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL( elts, (drm_r128_indices_t __user *) data, sizeof(elts) ); DRM_DEBUG( "pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID, elts.idx, elts.start, elts.end, elts.discard ); if ( elts.idx < 0 || elts.idx >= dma->buf_count ) { DRM_ERROR( "buffer index %d (of %d max)\n", elts.idx, dma->buf_count - 1 ); return DRM_ERR(EINVAL); } if ( elts.prim < 0 || elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) { DRM_ERROR( "buffer prim %d\n", elts.prim ); return DRM_ERR(EINVAL); } RING_SPACE_TEST_WITH_RETURN( dev_priv ); VB_AGE_TEST_WITH_RETURN( dev_priv ); buf = dma->buflist[elts.idx]; buf_priv = buf->dev_private; if ( buf->filp != filp ) { DRM_ERROR( "process %d using buffer owned by %p\n", DRM_CURRENTPID, buf->filp ); return DRM_ERR(EINVAL); } if ( buf->pending ) { DRM_ERROR( "sending pending buffer %d\n", elts.idx ); return DRM_ERR(EINVAL); } count = (elts.end - elts.start) / sizeof(u16); elts.start -= R128_INDEX_PRIM_OFFSET; if ( elts.start & 0x7 ) { DRM_ERROR( "misaligned buffer 0x%x\n", elts.start ); return DRM_ERR(EINVAL); } if ( elts.start < buf->used ) { DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used ); return DRM_ERR(EINVAL); } buf->used = elts.end; buf_priv->prim = elts.prim; buf_priv->discard = elts.discard; r128_cce_dispatch_indices( dev, buf, elts.start, elts.end, count ); COMMIT_RING(); return 0;}int r128_cce_blit( DRM_IOCTL_ARGS ){ DRM_DEVICE; drm_device_dma_t *dma = dev->dma; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_blit_t blit; int ret; LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( blit, (drm_r128_blit_t __user *) data, sizeof(blit) ); DRM_DEBUG( "pid=%d index=%d\n", DRM_CURRENTPID, blit.idx ); if ( blit.idx < 0 || blit.idx >= dma->buf_count ) { DRM_ERROR( "buffer index %d (of %d max)\n", blit.idx, dma->buf_count - 1 ); return DRM_ERR(EINVAL); } RING_SPACE_TEST_WITH_RETURN( dev_priv ); VB_AGE_TEST_WITH_RETURN( dev_priv ); ret = r128_cce_dispatch_blit( filp, dev, &blit ); COMMIT_RING(); return ret;}int r128_cce_depth( DRM_IOCTL_ARGS ){ DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_depth_t depth; int ret; LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( depth, (drm_r128_depth_t __user *) data, sizeof(depth) ); RING_SPACE_TEST_WITH_RETURN( dev_priv ); ret = DRM_ERR(EINVAL); switch ( depth.func ) { case R128_WRITE_SPAN: ret = r128_cce_dispatch_write_span( dev, &depth ); case R128_WRITE_PIXELS: ret = r128_cce_dispatch_write_pixels( dev, &depth ); case R128_READ_SPAN: ret = r128_cce_dispatch_read_span( dev, &depth ); case R128_READ_PIXELS: ret = r128_cce_dispatch_read_pixels( dev, &depth ); } COMMIT_RING(); return ret;}int r128_cce_stipple( DRM_IOCTL_ARGS ){ DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_stipple_t stipple; u32 mask[32]; LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( stipple, (drm_r128_stipple_t __user *) data, sizeof(stipple) ); if ( DRM_COPY_FROM_USER( &mask, stipple.mask, 32 * sizeof(u32) ) ) return DRM_ERR( EFAULT ); RING_SPACE_TEST_WITH_RETURN( dev_priv ); r128_cce_dispatch_stipple( dev, mask ); COMMIT_RING(); return 0;}int r128_cce_indirect( DRM_IOCTL_ARGS ){ DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_r128_buf_priv_t *buf_priv; drm_r128_indirect_t indirect;#if 0 RING_LOCALS;#endif LOCK_TEST_WITH_RETURN( dev, filp ); if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL( indirect, (drm_r128_indirect_t __user *) data, sizeof(indirect) ); DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n", indirect.idx, indirect.start, indirect.end, indirect.discard ); if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) { DRM_ERROR( "buffer index %d (of %d max)\n", indirect.idx, dma->buf_count - 1 ); return DRM_ERR(EINVAL); } buf = dma->buflist[indirect.idx]; buf_priv = buf->dev_private; if ( buf->filp != filp ) { DRM_ERROR( "process %d using buffer owned by %p\n", DRM_CURRENTPID, buf->filp ); return DRM_ERR(EINVAL); } if ( buf->pending ) { DRM_ERROR( "sending pending buffer %d\n", indirect.idx ); return DRM_ERR(EINVAL); } if ( indirect.start < buf->used ) { DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n", indirect.start, buf->used ); return DRM_ERR(EINVAL); } RING_SPACE_TEST_WITH_RETURN( dev_priv ); VB_AGE_TEST_WITH_RETURN( dev_priv ); buf->used = indirect.end; buf_priv->discard = indirect.discard;#if 0 /* Wait for the 3D stream to idle before the indirect buffer * containing 2D acceleration commands is processed. */ BEGIN_RING( 2 ); RADEON_WAIT_UNTIL_3D_IDLE(); ADVANCE_RING();#endif /* Dispatch the indirect buffer full of commands from the * X server. This is insecure and is thus only available to * privileged clients. */ r128_cce_dispatch_indirect( dev, buf, indirect.start, indirect.end ); COMMIT_RING(); return 0;}int r128_getparam( DRM_IOCTL_ARGS ){ DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_getparam_t param; int value; if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL( param, (drm_r128_getparam_t __user *)data, sizeof(param) ); DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID ); switch( param.param ) { case R128_PARAM_IRQ_NR: value = dev->irq; break; default: return DRM_ERR(EINVAL); } if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) { DRM_ERROR( "copy_to_user\n" ); return DRM_ERR(EFAULT); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -