📄 i830_dma.c
字号:
pbox->x1, pbox->y1, pbox->x2, pbox->y2); BEGIN_LP_RING( 8 ); OUT_RING( CMD ); OUT_RING( BR13 ); OUT_RING( (pbox->y1 << 16) | pbox->x1 ); OUT_RING( (pbox->y2 << 16) | pbox->x2 ); if (dev_priv->current_page == 0) OUT_RING( dev_priv->front_offset ); else OUT_RING( dev_priv->back_offset ); OUT_RING( (pbox->y1 << 16) | pbox->x1 ); OUT_RING( BR13 & 0xffff ); if (dev_priv->current_page == 0) OUT_RING( dev_priv->back_offset ); else OUT_RING( dev_priv->front_offset ); ADVANCE_LP_RING(); }}static void i830_dma_dispatch_flip( drm_device_t *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(drm_device_t *dev, drm_buf_t *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; drm_clip_rect_t *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(); }}void i830_dma_quiescent(drm_device_t *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(drm_device_t *dev){ drm_i830_private_t *dev_priv = dev->dev_private; drm_device_dma_t *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++) { drm_buf_t *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 */void i830_reclaim_buffers(drm_device_t *dev, struct file *filp){ drm_device_dma_t *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++) { drm_buf_t *buf = dma->buflist[ i ]; drm_i830_buf_priv_t *buf_priv = buf->dev_private; if (buf->filp == filp && 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; } }}int i830_flush_ioctl(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; LOCK_TEST_WITH_RETURN(dev, filp); i830_flush_queue(dev); return 0;}int i830_dma_vertex(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; 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; if (copy_from_user(&vertex, (drm_i830_vertex_t __user *)arg, sizeof(vertex))) return -EFAULT; LOCK_TEST_WITH_RETURN(dev, filp); 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;}int i830_clear_bufs(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_i830_clear_t clear; if (copy_from_user(&clear, (drm_i830_clear_t __user *)arg, sizeof(clear))) return -EFAULT; LOCK_TEST_WITH_RETURN(dev, filp); /* 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;}int i830_swap_bufs(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_DEBUG("i830_swap_bufs\n"); LOCK_TEST_WITH_RETURN(dev, filp); i830_dma_dispatch_swap( dev ); return 0;}/* Not sure why this isn't set all the time: */ static void i830_do_init_pageflip( drm_device_t *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;}int i830_do_cleanup_pageflip( drm_device_t *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;}int i830_flip_bufs(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_i830_private_t *dev_priv = dev->dev_private; DRM_DEBUG("%s\n", __FUNCTION__); LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv->page_flipping) i830_do_init_pageflip( dev ); i830_dma_dispatch_flip( dev ); return 0;}int i830_getage(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_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;}int i830_getbuf(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; int retcode = 0; drm_i830_dma_t d; 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"); if (copy_from_user(&d, (drm_i830_dma_t __user *)arg, sizeof(d))) return -EFAULT; LOCK_TEST_WITH_RETURN(dev, filp); d.granted = 0; retcode = i830_dma_get_buffer(dev, &d, filp); DRM_DEBUG("i830_dma: %d returning %d, granted = %d\n", current->pid, retcode, d.granted); if (copy_to_user((drm_dma_t __user *)arg, &d, sizeof(d))) return -EFAULT; sarea_priv->last_dispatch = (int) hw_status[5]; return retcode;}int i830_copybuf(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ /* Never copy - 2.4.x doesn't need it */ return 0;}int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ return 0;}int i830_getparam( 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_i830_private_t *dev_priv = dev->dev_private; drm_i830_getparam_t param; int value; if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); return -EINVAL; } if (copy_from_user(¶m, (drm_i830_getparam_t __user *)arg, sizeof(param) )) return -EFAULT; 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;}int i830_setparam( 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_i830_private_t *dev_priv = dev->dev_private; drm_i830_setparam_t param; if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); return -EINVAL; } if (copy_from_user(¶m, (drm_i830_setparam_t __user *)arg, sizeof(param) )) return -EFAULT; switch( param.param ) { case I830_SETPARAM_USE_MI_BATCHBUFFER_START: dev_priv->use_mi_batchbuffer_start = param.value; break; default: return -EINVAL; } return 0;}void i830_driver_pretakedown(drm_device_t *dev){ i830_dma_cleanup( dev );}void i830_driver_release(drm_device_t *dev, struct file *filp){ i830_reclaim_buffers(dev, filp);}int i830_driver_dma_quiescent(drm_device_t *dev){ i830_dma_quiescent( dev ); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -