3 * Generic driver template
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
8 * To use this template, you must at least define the following (samples
9 * given for the MGA driver):
12 * #define DRIVER_AUTHOR "VA Linux Systems, Inc."
14 * #define DRIVER_NAME "mga"
15 * #define DRIVER_DESC "Matrox G200/G400"
16 * #define DRIVER_DATE "20001127"
18 * #define DRIVER_MAJOR 2
19 * #define DRIVER_MINOR 0
20 * #define DRIVER_PATCHLEVEL 2
22 * #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( mga_ioctls )
24 * #define drm_x mga_##x
29 * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
31 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
32 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
33 * All Rights Reserved.
35 * Permission is hereby granted, free of charge, to any person obtaining a
36 * copy of this software and associated documentation files (the "Software"),
37 * to deal in the Software without restriction, including without limitation
38 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
39 * and/or sell copies of the Software, and to permit persons to whom the
40 * Software is furnished to do so, subject to the following conditions:
42 * The above copyright notice and this permission notice (including the next
43 * paragraph) shall be included in all copies or substantial portions of the
46 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
47 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
48 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
49 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
50 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
51 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
52 * OTHER DEALINGS IN THE SOFTWARE.
59 drm_ioctl_desc_t drm_ioctls[] = {
60 [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { drm_version, 0, 0 },
61 [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 },
62 [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 },
63 [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_by_busid, 0, 1 },
64 [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { drm_getmap, 0, 0 },
65 [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { drm_getclient, 0, 0 },
66 [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { drm_getstats, 0, 0 },
67 [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = { drm_setversion, 0, 1 },
69 [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 },
70 [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_noop, 1, 1 },
71 [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_noop, 1, 1 },
72 [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 },
74 [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 },
75 [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { drm_rmmap, 1, 0 },
77 [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { drm_setsareactx, 1, 1 },
78 [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { drm_getsareactx, 1, 0 },
80 [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { drm_addctx, 1, 1 },
81 [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { drm_rmctx, 1, 1 },
82 [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { drm_modctx, 1, 1 },
83 [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { drm_getctx, 1, 0 },
84 [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { drm_switchctx, 1, 1 },
85 [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { drm_newctx, 1, 1 },
86 [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { drm_resctx, 1, 0 },
88 [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 },
89 [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 },
91 [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { drm_lock, 1, 0 },
92 [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { drm_unlock, 1, 0 },
94 [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_noop, 1, 0 },
96 [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { drm_addbufs, 1, 1 },
97 [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 },
98 [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 },
99 [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { drm_mapbufs, 1, 0 },
100 [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 },
101 /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
103 [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { drm_control, 1, 1 },
106 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 },
107 [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 },
108 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 },
109 [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 },
110 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 },
111 [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 },
112 [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
113 [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
116 [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { drm_sg_alloc, 1, 1 },
117 [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { drm_sg_free, 1, 1 },
119 [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = { drm_wait_vblank, 0, 0 },
122 #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( drm_ioctls )
125 * Take down the DRM device.
127 * \param dev DRM device structure.
129 * Frees every resource in \p dev.
131 * \sa drm_device and setup().
133 int drm_takedown( drm_device_t *dev )
135 drm_magic_entry_t *pt, *next;
137 drm_map_list_t *r_list;
138 struct list_head *list, *list_next;
139 drm_vma_entry_t *vma, *vma_next;
144 if (dev->driver->pretakedown)
145 dev->driver->pretakedown(dev);
147 if ( dev->irq_enabled ) drm_irq_uninstall( dev );
149 down( &dev->struct_sem );
150 del_timer( &dev->timer );
152 if ( dev->devname ) {
153 drm_free( dev->devname, strlen( dev->devname ) + 1,
159 drm_free( dev->unique, strlen( dev->unique ) + 1,
165 for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
166 for ( pt = dev->magiclist[i].head ; pt ; pt = next ) {
168 drm_free( pt, sizeof(*pt), DRM_MEM_MAGIC );
170 dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
173 /* Clear AGP information */
174 if (drm_core_has_AGP(dev) && dev->agp) {
175 drm_agp_mem_t *entry;
176 drm_agp_mem_t *nexte;
178 /* Remove AGP resources, but leave dev->agp
179 intact until drv_cleanup is called. */
180 for ( entry = dev->agp->memory ; entry ; entry = nexte ) {
182 if ( entry->bound ) drm_unbind_agp( entry->memory );
183 drm_free_agp( entry->memory, entry->pages );
184 drm_free( entry, sizeof(*entry), DRM_MEM_AGPLISTS );
186 dev->agp->memory = NULL;
188 if ( dev->agp->acquired ) drm_agp_do_release();
190 dev->agp->acquired = 0;
191 dev->agp->enabled = 0;
194 /* Clear vma list (only built for debugging) */
195 if ( dev->vmalist ) {
196 for ( vma = dev->vmalist ; vma ; vma = vma_next ) {
197 vma_next = vma->next;
198 drm_free( vma, sizeof(*vma), DRM_MEM_VMAS );
204 list_for_each_safe( list, list_next, &dev->maplist->head ) {
205 r_list = (drm_map_list_t *)list;
207 if ( ( map = r_list->map ) ) {
208 switch ( map->type ) {
210 case _DRM_FRAME_BUFFER:
211 if (drm_core_has_MTRR(dev)) {
212 if ( map->mtrr >= 0 ) {
214 retcode = mtrr_del( map->mtrr,
217 DRM_DEBUG( "mtrr_del=%d\n", retcode );
220 drm_ioremapfree( map->handle, map->size, dev );
227 /* Do nothing here, because this is all
228 * handled in the AGP/GART driver.
231 case _DRM_SCATTER_GATHER:
233 if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {
234 drm_sg_cleanup(dev->sg);
239 drm_free(map, sizeof(*map), DRM_MEM_MAPS);
242 drm_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
244 drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
248 if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist ) {
249 for ( i = 0 ; i < dev->queue_count ; i++ ) {
250 if ( dev->queuelist[i] ) {
251 drm_free( dev->queuelist[i],
252 sizeof(*dev->queuelist[0]),
254 dev->queuelist[i] = NULL;
257 drm_free( dev->queuelist,
258 dev->queue_slots * sizeof(*dev->queuelist),
260 dev->queuelist = NULL;
262 dev->queue_count = 0;
264 if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
265 drm_dma_takedown( dev );
267 if ( dev->lock.hw_lock ) {
268 dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */
269 dev->lock.filp = NULL;
270 wake_up_interruptible( &dev->lock.lock_queue );
272 up( &dev->struct_sem );
280 * Module initialization. Called via init_module at module load time, or via
281 * linux/init/main.c (this is not currently supported).
283 * \return zero on success or a negative number on failure.
285 * Initializes an array of drm_device structures, and attempts to
286 * initialize all available devices, using consecutive minors, registering the
287 * stubs and initializing the AGP device.
289 * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
290 * after the initialization for driver customization.
292 int drm_init( struct drm_driver *driver )
294 struct pci_dev *pdev = NULL;
295 struct pci_device_id *pid;
302 for (i=0; driver->pci_driver.id_table[i].vendor != 0; i++) {
303 pid = (struct pci_device_id *)&driver->pci_driver.id_table[i];
306 /* pass back in pdev to account for multiple identical cards */
307 while ((pdev = pci_get_subsys(pid->vendor, pid->device, pid->subvendor, pid->subdevice, pdev)) != NULL) {
308 /* stealth mode requires a manual probe */
310 drm_probe(pdev, pid, driver);
315 EXPORT_SYMBOL(drm_init);
318 * Called via cleanup_module() at module unload time.
320 * Cleans up all DRM device, calling takedown().
324 static void drm_cleanup( drm_device_t *dev )
329 DRM_ERROR("cleanup called no dev\n");
335 drm_ctxbitmap_cleanup( dev );
337 if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
338 dev->agp && dev->agp->agp_mtrr >= 0) {
340 retval = mtrr_del( dev->agp->agp_mtrr,
341 dev->agp->agp_info.aper_base,
342 dev->agp->agp_info.aper_size*1024*1024 );
343 DRM_DEBUG( "mtrr_del=%d\n", retval );
346 if (drm_core_has_AGP(dev) && dev->agp ) {
347 drm_free( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
351 if (dev->driver->postcleanup)
352 dev->driver->postcleanup(dev);
354 if ( drm_put_minor(dev) )
355 DRM_ERROR( "Cannot unload module\n" );
358 void drm_exit (struct drm_driver *driver)
361 drm_device_t *dev = NULL;
366 for (i = 0; i < drm_cards_limit; i++) {
367 minor = &drm_minors[i];
370 if (minor->dev->driver!=driver)
377 /* release the pci driver */
379 pci_dev_put(dev->pdev);
383 DRM_INFO( "Module unloaded\n" );
385 EXPORT_SYMBOL(drm_exit);
387 /** File operations structure */
388 static struct file_operations drm_stub_fops = {
389 .owner = THIS_MODULE,
390 .open = drm_stub_open
393 static int __init drm_core_init(void)
397 drm_cards_limit = (drm_cards_limit < DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1);
398 drm_minors = drm_calloc(drm_cards_limit,
399 sizeof(*drm_minors), DRM_MEM_STUB);
403 if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
406 drm_class = drm_sysfs_create(THIS_MODULE, "drm");
407 if (IS_ERR(drm_class)) {
408 printk (KERN_ERR "DRM: Error creating drm class.\n");
409 ret = PTR_ERR(drm_class);
413 drm_proc_root = create_proc_entry("dri", S_IFDIR, NULL);
414 if (!drm_proc_root) {
415 DRM_ERROR("Cannot create /proc/dri\n");
420 DRM_INFO( "Initialized %s %d.%d.%d %s\n",
429 drm_sysfs_destroy(drm_class);
431 unregister_chrdev(DRM_MAJOR, "drm");
432 drm_free(drm_minors, sizeof(*drm_minors) * drm_cards_limit, DRM_MEM_STUB);
437 static void __exit drm_core_exit (void)
439 remove_proc_entry("dri", NULL);
440 drm_sysfs_destroy(drm_class);
442 unregister_chrdev(DRM_MAJOR, "drm");
444 drm_free(drm_minors, sizeof(*drm_minors) *
445 drm_cards_limit, DRM_MEM_STUB);
449 module_init( drm_core_init );
450 module_exit( drm_core_exit );
454 * Get version information
456 * \param inode device inode.
457 * \param filp file pointer.
458 * \param cmd command.
459 * \param arg user argument, pointing to a drm_version structure.
460 * \return zero on success or negative number on failure.
462 * Fills in the version information in \p arg.
464 int drm_version( struct inode *inode, struct file *filp,
465 unsigned int cmd, unsigned long arg )
467 drm_file_t *priv = filp->private_data;
468 drm_device_t *dev = priv->dev;
469 drm_version_t __user *argp = (void __user *)arg;
470 drm_version_t version;
473 if ( copy_from_user( &version, argp, sizeof(version) ) )
476 /* version is a required function to return the personality module version */
477 if ((ret = dev->driver->version(&version)))
480 if ( copy_to_user( argp, &version, sizeof(version) ) )
488 * Called whenever a process performs an ioctl on /dev/drm.
490 * \param inode device inode.
491 * \param filp file pointer.
492 * \param cmd command.
493 * \param arg user argument.
494 * \return zero on success or negative number on failure.
496 * Looks up the ioctl function in the ::ioctls table, checking for root
497 * previleges if so required, and dispatches to the respective function.
499 int drm_ioctl( struct inode *inode, struct file *filp,
500 unsigned int cmd, unsigned long arg )
502 drm_file_t *priv = filp->private_data;
503 drm_device_t *dev = priv->dev;
504 drm_ioctl_desc_t *ioctl;
506 unsigned int nr = DRM_IOCTL_NR(cmd);
507 int retcode = -EINVAL;
509 atomic_inc( &dev->ioctl_count );
510 atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
513 DRM_DEBUG( "pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
514 current->pid, cmd, nr, (long)old_encode_dev(dev->device),
515 priv->authenticated );
517 if (nr < DRIVER_IOCTL_COUNT)
518 ioctl = &drm_ioctls[nr];
519 else if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
520 ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
525 /* is there a local override? */
526 if ((nr == DRM_IOCTL_NR(DRM_IOCTL_DMA)) && dev->driver->dma_ioctl)
527 func = dev->driver->dma_ioctl;
530 DRM_DEBUG( "no function\n" );
532 } else if ( ( ioctl->root_only && !capable( CAP_SYS_ADMIN ) )||
533 ( ioctl->auth_needed && !priv->authenticated ) ) {
536 retcode = func( inode, filp, cmd, arg );
540 atomic_dec( &dev->ioctl_count );
541 if (retcode) DRM_DEBUG( "ret = %x\n", retcode);
544 EXPORT_SYMBOL(drm_ioctl);