📄 i810_dma.c
字号:
if (buf_priv->currently_mapped == I810_BUF_MAPPED) { *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE | sarea_priv->vertex_prim | ((used/4)-2)); if (used & 4) { *(u32 *)((u32)buf_priv->virtual + used) = 0; used += 4; } i810_unmap_buffer(buf); } if (used) { do { if (i < nbox) { BEGIN_LP_RING(4); OUT_RING( GFX_OP_SCISSOR | SC_UPDATE_SCISSOR | SC_ENABLE ); OUT_RING( GFX_OP_SCISSOR_INFO ); OUT_RING( box[i].x1 | (box[i].y1<<16) ); OUT_RING( (box[i].x2-1) | ((box[i].y2-1)<<16) ); ADVANCE_LP_RING(); } 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(); } while (++i < nbox); } BEGIN_LP_RING(10); OUT_RING( CMD_STORE_DWORD_IDX ); OUT_RING( 20 ); OUT_RING( dev_priv->counter ); OUT_RING( 0 ); if (discard) { OUT_RING( CMD_STORE_DWORD_IDX ); OUT_RING( buf_priv->my_use_idx ); OUT_RING( I810_BUF_FREE ); OUT_RING( 0 ); } OUT_RING( CMD_REPORT_HEAD ); OUT_RING( 0 ); ADVANCE_LP_RING();}/* Interrupts are only for flushing */void i810_dma_service(int irq, void *device, struct pt_regs *regs){ drm_device_t *dev = (drm_device_t *)device; drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; u16 temp; atomic_inc(&dev->counts[_DRM_STAT_IRQ]); temp = I810_READ16(I810REG_INT_IDENTITY_R); temp = temp & ~(0x6000); if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R, temp); /* Clear all interrupts */ else return; queue_task(&dev->tq, &tq_immediate); mark_bh(IMMEDIATE_BH);}void i810_dma_immediate_bh(void *device){ drm_device_t *dev = (drm_device_t *) device; drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; atomic_set(&dev_priv->flush_done, 1); wake_up_interruptible(&dev_priv->flush_queue);}static inline void i810_dma_emit_flush(drm_device_t *dev){ drm_i810_private_t *dev_priv = dev->dev_private; RING_LOCALS; i810_kernel_lost_context(dev); BEGIN_LP_RING(2); OUT_RING( CMD_REPORT_HEAD ); OUT_RING( GFX_OP_USER_INTERRUPT ); ADVANCE_LP_RING();/* i810_wait_ring( dev, dev_priv->ring.Size - 8 ); *//* atomic_set(&dev_priv->flush_done, 1); *//* wake_up_interruptible(&dev_priv->flush_queue); */}static inline void i810_dma_quiescent_emit(drm_device_t *dev){ drm_i810_private_t *dev_priv = dev->dev_private; RING_LOCALS; i810_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( GFX_OP_USER_INTERRUPT ); ADVANCE_LP_RING();/* i810_wait_ring( dev, dev_priv->ring.Size - 8 ); *//* atomic_set(&dev_priv->flush_done, 1); *//* wake_up_interruptible(&dev_priv->flush_queue); */}void i810_dma_quiescent(drm_device_t *dev){ DECLARE_WAITQUEUE(entry, current); drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; unsigned long end; if(dev_priv == NULL) { return; } atomic_set(&dev_priv->flush_done, 0); add_wait_queue(&dev_priv->flush_queue, &entry); end = jiffies + (HZ*3); for (;;) { current->state = TASK_INTERRUPTIBLE; i810_dma_quiescent_emit(dev); if (atomic_read(&dev_priv->flush_done) == 1) break; if((signed)(end - jiffies) <= 0) { DRM_ERROR("lockup\n"); break; } schedule_timeout(HZ*3); if (signal_pending(current)) { break; } } current->state = TASK_RUNNING; remove_wait_queue(&dev_priv->flush_queue, &entry); return;}static int i810_flush_queue(drm_device_t *dev){ DECLARE_WAITQUEUE(entry, current); drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; drm_device_dma_t *dma = dev->dma; unsigned long end; int i, ret = 0; if(dev_priv == NULL) { return 0; } atomic_set(&dev_priv->flush_done, 0); add_wait_queue(&dev_priv->flush_queue, &entry); end = jiffies + (HZ*3); for (;;) { current->state = TASK_INTERRUPTIBLE; i810_dma_emit_flush(dev); if (atomic_read(&dev_priv->flush_done) == 1) break; if((signed)(end - jiffies) <= 0) { DRM_ERROR("lockup\n"); break; } schedule_timeout(HZ*3); if (signal_pending(current)) { ret = -EINTR; /* Can't restart */ break; } } current->state = TASK_RUNNING; remove_wait_queue(&dev_priv->flush_queue, &entry); for (i = 0; i < dma->buf_count; i++) { drm_buf_t *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 HARDWARE\n"); } return ret;}/* Must be called with the lock held */void i810_reclaim_buffers(drm_device_t *dev, pid_t pid){ drm_device_dma_t *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++) { drm_buf_t *buf = dma->buflist[ i ]; drm_i810_buf_priv_t *buf_priv = buf->dev_private; if (buf->pid == pid && 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; } }}int i810_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; DRM_DEBUG("i810_flush_ioctl\n"); if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_flush_ioctl called without lock held\n"); return -EINVAL; } i810_flush_queue(dev); return 0;}int i810_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_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; u32 *hw_status = (u32 *)dev_priv->hw_status_page; drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) dev_priv->sarea_priv; drm_i810_vertex_t vertex; if (copy_from_user(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex))) return -EFAULT; if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_dma_vertex called without lock held\n"); return -EINVAL; } 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;}int i810_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_i810_clear_t clear; if (copy_from_user(&clear, (drm_i810_clear_t *)arg, sizeof(clear))) return -EFAULT; if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_clear_bufs called without lock held\n"); return -EINVAL; } /* 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;}int i810_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("i810_swap_bufs\n"); if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_swap_buf called without lock held\n"); return -EINVAL; } i810_dma_dispatch_swap( dev ); return 0;}int i810_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_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; u32 *hw_status = (u32 *)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;}int i810_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_i810_dma_t d; drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; u32 *hw_status = (u32 *)dev_priv->hw_status_page; drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) dev_priv->sarea_priv; DRM_DEBUG("getbuf\n"); if (copy_from_user(&d, (drm_i810_dma_t *)arg, sizeof(d))) return -EFAULT; if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_dma called without lock held\n"); return -EINVAL; } d.granted = 0; retcode = i810_dma_get_buffer(dev, &d, filp); DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n", current->pid, retcode, d.granted); if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d))) return -EFAULT; sarea_priv->last_dispatch = (int) hw_status[5]; return retcode;}int i810_copybuf(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_i810_copy_t d; drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; u32 *hw_status = (u32 *)dev_priv->hw_status_page; drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) dev_priv->sarea_priv; drm_buf_t *buf; drm_i810_buf_priv_t *buf_priv; drm_device_dma_t *dma = dev->dma; if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_dma called without lock held\n"); return -EINVAL; } if (copy_from_user(&d, (drm_i810_copy_t *)arg, sizeof(d))) return -EFAULT; if(d.idx < 0 || d.idx > dma->buf_count) return -EINVAL; buf = dma->buflist[ d.idx ]; buf_priv = buf->dev_private; if (buf_priv->currently_mapped != I810_BUF_MAPPED) return -EPERM; if(d.used < 0 || d.used > buf->total) return -EINVAL; if (copy_from_user(buf_priv->virtual, d.address, d.used)) return -EFAULT; sarea_priv->last_dispatch = (int) hw_status[5]; return 0;}int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ if(VM_DONTCOPY == 0) return 1; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -