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

📄 radeon_cp.c

📁 ati driver
💻 C
📖 第 1 页 / 共 3 页
字号:
	if(!dev_priv->sarea) {		DRM_ERROR("could not find sarea!\n");		dev->dev_private = (void *)dev_priv;		radeon_do_cleanup_cp(dev);		return DRM_ERR(EINVAL);	}	DRM_FIND_MAP( dev_priv->fb, init->fb_offset );	if(!dev_priv->fb) {		DRM_ERROR("could not find framebuffer!\n");		dev->dev_private = (void *)dev_priv;		radeon_do_cleanup_cp(dev);		return DRM_ERR(EINVAL);	}	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );	if(!dev_priv->mmio) {		DRM_ERROR("could not find mmio region!\n");		dev->dev_private = (void *)dev_priv;		radeon_do_cleanup_cp(dev);		return DRM_ERR(EINVAL);	}	DRM_FIND_MAP( dev_priv->cp_ring, init->ring_offset );	if(!dev_priv->cp_ring) {		DRM_ERROR("could not find cp ring region!\n");		dev->dev_private = (void *)dev_priv;		radeon_do_cleanup_cp(dev);		return DRM_ERR(EINVAL);	}	DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );	if(!dev_priv->ring_rptr) {		DRM_ERROR("could not find ring read pointer!\n");		dev->dev_private = (void *)dev_priv;		radeon_do_cleanup_cp(dev);		return DRM_ERR(EINVAL);	}	DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );	if(!dev_priv->buffers) {		DRM_ERROR("could not find dma buffer region!\n");		dev->dev_private = (void *)dev_priv;		radeon_do_cleanup_cp(dev);		return DRM_ERR(EINVAL);	}	if ( !dev_priv->is_pci ) {		DRM_FIND_MAP( dev_priv->agp_textures,			      init->agp_textures_offset );		if(!dev_priv->agp_textures) {			DRM_ERROR("could not find agp texture region!\n");			dev->dev_private = (void *)dev_priv;			radeon_do_cleanup_cp(dev);			return DRM_ERR(EINVAL);		}	}	dev_priv->sarea_priv =		(drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle +				       init->sarea_priv_offset);	if ( !dev_priv->is_pci ) {		DRM_IOREMAP( dev_priv->cp_ring );		DRM_IOREMAP( dev_priv->ring_rptr );		DRM_IOREMAP( dev_priv->buffers );		if(!dev_priv->cp_ring->handle ||		   !dev_priv->ring_rptr->handle ||		   !dev_priv->buffers->handle) {			DRM_ERROR("could not find ioremap agp regions!\n");			dev->dev_private = (void *)dev_priv;			radeon_do_cleanup_cp(dev);			return DRM_ERR(EINVAL);		}	} else {		dev_priv->cp_ring->handle =			(void *)dev_priv->cp_ring->offset;		dev_priv->ring_rptr->handle =			(void *)dev_priv->ring_rptr->offset;		dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;		DRM_DEBUG( "dev_priv->cp_ring->handle %p\n",			   dev_priv->cp_ring->handle );		DRM_DEBUG( "dev_priv->ring_rptr->handle %p\n",			   dev_priv->ring_rptr->handle );		DRM_DEBUG( "dev_priv->buffers->handle %p\n",			   dev_priv->buffers->handle );	}	dev_priv->agp_size = init->agp_size;	dev_priv->agp_vm_start = RADEON_READ( RADEON_CONFIG_APER_SIZE );#if __REALLY_HAVE_AGP	if ( !dev_priv->is_pci )		dev_priv->agp_buffers_offset = (dev_priv->buffers->offset						- dev->agp->base						+ dev_priv->agp_vm_start);	else#endif		dev_priv->agp_buffers_offset = (dev_priv->buffers->offset						- dev->sg->handle						+ dev_priv->agp_vm_start);	DRM_DEBUG( "dev_priv->agp_size %d\n",		   dev_priv->agp_size );	DRM_DEBUG( "dev_priv->agp_vm_start 0x%x\n",		   dev_priv->agp_vm_start );	DRM_DEBUG( "dev_priv->agp_buffers_offset 0x%lx\n",		   dev_priv->agp_buffers_offset );	dev_priv->ring.head = ((__volatile__ u32 *)			       dev_priv->ring_rptr->handle);	dev_priv->ring.start = (u32 *)dev_priv->cp_ring->handle;	dev_priv->ring.end = ((u32 *)dev_priv->cp_ring->handle			      + init->ring_size / sizeof(u32));	dev_priv->ring.size = init->ring_size;	dev_priv->ring.size_l2qw = DRM(order)( init->ring_size / 8 );	dev_priv->ring.tail_mask =		(dev_priv->ring.size / sizeof(u32)) - 1;	dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;#if __REALLY_HAVE_SG	if ( dev_priv->is_pci ) {		if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart,					    &dev_priv->bus_pci_gart)) {			DRM_ERROR( "failed to init PCI GART!\n" );			dev->dev_private = (void *)dev_priv;			radeon_do_cleanup_cp(dev);			return DRM_ERR(ENOMEM);		}		/* Turn on PCI GART		 */		tmp = RADEON_READ( RADEON_AIC_CNTL )		      | RADEON_PCIGART_TRANSLATE_EN;		RADEON_WRITE( RADEON_AIC_CNTL, tmp );		/* set PCI GART page-table base address		 */		RADEON_WRITE( RADEON_AIC_PT_BASE, dev_priv->bus_pci_gart );		/* set address range for PCI address translate		 */		RADEON_WRITE( RADEON_AIC_LO_ADDR, dev_priv->agp_vm_start );		RADEON_WRITE( RADEON_AIC_HI_ADDR, dev_priv->agp_vm_start						  + dev_priv->agp_size - 1);		/* Turn off AGP aperture -- is this required for PCIGART?		 */		RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0xffffffc0 ); /* ?? */		RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */	} else {#endif /* __REALLY_HAVE_SG */		/* Turn off PCI GART		 */		tmp = RADEON_READ( RADEON_AIC_CNTL )		      & ~RADEON_PCIGART_TRANSLATE_EN;		RADEON_WRITE( RADEON_AIC_CNTL, tmp );#if __REALLY_HAVE_SG	}#endif /* __REALLY_HAVE_SG */	radeon_cp_load_microcode( dev_priv );	radeon_cp_init_ring_buffer( dev, dev_priv );	dev_priv->last_buf = 0;	dev->dev_private = (void *)dev_priv;	radeon_do_engine_reset( dev );	return 0;}int radeon_do_cleanup_cp( drm_device_t *dev ){	DRM_DEBUG( "\n" );	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 __REALLY_HAVE_SG			if (!DRM(ati_pcigart_cleanup)( dev,						dev_priv->phys_pci_gart,						dev_priv->bus_pci_gart ))				DRM_ERROR( "failed to cleanup PCI GART!\n" );#endif /* __REALLY_HAVE_SG */		}		DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t),			   DRM_MEM_DRIVER );		dev->dev_private = NULL;	}	return 0;}int radeon_cp_init( DRM_IOCTL_ARGS ){	DRM_DEVICE;	drm_radeon_init_t init;	DRM_COPY_FROM_USER_IOCTL( init, (drm_radeon_init_t *)data, sizeof(init) );	switch ( init.func ) {	case RADEON_INIT_CP:	case RADEON_INIT_R200_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 );	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 );	DRM_COPY_FROM_USER_IOCTL( stop, (drm_radeon_cp_stop_t *)data, sizeof(stop) );	/* 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;}/* 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 );	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 );/* 	if (dev->irq)  *//* 		radeon_emit_and_wait_irq( dev ); */	return radeon_do_cp_idle( dev_priv );}int radeon_engine_reset( DRM_IOCTL_ARGS ){	DRM_DEVICE;	DRM_DEBUG( "\n" );	LOCK_TEST_WITH_RETURN( dev );	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->pid == 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->scratch[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->pid == 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(ring);	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {		u32 head = GET_RING_HEAD(ring);		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( 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->pid = DRM_CURRENTPID;		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 d;	LOCK_TEST_WITH_RETURN( dev );	DRM_COPY_FROM_USER_IOCTL( d, (drm_dma_t *)data, 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( dev, &d );	}	DRM_COPY_TO_USER_IOCTL( (drm_dma_t *)data, d, sizeof(d) );	return ret;}

⌨️ 快捷键说明

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