drm_drv.c

来自「linux2.6.16版本」· C语言 代码 · 共 515 行 · 第 1/2 页

C
515
字号
/** * \file drm_drv.c * Generic driver template * * \author Rickard E. (Rik) Faith <faith@valinux.com> * \author Gareth Hughes <gareth@valinux.com> * * To use this template, you must at least define the following (samples * given for the MGA driver): * * \code * #define DRIVER_AUTHOR	"VA Linux Systems, Inc." * * #define DRIVER_NAME		"mga" * #define DRIVER_DESC		"Matrox G200/G400" * #define DRIVER_DATE		"20001127" * * #define DRIVER_IOCTL_COUNT	DRM_ARRAY_SIZE( mga_ioctls ) * * #define drm_x		mga_##x * \endcode *//* * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com * * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */#include "drmP.h"#include "drm_core.h"static int drm_version(struct inode *inode, struct file *filp,		       unsigned int cmd, unsigned long arg);/** Ioctl table */static drm_ioctl_desc_t drm_ioctls[] = {	[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = {drm_version, 0},	[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = {drm_getunique, 0},	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = {drm_getmagic, 0},	[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = {drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = {drm_getmap, 0},	[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = {drm_getclient, 0},	[DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = {drm_getstats, 0},	[DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = {drm_setversion, DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = {drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = {drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = {drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = {drm_rmmap_ioctl, DRM_AUTH},	[DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, DRM_AUTH},	[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, DRM_AUTH},	[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = {drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = {drm_resctx, DRM_AUTH},	[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = {drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = {drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = {drm_lock, DRM_AUTH},	[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = {drm_unlock, DRM_AUTH},	[DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = {drm_noop, DRM_AUTH},	[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = {drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = {drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = {drm_infobufs, DRM_AUTH},	[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = {drm_mapbufs, DRM_AUTH},	[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = {drm_freebufs, DRM_AUTH},	/* The DRM_IOCTL_DMA ioctl should be defined by the driver. */	[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = {NULL, DRM_AUTH},	[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = {drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},#if __OS_HAS_AGP	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = {drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = {drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = {drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = {drm_agp_info_ioctl, DRM_AUTH},	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = {drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = {drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = {drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = {drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},#endif	[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = {drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},	[DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0},};#define DRIVER_IOCTL_COUNT	DRM_ARRAY_SIZE( drm_ioctls )/** * Take down the DRM device. * * \param dev DRM device structure. * * Frees every resource in \p dev. * * \sa drm_device */int drm_lastclose(drm_device_t * dev){	drm_magic_entry_t *pt, *next;	drm_map_list_t *r_list;	drm_vma_entry_t *vma, *vma_next;	int i;	DRM_DEBUG("\n");	if (dev->driver->lastclose)		dev->driver->lastclose(dev);	DRM_DEBUG("driver lastclose completed\n");	if (dev->unique) {		drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);		dev->unique = NULL;		dev->unique_len = 0;	}	if (dev->irq_enabled)		drm_irq_uninstall(dev);	mutex_lock(&dev->struct_mutex);	del_timer(&dev->timer);	/* Clear pid list */	for (i = 0; i < DRM_HASH_SIZE; i++) {		for (pt = dev->magiclist[i].head; pt; pt = next) {			next = pt->next;			drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);		}		dev->magiclist[i].head = dev->magiclist[i].tail = NULL;	}	/* Clear AGP information */	if (drm_core_has_AGP(dev) && dev->agp) {		drm_agp_mem_t *entry;		drm_agp_mem_t *nexte;		/* Remove AGP resources, but leave dev->agp		   intact until drv_cleanup is called. */		for (entry = dev->agp->memory; entry; entry = nexte) {			nexte = entry->next;			if (entry->bound)				drm_unbind_agp(entry->memory);			drm_free_agp(entry->memory, entry->pages);			drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);		}		dev->agp->memory = NULL;		if (dev->agp->acquired)			drm_agp_release(dev);		dev->agp->acquired = 0;		dev->agp->enabled = 0;	}	if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {		drm_sg_cleanup(dev->sg);		dev->sg = NULL;	}	/* Clear vma list (only built for debugging) */	if (dev->vmalist) {		for (vma = dev->vmalist; vma; vma = vma_next) {			vma_next = vma->next;			drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);		}		dev->vmalist = NULL;	}	if (dev->maplist) {		while (!list_empty(&dev->maplist->head)) {			struct list_head *list = dev->maplist->head.next;			r_list = list_entry(list, drm_map_list_t, head);			drm_rmmap_locked(dev, r_list->map);		}	}	if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) {		for (i = 0; i < dev->queue_count; i++) {			if (dev->queuelist[i]) {				drm_free(dev->queuelist[i],					 sizeof(*dev->queuelist[0]),					 DRM_MEM_QUEUES);				dev->queuelist[i] = NULL;			}		}		drm_free(dev->queuelist,			 dev->queue_slots * sizeof(*dev->queuelist),			 DRM_MEM_QUEUES);		dev->queuelist = NULL;	}	dev->queue_count = 0;	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))		drm_dma_takedown(dev);	if (dev->lock.hw_lock) {		dev->sigdata.lock = dev->lock.hw_lock = NULL;	/* SHM removed */		dev->lock.filp = NULL;		wake_up_interruptible(&dev->lock.lock_queue);	}	mutex_unlock(&dev->struct_mutex);	DRM_DEBUG("lastclose completed\n");	return 0;}/** * Module initialization. Called via init_module at module load time, or via * linux/init/main.c (this is not currently supported). * * \return zero on success or a negative number on failure. * * Initializes an array of drm_device structures, and attempts to * initialize all available devices, using consecutive minors, registering the * stubs and initializing the AGP device. * * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and * after the initialization for driver customization. */int drm_init(struct drm_driver *driver){	struct pci_dev *pdev = NULL;	struct pci_device_id *pid;	int i;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?