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

📄 mga_dma.c

📁 h内核
💻 C
📖 第 1 页 / 共 2 页
字号:
		next = dev_priv->tail;		prev->next = NULL;		next->prev = next->next = NULL;		dev_priv->tail = prev;		SET_AGE( &next->age, MGA_BUFFER_USED, 0 );		return next->buf;	}	DRM_DEBUG( "returning NULL!\n" );	return NULL;}int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf ){	drm_mga_private_t *dev_priv = dev->dev_private;	drm_mga_buf_priv_t *buf_priv = buf->dev_private;	drm_mga_freelist_t *head, *entry, *prev;	DRM_DEBUG( "age=0x%06lx wrap=%d\n",		   buf_priv->list_entry->age.head -		   dev_priv->primary->offset,		   buf_priv->list_entry->age.wrap );	entry = buf_priv->list_entry;	head = dev_priv->head;	if ( buf_priv->list_entry->age.head == MGA_BUFFER_USED ) {		SET_AGE( &entry->age, MGA_BUFFER_FREE, 0 );		prev = dev_priv->tail;		prev->next = entry;		entry->prev = prev;		entry->next = NULL;	} else {		prev = head->next;		head->next = entry;		prev->prev = entry;		entry->prev = head;		entry->next = prev;	}	return 0;}/* ================================================================ * DMA initialization, cleanup */static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ){	drm_mga_private_t *dev_priv;	int ret;	DRM_DEBUG( "\n" );	dev_priv = drm_alloc( sizeof(drm_mga_private_t), DRM_MEM_DRIVER );	if ( !dev_priv )		return DRM_ERR(ENOMEM);	memset( dev_priv, 0, sizeof(drm_mga_private_t) );	dev_priv->chipset = init->chipset;	dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;	if ( init->sgram ) {		dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK;	} else {		dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;	}	dev_priv->maccess	= init->maccess;	dev_priv->fb_cpp	= init->fb_cpp;	dev_priv->front_offset	= init->front_offset;	dev_priv->front_pitch	= init->front_pitch;	dev_priv->back_offset	= init->back_offset;	dev_priv->back_pitch	= init->back_pitch;	dev_priv->depth_cpp	= init->depth_cpp;	dev_priv->depth_offset	= init->depth_offset;	dev_priv->depth_pitch	= init->depth_pitch;	/* FIXME: Need to support AGP textures...	 */	dev_priv->texture_offset = init->texture_offset[0];	dev_priv->texture_size = init->texture_size[0];	DRM_GETSAREA();	if(!dev_priv->sarea) {		DRM_ERROR( "failed to find sarea!\n" );		/* Assign dev_private so we can do cleanup. */		dev->dev_private = (void *)dev_priv;		mga_do_cleanup_dma( dev );		return DRM_ERR(EINVAL);	}	dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);	if(!dev_priv->mmio) {		DRM_ERROR( "failed to find mmio region!\n" );		/* Assign dev_private so we can do cleanup. */		dev->dev_private = (void *)dev_priv;		mga_do_cleanup_dma( dev );		return DRM_ERR(EINVAL);	}	dev_priv->status = drm_core_findmap(dev, init->status_offset);	if(!dev_priv->status) {		DRM_ERROR( "failed to find status page!\n" );		/* Assign dev_private so we can do cleanup. */		dev->dev_private = (void *)dev_priv;		mga_do_cleanup_dma( dev );		return DRM_ERR(EINVAL);	}	dev_priv->warp = drm_core_findmap(dev, init->warp_offset);	if(!dev_priv->warp) {		DRM_ERROR( "failed to find warp microcode region!\n" );		/* Assign dev_private so we can do cleanup. */		dev->dev_private = (void *)dev_priv;		mga_do_cleanup_dma( dev );		return DRM_ERR(EINVAL);	}	dev_priv->primary = drm_core_findmap(dev, init->primary_offset);	if(!dev_priv->primary) {		DRM_ERROR( "failed to find primary dma region!\n" );		/* Assign dev_private so we can do cleanup. */		dev->dev_private = (void *)dev_priv;		mga_do_cleanup_dma( dev );		return DRM_ERR(EINVAL);	}	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);	if(!dev->agp_buffer_map) {		DRM_ERROR( "failed to find dma buffer region!\n" );		/* Assign dev_private so we can do cleanup. */		dev->dev_private = (void *)dev_priv;		mga_do_cleanup_dma( dev );		return DRM_ERR(EINVAL);	}	dev_priv->sarea_priv =		(drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle +				    init->sarea_priv_offset);	drm_core_ioremap( dev_priv->warp, dev );	drm_core_ioremap( dev_priv->primary, dev );	drm_core_ioremap( dev->agp_buffer_map, dev );	if(!dev_priv->warp->handle ||	   !dev_priv->primary->handle ||	   !dev->agp_buffer_map->handle ) {		DRM_ERROR( "failed to ioremap agp regions!\n" );		/* Assign dev_private so we can do cleanup. */		dev->dev_private = (void *)dev_priv;		mga_do_cleanup_dma( dev );		return DRM_ERR(ENOMEM);	}	ret = mga_warp_install_microcode( dev_priv );	if ( ret < 0 ) {		DRM_ERROR( "failed to install WARP ucode!\n" );		/* Assign dev_private so we can do cleanup. */		dev->dev_private = (void *)dev_priv;		mga_do_cleanup_dma( dev );		return ret;	}	ret = mga_warp_init( dev_priv );	if ( ret < 0 ) {		DRM_ERROR( "failed to init WARP engine!\n" );		/* Assign dev_private so we can do cleanup. */		dev->dev_private = (void *)dev_priv;		mga_do_cleanup_dma( dev );		return ret;	}	dev_priv->prim.status = (u32 *)dev_priv->status->handle;	mga_do_wait_for_idle( dev_priv );	/* Init the primary DMA registers.	 */	MGA_WRITE( MGA_PRIMADDRESS,		   dev_priv->primary->offset | MGA_DMA_GENERAL );#if 0	MGA_WRITE( MGA_PRIMPTR,		   virt_to_bus((void *)dev_priv->prim.status) |		   MGA_PRIMPTREN0 |	/* Soft trap, SECEND, SETUPEND */		   MGA_PRIMPTREN1 );	/* DWGSYNC */#endif	dev_priv->prim.start = (u8 *)dev_priv->primary->handle;	dev_priv->prim.end = ((u8 *)dev_priv->primary->handle			      + dev_priv->primary->size);	dev_priv->prim.size = dev_priv->primary->size;	dev_priv->prim.tail = 0;	dev_priv->prim.space = dev_priv->prim.size;	dev_priv->prim.wrapped = 0;	dev_priv->prim.last_flush = 0;	dev_priv->prim.last_wrap = 0;	dev_priv->prim.high_mark = 256 * DMA_BLOCK_SIZE;	dev_priv->prim.status[0] = dev_priv->primary->offset;	dev_priv->prim.status[1] = 0;	dev_priv->sarea_priv->last_wrap = 0;	dev_priv->sarea_priv->last_frame.head = 0;	dev_priv->sarea_priv->last_frame.wrap = 0;	if ( mga_freelist_init( dev, dev_priv ) < 0 ) {		DRM_ERROR( "could not initialize freelist\n" );		/* Assign dev_private so we can do cleanup. */		dev->dev_private = (void *)dev_priv;		mga_do_cleanup_dma( dev );		return DRM_ERR(ENOMEM);	}	/* Make dev_private visable to others. */	dev->dev_private = (void *)dev_priv;	return 0;}int mga_do_cleanup_dma( drm_device_t *dev ){	DRM_DEBUG( "\n" );	/* Make sure interrupts are disabled here because the uninstall ioctl	 * may not have been called from userspace and after dev_private	 * is freed, it's too late.	 */	if ( dev->irq_enabled ) drm_irq_uninstall(dev);	if ( dev->dev_private ) {		drm_mga_private_t *dev_priv = dev->dev_private;		if ( dev_priv->warp != NULL )			drm_core_ioremapfree( dev_priv->warp, dev );		if ( dev_priv->primary != NULL )			drm_core_ioremapfree( dev_priv->primary, dev );		if ( dev->agp_buffer_map != NULL )			drm_core_ioremapfree( dev->agp_buffer_map, dev );		if ( dev_priv->head != NULL ) {			mga_freelist_cleanup( dev );		}		drm_free( dev->dev_private, sizeof(drm_mga_private_t),			   DRM_MEM_DRIVER );		dev->dev_private = NULL;	}	return 0;}int mga_dma_init( DRM_IOCTL_ARGS ){	DRM_DEVICE;	drm_mga_init_t init;	LOCK_TEST_WITH_RETURN( dev, filp );	DRM_COPY_FROM_USER_IOCTL( init, (drm_mga_init_t __user *)data, sizeof(init) );	switch ( init.func ) {	case MGA_INIT_DMA:		return mga_do_init_dma( dev, &init );	case MGA_CLEANUP_DMA:		return mga_do_cleanup_dma( dev );	}	return DRM_ERR(EINVAL);}/* ================================================================ * Primary DMA stream management */int mga_dma_flush( DRM_IOCTL_ARGS ){	DRM_DEVICE;	drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;	drm_lock_t lock;	LOCK_TEST_WITH_RETURN( dev, filp );	DRM_COPY_FROM_USER_IOCTL( lock, (drm_lock_t __user *)data, sizeof(lock) );	DRM_DEBUG( "%s%s%s\n",		   (lock.flags & _DRM_LOCK_FLUSH) ?	"flush, " : "",		   (lock.flags & _DRM_LOCK_FLUSH_ALL) ?	"flush all, " : "",		   (lock.flags & _DRM_LOCK_QUIESCENT) ?	"idle, " : "" );	WRAP_WAIT_WITH_RETURN( dev_priv );	if ( lock.flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL) ) {		mga_do_dma_flush( dev_priv );	}	if ( lock.flags & _DRM_LOCK_QUIESCENT ) {#if MGA_DMA_DEBUG		int ret = mga_do_wait_for_idle( dev_priv );		if ( ret < 0 )			DRM_INFO( "%s: -EBUSY\n", __FUNCTION__ );		return ret;#else		return mga_do_wait_for_idle( dev_priv );#endif	} else {		return 0;	}}int mga_dma_reset( DRM_IOCTL_ARGS ){	DRM_DEVICE;	drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;	LOCK_TEST_WITH_RETURN( dev, filp );	return mga_do_dma_reset( dev_priv );}/* ================================================================ * DMA buffer management */static int mga_dma_get_buffers( DRMFILE filp,				drm_device_t *dev, drm_dma_t *d ){	drm_buf_t *buf;	int i;	for ( i = d->granted_count ; i < d->request_count ; i++ ) {		buf = mga_freelist_get( dev );		if ( !buf ) return DRM_ERR(EAGAIN);		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 mga_dma_buffers( DRM_IOCTL_ARGS ){	DRM_DEVICE;	drm_device_dma_t *dma = dev->dma;	drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;	drm_dma_t __user *argp = (void __user *)data;	drm_dma_t d;	int ret = 0;	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);	}	WRAP_TEST_WITH_RETURN( dev_priv );	d.granted_count = 0;	if ( d.request_count ) {		ret = mga_dma_get_buffers( filp, dev, &d );	}	DRM_COPY_TO_USER_IOCTL( argp, d, sizeof(d) );	return ret;}void mga_driver_pretakedown(drm_device_t *dev){	mga_do_cleanup_dma( dev );}int mga_driver_dma_quiescent(drm_device_t *dev){	drm_mga_private_t *dev_priv = dev->dev_private;	return mga_do_wait_for_idle( dev_priv );}

⌨️ 快捷键说明

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