1*592ffb21SWarner Losh /** 2*592ffb21SWarner Losh * \file drm_stub.h 3*592ffb21SWarner Losh * Stub support 4*592ffb21SWarner Losh * 5*592ffb21SWarner Losh * \author Rickard E. (Rik) Faith <faith@valinux.com> 6*592ffb21SWarner Losh */ 7*592ffb21SWarner Losh 8*592ffb21SWarner Losh /* 9*592ffb21SWarner Losh * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org 10*592ffb21SWarner Losh * 11*592ffb21SWarner Losh * Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California. 12*592ffb21SWarner Losh * All Rights Reserved. 13*592ffb21SWarner Losh * 14*592ffb21SWarner Losh * Permission is hereby granted, free of charge, to any person obtaining a 15*592ffb21SWarner Losh * copy of this software and associated documentation files (the "Software"), 16*592ffb21SWarner Losh * to deal in the Software without restriction, including without limitation 17*592ffb21SWarner Losh * the rights to use, copy, modify, merge, publish, distribute, sublicense, 18*592ffb21SWarner Losh * and/or sell copies of the Software, and to permit persons to whom the 19*592ffb21SWarner Losh * Software is furnished to do so, subject to the following conditions: 20*592ffb21SWarner Losh * 21*592ffb21SWarner Losh * The above copyright notice and this permission notice (including the next 22*592ffb21SWarner Losh * paragraph) shall be included in all copies or substantial portions of the 23*592ffb21SWarner Losh * Software. 24*592ffb21SWarner Losh * 25*592ffb21SWarner Losh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26*592ffb21SWarner Losh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27*592ffb21SWarner Losh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 28*592ffb21SWarner Losh * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 29*592ffb21SWarner Losh * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 30*592ffb21SWarner Losh * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 31*592ffb21SWarner Losh * DEALINGS IN THE SOFTWARE. 32*592ffb21SWarner Losh */ 33*592ffb21SWarner Losh 34*592ffb21SWarner Losh #include <sys/cdefs.h> 35*592ffb21SWarner Losh __FBSDID("$FreeBSD$"); 36*592ffb21SWarner Losh 37*592ffb21SWarner Losh #include <dev/drm2/drmP.h> 38*592ffb21SWarner Losh #include <dev/drm2/drm_core.h> 39*592ffb21SWarner Losh 40*592ffb21SWarner Losh #ifdef DRM_DEBUG_DEFAULT_ON 41*592ffb21SWarner Losh unsigned int drm_debug = (DRM_DEBUGBITS_DEBUG | DRM_DEBUGBITS_KMS | 42*592ffb21SWarner Losh DRM_DEBUGBITS_FAILED_IOCTL); 43*592ffb21SWarner Losh #else 44*592ffb21SWarner Losh unsigned int drm_debug = 0; /* 1 to enable debug output */ 45*592ffb21SWarner Losh #endif 46*592ffb21SWarner Losh EXPORT_SYMBOL(drm_debug); 47*592ffb21SWarner Losh 48*592ffb21SWarner Losh unsigned int drm_notyet = 0; 49*592ffb21SWarner Losh 50*592ffb21SWarner Losh unsigned int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */ 51*592ffb21SWarner Losh EXPORT_SYMBOL(drm_vblank_offdelay); 52*592ffb21SWarner Losh 53*592ffb21SWarner Losh unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */ 54*592ffb21SWarner Losh EXPORT_SYMBOL(drm_timestamp_precision); 55*592ffb21SWarner Losh 56*592ffb21SWarner Losh /* 57*592ffb21SWarner Losh * Default to use monotonic timestamps for wait-for-vblank and page-flip 58*592ffb21SWarner Losh * complete events. 59*592ffb21SWarner Losh */ 60*592ffb21SWarner Losh unsigned int drm_timestamp_monotonic = 1; 61*592ffb21SWarner Losh 62*592ffb21SWarner Losh MODULE_AUTHOR(CORE_AUTHOR); 63*592ffb21SWarner Losh MODULE_DESCRIPTION(CORE_DESC); 64*592ffb21SWarner Losh MODULE_LICENSE("GPL and additional rights"); 65*592ffb21SWarner Losh MODULE_PARM_DESC(debug, "Enable debug output"); 66*592ffb21SWarner Losh MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]"); 67*592ffb21SWarner Losh MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]"); 68*592ffb21SWarner Losh MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps"); 69*592ffb21SWarner Losh 70*592ffb21SWarner Losh module_param_named(debug, drm_debug, int, 0600); 71*592ffb21SWarner Losh module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600); 72*592ffb21SWarner Losh module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600); 73*592ffb21SWarner Losh module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600); 74*592ffb21SWarner Losh 75*592ffb21SWarner Losh static struct cdevsw drm_cdevsw = { 76*592ffb21SWarner Losh .d_version = D_VERSION, 77*592ffb21SWarner Losh .d_open = drm_open, 78*592ffb21SWarner Losh .d_read = drm_read, 79*592ffb21SWarner Losh .d_ioctl = drm_ioctl, 80*592ffb21SWarner Losh .d_poll = drm_poll, 81*592ffb21SWarner Losh .d_mmap_single = drm_mmap_single, 82*592ffb21SWarner Losh .d_name = "drm", 83*592ffb21SWarner Losh .d_flags = D_TRACKCLOSE 84*592ffb21SWarner Losh }; 85*592ffb21SWarner Losh 86*592ffb21SWarner Losh static int drm_minor_get_id(struct drm_device *dev, int type) 87*592ffb21SWarner Losh { 88*592ffb21SWarner Losh int new_id; 89*592ffb21SWarner Losh 90*592ffb21SWarner Losh new_id = device_get_unit(dev->dev); 91*592ffb21SWarner Losh 92*592ffb21SWarner Losh if (new_id >= 64) 93*592ffb21SWarner Losh return -EINVAL; 94*592ffb21SWarner Losh 95*592ffb21SWarner Losh if (type == DRM_MINOR_CONTROL) { 96*592ffb21SWarner Losh new_id += 64; 97*592ffb21SWarner Losh } else if (type == DRM_MINOR_RENDER) { 98*592ffb21SWarner Losh new_id += 128; 99*592ffb21SWarner Losh } 100*592ffb21SWarner Losh 101*592ffb21SWarner Losh return new_id; 102*592ffb21SWarner Losh } 103*592ffb21SWarner Losh 104*592ffb21SWarner Losh struct drm_master *drm_master_create(struct drm_minor *minor) 105*592ffb21SWarner Losh { 106*592ffb21SWarner Losh struct drm_master *master; 107*592ffb21SWarner Losh 108*592ffb21SWarner Losh master = malloc(sizeof(*master), DRM_MEM_KMS, M_NOWAIT | M_ZERO); 109*592ffb21SWarner Losh if (!master) 110*592ffb21SWarner Losh return NULL; 111*592ffb21SWarner Losh 112*592ffb21SWarner Losh refcount_init(&master->refcount, 1); 113*592ffb21SWarner Losh mtx_init(&master->lock.spinlock, "drm_master__lock__spinlock", 114*592ffb21SWarner Losh NULL, MTX_DEF); 115*592ffb21SWarner Losh DRM_INIT_WAITQUEUE(&master->lock.lock_queue); 116*592ffb21SWarner Losh drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER); 117*592ffb21SWarner Losh INIT_LIST_HEAD(&master->magicfree); 118*592ffb21SWarner Losh master->minor = minor; 119*592ffb21SWarner Losh 120*592ffb21SWarner Losh list_add_tail(&master->head, &minor->master_list); 121*592ffb21SWarner Losh 122*592ffb21SWarner Losh return master; 123*592ffb21SWarner Losh } 124*592ffb21SWarner Losh 125*592ffb21SWarner Losh struct drm_master *drm_master_get(struct drm_master *master) 126*592ffb21SWarner Losh { 127*592ffb21SWarner Losh refcount_acquire(&master->refcount); 128*592ffb21SWarner Losh return master; 129*592ffb21SWarner Losh } 130*592ffb21SWarner Losh EXPORT_SYMBOL(drm_master_get); 131*592ffb21SWarner Losh 132*592ffb21SWarner Losh static void drm_master_destroy(struct drm_master *master) 133*592ffb21SWarner Losh { 134*592ffb21SWarner Losh struct drm_magic_entry *pt, *next; 135*592ffb21SWarner Losh struct drm_device *dev = master->minor->dev; 136*592ffb21SWarner Losh struct drm_map_list *r_list, *list_temp; 137*592ffb21SWarner Losh 138*592ffb21SWarner Losh list_del(&master->head); 139*592ffb21SWarner Losh 140*592ffb21SWarner Losh if (dev->driver->master_destroy) 141*592ffb21SWarner Losh dev->driver->master_destroy(dev, master); 142*592ffb21SWarner Losh 143*592ffb21SWarner Losh list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) { 144*592ffb21SWarner Losh if (r_list->master == master) { 145*592ffb21SWarner Losh drm_rmmap_locked(dev, r_list->map); 146*592ffb21SWarner Losh r_list = NULL; 147*592ffb21SWarner Losh } 148*592ffb21SWarner Losh } 149*592ffb21SWarner Losh 150*592ffb21SWarner Losh if (master->unique) { 151*592ffb21SWarner Losh free(master->unique, DRM_MEM_DRIVER); 152*592ffb21SWarner Losh master->unique = NULL; 153*592ffb21SWarner Losh master->unique_len = 0; 154*592ffb21SWarner Losh } 155*592ffb21SWarner Losh 156*592ffb21SWarner Losh list_for_each_entry_safe(pt, next, &master->magicfree, head) { 157*592ffb21SWarner Losh list_del(&pt->head); 158*592ffb21SWarner Losh drm_ht_remove_item(&master->magiclist, &pt->hash_item); 159*592ffb21SWarner Losh free(pt, DRM_MEM_MAGIC); 160*592ffb21SWarner Losh } 161*592ffb21SWarner Losh 162*592ffb21SWarner Losh drm_ht_remove(&master->magiclist); 163*592ffb21SWarner Losh 164*592ffb21SWarner Losh free(master, DRM_MEM_KMS); 165*592ffb21SWarner Losh } 166*592ffb21SWarner Losh 167*592ffb21SWarner Losh void drm_master_put(struct drm_master **master) 168*592ffb21SWarner Losh { 169*592ffb21SWarner Losh if (refcount_release(&(*master)->refcount)) 170*592ffb21SWarner Losh drm_master_destroy(*master); 171*592ffb21SWarner Losh *master = NULL; 172*592ffb21SWarner Losh } 173*592ffb21SWarner Losh EXPORT_SYMBOL(drm_master_put); 174*592ffb21SWarner Losh 175*592ffb21SWarner Losh int drm_setmaster_ioctl(struct drm_device *dev, void *data, 176*592ffb21SWarner Losh struct drm_file *file_priv) 177*592ffb21SWarner Losh { 178*592ffb21SWarner Losh int ret; 179*592ffb21SWarner Losh 180*592ffb21SWarner Losh if (file_priv->is_master) 181*592ffb21SWarner Losh return 0; 182*592ffb21SWarner Losh 183*592ffb21SWarner Losh if (file_priv->minor->master && file_priv->minor->master != file_priv->master) 184*592ffb21SWarner Losh return -EINVAL; 185*592ffb21SWarner Losh 186*592ffb21SWarner Losh if (!file_priv->master) 187*592ffb21SWarner Losh return -EINVAL; 188*592ffb21SWarner Losh 189*592ffb21SWarner Losh if (file_priv->minor->master) 190*592ffb21SWarner Losh return -EINVAL; 191*592ffb21SWarner Losh 192*592ffb21SWarner Losh DRM_LOCK(dev); 193*592ffb21SWarner Losh file_priv->minor->master = drm_master_get(file_priv->master); 194*592ffb21SWarner Losh file_priv->is_master = 1; 195*592ffb21SWarner Losh if (dev->driver->master_set) { 196*592ffb21SWarner Losh ret = dev->driver->master_set(dev, file_priv, false); 197*592ffb21SWarner Losh if (unlikely(ret != 0)) { 198*592ffb21SWarner Losh file_priv->is_master = 0; 199*592ffb21SWarner Losh drm_master_put(&file_priv->minor->master); 200*592ffb21SWarner Losh } 201*592ffb21SWarner Losh } 202*592ffb21SWarner Losh DRM_UNLOCK(dev); 203*592ffb21SWarner Losh 204*592ffb21SWarner Losh return 0; 205*592ffb21SWarner Losh } 206*592ffb21SWarner Losh 207*592ffb21SWarner Losh int drm_dropmaster_ioctl(struct drm_device *dev, void *data, 208*592ffb21SWarner Losh struct drm_file *file_priv) 209*592ffb21SWarner Losh { 210*592ffb21SWarner Losh if (!file_priv->is_master) 211*592ffb21SWarner Losh return -EINVAL; 212*592ffb21SWarner Losh 213*592ffb21SWarner Losh if (!file_priv->minor->master) 214*592ffb21SWarner Losh return -EINVAL; 215*592ffb21SWarner Losh 216*592ffb21SWarner Losh DRM_LOCK(dev); 217*592ffb21SWarner Losh if (dev->driver->master_drop) 218*592ffb21SWarner Losh dev->driver->master_drop(dev, file_priv, false); 219*592ffb21SWarner Losh drm_master_put(&file_priv->minor->master); 220*592ffb21SWarner Losh file_priv->is_master = 0; 221*592ffb21SWarner Losh DRM_UNLOCK(dev); 222*592ffb21SWarner Losh return 0; 223*592ffb21SWarner Losh } 224*592ffb21SWarner Losh 225*592ffb21SWarner Losh int drm_fill_in_dev(struct drm_device *dev, 226*592ffb21SWarner Losh struct drm_driver *driver) 227*592ffb21SWarner Losh { 228*592ffb21SWarner Losh int retcode, i; 229*592ffb21SWarner Losh 230*592ffb21SWarner Losh INIT_LIST_HEAD(&dev->filelist); 231*592ffb21SWarner Losh INIT_LIST_HEAD(&dev->ctxlist); 232*592ffb21SWarner Losh INIT_LIST_HEAD(&dev->maplist); 233*592ffb21SWarner Losh INIT_LIST_HEAD(&dev->vblank_event_list); 234*592ffb21SWarner Losh 235*592ffb21SWarner Losh mtx_init(&dev->irq_lock, "drmirq", NULL, MTX_DEF); 236*592ffb21SWarner Losh mtx_init(&dev->count_lock, "drmcount", NULL, MTX_DEF); 237*592ffb21SWarner Losh mtx_init(&dev->event_lock, "drmev", NULL, MTX_DEF); 238*592ffb21SWarner Losh sx_init(&dev->dev_struct_lock, "drmslk"); 239*592ffb21SWarner Losh mtx_init(&dev->ctxlist_mutex, "drmctxlist", NULL, MTX_DEF); 240*592ffb21SWarner Losh mtx_init(&dev->pcir_lock, "drmpcir", NULL, MTX_DEF); 241*592ffb21SWarner Losh 242*592ffb21SWarner Losh if (drm_ht_create(&dev->map_hash, 12)) { 243*592ffb21SWarner Losh return -ENOMEM; 244*592ffb21SWarner Losh } 245*592ffb21SWarner Losh 246*592ffb21SWarner Losh /* the DRM has 6 basic counters */ 247*592ffb21SWarner Losh dev->counters = 6; 248*592ffb21SWarner Losh dev->types[0] = _DRM_STAT_LOCK; 249*592ffb21SWarner Losh dev->types[1] = _DRM_STAT_OPENS; 250*592ffb21SWarner Losh dev->types[2] = _DRM_STAT_CLOSES; 251*592ffb21SWarner Losh dev->types[3] = _DRM_STAT_IOCTLS; 252*592ffb21SWarner Losh dev->types[4] = _DRM_STAT_LOCKS; 253*592ffb21SWarner Losh dev->types[5] = _DRM_STAT_UNLOCKS; 254*592ffb21SWarner Losh 255*592ffb21SWarner Losh /* 256*592ffb21SWarner Losh * FIXME Linux<->FreeBSD: this is done in drm_setup() on Linux. 257*592ffb21SWarner Losh */ 258*592ffb21SWarner Losh for (i = 0; i < ARRAY_SIZE(dev->counts); i++) 259*592ffb21SWarner Losh atomic_set(&dev->counts[i], 0); 260*592ffb21SWarner Losh 261*592ffb21SWarner Losh dev->driver = driver; 262*592ffb21SWarner Losh 263*592ffb21SWarner Losh retcode = drm_pci_agp_init(dev); 264*592ffb21SWarner Losh if (retcode) 265*592ffb21SWarner Losh goto error_out_unreg; 266*592ffb21SWarner Losh 267*592ffb21SWarner Losh 268*592ffb21SWarner Losh 269*592ffb21SWarner Losh retcode = drm_ctxbitmap_init(dev); 270*592ffb21SWarner Losh if (retcode) { 271*592ffb21SWarner Losh DRM_ERROR("Cannot allocate memory for context bitmap.\n"); 272*592ffb21SWarner Losh goto error_out_unreg; 273*592ffb21SWarner Losh } 274*592ffb21SWarner Losh 275*592ffb21SWarner Losh if (driver->driver_features & DRIVER_GEM) { 276*592ffb21SWarner Losh retcode = drm_gem_init(dev); 277*592ffb21SWarner Losh if (retcode) { 278*592ffb21SWarner Losh DRM_ERROR("Cannot initialize graphics execution " 279*592ffb21SWarner Losh "manager (GEM)\n"); 280*592ffb21SWarner Losh goto error_out_unreg; 281*592ffb21SWarner Losh } 282*592ffb21SWarner Losh } 283*592ffb21SWarner Losh 284*592ffb21SWarner Losh retcode = drm_sysctl_init(dev); 285*592ffb21SWarner Losh if (retcode != 0) { 286*592ffb21SWarner Losh DRM_ERROR("Failed to create hw.dri sysctl entry: %d\n", 287*592ffb21SWarner Losh retcode); 288*592ffb21SWarner Losh } 289*592ffb21SWarner Losh 290*592ffb21SWarner Losh return 0; 291*592ffb21SWarner Losh 292*592ffb21SWarner Losh error_out_unreg: 293*592ffb21SWarner Losh drm_cancel_fill_in_dev(dev); 294*592ffb21SWarner Losh return retcode; 295*592ffb21SWarner Losh } 296*592ffb21SWarner Losh EXPORT_SYMBOL(drm_fill_in_dev); 297*592ffb21SWarner Losh 298*592ffb21SWarner Losh void drm_cancel_fill_in_dev(struct drm_device *dev) 299*592ffb21SWarner Losh { 300*592ffb21SWarner Losh struct drm_driver *driver; 301*592ffb21SWarner Losh 302*592ffb21SWarner Losh driver = dev->driver; 303*592ffb21SWarner Losh 304*592ffb21SWarner Losh drm_sysctl_cleanup(dev); 305*592ffb21SWarner Losh if (driver->driver_features & DRIVER_GEM) 306*592ffb21SWarner Losh drm_gem_destroy(dev); 307*592ffb21SWarner Losh drm_ctxbitmap_cleanup(dev); 308*592ffb21SWarner Losh 309*592ffb21SWarner Losh if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && 310*592ffb21SWarner Losh dev->agp && dev->agp->agp_mtrr >= 0) { 311*592ffb21SWarner Losh int retval; 312*592ffb21SWarner Losh retval = drm_mtrr_del(dev->agp->agp_mtrr, 313*592ffb21SWarner Losh dev->agp->agp_info.ai_aperture_base, 314*592ffb21SWarner Losh dev->agp->agp_info.ai_aperture_size, 315*592ffb21SWarner Losh DRM_MTRR_WC); 316*592ffb21SWarner Losh DRM_DEBUG("mtrr_del=%d\n", retval); 317*592ffb21SWarner Losh } 318*592ffb21SWarner Losh free(dev->agp, DRM_MEM_AGPLISTS); 319*592ffb21SWarner Losh dev->agp = NULL; 320*592ffb21SWarner Losh 321*592ffb21SWarner Losh drm_ht_remove(&dev->map_hash); 322*592ffb21SWarner Losh 323*592ffb21SWarner Losh mtx_destroy(&dev->irq_lock); 324*592ffb21SWarner Losh mtx_destroy(&dev->count_lock); 325*592ffb21SWarner Losh mtx_destroy(&dev->event_lock); 326*592ffb21SWarner Losh sx_destroy(&dev->dev_struct_lock); 327*592ffb21SWarner Losh mtx_destroy(&dev->ctxlist_mutex); 328*592ffb21SWarner Losh mtx_destroy(&dev->pcir_lock); 329*592ffb21SWarner Losh } 330*592ffb21SWarner Losh 331*592ffb21SWarner Losh /** 332*592ffb21SWarner Losh * Get a secondary minor number. 333*592ffb21SWarner Losh * 334*592ffb21SWarner Losh * \param dev device data structure 335*592ffb21SWarner Losh * \param sec-minor structure to hold the assigned minor 336*592ffb21SWarner Losh * \return negative number on failure. 337*592ffb21SWarner Losh * 338*592ffb21SWarner Losh * Search an empty entry and initialize it to the given parameters, and 339*592ffb21SWarner Losh * create the proc init entry via proc_init(). This routines assigns 340*592ffb21SWarner Losh * minor numbers to secondary heads of multi-headed cards 341*592ffb21SWarner Losh */ 342*592ffb21SWarner Losh int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type) 343*592ffb21SWarner Losh { 344*592ffb21SWarner Losh struct drm_minor *new_minor; 345*592ffb21SWarner Losh int ret; 346*592ffb21SWarner Losh int minor_id; 347*592ffb21SWarner Losh const char *minor_devname; 348*592ffb21SWarner Losh 349*592ffb21SWarner Losh DRM_DEBUG("\n"); 350*592ffb21SWarner Losh 351*592ffb21SWarner Losh minor_id = drm_minor_get_id(dev, type); 352*592ffb21SWarner Losh if (minor_id < 0) 353*592ffb21SWarner Losh return minor_id; 354*592ffb21SWarner Losh 355*592ffb21SWarner Losh new_minor = malloc(sizeof(struct drm_minor), DRM_MEM_MINOR, 356*592ffb21SWarner Losh M_NOWAIT | M_ZERO); 357*592ffb21SWarner Losh if (!new_minor) { 358*592ffb21SWarner Losh ret = -ENOMEM; 359*592ffb21SWarner Losh goto err_idr; 360*592ffb21SWarner Losh } 361*592ffb21SWarner Losh 362*592ffb21SWarner Losh new_minor->type = type; 363*592ffb21SWarner Losh new_minor->dev = dev; 364*592ffb21SWarner Losh new_minor->index = minor_id; 365*592ffb21SWarner Losh INIT_LIST_HEAD(&new_minor->master_list); 366*592ffb21SWarner Losh 367*592ffb21SWarner Losh new_minor->buf_sigio = NULL; 368*592ffb21SWarner Losh 369*592ffb21SWarner Losh switch (type) { 370*592ffb21SWarner Losh case DRM_MINOR_CONTROL: 371*592ffb21SWarner Losh minor_devname = "dri/controlD%d"; 372*592ffb21SWarner Losh break; 373*592ffb21SWarner Losh case DRM_MINOR_RENDER: 374*592ffb21SWarner Losh minor_devname = "dri/renderD%d"; 375*592ffb21SWarner Losh break; 376*592ffb21SWarner Losh default: 377*592ffb21SWarner Losh minor_devname = "dri/card%d"; 378*592ffb21SWarner Losh break; 379*592ffb21SWarner Losh } 380*592ffb21SWarner Losh 381*592ffb21SWarner Losh ret = make_dev_p(MAKEDEV_WAITOK | MAKEDEV_CHECKNAME, &new_minor->device, 382*592ffb21SWarner Losh &drm_cdevsw, 0, DRM_DEV_UID, DRM_DEV_GID, 383*592ffb21SWarner Losh DRM_DEV_MODE, minor_devname, minor_id); 384*592ffb21SWarner Losh if (ret) { 385*592ffb21SWarner Losh DRM_ERROR("Failed to create cdev: %d\n", ret); 386*592ffb21SWarner Losh goto err_mem; 387*592ffb21SWarner Losh } 388*592ffb21SWarner Losh new_minor->device->si_drv1 = new_minor; 389*592ffb21SWarner Losh *minor = new_minor; 390*592ffb21SWarner Losh 391*592ffb21SWarner Losh DRM_DEBUG("new minor assigned %d\n", minor_id); 392*592ffb21SWarner Losh return 0; 393*592ffb21SWarner Losh 394*592ffb21SWarner Losh 395*592ffb21SWarner Losh err_mem: 396*592ffb21SWarner Losh free(new_minor, DRM_MEM_MINOR); 397*592ffb21SWarner Losh err_idr: 398*592ffb21SWarner Losh *minor = NULL; 399*592ffb21SWarner Losh return ret; 400*592ffb21SWarner Losh } 401*592ffb21SWarner Losh EXPORT_SYMBOL(drm_get_minor); 402*592ffb21SWarner Losh 403*592ffb21SWarner Losh /** 404*592ffb21SWarner Losh * Put a secondary minor number. 405*592ffb21SWarner Losh * 406*592ffb21SWarner Losh * \param sec_minor - structure to be released 407*592ffb21SWarner Losh * \return always zero 408*592ffb21SWarner Losh * 409*592ffb21SWarner Losh * Cleans up the proc resources. Not legal for this to be the 410*592ffb21SWarner Losh * last minor released. 411*592ffb21SWarner Losh * 412*592ffb21SWarner Losh */ 413*592ffb21SWarner Losh int drm_put_minor(struct drm_minor **minor_p) 414*592ffb21SWarner Losh { 415*592ffb21SWarner Losh struct drm_minor *minor = *minor_p; 416*592ffb21SWarner Losh 417*592ffb21SWarner Losh DRM_DEBUG("release secondary minor %d\n", minor->index); 418*592ffb21SWarner Losh 419*592ffb21SWarner Losh funsetown(&minor->buf_sigio); 420*592ffb21SWarner Losh 421*592ffb21SWarner Losh destroy_dev(minor->device); 422*592ffb21SWarner Losh 423*592ffb21SWarner Losh free(minor, DRM_MEM_MINOR); 424*592ffb21SWarner Losh *minor_p = NULL; 425*592ffb21SWarner Losh return 0; 426*592ffb21SWarner Losh } 427*592ffb21SWarner Losh EXPORT_SYMBOL(drm_put_minor); 428*592ffb21SWarner Losh 429*592ffb21SWarner Losh /** 430*592ffb21SWarner Losh * Called via drm_exit() at module unload time or when pci device is 431*592ffb21SWarner Losh * unplugged. 432*592ffb21SWarner Losh * 433*592ffb21SWarner Losh * Cleans up all DRM device, calling drm_lastclose(). 434*592ffb21SWarner Losh * 435*592ffb21SWarner Losh */ 436*592ffb21SWarner Losh void drm_put_dev(struct drm_device *dev) 437*592ffb21SWarner Losh { 438*592ffb21SWarner Losh struct drm_driver *driver; 439*592ffb21SWarner Losh struct drm_map_list *r_list, *list_temp; 440*592ffb21SWarner Losh 441*592ffb21SWarner Losh DRM_DEBUG("\n"); 442*592ffb21SWarner Losh 443*592ffb21SWarner Losh if (!dev) { 444*592ffb21SWarner Losh DRM_ERROR("cleanup called no dev\n"); 445*592ffb21SWarner Losh return; 446*592ffb21SWarner Losh } 447*592ffb21SWarner Losh driver = dev->driver; 448*592ffb21SWarner Losh 449*592ffb21SWarner Losh drm_lastclose(dev); 450*592ffb21SWarner Losh 451*592ffb21SWarner Losh if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && 452*592ffb21SWarner Losh dev->agp && dev->agp->agp_mtrr >= 0) { 453*592ffb21SWarner Losh int retval; 454*592ffb21SWarner Losh retval = drm_mtrr_del(dev->agp->agp_mtrr, 455*592ffb21SWarner Losh dev->agp->agp_info.ai_aperture_base, 456*592ffb21SWarner Losh dev->agp->agp_info.ai_aperture_size, 457*592ffb21SWarner Losh DRM_MTRR_WC); 458*592ffb21SWarner Losh DRM_DEBUG("mtrr_del=%d\n", retval); 459*592ffb21SWarner Losh } 460*592ffb21SWarner Losh 461*592ffb21SWarner Losh if (drm_core_check_feature(dev, DRIVER_MODESET)) 462*592ffb21SWarner Losh drm_mode_group_free(&dev->primary->mode_group); 463*592ffb21SWarner Losh 464*592ffb21SWarner Losh if (dev->driver->unload) 465*592ffb21SWarner Losh dev->driver->unload(dev); 466*592ffb21SWarner Losh 467*592ffb21SWarner Losh drm_sysctl_cleanup(dev); 468*592ffb21SWarner Losh 469*592ffb21SWarner Losh if (drm_core_has_AGP(dev) && dev->agp) { 470*592ffb21SWarner Losh free(dev->agp, DRM_MEM_AGPLISTS); 471*592ffb21SWarner Losh dev->agp = NULL; 472*592ffb21SWarner Losh } 473*592ffb21SWarner Losh 474*592ffb21SWarner Losh drm_vblank_cleanup(dev); 475*592ffb21SWarner Losh 476*592ffb21SWarner Losh list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) 477*592ffb21SWarner Losh drm_rmmap(dev, r_list->map); 478*592ffb21SWarner Losh drm_ht_remove(&dev->map_hash); 479*592ffb21SWarner Losh 480*592ffb21SWarner Losh drm_ctxbitmap_cleanup(dev); 481*592ffb21SWarner Losh 482*592ffb21SWarner Losh if (drm_core_check_feature(dev, DRIVER_MODESET)) 483*592ffb21SWarner Losh drm_put_minor(&dev->control); 484*592ffb21SWarner Losh 485*592ffb21SWarner Losh if (driver->driver_features & DRIVER_GEM) 486*592ffb21SWarner Losh drm_gem_destroy(dev); 487*592ffb21SWarner Losh 488*592ffb21SWarner Losh drm_put_minor(&dev->primary); 489*592ffb21SWarner Losh 490*592ffb21SWarner Losh mtx_destroy(&dev->irq_lock); 491*592ffb21SWarner Losh mtx_destroy(&dev->count_lock); 492*592ffb21SWarner Losh mtx_destroy(&dev->event_lock); 493*592ffb21SWarner Losh sx_destroy(&dev->dev_struct_lock); 494*592ffb21SWarner Losh mtx_destroy(&dev->ctxlist_mutex); 495*592ffb21SWarner Losh mtx_destroy(&dev->pcir_lock); 496*592ffb21SWarner Losh 497*592ffb21SWarner Losh #ifdef FREEBSD_NOTYET 498*592ffb21SWarner Losh list_del(&dev->driver_item); 499*592ffb21SWarner Losh #endif /* FREEBSD_NOTYET */ 500*592ffb21SWarner Losh } 501*592ffb21SWarner Losh EXPORT_SYMBOL(drm_put_dev); 502