📄 i810_drv.c
字号:
dev->queue_count = 0; if (dev->lock.hw_lock) { dev->lock.hw_lock = NULL; /* SHM removed */ dev->lock.pid = 0; wake_up_interruptible(&dev->lock.lock_queue); } up(&dev->struct_sem); return 0;}/* i810_init is called via init_module at module load time, or via * linux/init/main.c (this is not currently supported). */static int __init i810_init(void){ int retcode; drm_device_t *dev = &i810_device; DRM_DEBUG("\n"); memset((void *)dev, 0, sizeof(*dev)); dev->count_lock = SPIN_LOCK_UNLOCKED; sema_init(&dev->struct_sem, 1);#ifdef MODULE drm_parse_options(i810);#endif DRM_DEBUG("doing misc_register\n"); if ((retcode = misc_register(&i810_misc))) { DRM_ERROR("Cannot register \"%s\"\n", I810_NAME); return retcode; } dev->device = MKDEV(MISC_MAJOR, i810_misc.minor); dev->name = I810_NAME; DRM_DEBUG("doing mem init\n"); drm_mem_init(); DRM_DEBUG("doing proc init\n"); drm_proc_init(dev); DRM_DEBUG("doing agp init\n"); dev->agp = drm_agp_init(); if(dev->agp == NULL) { DRM_INFO("The i810 drm module requires the agpgart module" " to function correctly\nPlease load the agpgart" " module before you load the i810 module\n"); drm_proc_cleanup(); misc_deregister(&i810_misc); i810_takedown(dev); return -ENOMEM; } DRM_DEBUG("doing ctxbitmap init\n"); if((retcode = drm_ctxbitmap_init(dev))) { DRM_ERROR("Cannot allocate memory for context bitmap.\n"); drm_proc_cleanup(); misc_deregister(&i810_misc); i810_takedown(dev); return retcode; } DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", I810_NAME, I810_MAJOR, I810_MINOR, I810_PATCHLEVEL, I810_DATE, i810_misc.minor); return 0;}/* i810_cleanup is called via cleanup_module at module unload time. */static void __exit i810_cleanup(void){ drm_device_t *dev = &i810_device; DRM_DEBUG("\n"); drm_proc_cleanup(); if (misc_deregister(&i810_misc)) { DRM_ERROR("Cannot unload module\n"); } else { DRM_INFO("Module unloaded\n"); } drm_ctxbitmap_cleanup(dev); i810_takedown(dev); if (dev->agp) { drm_agp_uninit(); drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS); dev->agp = NULL; }}module_init(i810_init);module_exit(i810_cleanup);int i810_version(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ drm_version_t version; int len; if (copy_from_user(&version, (drm_version_t *)arg, sizeof(version))) return -EFAULT;#define DRM_COPY(name,value) \ len = strlen(value); \ if (len > name##_len) len = name##_len; \ name##_len = strlen(value); \ if (len && name) { \ if (copy_to_user(name, value, len)) \ return -EFAULT; \ } version.version_major = I810_MAJOR; version.version_minor = I810_MINOR; version.version_patchlevel = I810_PATCHLEVEL; DRM_COPY(version.name, I810_NAME); DRM_COPY(version.date, I810_DATE); DRM_COPY(version.desc, I810_DESC); if (copy_to_user((drm_version_t *)arg, &version, sizeof(version))) return -EFAULT; return 0;}int i810_open(struct inode *inode, struct file *filp){ drm_device_t *dev = &i810_device; int retcode = 0; DRM_DEBUG("open_count = %d\n", dev->open_count); if (!(retcode = drm_open_helper(inode, filp, dev))) {#if LINUX_VERSION_CODE < 0x020333 MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */#endif atomic_inc(&dev->total_open); spin_lock(&dev->count_lock); if (!dev->open_count++) { spin_unlock(&dev->count_lock); return i810_setup(dev); } spin_unlock(&dev->count_lock); } return retcode;}int i810_release(struct inode *inode, struct file *filp){ drm_file_t *priv = filp->private_data; drm_device_t *dev; int retcode = 0; lock_kernel(); dev = priv->dev; DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n", current->pid, dev->device, dev->open_count); if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) && dev->lock.pid == current->pid) { i810_reclaim_buffers(dev, priv->pid); DRM_ERROR("Process %d dead, freeing lock for context %d\n", current->pid, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); drm_lock_free(dev, &dev->lock.hw_lock->lock, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); /* FIXME: may require heavy-handed reset of hardware at this point, possibly processed via a callback to the X server. */ } else if (dev->lock.hw_lock) { /* The lock is required to reclaim buffers */ DECLARE_WAITQUEUE(entry, current); add_wait_queue(&dev->lock.lock_queue, &entry); for (;;) { current->state = TASK_INTERRUPTIBLE; if (!dev->lock.hw_lock) { /* Device has been unregistered */ retcode = -EINTR; break; } if (drm_lock_take(&dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) { dev->lock.pid = priv->pid; dev->lock.lock_time = jiffies; atomic_inc(&dev->total_locks); break; /* Got lock */ } /* Contention */ atomic_inc(&dev->total_sleeps); schedule(); if (signal_pending(current)) { retcode = -ERESTARTSYS; break; } } current->state = TASK_RUNNING; remove_wait_queue(&dev->lock.lock_queue, &entry); if(!retcode) { i810_reclaim_buffers(dev, priv->pid); drm_lock_free(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT); } } drm_fasync(-1, filp, 0); down(&dev->struct_sem); if (priv->prev) priv->prev->next = priv->next; else dev->file_first = priv->next; if (priv->next) priv->next->prev = priv->prev; else dev->file_last = priv->prev; up(&dev->struct_sem); drm_free(priv, sizeof(*priv), DRM_MEM_FILES);#if LINUX_VERSION_CODE < 0x020333 MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */#endif atomic_inc(&dev->total_close); spin_lock(&dev->count_lock); if (!--dev->open_count) { if (atomic_read(&dev->ioctl_count) || dev->blocked) { DRM_ERROR("Device busy: %d %d\n", atomic_read(&dev->ioctl_count), dev->blocked); spin_unlock(&dev->count_lock); unlock_kernel(); return -EBUSY; } spin_unlock(&dev->count_lock); unlock_kernel(); return i810_takedown(dev); } spin_unlock(&dev->count_lock); unlock_kernel(); return retcode;}/* drm_ioctl is called whenever a process performs an ioctl on /dev/drm. */int i810_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ int nr = DRM_IOCTL_NR(cmd); drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; int retcode = 0; drm_ioctl_desc_t *ioctl; drm_ioctl_t *func; atomic_inc(&dev->ioctl_count); atomic_inc(&dev->total_ioctl); ++priv->ioctl_count; DRM_DEBUG("pid = %d, cmd = 0x%02x, nr = 0x%02x, dev 0x%x, auth = %d\n", current->pid, cmd, nr, dev->device, priv->authenticated); if (nr >= I810_IOCTL_COUNT) { retcode = -EINVAL; } else { ioctl = &i810_ioctls[nr]; func = ioctl->func; if (!func) { DRM_DEBUG("no function\n"); retcode = -EINVAL; } else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN)) || (ioctl->auth_needed && !priv->authenticated)) { retcode = -EACCES; } else { retcode = (func)(inode, filp, cmd, arg); } } atomic_dec(&dev->ioctl_count); return retcode;}int i810_unlock(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_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 frees lock (%d holds)\n", lock.context, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); atomic_inc(&dev->total_unlocks); if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock)) atomic_inc(&dev->total_contends); drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT); if (!dev->context_flag) { if (drm_lock_free(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) { DRM_ERROR("\n"); } }#if DRM_DMA_HISTOGRAM atomic_inc(&dev->histo.lhld[drm_histogram_slot(get_cycles() - dev->lck_start)]);#endif unblock_all_signals(); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -