i810_dma.c

来自「linux 内核源代码」· C语言 代码 · 共 1,290 行 · 第 1/3 页

C
1,290
字号
	i810_wait_ring(dev, dev_priv->ring.Size - 8);}static int i810_flush_queue(struct drm_device * dev){	drm_i810_private_t *dev_priv = dev->dev_private;	struct drm_device_dma *dma = dev->dma;	int i, ret = 0;	RING_LOCALS;/*  	printk("%s\n", __FUNCTION__); */	i810_kernel_lost_context(dev);	BEGIN_LP_RING(2);	OUT_RING(CMD_REPORT_HEAD);	OUT_RING(0);	ADVANCE_LP_RING();	i810_wait_ring(dev, dev_priv->ring.Size - 8);	for (i = 0; i < dma->buf_count; i++) {		struct drm_buf *buf = dma->buflist[i];		drm_i810_buf_priv_t *buf_priv = buf->dev_private;		int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE,				   I810_BUF_FREE);		if (used == I810_BUF_HARDWARE)			DRM_DEBUG("reclaimed from HARDWARE\n");		if (used == I810_BUF_CLIENT)			DRM_DEBUG("still on client\n");	}	return ret;}/* Must be called with the lock held */static void i810_reclaim_buffers(struct drm_device * dev,				 struct drm_file *file_priv){	struct drm_device_dma *dma = dev->dma;	int i;	if (!dma)		return;	if (!dev->dev_private)		return;	if (!dma->buflist)		return;	i810_flush_queue(dev);	for (i = 0; i < dma->buf_count; i++) {		struct drm_buf *buf = dma->buflist[i];		drm_i810_buf_priv_t *buf_priv = buf->dev_private;		if (buf->file_priv == file_priv && buf_priv) {			int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,					   I810_BUF_FREE);			if (used == I810_BUF_CLIENT)				DRM_DEBUG("reclaimed from client\n");			if (buf_priv->currently_mapped == I810_BUF_MAPPED)				buf_priv->currently_mapped = I810_BUF_UNMAPPED;		}	}}static int i810_flush_ioctl(struct drm_device *dev, void *data,			    struct drm_file *file_priv){	LOCK_TEST_WITH_RETURN(dev, file_priv);	i810_flush_queue(dev);	return 0;}static int i810_dma_vertex(struct drm_device *dev, void *data,			   struct drm_file *file_priv){	struct drm_device_dma *dma = dev->dma;	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;	u32 *hw_status = dev_priv->hw_status_page;	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)	    dev_priv->sarea_priv;	drm_i810_vertex_t *vertex = data;	LOCK_TEST_WITH_RETURN(dev, file_priv);	DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n",		  vertex->idx, vertex->used, vertex->discard);	if (vertex->idx < 0 || vertex->idx > dma->buf_count)		return -EINVAL;	i810_dma_dispatch_vertex(dev,				 dma->buflist[vertex->idx],				 vertex->discard, vertex->used);	atomic_add(vertex->used, &dev->counts[_DRM_STAT_SECONDARY]);	atomic_inc(&dev->counts[_DRM_STAT_DMA]);	sarea_priv->last_enqueue = dev_priv->counter - 1;	sarea_priv->last_dispatch = (int)hw_status[5];	return 0;}static int i810_clear_bufs(struct drm_device *dev, void *data,			   struct drm_file *file_priv){	drm_i810_clear_t *clear = data;	LOCK_TEST_WITH_RETURN(dev, file_priv);	/* GH: Someone's doing nasty things... */	if (!dev->dev_private) {		return -EINVAL;	}	i810_dma_dispatch_clear(dev, clear->flags,				clear->clear_color, clear->clear_depth);	return 0;}static int i810_swap_bufs(struct drm_device *dev, void *data,			  struct drm_file *file_priv){	DRM_DEBUG("i810_swap_bufs\n");	LOCK_TEST_WITH_RETURN(dev, file_priv);	i810_dma_dispatch_swap(dev);	return 0;}static int i810_getage(struct drm_device *dev, void *data,		       struct drm_file *file_priv){	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;	u32 *hw_status = dev_priv->hw_status_page;	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)	    dev_priv->sarea_priv;	sarea_priv->last_dispatch = (int)hw_status[5];	return 0;}static int i810_getbuf(struct drm_device *dev, void *data,		       struct drm_file *file_priv){	int retcode = 0;	drm_i810_dma_t *d = data;	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;	u32 *hw_status = dev_priv->hw_status_page;	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)	    dev_priv->sarea_priv;	LOCK_TEST_WITH_RETURN(dev, file_priv);	d->granted = 0;	retcode = i810_dma_get_buffer(dev, d, file_priv);	DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",		  task_pid_nr(current), retcode, d->granted);	sarea_priv->last_dispatch = (int)hw_status[5];	return retcode;}static int i810_copybuf(struct drm_device *dev, void *data,			struct drm_file *file_priv){	/* Never copy - 2.4.x doesn't need it */	return 0;}static int i810_docopy(struct drm_device *dev, void *data,			struct drm_file *file_priv){	/* Never copy - 2.4.x doesn't need it */	return 0;}static void i810_dma_dispatch_mc(struct drm_device * dev, struct drm_buf * buf, int used,				 unsigned int last_render){	drm_i810_private_t *dev_priv = dev->dev_private;	drm_i810_buf_priv_t *buf_priv = buf->dev_private;	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;	unsigned long address = (unsigned long)buf->bus_address;	unsigned long start = address - dev->agp->base;	int u;	RING_LOCALS;	i810_kernel_lost_context(dev);	u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_HARDWARE);	if (u != I810_BUF_CLIENT) {		DRM_DEBUG("MC found buffer that isn't mine!\n");	}	if (used > 4 * 1024)		used = 0;	sarea_priv->dirty = 0x7f;	DRM_DEBUG("dispatch mc addr 0x%lx, used 0x%x\n", address, used);	dev_priv->counter++;	DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter);	DRM_DEBUG("i810_dma_dispatch_mc\n");	DRM_DEBUG("start : %lx\n", start);	DRM_DEBUG("used : %d\n", used);	DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4);	if (buf_priv->currently_mapped == I810_BUF_MAPPED) {		if (used & 4) {			*(u32 *) ((char *) buf_priv->virtual + used) = 0;			used += 4;		}		i810_unmap_buffer(buf);	}	BEGIN_LP_RING(4);	OUT_RING(CMD_OP_BATCH_BUFFER);	OUT_RING(start | BB1_PROTECTED);	OUT_RING(start + used - 4);	OUT_RING(0);	ADVANCE_LP_RING();	BEGIN_LP_RING(8);	OUT_RING(CMD_STORE_DWORD_IDX);	OUT_RING(buf_priv->my_use_idx);	OUT_RING(I810_BUF_FREE);	OUT_RING(0);	OUT_RING(CMD_STORE_DWORD_IDX);	OUT_RING(16);	OUT_RING(last_render);	OUT_RING(0);	ADVANCE_LP_RING();}static int i810_dma_mc(struct drm_device *dev, void *data,		       struct drm_file *file_priv){	struct drm_device_dma *dma = dev->dma;	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;	u32 *hw_status = dev_priv->hw_status_page;	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)	    dev_priv->sarea_priv;	drm_i810_mc_t *mc = data;	LOCK_TEST_WITH_RETURN(dev, file_priv);	if (mc->idx >= dma->buf_count || mc->idx < 0)		return -EINVAL;	i810_dma_dispatch_mc(dev, dma->buflist[mc->idx], mc->used,			     mc->last_render);	atomic_add(mc->used, &dev->counts[_DRM_STAT_SECONDARY]);	atomic_inc(&dev->counts[_DRM_STAT_DMA]);	sarea_priv->last_enqueue = dev_priv->counter - 1;	sarea_priv->last_dispatch = (int)hw_status[5];	return 0;}static int i810_rstatus(struct drm_device *dev, void *data,			struct drm_file *file_priv){	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;	return (int)(((u32 *) (dev_priv->hw_status_page))[4]);}static int i810_ov0_info(struct drm_device *dev, void *data,			 struct drm_file *file_priv){	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;	drm_i810_overlay_t *ov = data;	ov->offset = dev_priv->overlay_offset;	ov->physical = dev_priv->overlay_physical;	return 0;}static int i810_fstatus(struct drm_device *dev, void *data,			struct drm_file *file_priv){	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;	LOCK_TEST_WITH_RETURN(dev, file_priv);	return I810_READ(0x30008);}static int i810_ov0_flip(struct drm_device *dev, void *data,			 struct drm_file *file_priv){	drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;	LOCK_TEST_WITH_RETURN(dev, file_priv);	//Tell the overlay to update	I810_WRITE(0x30000, dev_priv->overlay_physical | 0x80000000);	return 0;}/* Not sure why this isn't set all the time: */static void i810_do_init_pageflip(struct drm_device * dev){	drm_i810_private_t *dev_priv = dev->dev_private;	DRM_DEBUG("%s\n", __FUNCTION__);	dev_priv->page_flipping = 1;	dev_priv->current_page = 0;	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;}static int i810_do_cleanup_pageflip(struct drm_device * dev){	drm_i810_private_t *dev_priv = dev->dev_private;	DRM_DEBUG("%s\n", __FUNCTION__);	if (dev_priv->current_page != 0)		i810_dma_dispatch_flip(dev);	dev_priv->page_flipping = 0;	return 0;}static int i810_flip_bufs(struct drm_device *dev, void *data,			  struct drm_file *file_priv){	drm_i810_private_t *dev_priv = dev->dev_private;	DRM_DEBUG("%s\n", __FUNCTION__);	LOCK_TEST_WITH_RETURN(dev, file_priv);	if (!dev_priv->page_flipping)		i810_do_init_pageflip(dev);	i810_dma_dispatch_flip(dev);	return 0;}int i810_driver_load(struct drm_device *dev, unsigned long flags){	/* i810 has 4 more counters */	dev->counters += 4;	dev->types[6] = _DRM_STAT_IRQ;	dev->types[7] = _DRM_STAT_PRIMARY;	dev->types[8] = _DRM_STAT_SECONDARY;	dev->types[9] = _DRM_STAT_DMA;	return 0;}void i810_driver_lastclose(struct drm_device * dev){	i810_dma_cleanup(dev);}void i810_driver_preclose(struct drm_device * dev, struct drm_file *file_priv){	if (dev->dev_private) {		drm_i810_private_t *dev_priv = dev->dev_private;		if (dev_priv->page_flipping) {			i810_do_cleanup_pageflip(dev);		}	}}void i810_driver_reclaim_buffers_locked(struct drm_device * dev,					struct drm_file *file_priv){	i810_reclaim_buffers(dev, file_priv);}int i810_driver_dma_quiescent(struct drm_device * dev){	i810_dma_quiescent(dev);	return 0;}struct drm_ioctl_desc i810_ioctls[] = {	DRM_IOCTL_DEF(DRM_I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),	DRM_IOCTL_DEF(DRM_I810_VERTEX, i810_dma_vertex, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I810_CLEAR, i810_clear_bufs, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I810_FLUSH, i810_flush_ioctl, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I810_GETAGE, i810_getage, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I810_GETBUF, i810_getbuf, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I810_SWAP, i810_swap_bufs, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I810_COPY, i810_copybuf, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I810_DOCOPY, i810_docopy, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I810_OV0INFO, i810_ov0_info, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I810_FSTATUS, i810_fstatus, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I810_OV0FLIP, i810_ov0_flip, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I810_MC, i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),	DRM_IOCTL_DEF(DRM_I810_RSTATUS, i810_rstatus, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I810_FLIP, i810_flip_bufs, DRM_AUTH)};int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);/** * Determine if the device really is AGP or not. * * All Intel graphics chipsets are treated as AGP, even if they are really * PCI-e. * * \param dev   The device to be tested. * * \returns * A value of 1 is always retured to indictate every i810 is AGP. */int i810_driver_device_is_agp(struct drm_device * dev){	return 1;}

⌨️ 快捷键说明

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