drm_stub.c revision c94f70298529d99ac6e1ee7709f61eab00adeb39
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \file drm_stub.h 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Stub support 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \author Rickard E. (Rik) Faith <faith@valinux.com> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California. 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All Rights Reserved. 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Permission is hereby granted, free of charge, to any person obtaining a 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * copy of this software and associated documentation files (the "Software"), 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to deal in the Software without restriction, including without limitation 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the rights to use, copy, modify, merge, publish, distribute, sublicense, 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and/or sell copies of the Software, and to permit persons to whom the 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Software is furnished to do so, subject to the following conditions: 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The above copyright notice and this permission notice (including the next 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * paragraph) shall be included in all copies or substantial portions of the 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Software. 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DEALINGS IN THE SOFTWARE. 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "drmP.h" 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "drm_core.h" 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int drm_cards_limit = 16; /* Enough for one machine */ 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int drm_debug = 0; /* 1 to enable debug output */ 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(drm_debug); 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR( CORE_AUTHOR ); 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION( CORE_DESC ); 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL and additional rights"); 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(cards_limit, "Maximum number of graphics cards"); 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug, "Enable debug output"); 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(cards_limit, drm_cards_limit, int, 0444); 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_named(debug, drm_debug, int, 0666); 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdrm_head_t **drm_heads; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct drm_sysfs_class *drm_class; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct proc_dir_entry *drm_proc_root; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver) 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retcode; 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&dev->count_lock); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_timer( &dev->timer ); 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sema_init( &dev->struct_sem, 1 ); 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sema_init( &dev->ctxlist_sem, 1 ); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pdev = pdev; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef __alpha__ 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->hose = pdev->sysdata; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pci_domain = dev->hose->bus->number; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pci_domain = 0; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pci_bus = pdev->bus->number; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pci_slot = PCI_SLOT(pdev->devfn); 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pci_func = PCI_FUNC(pdev->devfn); 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->irq = pdev->irq; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the DRM has 6 basic counters */ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->counters = 6; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->types[0] = _DRM_STAT_LOCK; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->types[1] = _DRM_STAT_OPENS; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->types[2] = _DRM_STAT_CLOSES; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->types[3] = _DRM_STAT_IOCTLS; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->types[4] = _DRM_STAT_LOCKS; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->types[5] = _DRM_STAT_UNLOCKS; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->driver = driver; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->driver->preinit) 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((retcode = dev->driver->preinit(dev, ent->driver_data))) 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error_out_unreg; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drm_core_has_AGP(dev)) { 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->agp = drm_agp_init(dev); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) { 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR( "Cannot initialize the agpgart module.\n" ); 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retcode = -EINVAL; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error_out_unreg; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drm_core_has_MTRR(dev)) { 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->agp) 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base, 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->agp->agp_info.aper_size*1024*1024, 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MTRR_TYPE_WRCOMB, 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1 ); 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retcode = drm_ctxbitmap_init( dev ); 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if( retcode ) { 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR( "Cannot allocate memory for context bitmap.\n" ); 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error_out_unreg; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserror_out_unreg: 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_takedown(dev); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retcode; 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * File \c open operation. 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \param inode device inode. 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \param filp file pointer. 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Puts the dev->fops corresponding to the device minor number into 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \p filp, call the \c open method, and restore the file operations. 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint drm_stub_open(struct inode *inode, struct file *filp) 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_device_t *dev = NULL; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int minor = iminor(inode); 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = -ENODEV; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct file_operations *old_fops; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_DEBUG("\n"); 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!((minor >= 0) && (minor < drm_cards_limit))) 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!drm_heads[minor]) 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(dev = drm_heads[minor]->dev)) 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_fops = filp->f_op; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds filp->f_op = fops_get(&dev->driver->fops); 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) { 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fops_put(filp->f_op); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds filp->f_op = fops_get(old_fops); 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fops_put(old_fops); 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get a secondary minor number. 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \param dev device data structure 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \param sec-minor structure to hold the assigned minor 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \return negative number on failure. 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Search an empty entry and initialize it to the given parameters, and 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * create the proc init entry via proc_init(). This routines assigns 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * minor numbers to secondary heads of multi-headed cards 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 171c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airliestatic int drm_get_head(drm_device_t *dev, drm_head_t *head) 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_head_t **heads = drm_heads; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int minor; 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_DEBUG("\n"); 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (minor = 0; minor < drm_cards_limit; minor++, heads++) { 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!*heads) { 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *head = (drm_head_t) { 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .dev = dev, 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device = MKDEV(DRM_MAJOR, minor), 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .minor = minor, 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ret = drm_proc_init(dev, minor, drm_proc_root, &head->dev_root))) { 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk (KERN_ERR "DRM: Failed to initialize /proc/dri.\n"); 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_g1; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->dev_class = drm_sysfs_device_add(drm_class, 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MKDEV(DRM_MAJOR, 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds minor), 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &dev->pdev->dev, 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "card%d", minor); 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(head->dev_class)) { 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "DRM: Error sysfs_device_add.\n"); 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = PTR_ERR(head->dev_class); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_g2; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *heads = head; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_DEBUG("new minor assigned %d\n", minor); 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR("out of minors\n"); 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_g2: 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_proc_cleanup(minor, drm_proc_root, head->dev_root); 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_g1: 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *head = (drm_head_t) {.dev = NULL}; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 219c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie/** 220c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie * Register. 221c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie * 222c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie * \param pdev - PCI device structure 223c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie * \param ent entry from the PCI ID table with device type flags 224c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie * \return zero on success or a negative number on failure. 225c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie * 226c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie * Attempt to gets inter module "drm" information. If we are first 227c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie * then register the character device and inter module information. 228c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie * Try and register, if we fail to register, backout previous work. 229c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie */ 230c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlieint drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, 231c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie struct drm_driver *driver) 232c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie{ 233c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie drm_device_t *dev; 234c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie int ret; 235c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie 236c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie DRM_DEBUG("\n"); 237c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie 238c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB); 239c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie if (!dev) 240c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie return -ENOMEM; 241c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie 242c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie pci_enable_device(pdev); 243c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie 244c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) { 245c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); 246c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie goto err_g1; 247c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie } 248c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie if ((ret = drm_get_head(dev, &dev->primary))) 249c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie goto err_g1; 250c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie 251c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie /* postinit is a required function to display the signon banner */ 252c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie /* drivers add secondary heads here if needed */ 253c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie if ((ret = dev->driver->postinit(dev, ent->driver_data))) 254c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie goto err_g1; 255c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie 256c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie return 0; 257c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie 258c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlieerr_g1: 259c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie drm_free(dev, sizeof(*dev), DRM_MEM_STUB); 260c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie return ret; 261c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie} 262c94f70298529d99ac6e1ee7709f61eab00adeb39Dave AirlieEXPORT_SYMBOL(drm_get_dev); 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Put a device minor number. 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \param dev device data structure 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \return always zero 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Cleans up the proc resources. If it is the last minor then release the foreign 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * "drm" data, otherwise unregisters the "drm" data, frees the dev list and 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unregisters the character device. 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint drm_put_dev(drm_device_t * dev) 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name); 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->unique) { 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER); 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->unique = NULL; 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->unique_len = 0; 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->devname) { 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_free(dev->devname, strlen(dev->devname) + 1, 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_MEM_DRIVER); 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->devname = NULL; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_free(dev, sizeof(*dev), DRM_MEM_STUB); 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Put a secondary minor number. 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \param sec_minor - structure to be released 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * \return always zero 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Cleans up the proc resources. Not legal for this to be the 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * last minor released. 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint drm_put_head(drm_head_t *head) 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int minor = head->minor; 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_DEBUG("release secondary minor %d\n", minor); 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_proc_cleanup(minor, drm_proc_root, head->dev_root); 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_sysfs_device_remove(MKDEV(DRM_MAJOR, head->minor)); 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *head = (drm_head_t){.dev = NULL}; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_heads[minor] = NULL; 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 318