drm_drv.c
来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 515 行 · 第 1/2 页
C
515 行
DRM_DEBUG("\n"); drm_mem_init(); for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) { pid = (struct pci_device_id *)&driver->pci_driver.id_table[i]; pdev = NULL; /* pass back in pdev to account for multiple identical cards */ while ((pdev = pci_get_subsys(pid->vendor, pid->device, pid->subvendor, pid->subdevice, pdev)) != NULL) { /* stealth mode requires a manual probe */ pci_dev_get(pdev); drm_get_dev(pdev, pid, driver); } } 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(drm_device_t * dev){ DRM_DEBUG("\n"); if (!dev) { DRM_ERROR("cleanup called no dev\n"); return; } drm_lastclose(dev); if (dev->maplist) { drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS); dev->maplist = NULL; } 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; drm_device_t *dev = NULL; drm_head_t *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 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 inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->head->dev; drm_version_t __user *argp = (void __user *)arg; drm_version_t version; int len; if (copy_from_user(&version, argp, sizeof(version))) return -EFAULT; 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); if (copy_to_user(argp, &version, sizeof(version))) return -EFAULT; return 0;}/** * Called whenever a process performs an ioctl on /dev/drm. * * \param inode device inode. * \param filp file pointer. * \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){ drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->head->dev; drm_ioctl_desc_t *ioctl; drm_ioctl_t *func; unsigned int nr = DRM_IOCTL_NR(cmd); int retcode = -EINVAL; atomic_inc(&dev->ioctl_count); atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]); ++priv->ioctl_count; DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n", current->pid, cmd, nr, (long)old_encode_dev(priv->head->device), priv->authenticated); if (nr < DRIVER_IOCTL_COUNT) ioctl = &drm_ioctls[nr]; else if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE]; 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) && !priv->authenticated) || ((ioctl->flags & DRM_MASTER) && !priv->master)) { retcode = -EACCES; } else { retcode = func(inode, filp, cmd, arg); } err_i1: atomic_dec(&dev->ioctl_count); if (retcode) DRM_DEBUG("ret = %x\n", retcode); return retcode;}EXPORT_SYMBOL(drm_ioctl);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?