📄 r128_drv.c
字号:
if ((retcode = misc_register(&r128_misc))) { DRM_ERROR("Cannot register \"%s\"\n", R128_NAME); return retcode; } dev->device = MKDEV(MISC_MAJOR, r128_misc.minor); dev->name = R128_NAME; drm_mem_init(); drm_proc_init(dev);#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE) dev->agp = drm_agp_init(); if (dev->agp == NULL) { DRM_ERROR("Cannot initialize agpgart module.\n"); drm_proc_cleanup(); misc_deregister(&r128_misc); r128_takedown(dev); return -ENOMEM; }#ifdef CONFIG_MTRR dev->agp->agp_mtrr = mtrr_add(dev->agp->agp_info.aper_base, dev->agp->agp_info.aper_size*1024*1024, MTRR_TYPE_WRCOMB, 1);#endif#endif if((retcode = drm_ctxbitmap_init(dev))) { DRM_ERROR("Cannot allocate memory for context bitmap.\n"); drm_proc_cleanup(); misc_deregister(&r128_misc); r128_takedown(dev); return retcode; } DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", R128_NAME, R128_MAJOR, R128_MINOR, R128_PATCHLEVEL, R128_DATE, r128_misc.minor); return 0;}/* r128_cleanup is called via cleanup_module at module unload time. */static void __exit r128_cleanup(void){ drm_device_t *dev = &r128_device; DRM_DEBUG("\n"); drm_proc_cleanup(); if (misc_deregister(&r128_misc)) { DRM_ERROR("Cannot unload module\n"); } else { DRM_INFO("Module unloaded\n"); } drm_ctxbitmap_cleanup(dev); r128_takedown(dev);#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE) if (dev->agp) { drm_agp_uninit(); drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS); dev->agp = NULL; }#endif}module_init(r128_init);module_exit(r128_cleanup);int r128_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 = R128_MAJOR; version.version_minor = R128_MINOR; version.version_patchlevel = R128_PATCHLEVEL; DRM_COPY(version.name, R128_NAME); DRM_COPY(version.date, R128_DATE); DRM_COPY(version.desc, R128_DESC); if (copy_to_user((drm_version_t *)arg, &version, sizeof(version))) return -EFAULT; return 0;}int r128_open(struct inode *inode, struct file *filp){ drm_device_t *dev = &r128_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 r128_setup(dev); } spin_unlock(&dev->count_lock); } return retcode;}int r128_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("open_count = %d\n", dev->open_count); if (!(retcode = drm_release(inode, filp))) {#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 r128_takedown(dev); } spin_unlock(&dev->count_lock); } unlock_kernel(); return retcode;}/* r128_ioctl is called whenever a process performs an ioctl on /dev/drm. */int r128_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 >= R128_IOCTL_COUNT) { retcode = -EINVAL; } else { ioctl = &r128_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); } }#if 0 if ( retcode ) { DRM_INFO( "%s 0x%x ret = %d\n", __FUNCTION__, nr, retcode ); }#endif atomic_dec(&dev->ioctl_count); return retcode;}int r128_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 DRM_DMA_HISTOGRAM cycles_t start; dev->lck_start = start = get_cycles();#endif 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; 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); 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_READY) { /* Wait for space in DMA/FIFO */ } if (lock.flags & _DRM_LOCK_QUIESCENT) { /* Make hardware quiescent */ DRM_DEBUG( "not quiescent!\n" );#if 0 r128_quiescent(dev);#endif } }#if LINUX_VERSION_CODE < 0x020400 if (lock.context != r128_res_ctx.handle) { current->counter = 5; current->priority = DEF_PRIORITY/4; }#endif DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");#if DRM_DMA_HISTOGRAM atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]);#endif return ret;}int r128_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); /* FIXME: Try to send data to card here */ if (!dev->context_flag) { if (drm_lock_free(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) { DRM_ERROR("\n"); } }#if LINUX_VERSION_CODE < 0x020400 if (lock.context != r128_res_ctx.handle) { current->counter = 5; current->priority = DEF_PRIORITY; }#endif unblock_all_signals(); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -