📄 i810_dma.c
字号:
}int i810_irq_uninstall(drm_device_t *dev){ int irq; u16 temp;/* return 0; */ down(&dev->struct_sem); irq = dev->irq; dev->irq = 0; up(&dev->struct_sem); if (!irq) return -EINVAL; DRM_DEBUG( "Interrupt UnInstall: %d\n", irq); DRM_DEBUG("%d\n", irq); temp = I810_READ16(I810REG_INT_IDENTITY_R); temp = temp & ~(0x6000); if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R, temp); /* Clear all interrupts */ temp = I810_READ16(I810REG_INT_ENABLE_R); temp = temp & 0x6000; I810_WRITE16(I810REG_INT_ENABLE_R, temp); /* Disable all interrupts */ free_irq(irq, dev); return 0;}int i810_control(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_control_t ctl; int retcode; DRM_DEBUG( "i810_control\n"); if (copy_from_user(&ctl, (drm_control_t *)arg, sizeof(ctl))) return -EFAULT; switch (ctl.func) { case DRM_INST_HANDLER: if ((retcode = i810_irq_install(dev, ctl.irq))) return retcode; break; case DRM_UNINST_HANDLER: if ((retcode = i810_irq_uninstall(dev))) return retcode; break; default: return -EINVAL; } return 0;}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); */}static 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_lock(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; DECLARE_WAITQUEUE(entry, current); int ret = 0; drm_lock_t lock; if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock))) return -EFAULT; if (lock.context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", current->pid, lock.context); return -EINVAL; } DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n", lock.context, current->pid, dev->lock.hw_lock->lock, lock.flags); if (lock.context < 0) { return -EINVAL; } /* Only one queue: */ if (!ret) { add_wait_queue(&dev->lock.lock_queue, &entry); for (;;) { current->state = TASK_INTERRUPTIBLE; if (!dev->lock.hw_lock) { /* Device has been unregistered */ ret = -EINTR; break; } if (drm_lock_take(&dev->lock.hw_lock->lock, lock.context)) { dev->lock.pid = current->pid; dev->lock.lock_time = jiffies; atomic_inc(&dev->total_locks); break; /* Got lock */ } /* Contention */ atomic_inc(&dev->total_sleeps); DRM_DEBUG("Calling lock schedule\n"); schedule(); if (signal_pending(current)) { ret = -ERESTARTSYS; break; } } current->state = TASK_RUNNING; remove_wait_queue(&dev->lock.lock_queue, &entry); } if (!ret) { sigemptyset(&dev->sigmask); sigaddset(&dev->sigmask, SIGSTOP); sigaddset(&dev->sigmask, SIGTSTP); sigaddset(&dev->sigmask, SIGTTIN); sigaddset(&dev->sigmask, SIGTTOU); dev->sigdata.context = lock.context; dev->sigdata.lock = dev->lock.hw_lock; block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); if (lock.flags & _DRM_LOCK_QUIESCENT) { DRM_DEBUG("_DRM_LOCK_QUIESCENT\n"); DRM_DEBUG("fred\n"); i810_dma_quiescent(dev); } } DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); return ret;}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, &dma->total_bytes); atomic_inc(&dma->total_dmas); 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; } 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; /* Stopping end users copying their data to the entire kernel is good.. */ 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 + -