📄 i830_dma.c
字号:
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(); }}static 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; } }}static 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->head->dev; LOCK_TEST_WITH_RETURN(dev, filp); i830_flush_queue(dev); return 0;}static 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->head->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;}static 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->head->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;}static 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->head->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;}static 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;}static 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->head->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;}static 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->head->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;}static 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->head->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;}static 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;}static int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ return 0;}static 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->head->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;}static 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->head->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_prerelease(drm_device_t * dev, DRMFILE filp){ 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_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;}drm_ioctl_desc_t i830_ioctls[] = { [DRM_IOCTL_NR(DRM_I830_INIT)] = {i830_dma_init, 1, 1}, [DRM_IOCTL_NR(DRM_I830_VERTEX)] = {i830_dma_vertex, 1, 0}, [DRM_IOCTL_NR(DRM_I830_CLEAR)] = {i830_clear_bufs, 1, 0}, [DRM_IOCTL_NR(DRM_I830_FLUSH)] = {i830_flush_ioctl, 1, 0}, [DRM_IOCTL_NR(DRM_I830_GETAGE)] = {i830_getage, 1, 0}, [DRM_IOCTL_NR(DRM_I830_GETBUF)] = {i830_getbuf, 1, 0}, [DRM_IOCTL_NR(DRM_I830_SWAP)] = {i830_swap_bufs, 1, 0}, [DRM_IOCTL_NR(DRM_I830_COPY)] = {i830_copybuf, 1, 0}, [DRM_IOCTL_NR(DRM_I830_DOCOPY)] = {i830_docopy, 1, 0}, [DRM_IOCTL_NR(DRM_I830_FLIP)] = {i830_flip_bufs, 1, 0}, [DRM_IOCTL_NR(DRM_I830_IRQ_EMIT)] = {i830_irq_emit, 1, 0}, [DRM_IOCTL_NR(DRM_I830_IRQ_WAIT)] = {i830_irq_wait, 1, 0}, [DRM_IOCTL_NR(DRM_I830_GETPARAM)] = {i830_getparam, 1, 0}, [DRM_IOCTL_NR(DRM_I830_SETPARAM)] = {i830_setparam, 1, 0}};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(drm_device_t * dev){ return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -