drm_drv.c
来自「linux 内核源代码」· C语言 代码 · 共 541 行 · 第 1/2 页
C
541 行
} return 0;}EXPORT_SYMBOL(drm_init);/** * Called via cleanup_module() at module unload time. * * Cleans up all DRM device, calling drm_lastclose(). * * \sa drm_init */static void drm_cleanup(struct drm_device * dev){ DRM_DEBUG("\n"); if (!dev) { DRM_ERROR("cleanup called no dev\n"); return; } drm_lastclose(dev); drm_ht_remove(&dev->map_hash); drm_ctxbitmap_cleanup(dev); if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && dev->agp && dev->agp->agp_mtrr >= 0) { 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); } if (drm_core_has_AGP(dev) && dev->agp) { drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS); dev->agp = NULL; } if (dev->driver->unload) dev->driver->unload(dev); drm_put_head(&dev->primary); if (drm_put_dev(dev)) DRM_ERROR("Cannot unload module\n");}void drm_exit(struct drm_driver *driver){ int i; struct drm_device *dev = NULL; struct drm_head *head; DRM_DEBUG("\n"); for (i = 0; i < drm_cards_limit; i++) { head = drm_heads[i]; if (!head) continue; if (!head->dev) continue; if (head->dev->driver != driver) continue; dev = head->dev; if (dev) { /* release the pci driver */ if (dev->pdev) pci_dev_put(dev->pdev); drm_cleanup(dev); } } DRM_INFO("Module unloaded\n");}EXPORT_SYMBOL(drm_exit);/** File operations structure */static const struct file_operations drm_stub_fops = { .owner = THIS_MODULE, .open = drm_stub_open};static int __init drm_core_init(void){ int ret = -ENOMEM; drm_cards_limit = (drm_cards_limit < DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1); drm_heads = drm_calloc(drm_cards_limit, sizeof(*drm_heads), DRM_MEM_STUB); if (!drm_heads) goto err_p1; if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops)) goto err_p1; drm_class = drm_sysfs_create(THIS_MODULE, "drm"); if (IS_ERR(drm_class)) { printk(KERN_ERR "DRM: Error creating drm class.\n"); ret = PTR_ERR(drm_class); goto err_p2; } drm_proc_root = proc_mkdir("dri", NULL); if (!drm_proc_root) { DRM_ERROR("Cannot create /proc/dri\n"); ret = -1; goto err_p3; } DRM_INFO("Initialized %s %d.%d.%d %s\n", CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE); return 0; err_p3: drm_sysfs_destroy(drm_class); err_p2: unregister_chrdev(DRM_MAJOR, "drm"); drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB); err_p1: return ret;}static void __exit drm_core_exit(void){ remove_proc_entry("dri", NULL); drm_sysfs_destroy(drm_class); unregister_chrdev(DRM_MAJOR, "drm"); drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);}module_init(drm_core_init);module_exit(drm_core_exit);/** * Get version information * * \param inode device inode. * \param filp file pointer. * \param cmd command. * \param arg user argument, pointing to a drm_version structure. * \return zero on success or negative number on failure. * * Fills in the version information in \p arg. */static int drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv){ struct drm_version *version = data; int len; version->version_major = dev->driver->major; version->version_minor = dev->driver->minor; version->version_patchlevel = dev->driver->patchlevel; DRM_COPY(version->name, dev->driver->name); DRM_COPY(version->date, dev->driver->date); DRM_COPY(version->desc, dev->driver->desc); return 0;}/** * Called whenever a process performs an ioctl on /dev/drm. * * \param inode device inode. * \param file_priv DRM file private. * \param cmd command. * \param arg user argument. * \return zero on success or negative number on failure. * * Looks up the ioctl function in the ::ioctls table, checking for root * previleges if so required, and dispatches to the respective function. */int drm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ struct drm_file *file_priv = filp->private_data; struct drm_device *dev = file_priv->head->dev; struct drm_ioctl_desc *ioctl; drm_ioctl_t *func; unsigned int nr = DRM_IOCTL_NR(cmd); int retcode = -EINVAL; char *kdata = NULL; atomic_inc(&dev->ioctl_count); atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]); ++file_priv->ioctl_count; DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n", task_pid_nr(current), cmd, nr, (long)old_encode_dev(file_priv->head->device), file_priv->authenticated); if ((nr >= DRM_CORE_IOCTL_COUNT) && ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END))) goto err_i1; if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE]; else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) ioctl = &drm_ioctls[nr]; else goto err_i1; func = ioctl->func; /* is there a local override? */ if ((nr == DRM_IOCTL_NR(DRM_IOCTL_DMA)) && dev->driver->dma_ioctl) func = dev->driver->dma_ioctl; if (!func) { DRM_DEBUG("no function\n"); retcode = -EINVAL; } else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) || ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) || ((ioctl->flags & DRM_MASTER) && !file_priv->master)) { retcode = -EACCES; } else { if (cmd & (IOC_IN | IOC_OUT)) { kdata = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); if (!kdata) return -ENOMEM; } if (cmd & IOC_IN) { if (copy_from_user(kdata, (void __user *)arg, _IOC_SIZE(cmd)) != 0) { retcode = -EACCES; goto err_i1; } } retcode = func(dev, kdata, file_priv); if (cmd & IOC_OUT) { if (copy_to_user((void __user *)arg, kdata, _IOC_SIZE(cmd)) != 0) retcode = -EACCES; } } err_i1: if (kdata) kfree(kdata); atomic_dec(&dev->ioctl_count); if (retcode) DRM_DEBUG("ret = %x\n", retcode); return retcode;}EXPORT_SYMBOL(drm_ioctl);drm_local_map_t *drm_getsarea(struct drm_device *dev){ struct drm_map_list *entry; list_for_each_entry(entry, &dev->maplist, head) { if (entry->map && entry->map->type == _DRM_SHM && (entry->map->flags & _DRM_CONTAINS_LOCK)) { return entry->map; } } return NULL;}EXPORT_SYMBOL(drm_getsarea);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?