📄 mga_drv.c
字号:
return 0;}/* mga_init is called via init_module at module load time, or via * linux/init/main.c (this is not currently supported). */static int __init mga_init(void){ int retcode; drm_device_t *dev = &mga_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(mga);#endif if ((retcode = misc_register(&mga_misc))) { DRM_ERROR("Cannot register \"%s\"\n", MGA_NAME); return retcode; } dev->device = MKDEV(MISC_MAJOR, mga_misc.minor); dev->name = MGA_NAME; drm_mem_init(); drm_proc_init(dev); dev->agp = drm_agp_init(); if(dev->agp == NULL) { DRM_INFO("The mga drm module requires the agpgart module" " to function correctly\nPlease load the agpgart" " module before you load the mga module\n"); drm_proc_cleanup(); misc_deregister(&mga_misc); mga_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 if((retcode = drm_ctxbitmap_init(dev))) { DRM_ERROR("Cannot allocate memory for context bitmap.\n"); drm_proc_cleanup(); misc_deregister(&mga_misc); mga_takedown(dev); return retcode; } DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", MGA_NAME, MGA_MAJOR, MGA_MINOR, MGA_PATCHLEVEL, MGA_DATE, mga_misc.minor); return 0;}/* mga_cleanup is called via cleanup_module at module unload time. */static void __exit mga_cleanup(void){ drm_device_t *dev = &mga_device; DRM_DEBUG("\n"); drm_proc_cleanup(); if (misc_deregister(&mga_misc)) { DRM_ERROR("Cannot unload module\n"); } else { DRM_INFO("Module unloaded\n"); } drm_ctxbitmap_cleanup(dev);#ifdef CONFIG_MTRR if(dev->agp && dev->agp->agp_mtrr) { int retval; retval = mtrr_del(dev->agp->agp_mtrr, dev->agp->agp_info.aper_base, dev->agp->agp_info.aper_size * 1024*1024); DRM_DEBUG("mtrr_del = %d\n", retval); }#endif mga_takedown(dev); if (dev->agp) { drm_agp_uninit(); drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS); dev->agp = NULL; }}module_init(mga_init);module_exit(mga_cleanup);int mga_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 = MGA_MAJOR; version.version_minor = MGA_MINOR; version.version_patchlevel = MGA_PATCHLEVEL; DRM_COPY(version.name, MGA_NAME); DRM_COPY(version.date, MGA_DATE); DRM_COPY(version.desc, MGA_DESC); if (copy_to_user((drm_version_t *)arg, &version, sizeof(version))) return -EFAULT; return 0;}int mga_open(struct inode *inode, struct file *filp){ drm_device_t *dev = &mga_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 mga_setup(dev); } spin_unlock(&dev->count_lock); } return retcode;}int mga_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) { mga_reclaim_buffers(dev, priv->pid); DRM_INFO("Process %d dead (ctx %d, d_s = 0x%02lx)\n", current->pid, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock), dev->dev_private ? ((drm_mga_private_t *)dev->dev_private) ->dispatch_status : 0); if (dev->dev_private) ((drm_mga_private_t *)dev->dev_private) ->dispatch_status &= MGA_IN_DISPATCH; drm_lock_free(dev, &dev->lock.hw_lock->lock, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); } 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) { mga_reclaim_buffers(dev, priv->pid); if (dev->dev_private) ((drm_mga_private_t *)dev->dev_private) ->dispatch_status &= MGA_IN_DISPATCH; drm_lock_free(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT); } } drm_fasync(-1, filp, 0); down(&dev->struct_sem); if (priv->remove_auth_on_close == 1) { drm_file_t *temp = dev->file_first; while(temp) { temp->authenticated = 0; temp = temp->next; } } 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 mga_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 mga_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; if (nr >= MGA_IOCTL_COUNT) { retcode = -EINVAL; } else { ioctl = &mga_ioctls[nr]; func = ioctl->func; if (!func) { DRM_DEBUG("no function: pid = %d, cmd = 0x%02x," " nr = 0x%02x, dev 0x%x, auth = %d\n", current->pid, cmd, nr, dev->device, priv->authenticated); 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 mga_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; } 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); mga_dma_schedule(dev, 1); if (drm_lock_free(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) DRM_ERROR("\n"); unblock_all_signals(); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -