i830_dma.c

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

C
1,554
字号
	}}static void i830_dma_dispatch_flip(struct drm_device * dev){	drm_i830_private_t *dev_priv = dev->dev_private;	RING_LOCALS;	DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",		  __FUNCTION__,		  dev_priv->current_page,		  dev_priv->sarea_priv->pf_current_page);	i830_kernel_lost_context(dev);	if (dev_priv->do_boxes) {		dev_priv->sarea_priv->perf_boxes |= I830_BOX_FLIP;		i830_cp_performance_boxes(dev);	}	BEGIN_LP_RING(2);	OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);	OUT_RING(0);	ADVANCE_LP_RING();	BEGIN_LP_RING(6);	OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);	OUT_RING(0);	if (dev_priv->current_page == 0) {		OUT_RING(dev_priv->back_offset);		dev_priv->current_page = 1;	} else {		OUT_RING(dev_priv->front_offset);		dev_priv->current_page = 0;	}	OUT_RING(0);	ADVANCE_LP_RING();	BEGIN_LP_RING(2);	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);	OUT_RING(0);	ADVANCE_LP_RING();	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;}static void i830_dma_dispatch_vertex(struct drm_device * dev,				     struct drm_buf * buf, int discard, int used){	drm_i830_private_t *dev_priv = dev->dev_private;	drm_i830_buf_priv_t *buf_priv = buf->dev_private;	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;	struct drm_clip_rect *box = sarea_priv->boxes;	int nbox = sarea_priv->nbox;	unsigned long address = (unsigned long)buf->bus_address;	unsigned long start = address - dev->agp->base;	int i = 0, u;	RING_LOCALS;	i830_kernel_lost_context(dev);	if (nbox > I830_NR_SAREA_CLIPRECTS)		nbox = I830_NR_SAREA_CLIPRECTS;	if (discard) {		u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,			    I830_BUF_HARDWARE);		if (u != I830_BUF_CLIENT) {			DRM_DEBUG("xxxx 2\n");		}	}	if (used > 4 * 1023)		used = 0;	if (sarea_priv->dirty)		i830EmitState(dev);	DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n",		  address, used, nbox);	dev_priv->counter++;	DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter);	DRM_DEBUG("i830_dma_dispatch\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 == I830_BUF_MAPPED) {		u32 *vp = buf_priv->kernel_virtual;		vp[0] = (GFX_OP_PRIMITIVE |			 sarea_priv->vertex_prim | ((used / 4) - 2));		if (dev_priv->use_mi_batchbuffer_start) {			vp[used / 4] = MI_BATCH_BUFFER_END;			used += 4;		}		if (used & 4) {			vp[used / 4] = 0;			used += 4;		}		i830_unmap_buffer(buf);	}	if (used) {		do {			if (i < nbox) {				BEGIN_LP_RING(6);				OUT_RING(GFX_OP_DRAWRECT_INFO);				OUT_RING(sarea_priv->					 BufferState[I830_DESTREG_DR1]);				OUT_RING(box[i].x1 | (box[i].y1 << 16));				OUT_RING(box[i].x2 | (box[i].y2 << 16));				OUT_RING(sarea_priv->					 BufferState[I830_DESTREG_DR4]);				OUT_RING(0);				ADVANCE_LP_RING();			}			if (dev_priv->use_mi_batchbuffer_start) {				BEGIN_LP_RING(2);				OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));				OUT_RING(start | MI_BATCH_NON_SECURE);				ADVANCE_LP_RING();			} else {				BEGIN_LP_RING(4);				OUT_RING(MI_BATCH_BUFFER);				OUT_RING(start | MI_BATCH_NON_SECURE);				OUT_RING(start + used - 4);				OUT_RING(0);				ADVANCE_LP_RING();			}		} while (++i < nbox);	}	if (discard) {		dev_priv->counter++;		(void)cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,			      I830_BUF_HARDWARE);		BEGIN_LP_RING(8);		OUT_RING(CMD_STORE_DWORD_IDX);		OUT_RING(20);		OUT_RING(dev_priv->counter);		OUT_RING(CMD_STORE_DWORD_IDX);		OUT_RING(buf_priv->my_use_idx);		OUT_RING(I830_BUF_FREE);		OUT_RING(CMD_REPORT_HEAD);		OUT_RING(0);		ADVANCE_LP_RING();	}}static void i830_dma_quiescent(struct drm_device * dev){	drm_i830_private_t *dev_priv = dev->dev_private;	RING_LOCALS;	i830_kernel_lost_context(dev);	BEGIN_LP_RING(4);	OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);	OUT_RING(CMD_REPORT_HEAD);	OUT_RING(0);	OUT_RING(0);	ADVANCE_LP_RING();	i830_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);}static int i830_flush_queue(struct drm_device * dev){	drm_i830_private_t *dev_priv = dev->dev_private;	struct drm_device_dma *dma = dev->dma;	int i, ret = 0;	RING_LOCALS;	i830_kernel_lost_context(dev);	BEGIN_LP_RING(2);	OUT_RING(CMD_REPORT_HEAD);	OUT_RING(0);	ADVANCE_LP_RING();	i830_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);	for (i = 0; i < dma->buf_count; i++) {		struct drm_buf *buf = dma->buflist[i];		drm_i830_buf_priv_t *buf_priv = buf->dev_private;		int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE,				   I830_BUF_FREE);		if (used == I830_BUF_HARDWARE)			DRM_DEBUG("reclaimed from HARDWARE\n");		if (used == I830_BUF_CLIENT)			DRM_DEBUG("still on client\n");	}	return ret;}/* Must be called with the lock held */static void i830_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;	i830_flush_queue(dev);	for (i = 0; i < dma->buf_count; i++) {		struct drm_buf *buf = dma->buflist[i];		drm_i830_buf_priv_t *buf_priv = buf->dev_private;		if (buf->file_priv == file_priv && buf_priv) {			int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,					   I830_BUF_FREE);			if (used == I830_BUF_CLIENT)				DRM_DEBUG("reclaimed from client\n");			if (buf_priv->currently_mapped == I830_BUF_MAPPED)				buf_priv->currently_mapped = I830_BUF_UNMAPPED;		}	}}static int i830_flush_ioctl(struct drm_device *dev, void *data,			    struct drm_file *file_priv){	LOCK_TEST_WITH_RETURN(dev, file_priv);	i830_flush_queue(dev);	return 0;}static int i830_dma_vertex(struct drm_device *dev, void *data,			   struct drm_file *file_priv){	struct drm_device_dma *dma = dev->dma;	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;	u32 *hw_status = dev_priv->hw_status_page;	drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)	    dev_priv->sarea_priv;	drm_i830_vertex_t *vertex = data;	LOCK_TEST_WITH_RETURN(dev, file_priv);	DRM_DEBUG("i830 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;	i830_dma_dispatch_vertex(dev,				 dma->buflist[vertex->idx],				 vertex->discard, vertex->used);	sarea_priv->last_enqueue = dev_priv->counter - 1;	sarea_priv->last_dispatch = (int)hw_status[5];	return 0;}static int i830_clear_bufs(struct drm_device *dev, void *data,			   struct drm_file *file_priv){	drm_i830_clear_t *clear = data;	LOCK_TEST_WITH_RETURN(dev, file_priv);	/* GH: Someone's doing nasty things... */	if (!dev->dev_private) {		return -EINVAL;	}	i830_dma_dispatch_clear(dev, clear->flags,				clear->clear_color,				clear->clear_depth, clear->clear_depthmask);	return 0;}static int i830_swap_bufs(struct drm_device *dev, void *data,			  struct drm_file *file_priv){	DRM_DEBUG("i830_swap_bufs\n");	LOCK_TEST_WITH_RETURN(dev, file_priv);	i830_dma_dispatch_swap(dev);	return 0;}/* Not sure why this isn't set all the time: */static void i830_do_init_pageflip(struct drm_device * dev){	drm_i830_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 i830_do_cleanup_pageflip(struct drm_device * dev){	drm_i830_private_t *dev_priv = dev->dev_private;	DRM_DEBUG("%s\n", __FUNCTION__);	if (dev_priv->current_page != 0)		i830_dma_dispatch_flip(dev);	dev_priv->page_flipping = 0;	return 0;}static int i830_flip_bufs(struct drm_device *dev, void *data,			  struct drm_file *file_priv){	drm_i830_private_t *dev_priv = dev->dev_private;	DRM_DEBUG("%s\n", __FUNCTION__);	LOCK_TEST_WITH_RETURN(dev, file_priv);	if (!dev_priv->page_flipping)		i830_do_init_pageflip(dev);	i830_dma_dispatch_flip(dev);	return 0;}static int i830_getage(struct drm_device *dev, void *data,		       struct drm_file *file_priv){	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;	u32 *hw_status = dev_priv->hw_status_page;	drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)	    dev_priv->sarea_priv;	sarea_priv->last_dispatch = (int)hw_status[5];	return 0;}static int i830_getbuf(struct drm_device *dev, void *data,		       struct drm_file *file_priv){	int retcode = 0;	drm_i830_dma_t *d = data;	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;	u32 *hw_status = dev_priv->hw_status_page;	drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)	    dev_priv->sarea_priv;	DRM_DEBUG("getbuf\n");	LOCK_TEST_WITH_RETURN(dev, file_priv);	d->granted = 0;	retcode = i830_dma_get_buffer(dev, d, file_priv);	DRM_DEBUG("i830_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 i830_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 i830_docopy(struct drm_device *dev, void *data,		       struct drm_file *file_priv){	return 0;}static int i830_getparam(struct drm_device *dev, void *data,			 struct drm_file *file_priv){	drm_i830_private_t *dev_priv = dev->dev_private;	drm_i830_getparam_t *param = data;	int value;	if (!dev_priv) {		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);		return -EINVAL;	}	switch (param->param) {	case I830_PARAM_IRQ_ACTIVE:		value = dev->irq_enabled;		break;	default:		return -EINVAL;	}	if (copy_to_user(param->value, &value, sizeof(int))) {		DRM_ERROR("copy_to_user\n");		return -EFAULT;	}	return 0;}static int i830_setparam(struct drm_device *dev, void *data,			 struct drm_file *file_priv){	drm_i830_private_t *dev_priv = dev->dev_private;	drm_i830_setparam_t *param = data;	if (!dev_priv) {		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);		return -EINVAL;	}	switch (param->param) {	case I830_SETPARAM_USE_MI_BATCHBUFFER_START:		dev_priv->use_mi_batchbuffer_start = param->value;		break;	default:		return -EINVAL;	}	return 0;}int i830_driver_load(struct drm_device *dev, unsigned long flags){	/* i830 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 i830_driver_lastclose(struct drm_device * dev){	i830_dma_cleanup(dev);}void i830_driver_preclose(struct drm_device * dev, struct drm_file *file_priv){	if (dev->dev_private) {		drm_i830_private_t *dev_priv = dev->dev_private;		if (dev_priv->page_flipping) {			i830_do_cleanup_pageflip(dev);		}	}}void i830_driver_reclaim_buffers_locked(struct drm_device * dev, struct drm_file *file_priv){	i830_reclaim_buffers(dev, file_priv);}int i830_driver_dma_quiescent(struct drm_device * dev){	i830_dma_quiescent(dev);	return 0;}struct drm_ioctl_desc i830_ioctls[] = {	DRM_IOCTL_DEF(DRM_I830_INIT, i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),	DRM_IOCTL_DEF(DRM_I830_VERTEX, i830_dma_vertex, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I830_CLEAR, i830_clear_bufs, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I830_FLUSH, i830_flush_ioctl, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I830_GETAGE, i830_getage, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I830_GETBUF, i830_getbuf, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I830_SWAP, i830_swap_bufs, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I830_COPY, i830_copybuf, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I830_DOCOPY, i830_docopy, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I830_FLIP, i830_flip_bufs, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I830_IRQ_EMIT, i830_irq_emit, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I830_IRQ_WAIT, i830_irq_wait, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I830_GETPARAM, i830_getparam, DRM_AUTH),	DRM_IOCTL_DEF(DRM_I830_SETPARAM, i830_setparam, DRM_AUTH)};int i830_max_ioctl = DRM_ARRAY_SIZE(i830_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 i8xx is AGP. */int i830_driver_device_is_agp(struct drm_device * dev){	return 1;}

⌨️ 快捷键说明

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