📄 radeon_cp.c
字号:
/* Turn off PCI GART */ tmp = RADEON_READ( RADEON_AIC_CNTL ) & ~RADEON_PCIGART_TRANSLATE_EN; RADEON_WRITE( RADEON_AIC_CNTL, tmp ); } radeon_cp_load_microcode( dev_priv ); radeon_cp_init_ring_buffer( dev, dev_priv );#if ROTATE_BUFS dev_priv->last_buf = 0;#endif dev->dev_private = (void *)dev_priv; radeon_do_engine_reset( dev ); return 0;}int radeon_do_cleanup_cp( drm_device_t *dev ){ DRM_DEBUG( "%s\n", __FUNCTION__ ); if ( dev->dev_private ) { drm_radeon_private_t *dev_priv = dev->dev_private; if ( !dev_priv->is_pci ) { DRM_IOREMAPFREE( dev_priv->cp_ring ); DRM_IOREMAPFREE( dev_priv->ring_rptr ); DRM_IOREMAPFREE( dev_priv->buffers ); } else { if (!DRM(ati_pcigart_cleanup)( dev, dev_priv->phys_pci_gart, dev_priv->bus_pci_gart )) DRM_ERROR( "failed to cleanup PCI GART!\n" ); } DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t), DRM_MEM_DRIVER ); dev->dev_private = NULL; } return 0;}int radeon_cp_init( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ){ drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_radeon_init_t init; if ( copy_from_user( &init, (drm_radeon_init_t *)arg, sizeof(init) ) ) return -EFAULT; switch ( init.func ) { case RADEON_INIT_CP: return radeon_do_init_cp( dev, &init ); case RADEON_CLEANUP_CP: return radeon_do_cleanup_cp( dev ); } return -EINVAL;}int radeon_cp_start( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ){ drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "%s\n", __FUNCTION__ ); LOCK_TEST_WITH_RETURN( dev ); if ( dev_priv->cp_running ) { DRM_DEBUG( "%s while CP running\n", __FUNCTION__ ); return 0; } if ( dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS ) { DRM_DEBUG( "%s called with bogus CP mode (%d)\n", __FUNCTION__, dev_priv->cp_mode ); return 0; } radeon_do_cp_start( dev_priv ); return 0;}/* Stop the CP. The engine must have been idled before calling this * routine. */int radeon_cp_stop( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ){ drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_cp_stop_t stop; int ret; DRM_DEBUG( "%s\n", __FUNCTION__ ); LOCK_TEST_WITH_RETURN( dev ); if ( copy_from_user( &stop, (drm_radeon_init_t *)arg, sizeof(stop) ) ) return -EFAULT; /* Flush any pending CP commands. This ensures any outstanding * commands are exectuted by the engine before we turn it off. */ if ( stop.flush ) { radeon_do_cp_flush( dev_priv ); } /* If we fail to make the engine go idle, we return an error * code so that the DRM ioctl wrapper can try again. */ if ( stop.idle ) { ret = radeon_do_cp_idle( dev_priv ); if ( ret < 0 ) return ret; } /* Finally, we can turn off the CP. If the engine isn't idle, * we will get some dropped triangles as they won't be fully * rendered before the CP is shut down. */ radeon_do_cp_stop( dev_priv ); /* Reset the engine */ radeon_do_engine_reset( dev ); return 0;}/* Just reset the CP ring. Called as part of an X Server engine reset. */int radeon_cp_reset( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ){ drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "%s\n", __FUNCTION__ ); LOCK_TEST_WITH_RETURN( dev ); if ( !dev_priv ) { DRM_DEBUG( "%s called before init done\n", __FUNCTION__ ); return -EINVAL; } radeon_do_cp_reset( dev_priv ); /* The CP is no longer running after an engine reset */ dev_priv->cp_running = 0; return 0;}int radeon_cp_idle( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ){ drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "%s\n", __FUNCTION__ ); LOCK_TEST_WITH_RETURN( dev ); return radeon_do_cp_idle( dev_priv );}int radeon_engine_reset( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ){ drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; DRM_DEBUG( "%s\n", __FUNCTION__ ); LOCK_TEST_WITH_RETURN( dev ); return radeon_do_engine_reset( dev );}/* ================================================================ * Fullscreen mode */static int radeon_do_init_pageflip( drm_device_t *dev ){ drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "%s\n", __FUNCTION__ ); dev_priv->crtc_offset = RADEON_READ( RADEON_CRTC_OFFSET ); dev_priv->crtc_offset_cntl = RADEON_READ( RADEON_CRTC_OFFSET_CNTL ); RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->front_offset ); RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl | RADEON_CRTC_OFFSET_FLIP_CNTL ); dev_priv->page_flipping = 1; dev_priv->current_page = 0; return 0;}int radeon_do_cleanup_pageflip( drm_device_t *dev ){ drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "%s\n", __FUNCTION__ ); RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->crtc_offset ); RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl ); dev_priv->page_flipping = 0; dev_priv->current_page = 0; return 0;}int radeon_fullscreen( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ){ drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_radeon_fullscreen_t fs; LOCK_TEST_WITH_RETURN( dev ); if ( copy_from_user( &fs, (drm_radeon_fullscreen_t *)arg, sizeof(fs) ) ) return -EFAULT; switch ( fs.func ) { case RADEON_INIT_FULLSCREEN: return radeon_do_init_pageflip( dev ); case RADEON_CLEANUP_FULLSCREEN: return radeon_do_cleanup_pageflip( dev ); } return -EINVAL;}/* ================================================================ * Freelist management */#define RADEON_BUFFER_USED 0xffffffff#define RADEON_BUFFER_FREE 0#if 0static int radeon_freelist_init( drm_device_t *dev ){ drm_device_dma_t *dma = dev->dma; drm_radeon_private_t *dev_priv = dev->dev_private; drm_buf_t *buf; drm_radeon_buf_priv_t *buf_priv; drm_radeon_freelist_t *entry; int i; dev_priv->head = DRM(alloc)( sizeof(drm_radeon_freelist_t), DRM_MEM_DRIVER ); if ( dev_priv->head == NULL ) return -ENOMEM; memset( dev_priv->head, 0, sizeof(drm_radeon_freelist_t) ); dev_priv->head->age = RADEON_BUFFER_USED; for ( i = 0 ; i < dma->buf_count ; i++ ) { buf = dma->buflist[i]; buf_priv = buf->dev_private; entry = DRM(alloc)( sizeof(drm_radeon_freelist_t), DRM_MEM_DRIVER ); if ( !entry ) return -ENOMEM; entry->age = RADEON_BUFFER_FREE; entry->buf = buf; entry->prev = dev_priv->head; entry->next = dev_priv->head->next; if ( !entry->next ) dev_priv->tail = entry; buf_priv->discard = 0; buf_priv->dispatched = 0; buf_priv->list_entry = entry; dev_priv->head->next = entry; if ( dev_priv->head->next ) dev_priv->head->next->prev = entry; } return 0;}#endifdrm_buf_t *radeon_freelist_get( drm_device_t *dev ){ drm_device_dma_t *dma = dev->dma; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_buf_priv_t *buf_priv; drm_buf_t *buf; int i, t;#if ROTATE_BUFS int start;#endif /* FIXME: Optimize -- use freelist code */ for ( i = 0 ; i < dma->buf_count ; i++ ) { buf = dma->buflist[i]; buf_priv = buf->dev_private; if ( buf->pid == 0 ) { DRM_DEBUG( " ret buf=%d last=%d pid=0\n", buf->idx, dev_priv->last_buf ); return buf; } DRM_DEBUG( " skipping buf=%d pid=%d\n", buf->idx, buf->pid ); }#if ROTATE_BUFS if ( ++dev_priv->last_buf >= dma->buf_count ) dev_priv->last_buf = 0; start = dev_priv->last_buf;#endif for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {#if 0 /* FIXME: Disable this for now */ u32 done_age = dev_priv->scratch[RADEON_LAST_DISPATCH];#else u32 done_age = RADEON_READ( RADEON_LAST_DISPATCH_REG );#endif#if ROTATE_BUFS for ( i = start ; i < dma->buf_count ; i++ ) {#else for ( i = 0 ; i < dma->buf_count ; i++ ) {#endif buf = dma->buflist[i]; buf_priv = buf->dev_private; if ( buf->pending && buf_priv->age <= done_age ) { /* The buffer has been processed, so it * can now be used. */ buf->pending = 0; DRM_DEBUG( " ret buf=%d last=%d age=%d done=%d\n", buf->idx, dev_priv->last_buf, buf_priv->age, done_age ); return buf; } DRM_DEBUG( " skipping buf=%d age=%d done=%d\n", buf->idx, buf_priv->age, done_age );#if ROTATE_BUFS start = 0;#endif } udelay( 1 ); } DRM_ERROR( "returning NULL!\n" ); return NULL;}void radeon_freelist_reset( drm_device_t *dev ){ drm_device_dma_t *dma = dev->dma;#if ROTATE_BUFS drm_radeon_private_t *dev_priv = dev->dev_private;#endif int i;#if ROTATE_BUFS dev_priv->last_buf = 0;#endif for ( i = 0 ; i < dma->buf_count ; i++ ) { drm_buf_t *buf = dma->buflist[i]; drm_radeon_buf_priv_t *buf_priv = buf->dev_private; buf_priv->age = 0; }}/* ================================================================ * CP command submission */int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n ){ drm_radeon_ring_buffer_t *ring = &dev_priv->ring; int i; for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { radeon_update_ring_snapshot( ring ); if ( ring->space > n ) return 0; udelay( 1 ); } /* FIXME: This return value is ignored in the BEGIN_RING macro! */#if RADEON_FIFO_DEBUG radeon_status( dev_priv ); DRM_ERROR( "failed!\n" );#endif return -EBUSY;}static int radeon_cp_get_buffers( drm_device_t *dev, drm_dma_t *d ){ int i; drm_buf_t *buf; for ( i = d->granted_count ; i < d->request_count ; i++ ) { buf = radeon_freelist_get( dev ); if ( !buf ) return -EAGAIN; buf->pid = current->pid; if ( copy_to_user( &d->request_indices[i], &buf->idx, sizeof(buf->idx) ) ) return -EFAULT; if ( copy_to_user( &d->request_sizes[i], &buf->total, sizeof(buf->total) ) ) return -EFAULT; d->granted_count++; } return 0;}int radeon_cp_buffers( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ){ drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_device_dma_t *dma = dev->dma; int ret = 0; drm_dma_t d; LOCK_TEST_WITH_RETURN( dev ); if ( copy_from_user( &d, (drm_dma_t *)arg, sizeof(d) ) ) return -EFAULT; /* Please don't send us buffers. */ if ( d.send_count != 0 ) { DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n", current->pid, d.send_count ); return -EINVAL; } /* We'll send you buffers. */ if ( d.request_count < 0 || d.request_count > dma->buf_count ) { DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n", current->pid, d.request_count, dma->buf_count ); return -EINVAL; } d.granted_count = 0; if ( d.request_count ) { ret = radeon_cp_get_buffers( dev, &d ); } if ( copy_to_user( (drm_dma_t *)arg, &d, sizeof(d) ) ) return -EFAULT; return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -