⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 radeon_cp.c

📁 h内核
💻 C
📖 第 1 页 / 共 4 页
字号:
	 */	if ( dev->irq_enabled ) drm_irq_uninstall(dev);#if __OS_HAS_AGP	if ( !dev_priv->is_pci ) {		if ( dev_priv->cp_ring != NULL )			drm_core_ioremapfree( dev_priv->cp_ring, dev );		if ( dev_priv->ring_rptr != NULL )			drm_core_ioremapfree( dev_priv->ring_rptr, dev );		if ( dev->agp_buffer_map != NULL )		{			drm_core_ioremapfree( dev->agp_buffer_map, dev );			dev->agp_buffer_map = NULL;		}	} else#endif	{		if (!drm_ati_pcigart_cleanup( dev,					      dev_priv->phys_pci_gart,					      dev_priv->bus_pci_gart ))			DRM_ERROR( "failed to cleanup PCI GART!\n" );	}		/* only clear to the start of flags */	memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));	return 0;}/* This code will reinit the Radeon CP hardware after a resume from disc.   * AFAIK, it would be very difficult to pickle the state at suspend time, so  * here we make sure that all Radeon hardware initialisation is re-done without * affecting running applications. * * Charl P. Botha <http://cpbotha.net> */static int radeon_do_resume_cp( drm_device_t *dev ){	drm_radeon_private_t *dev_priv = dev->dev_private;	if ( !dev_priv ) {		DRM_ERROR( "Called with no initialization\n" );		return DRM_ERR( EINVAL );	}	DRM_DEBUG("Starting radeon_do_resume_cp()\n");#if __OS_HAS_AGP	if ( !dev_priv->is_pci ) {		/* Turn off PCI GART */		radeon_set_pcigart( dev_priv, 0 );	} else#endif	{		/* Turn on PCI GART */		radeon_set_pcigart( dev_priv, 1 );	}	radeon_cp_load_microcode( dev_priv );	radeon_cp_init_ring_buffer( dev, dev_priv );	radeon_do_engine_reset( dev );	DRM_DEBUG("radeon_do_resume_cp() complete\n");	return 0;}int radeon_cp_init( DRM_IOCTL_ARGS ){	DRM_DEVICE;	drm_radeon_init_t init;	LOCK_TEST_WITH_RETURN( dev, filp );	DRM_COPY_FROM_USER_IOCTL( init, (drm_radeon_init_t __user *)data, sizeof(init) );	switch ( init.func ) {	case RADEON_INIT_CP:	case RADEON_INIT_R200_CP:	case RADEON_INIT_R300_CP:		return radeon_do_init_cp( dev, &init );	case RADEON_CLEANUP_CP:		return radeon_do_cleanup_cp( dev );	}	return DRM_ERR(EINVAL);}int radeon_cp_start( DRM_IOCTL_ARGS ){	DRM_DEVICE;	drm_radeon_private_t *dev_priv = dev->dev_private;	DRM_DEBUG( "\n" );	LOCK_TEST_WITH_RETURN( dev, filp );	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( DRM_IOCTL_ARGS ){	DRM_DEVICE;	drm_radeon_private_t *dev_priv = dev->dev_private;	drm_radeon_cp_stop_t stop;	int ret;	DRM_DEBUG( "\n" );	LOCK_TEST_WITH_RETURN( dev, filp );	DRM_COPY_FROM_USER_IOCTL( stop, (drm_radeon_cp_stop_t __user *)data, sizeof(stop) );	if (!dev_priv->cp_running)		return 0;	/* 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 ) 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;}void radeon_do_release( drm_device_t *dev ){	drm_radeon_private_t *dev_priv = dev->dev_private;	int i, ret;	if (dev_priv) {		if (dev_priv->cp_running) {			/* Stop the cp */			while ((ret = radeon_do_cp_idle( dev_priv )) != 0) {				DRM_DEBUG("radeon_do_cp_idle %d\n", ret);#ifdef __linux__				schedule();#else				tsleep(&ret, PZERO, "rdnrel", 1);#endif			}			radeon_do_cp_stop( dev_priv );			radeon_do_engine_reset( dev );		}		/* Disable *all* interrupts */		if (dev_priv->mmio)	/* remove this after permanent addmaps */			RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );		if (dev_priv->mmio) {/* remove all surfaces */			for (i = 0; i < RADEON_MAX_SURFACES; i++) {				RADEON_WRITE(RADEON_SURFACE0_INFO + 16*i, 0);				RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16*i, 0);				RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16*i, 0);			}		}		/* Free memory heap structures */		radeon_mem_takedown( &(dev_priv->gart_heap) );		radeon_mem_takedown( &(dev_priv->fb_heap) );		/* deallocate kernel resources */		radeon_do_cleanup_cp( dev );	}}/* Just reset the CP ring.  Called as part of an X Server engine reset. */int radeon_cp_reset( DRM_IOCTL_ARGS ){	DRM_DEVICE;	drm_radeon_private_t *dev_priv = dev->dev_private;	DRM_DEBUG( "\n" );	LOCK_TEST_WITH_RETURN( dev, filp );	if ( !dev_priv ) {		DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );		return DRM_ERR(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( DRM_IOCTL_ARGS ){	DRM_DEVICE;	drm_radeon_private_t *dev_priv = dev->dev_private;	DRM_DEBUG( "\n" );	LOCK_TEST_WITH_RETURN( dev, filp );	return radeon_do_cp_idle( dev_priv );}/* Added by Charl P. Botha to call radeon_do_resume_cp(). */int radeon_cp_resume( DRM_IOCTL_ARGS ){	DRM_DEVICE;	return radeon_do_resume_cp(dev);}int radeon_engine_reset( DRM_IOCTL_ARGS ){	DRM_DEVICE;	DRM_DEBUG( "\n" );	LOCK_TEST_WITH_RETURN( dev, filp );	return radeon_do_engine_reset( dev );}/* ================================================================ * Fullscreen mode *//* KW: Deprecated to say the least: */int radeon_fullscreen( DRM_IOCTL_ARGS ){	return 0;}/* ================================================================ * Freelist management *//* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through *   bufs until freelist code is used.  Note this hides a problem with *   the scratch register * (used to keep track of last buffer *   completed) being written to before * the last buffer has actually *   completed rendering.   * * KW:  It's also a good way to find free buffers quickly. * * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't * sleep.  However, bugs in older versions of radeon_accel.c mean that * we essentially have to do this, else old clients will break. *  * However, it does leave open a potential deadlock where all the * buffers are held by other clients, which can't release them because * they can't get the lock.   */drm_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;	int start;	if ( ++dev_priv->last_buf >= dma->buf_count )		dev_priv->last_buf = 0;	start = dev_priv->last_buf;	for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {		u32 done_age = GET_SCRATCH( 1 );		DRM_DEBUG("done_age = %d\n",done_age);		for ( i = start ; i < dma->buf_count ; i++ ) {			buf = dma->buflist[i];			buf_priv = buf->dev_private;			if ( buf->filp == 0 || (buf->pending && 					       buf_priv->age <= done_age) ) {				dev_priv->stats.requested_bufs++;				buf->pending = 0;				return buf;			}			start = 0;		}		if (t) {			DRM_UDELAY( 1 );			dev_priv->stats.freelist_loops++;		}	}	DRM_DEBUG( "returning NULL!\n" );	return NULL;}#if 0drm_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;	int start;	u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1));	if ( ++dev_priv->last_buf >= dma->buf_count )		dev_priv->last_buf = 0;	start = dev_priv->last_buf;	dev_priv->stats.freelist_loops++;		for ( t = 0 ; t < 2 ; t++ ) {		for ( i = start ; i < dma->buf_count ; i++ ) {			buf = dma->buflist[i];			buf_priv = buf->dev_private;			if ( buf->filp == 0 || (buf->pending && 					       buf_priv->age <= done_age) ) {				dev_priv->stats.requested_bufs++;				buf->pending = 0;				return buf;			}		}		start = 0;	}	return NULL;}#endifvoid radeon_freelist_reset( drm_device_t *dev ){	drm_device_dma_t *dma = dev->dma;	drm_radeon_private_t *dev_priv = dev->dev_private;	int i;	dev_priv->last_buf = 0;	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;	u32 last_head = GET_RING_HEAD( dev_priv );	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {		u32 head = GET_RING_HEAD( dev_priv );		ring->space = (head - ring->tail) * sizeof(u32);		if ( ring->space <= 0 )			ring->space += ring->size;		if ( ring->space > n )			return 0;				dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;		if (head != last_head)			i = 0;		last_head = head;		DRM_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 DRM_ERR(EBUSY);}static int radeon_cp_get_buffers( DRMFILE filp, 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 DRM_ERR(EBUSY); /* NOTE: broken client */		buf->filp = filp;		if ( DRM_COPY_TO_USER( &d->request_indices[i], &buf->idx,				   sizeof(buf->idx) ) )			return DRM_ERR(EFAULT);		if ( DRM_COPY_TO_USER( &d->request_sizes[i], &buf->total,				   sizeof(buf->total) ) )			return DRM_ERR(EFAULT);		d->granted_count++;	}	return 0;}int radeon_cp_buffers( DRM_IOCTL_ARGS ){	DRM_DEVICE;	drm_device_dma_t *dma = dev->dma;	int ret = 0;	drm_dma_t __user *argp = (void __user *)data;	drm_dma_t d;	LOCK_TEST_WITH_RETURN( dev, filp );	DRM_COPY_FROM_USER_IOCTL( d, argp, sizeof(d) );	/* Please don't send us buffers.	 */	if ( d.send_count != 0 ) {		DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",			   DRM_CURRENTPID, d.send_count );		return DRM_ERR(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",			   DRM_CURRENTPID, d.request_count, dma->buf_count );		return DRM_ERR(EINVAL);	}	d.granted_count = 0;	if ( d.request_count ) {		ret = radeon_cp_get_buffers( filp, dev, &d );	}	DRM_COPY_TO_USER_IOCTL( argp, d, sizeof(d) );	return ret;}int radeon_driver_preinit(struct drm_device *dev, unsigned long flags){	drm_radeon_private_t *dev_priv;	int ret = 0;	dev_priv = drm_alloc(sizeof(drm_radeon_private_t), DRM_MEM_DRIVER);	if (dev_priv == NULL)		return DRM_ERR(ENOMEM);	memset(dev_priv, 0, sizeof(drm_radeon_private_t));	dev->dev_private = (void *)dev_priv;	dev_priv->flags = flags;	switch (flags & CHIP_FAMILY_MASK) {	case CHIP_R100:	case CHIP_RV200:	case CHIP_R200:	case CHIP_R300:		dev_priv->flags |= CHIP_HAS_HIERZ;		break;	default:	/* all other chips have no hierarchical z buffer */		break;	}	return ret;}int radeon_driver_postcleanup(struct drm_device *dev){	drm_radeon_private_t *dev_priv = dev->dev_private;	DRM_DEBUG("\n");	drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);	dev->dev_private = NULL;	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -