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