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 + -
显示快捷键?