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

📄 gamma_dma.c

📁 h内核
💻 C
📖 第 1 页 / 共 2 页
字号:
		last_buf = buf;	}cleanup:	if (last_buf) {		gamma_dma_ready(dev);		gamma_free_buffer(dev, last_buf);	}	if (send_indices)		DRM(free)(send_indices, d->send_count * sizeof(*send_indices), 			  DRM_MEM_DRIVER);	if (send_sizes)		DRM(free)(send_sizes, d->send_count * sizeof(*send_sizes), 			  DRM_MEM_DRIVER);	if (must_free && !dev->context_flag) {		if (gamma_lock_free(dev, &dev->lock.hw_lock->lock,				  DRM_KERNEL_CONTEXT)) {			DRM_ERROR("\n");		}	}	clear_bit(0, &dev->interrupt_flag);	return retcode;}static int gamma_dma_send_buffers(struct file *filp,				  drm_device_t *dev, drm_dma_t *d){	DECLARE_WAITQUEUE(entry, current);	drm_buf_t	  *last_buf = NULL;	int		  retcode   = 0;	drm_device_dma_t  *dma	    = dev->dma;	int               send_index;	if (get_user(send_index, &d->send_indices[d->send_count-1]))		return -EFAULT;	if (d->flags & _DRM_DMA_BLOCK) {		last_buf = dma->buflist[send_index];		add_wait_queue(&last_buf->dma_wait, &entry);	}	if ((retcode = gamma_dma_enqueue(filp, d))) {		if (d->flags & _DRM_DMA_BLOCK)			remove_wait_queue(&last_buf->dma_wait, &entry);		return retcode;	}	gamma_dma_schedule(dev, 0);	if (d->flags & _DRM_DMA_BLOCK) {		DRM_DEBUG("%d waiting\n", current->pid);		for (;;) {			current->state = TASK_INTERRUPTIBLE;			if (!last_buf->waiting && !last_buf->pending)				break; /* finished */			schedule();			if (signal_pending(current)) {				retcode = -EINTR; /* Can't restart */				break;			}		}		current->state = TASK_RUNNING;		DRM_DEBUG("%d running\n", current->pid);		remove_wait_queue(&last_buf->dma_wait, &entry);		if (!retcode		    || (last_buf->list==DRM_LIST_PEND && !last_buf->pending)) {			if (!waitqueue_active(&last_buf->dma_wait)) {				gamma_free_buffer(dev, last_buf);			}		}		if (retcode) {			DRM_ERROR("ctx%d w%d p%d c%ld i%d l%d pid:%d\n",				  d->context,				  last_buf->waiting,				  last_buf->pending,				  (long)DRM_WAITCOUNT(dev, d->context),				  last_buf->idx,				  last_buf->list,				  current->pid);		}	}	return retcode;}int gamma_dma(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		  retcode   = 0;	drm_dma_t	  __user *argp = (void __user *)arg;	drm_dma_t	  d;	if (copy_from_user(&d, argp, sizeof(d)))		return -EFAULT;	if (d.send_count < 0 || d.send_count > dma->buf_count) {		DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n",			  current->pid, d.send_count, dma->buf_count);		return -EINVAL;	}	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;	}	if (d.send_count) {		if (d.flags & _DRM_DMA_PRIORITY)			retcode = gamma_dma_priority(filp, dev, &d);		else			retcode = gamma_dma_send_buffers(filp, dev, &d);	}	d.granted_count = 0;	if (!retcode && d.request_count) {		retcode = gamma_dma_get_buffers(filp, &d);	}	DRM_DEBUG("%d returning, granted = %d\n",		  current->pid, d.granted_count);	if (copy_to_user(argp, &d, sizeof(d)))		return -EFAULT;	return retcode;}/* ============================================================= * DMA initialization, cleanup */static int gamma_do_init_dma( drm_device_t *dev, drm_gamma_init_t *init ){	drm_gamma_private_t *dev_priv;	drm_device_dma_t    *dma = dev->dma;	drm_buf_t	    *buf;	int i;	struct list_head    *list;	unsigned long	    *pgt;	DRM_DEBUG( "%s\n", __FUNCTION__ );	dev_priv = DRM(alloc)( sizeof(drm_gamma_private_t),							DRM_MEM_DRIVER );	if ( !dev_priv )		return -ENOMEM;	dev->dev_private = (void *)dev_priv;	memset( dev_priv, 0, sizeof(drm_gamma_private_t) );	dev_priv->num_rast = init->num_rast;	list_for_each(list, &dev->maplist->head) {		drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);		if( r_list->map &&		    r_list->map->type == _DRM_SHM &&		    r_list->map->flags & _DRM_CONTAINS_LOCK ) {			dev_priv->sarea = r_list->map; 			break; 		} 	}		dev_priv->mmio0 = drm_core_findmap(dev, init->mmio0);	dev_priv->mmio1 = drm_core_findmap(dev, init->mmio1);	dev_priv->mmio2 = drm_core_findmap(dev, init->mmio2);	dev_priv->mmio3 = drm_core_findmap(dev, init->mmio3);		dev_priv->sarea_priv = (drm_gamma_sarea_t *)		((u8 *)dev_priv->sarea->handle +		 init->sarea_priv_offset);	if (init->pcimode) {		buf = dma->buflist[GLINT_DRI_BUF_COUNT];		pgt = buf->address; 		for (i = 0; i < GLINT_DRI_BUF_COUNT; i++) {			buf = dma->buflist[i];			*pgt = virt_to_phys((void*)buf->address) | 0x07;			pgt++;		}		buf = dma->buflist[GLINT_DRI_BUF_COUNT];	} else {		dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);		drm_core_ioremap( dev->agp_buffer_map, dev);		buf = dma->buflist[GLINT_DRI_BUF_COUNT];		pgt = buf->address; 		for (i = 0; i < GLINT_DRI_BUF_COUNT; i++) {			buf = dma->buflist[i];			*pgt = (unsigned long)buf->address + 0x07;			pgt++;		}		buf = dma->buflist[GLINT_DRI_BUF_COUNT];		while (GAMMA_READ(GAMMA_INFIFOSPACE) < 1);		GAMMA_WRITE( GAMMA_GDMACONTROL, 0xe);	}	while (GAMMA_READ(GAMMA_INFIFOSPACE) < 2);	GAMMA_WRITE( GAMMA_PAGETABLEADDR, virt_to_phys((void*)buf->address) );	GAMMA_WRITE( GAMMA_PAGETABLELENGTH, 2 );	return 0;}int gamma_do_cleanup_dma( drm_device_t *dev ){	DRM_DEBUG( "%s\n", __FUNCTION__ );	/* 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 (drm_core_check_feature(dev, DRIVER_HAVE_IRQ))		if ( dev->irq_enabled ) 			DRM(irq_uninstall)(dev);	if ( dev->dev_private ) {		if ( dev->agp_buffer_map != NULL )			drm_core_ioremapfree( dev->agp_buffer_map, dev );		DRM(free)( dev->dev_private, sizeof(drm_gamma_private_t),			   DRM_MEM_DRIVER );		dev->dev_private = NULL;	}	return 0;}int gamma_dma_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_gamma_init_t init;	LOCK_TEST_WITH_RETURN( dev, filp );	if ( copy_from_user( &init, (drm_gamma_init_t __user *)arg, sizeof(init) ) )		return -EFAULT;	switch ( init.func ) {	case GAMMA_INIT_DMA:		return gamma_do_init_dma( dev, &init );	case GAMMA_CLEANUP_DMA:		return gamma_do_cleanup_dma( dev );	}	return -EINVAL;}static int gamma_do_copy_dma( drm_device_t *dev, drm_gamma_copy_t *copy ){	drm_device_dma_t    *dma = dev->dma;	unsigned int        *screenbuf;	DRM_DEBUG( "%s\n", __FUNCTION__ );	/* We've DRM_RESTRICTED this DMA buffer */	screenbuf = dma->buflist[ GLINT_DRI_BUF_COUNT + 1 ]->address;#if 0	*buffer++ = 0x180;	/* Tag (FilterMode) */	*buffer++ = 0x200;	/* Allow FBColor through */	*buffer++ = 0x53B;	/* Tag */	*buffer++ = copy->Pitch;	*buffer++ = 0x53A;	/* Tag */	*buffer++ = copy->SrcAddress;	*buffer++ = 0x539;	/* Tag */	*buffer++ = copy->WidthHeight; /* Initiates transfer */	*buffer++ = 0x53C;	/* Tag - DMAOutputAddress */	*buffer++ = virt_to_phys((void*)screenbuf);	*buffer++ = 0x53D;	/* Tag - DMAOutputCount */	*buffer++ = copy->Count; /* Reads HostOutFifo BLOCKS until ..*/	/* Data now sitting in dma->buflist[ GLINT_DRI_BUF_COUNT + 1 ] */	/* Now put it back to the screen */	*buffer++ = 0x180;	/* Tag (FilterMode) */	*buffer++ = 0x400;	/* Allow Sync through */	*buffer++ = 0x538;	/* Tag - DMARectangleReadTarget */	*buffer++ = 0x155;	/* FBSourceData | count */	*buffer++ = 0x537;	/* Tag */	*buffer++ = copy->Pitch;	*buffer++ = 0x536;	/* Tag */	*buffer++ = copy->DstAddress;	*buffer++ = 0x535;	/* Tag */	*buffer++ = copy->WidthHeight; /* Initiates transfer */	*buffer++ = 0x530;	/* Tag - DMAAddr */	*buffer++ = virt_to_phys((void*)screenbuf);	*buffer++ = 0x531;	*buffer++ = copy->Count; /* initiates DMA transfer of color data */#endif	/* need to dispatch it now */	return 0;}int gamma_dma_copy( 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_gamma_copy_t copy;	if ( copy_from_user( &copy, (drm_gamma_copy_t __user *)arg, sizeof(copy) ) )		return -EFAULT;	return gamma_do_copy_dma( dev, &copy );}/* ============================================================= * Per Context SAREA Support */int gamma_getsareactx(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_ctx_priv_map_t __user *argp = (void __user *)arg;	drm_ctx_priv_map_t request;	drm_map_t *map;	if (copy_from_user(&request, argp, sizeof(request)))		return -EFAULT;	down(&dev->struct_sem);	if ((int)request.ctx_id >= dev->max_context) {		up(&dev->struct_sem);		return -EINVAL;	}	map = dev->context_sareas[request.ctx_id];	up(&dev->struct_sem);	request.handle = map->handle;	if (copy_to_user(argp, &request, sizeof(request)))		return -EFAULT;	return 0;}int gamma_setsareactx(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_ctx_priv_map_t request;	drm_map_t *map = NULL;	drm_map_list_t *r_list;	struct list_head *list;	if (copy_from_user(&request,			   (drm_ctx_priv_map_t __user *)arg,			   sizeof(request)))		return -EFAULT;	down(&dev->struct_sem);	r_list = NULL;	list_for_each(list, &dev->maplist->head) {		r_list = list_entry(list, drm_map_list_t, head);		if(r_list->map &&		   r_list->map->handle == request.handle) break;	}	if (list == &(dev->maplist->head)) {		up(&dev->struct_sem);		return -EINVAL;	}	map = r_list->map;	up(&dev->struct_sem);	if (!map) return -EINVAL;	down(&dev->struct_sem);	if ((int)request.ctx_id >= dev->max_context) {		up(&dev->struct_sem);		return -EINVAL;	}	dev->context_sareas[request.ctx_id] = map;	up(&dev->struct_sem);	return 0;}void gamma_driver_irq_preinstall( drm_device_t *dev ) {	drm_gamma_private_t *dev_priv =				(drm_gamma_private_t *)dev->dev_private;	while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2)		cpu_relax();	GAMMA_WRITE( GAMMA_GCOMMANDMODE,	0x00000004 );	GAMMA_WRITE( GAMMA_GDMACONTROL,		0x00000000 );}void gamma_driver_irq_postinstall( drm_device_t *dev ) {	drm_gamma_private_t *dev_priv =				(drm_gamma_private_t *)dev->dev_private;	while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3)		cpu_relax();	GAMMA_WRITE( GAMMA_GINTENABLE,		0x00002001 );	GAMMA_WRITE( GAMMA_COMMANDINTENABLE,	0x00000008 );	GAMMA_WRITE( GAMMA_GDELAYTIMER,		0x00039090 );}void gamma_driver_irq_uninstall( drm_device_t *dev ) {	drm_gamma_private_t *dev_priv =				(drm_gamma_private_t *)dev->dev_private;	if (!dev_priv)		return;	while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3)		cpu_relax();	GAMMA_WRITE( GAMMA_GDELAYTIMER,		0x00000000 );	GAMMA_WRITE( GAMMA_COMMANDINTENABLE,	0x00000000 );	GAMMA_WRITE( GAMMA_GINTENABLE,		0x00000000 );}extern drm_ioctl_desc_t DRM(ioctls)[];static int gamma_driver_preinit(drm_device_t *dev){	/* reset the finish ioctl */	DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_FINISH)].func = DRM(finish);	return 0;}static void gamma_driver_pretakedown(drm_device_t *dev){	gamma_do_cleanup_dma(dev);}static void gamma_driver_dma_ready(drm_device_t *dev){	gamma_dma_ready(dev);}static int gamma_driver_dma_quiescent(drm_device_t *dev){	drm_gamma_private_t *dev_priv =	(		drm_gamma_private_t *)dev->dev_private;	if (dev_priv->num_rast == 2)		gamma_dma_quiescent_dual(dev);	else gamma_dma_quiescent_single(dev);	return 0;}void gamma_driver_register_fns(drm_device_t *dev){	dev->driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ;	DRM(fops).read = gamma_fops_read;	DRM(fops).poll = gamma_fops_poll;	dev->driver.preinit = gamma_driver_preinit;	dev->driver.pretakedown = gamma_driver_pretakedown;	dev->driver.dma_ready = gamma_driver_dma_ready;	dev->driver.dma_quiescent = gamma_driver_dma_quiescent;	dev->driver.dma_flush_block_and_flush = gamma_flush_block_and_flush;	dev->driver.dma_flush_unblock = gamma_flush_unblock;}

⌨️ 快捷键说明

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