1 /*
   2  * drm_drv.h -- Generic driver template -*- linux-c -*-
   3  * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
   4  */
   5 /*
   6  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
   7  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
   8  * Copyright (c) 2009, Intel Corporation.
   9  * All Rights Reserved.
  10  *
  11  * Permission is hereby granted, free of charge, to any person obtaining a
  12  * copy of this software and associated documentation files (the "Software"),
  13  * to deal in the Software without restriction, including without limitation
  14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  15  * and/or sell copies of the Software, and to permit persons to whom the
  16  * Software is furnished to do so, subject to the following conditions:
  17  *
  18  * The above copyright notice and this permission notice (including the next
  19  * paragraph) shall be included in all copies or substantial portions of the
  20  * Software.
  21  *
  22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  23  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  25  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  26  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  27  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  28  * OTHER DEALINGS IN THE SOFTWARE.
  29  *
  30  * Authors:
  31  *    Rickard E. (Rik) Faith <faith@valinux.com>
  32  *    Gareth Hughes <gareth@valinux.com>
  33  *
  34  */
  35 
  36 /*
  37  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  38  * Use is subject to license terms.
  39  */
  40 
  41 #include "drmP.h"
  42 #include "drm.h"
  43 #include "drm_sarea.h"
  44 
  45 int drm_debug_flag = 1;
  46 
  47 #define DRIVER_IOCTL_COUNT      256
  48 drm_ioctl_desc_t drm_ioctls[DRIVER_IOCTL_COUNT] = {
  49         [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] =
  50             {drm_version, 0},
  51         [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] =
  52             {drm_getunique, 0},
  53         [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] =
  54             {drm_getmagic, 0},
  55         [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] =
  56             {drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY},
  57         [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] =
  58             {drm_getmap, 0},
  59         [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] =
  60             {drm_getclient, 0},
  61         [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] =
  62             {drm_getstats, 0},
  63         [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] =
  64             {drm_setversion, DRM_MASTER|DRM_ROOT_ONLY},
  65         [DRM_IOCTL_NR(DRM_IOCTL_MODESET_CTL)] =
  66             {drm_modeset_ctl, 0},
  67         [DRM_IOCTL_NR(DRM_IOCTL_GEM_CLOSE)] =
  68             {drm_gem_close_ioctl, 0},
  69         [DRM_IOCTL_NR(DRM_IOCTL_GEM_FLINK)] =
  70             {drm_gem_flink_ioctl, DRM_AUTH},
  71         [DRM_IOCTL_NR(DRM_IOCTL_GEM_OPEN)] =
  72             {drm_gem_open_ioctl, DRM_AUTH},
  73         [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] =
  74             {drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
  75         [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] =
  76             {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
  77         [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] =
  78             {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
  79         [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] =
  80             {drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
  81         [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] =
  82             {drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
  83         [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] =
  84             {drm_rmmap_ioctl, DRM_AUTH},
  85         [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] =
  86             {drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
  87         [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] =
  88             {drm_getsareactx, DRM_AUTH},
  89         [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] =
  90             {drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
  91         [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] =
  92             {drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
  93         [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] =
  94             {drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
  95         [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] =
  96             {drm_getctx, DRM_AUTH},
  97         [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] =
  98             {drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
  99         [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] =
 100             {drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 101         [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] =
 102             {drm_resctx, DRM_AUTH},
 103         [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] =
 104             {drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 105         [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] =
 106             {drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 107         [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] =
 108             {drm_lock, DRM_AUTH},
 109         [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] =
 110             {drm_unlock, DRM_AUTH},
 111         [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] =
 112             {drm_noop, DRM_AUTH},
 113         [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] =
 114             {drm_addbufs_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 115         [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] =
 116             {drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 117         [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] =
 118             {drm_infobufs, DRM_AUTH},
 119         [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] =
 120             {drm_mapbufs, DRM_AUTH},
 121         [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] =
 122             {drm_freebufs, DRM_AUTH},
 123         [DRM_IOCTL_NR(DRM_IOCTL_DMA)] =
 124             {drm_dma, DRM_AUTH},
 125         [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] =
 126             {drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 127         [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] =
 128             {drm_agp_acquire, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 129         [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] =
 130             {drm_agp_release, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 131         [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] =
 132             {drm_agp_enable, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 133         [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] =
 134             {drm_agp_info, DRM_AUTH},
 135         [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] =
 136             {drm_agp_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 137         [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] =
 138             {drm_agp_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 139         [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] =
 140             {drm_agp_bind, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 141         [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] =
 142             {drm_agp_unbind, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 143         [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] =
 144             {drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 145         [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] =
 146             {drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 147         [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] =
 148             {drm_wait_vblank, 0},
 149         [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] =
 150             {drm_update_draw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 151 };
 152 
 153 extern void idr_list_free(struct idr_list *head);
 154 
 155 const char *
 156 drm_find_description(int vendor, int device, drm_pci_id_list_t *idlist)
 157 {
 158         int i = 0;
 159         for (i = 0; idlist[i].vendor != 0; i++) {
 160         if ((idlist[i].vendor == vendor) &&
 161             (idlist[i].device == device)) {
 162                         return (idlist[i].name);
 163                 }
 164         }
 165         return ((char *)NULL);
 166 }
 167 
 168 static int
 169 drm_firstopen(drm_device_t *dev)
 170 {
 171         int i;
 172         int retval;
 173         drm_local_map_t *map;
 174 
 175         /* prebuild the SAREA */
 176         retval = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM,
 177             _DRM_CONTAINS_LOCK, &map);
 178         if (retval != 0) {
 179                 DRM_ERROR("firstopen: failed to prebuild SAREA");
 180                 return (retval);
 181         }
 182 
 183         if (dev->driver->use_agp) {
 184                 DRM_DEBUG("drm_firstopen: use_agp=%d", dev->driver->use_agp);
 185                 if (drm_device_is_agp(dev))
 186                         dev->agp = drm_agp_init(dev);
 187                 if (dev->driver->require_agp && dev->agp == NULL) {
 188                         DRM_ERROR("couldn't initialize AGP");
 189                         return (EIO);
 190                 }
 191         }
 192 
 193         if (dev->driver->firstopen)
 194                 retval = dev->driver->firstopen(dev);
 195 
 196         if (retval != 0) {
 197                 DRM_ERROR("drm_firstopen: driver-specific firstopen failed");
 198                 return (retval);
 199         }
 200 
 201         dev->buf_use = 0;
 202 
 203         if (dev->driver->use_dma) {
 204                 i = drm_dma_setup(dev);
 205                 if (i != 0)
 206                         return (i);
 207         }
 208         dev->counters  = 6;
 209         dev->types[0]  = _DRM_STAT_LOCK;
 210         dev->types[1]  = _DRM_STAT_OPENS;
 211         dev->types[2]  = _DRM_STAT_CLOSES;
 212         dev->types[3]  = _DRM_STAT_IOCTLS;
 213         dev->types[4]  = _DRM_STAT_LOCKS;
 214         dev->types[5]  = _DRM_STAT_UNLOCKS;
 215 
 216         for (i = 0; i < DRM_ARRAY_SIZE(dev->counts); i++)
 217                 *(&dev->counts[i]) = 0;
 218 
 219         for (i = 0; i < DRM_HASH_SIZE; i++) {
 220                 dev->magiclist[i].head = NULL;
 221                 dev->magiclist[i].tail = NULL;
 222         }
 223 
 224         dev->irq_enabled     = 0;
 225         dev->context_flag    = 0;
 226         dev->last_context    = 0;
 227         dev->if_version              = 0;
 228 
 229         return (0);
 230 }
 231 
 232 /* Free resources associated with the DRM on the last close. */
 233 static int
 234 drm_lastclose(drm_device_t *dev)
 235 {
 236         drm_magic_entry_t *pt, *next;
 237         drm_local_map_t *map, *mapsave;
 238         int i;
 239 
 240         DRM_SPINLOCK_ASSERT(&dev->dev_lock);
 241 
 242         if (dev->driver->lastclose != NULL)
 243                 dev->driver->lastclose(dev);
 244 
 245         if (dev->irq_enabled)
 246                 (void) drm_irq_uninstall(dev);
 247 
 248         if (dev->unique) {
 249                 drm_free(dev->unique, dev->unique_len + 1, DRM_MEM_DRIVER);
 250                 dev->unique = NULL;
 251                 dev->unique_len = 0;
 252         }
 253 
 254         /* Clear pid list */
 255         for (i = 0; i < DRM_HASH_SIZE; i++) {
 256                 for (pt = dev->magiclist[i].head; pt; pt = next) {
 257                         next = pt->next;
 258                         drm_free(pt, sizeof (*pt), DRM_MEM_MAGIC);
 259                 }
 260                 dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
 261         }
 262 
 263         /* Clear AGP information */
 264         if (dev->agp) {
 265                 drm_agp_mem_t *entry;
 266                 drm_agp_mem_t *nexte;
 267 
 268                 /*
 269                  * Remove AGP resources, but leave dev->agp
 270                  * intact until drm_cleanup is called.
 271                  */
 272                 for (entry = dev->agp->memory; entry; entry = nexte) {
 273                         nexte = entry->next;
 274                         if (entry->bound)
 275                                 (void) drm_agp_unbind_memory(
 276                                     (unsigned long)entry->handle, dev);
 277                         (void) drm_agp_free_memory(entry->handle, dev);
 278                         drm_free(entry, sizeof (*entry), DRM_MEM_AGPLISTS);
 279                 }
 280                 dev->agp->memory = NULL;
 281 
 282                 if (dev->agp->acquired)
 283                         (void) drm_agp_do_release(dev);
 284 
 285                 dev->agp->acquired = 0;
 286                 dev->agp->enabled  = 0;
 287                 drm_agp_fini(dev);
 288         }
 289 
 290         if (dev->sg != NULL) {
 291                 drm_sg_mem_t *entry;
 292                 entry = dev->sg;
 293                 dev->sg = NULL;
 294                 drm_sg_cleanup(dev, entry);
 295         }
 296 
 297 
 298         /* Clean up maps that weren't set up by the driver. */
 299         TAILQ_FOREACH_SAFE(map, &dev->maplist, link, mapsave) {
 300                 if (!map->kernel_owned)
 301                         drm_rmmap(dev, map);
 302         }
 303 
 304         drm_dma_takedown(dev);
 305         if (dev->lock.hw_lock) {
 306                 dev->lock.hw_lock = NULL; /* SHM removed */
 307                 dev->lock.filp = NULL;
 308 
 309                 mutex_enter(&(dev->lock.lock_mutex));
 310                 cv_broadcast(&(dev->lock.lock_cv));
 311                 mutex_exit(&(dev->lock.lock_mutex));
 312         }
 313 
 314         return (0);
 315 }
 316 
 317 static int
 318 drm_load(drm_device_t *dev)
 319 {
 320         int retcode;
 321 
 322         cv_init(&(dev->lock.lock_cv), NULL, CV_DRIVER, NULL);
 323         mutex_init(&(dev->lock.lock_mutex), NULL, MUTEX_DRIVER, NULL);
 324         mutex_init(&(dev->dev_lock), "drmdev", MUTEX_DRIVER, NULL);
 325         mutex_init(&dev->irq_lock, "drmirq", MUTEX_DRIVER,
 326             (void *)dev->intr_block);
 327         mutex_init(&dev->drw_lock, "drmdrw", MUTEX_DRIVER, NULL);
 328         mutex_init(&dev->tasklet_lock, "drmtsk", MUTEX_DRIVER, NULL);
 329 
 330         dev->irq = pci_get_irq(dev);
 331         dev->pci_vendor = pci_get_vendor(dev);
 332         dev->pci_device = pci_get_device(dev);
 333 
 334         TAILQ_INIT(&dev->maplist);
 335         TAILQ_INIT(&dev->minordevs);
 336         TAILQ_INIT(&dev->files);
 337         if (dev->driver->load != NULL) {
 338                 retcode = dev->driver->load(dev, 0);
 339                 if (retcode != 0) {
 340                         DRM_ERROR("drm_load: failed\n");
 341                         goto error;
 342                 }
 343         }
 344 
 345         retcode = drm_ctxbitmap_init(dev);
 346         if (retcode != 0) {
 347                 DRM_ERROR("drm_load: Cannot allocate memory for ctx bitmap");
 348                 goto error;
 349         }
 350 
 351         if (dev->driver->use_gem == 1) {
 352                 retcode = drm_gem_init(dev);
 353                 if (retcode) {
 354                         DRM_ERROR("Cannot initialize graphics execution "
 355                             "manager (GEM)\n");
 356                         goto error;
 357                 }
 358         }
 359 
 360         if (drm_init_kstats(dev)) {
 361                 DRM_ERROR("drm_attach => drm_load: init kstats error");
 362                 retcode = EFAULT;
 363                 goto error;
 364         }
 365 
 366         DRM_INFO("!drm: Initialized %s %d.%d.%d %s ",
 367             dev->driver->driver_name,
 368             dev->driver->driver_major,
 369             dev->driver->driver_minor,
 370             dev->driver->driver_patchlevel,
 371             dev->driver->driver_date);
 372         return (0);
 373 
 374 error:
 375         DRM_LOCK();
 376         (void) drm_lastclose(dev);
 377         DRM_UNLOCK();
 378         cv_destroy(&(dev->lock.lock_cv));
 379         mutex_destroy(&(dev->lock.lock_mutex));
 380         mutex_destroy(&dev->irq_lock);
 381         mutex_destroy(&(dev->dev_lock));
 382         mutex_destroy(&dev->drw_lock);
 383         mutex_destroy(&dev->tasklet_lock);
 384 
 385         return (retcode);
 386 }
 387 
 388 /* called when cleanup this module */
 389 static void
 390 drm_unload(drm_device_t *dev)
 391 {
 392         drm_local_map_t *map;
 393 
 394         drm_vblank_cleanup(dev);
 395 
 396         drm_ctxbitmap_cleanup(dev);
 397 
 398         if (dev->driver->use_gem == 1) {
 399                 idr_list_free(&dev->object_name_idr);
 400                 mutex_destroy(&dev->object_name_lock);
 401         }
 402 
 403         DRM_LOCK();
 404         (void) drm_lastclose(dev);
 405         DRM_UNLOCK();
 406 
 407         while ((map = TAILQ_FIRST(&dev->maplist)) != NULL) {
 408                 drm_rmmap(dev, map);
 409         }
 410 
 411         if (dev->driver->unload != NULL)
 412                 dev->driver->unload(dev);
 413 
 414         drm_mem_uninit();
 415         cv_destroy(&dev->lock.lock_cv);
 416         mutex_destroy(&dev->lock.lock_mutex);
 417         mutex_destroy(&dev->irq_lock);
 418         mutex_destroy(&dev->dev_lock);
 419         mutex_destroy(&dev->drw_lock);
 420         mutex_destroy(&dev->tasklet_lock);
 421 
 422         dev->gtt_total = 0;
 423         atomic_set(&dev->pin_memory, 0);
 424         DRM_ERROR("drm_unload");
 425 }
 426 
 427 
 428 /*ARGSUSED*/
 429 int
 430 drm_open(drm_device_t *dev, drm_cminor_t *mp, int openflags,
 431     int otyp, cred_t *credp)
 432 {
 433         int retcode;
 434 
 435         retcode = drm_open_helper(dev, mp, openflags, otyp, credp);
 436 
 437         if (!retcode) {
 438                 atomic_inc_32(&dev->counts[_DRM_STAT_OPENS]);
 439                 DRM_LOCK();
 440                 if (!dev->open_count ++)
 441                         retcode = drm_firstopen(dev);
 442                 DRM_UNLOCK();
 443         }
 444 
 445         return (retcode);
 446 }
 447 
 448 /*ARGSUSED*/
 449 int
 450 drm_close(drm_device_t *dev, int minor, int flag, int otyp,
 451     cred_t *credp)
 452 {
 453         drm_cminor_t    *mp;
 454         drm_file_t              *fpriv;
 455         int             retcode = 0;
 456 
 457         DRM_LOCK();
 458         mp = drm_find_file_by_minor(dev, minor);
 459         if (!mp) {
 460                 DRM_UNLOCK();
 461                 DRM_ERROR("drm_close: can't find authenticator");
 462                 return (EACCES);
 463         }
 464 
 465         fpriv = mp->fpriv;
 466         ASSERT(fpriv);
 467 
 468         if (--fpriv->refs != 0)
 469                 goto done;
 470 
 471         if (dev->driver->preclose != NULL)
 472                 dev->driver->preclose(dev, fpriv);
 473 
 474         /*
 475          * Begin inline drm_release
 476          */
 477         DRM_DEBUG("drm_close :pid = %d , open_count = %d",
 478             DRM_CURRENTPID, dev->open_count);
 479 
 480         if (dev->lock.hw_lock &&
 481             _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
 482             dev->lock.filp == fpriv) {
 483                 DRM_DEBUG("Process %d dead, freeing lock for context %d",
 484                     DRM_CURRENTPID,
 485                     _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
 486                 if (dev->driver->reclaim_buffers_locked != NULL)
 487                         dev->driver->reclaim_buffers_locked(dev, fpriv);
 488                 (void) drm_lock_free(dev, &dev->lock.hw_lock->lock,
 489                     _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
 490         } else if (dev->driver->reclaim_buffers_locked != NULL &&
 491             dev->lock.hw_lock != NULL) {
 492                 DRM_ERROR("drm_close: "
 493                     "retake lock not implemented yet");
 494         }
 495 
 496         if (dev->driver->use_dma) {
 497                 drm_reclaim_buffers(dev, fpriv);
 498         }
 499 
 500         if (dev->driver->use_gem == 1) {
 501                 drm_gem_release(dev, fpriv);
 502         }
 503 
 504         if (dev->driver->postclose != NULL) {
 505                 dev->driver->postclose(dev, fpriv);
 506         }
 507         TAILQ_REMOVE(&dev->files, fpriv, link);
 508         drm_free(fpriv, sizeof (*fpriv), DRM_MEM_FILES);
 509 
 510 done:
 511         atomic_inc_32(&dev->counts[_DRM_STAT_CLOSES]);
 512 
 513         TAILQ_REMOVE(&dev->minordevs, mp, link);
 514         drm_free(mp, sizeof (*mp), DRM_MEM_FILES);
 515 
 516         if (--dev->open_count == 0) {
 517                 retcode = drm_lastclose(dev);
 518         }
 519         DRM_UNLOCK();
 520 
 521         return (retcode);
 522 }
 523 
 524 int
 525 drm_attach(drm_device_t *dev)
 526 {
 527         return (drm_load(dev));
 528 }
 529 
 530 int
 531 drm_detach(drm_device_t *dev)
 532 {
 533         drm_unload(dev);
 534         drm_fini_kstats(dev);
 535         return (DDI_SUCCESS);
 536 }
 537 
 538 static int
 539 drm_get_businfo(drm_device_t *dev)
 540 {
 541         dev->irq = pci_get_irq(dev);
 542         if (dev->irq == -1) {
 543                 DRM_ERROR("drm_get_businfo: get irq error");
 544                 return (DDI_FAILURE);
 545         }
 546         /* XXX Fix domain number (alpha hoses) */
 547         dev->pci_domain = 0;
 548         if (pci_get_info(dev, &dev->pci_bus,
 549             &dev->pci_slot, &dev->pci_func) != DDI_SUCCESS) {
 550                 DRM_ERROR("drm_get_businfo: get bus slot func error ");
 551                 return (DDI_FAILURE);
 552         }
 553         DRM_DEBUG("drm_get_businfo: pci bus: %d, pci slot :%d pci func %d",
 554             dev->pci_bus, dev->pci_slot, dev->pci_func);
 555         return (DDI_SUCCESS);
 556 }
 557 
 558 int
 559 drm_probe(drm_device_t *dev, drm_pci_id_list_t *idlist)
 560 {
 561         const char *s = NULL;
 562         int vendor, device;
 563 
 564         vendor = pci_get_vendor(dev);
 565         device = pci_get_device(dev);
 566 
 567         s = drm_find_description(vendor, device, idlist);
 568         if (s != NULL) {
 569                 dev->desc = s;
 570                 if (drm_get_businfo(dev) != DDI_SUCCESS) {
 571                         DRM_ERROR("drm_probe: drm get bus info error");
 572                         return (DDI_FAILURE);
 573                 }
 574                 return (DDI_SUCCESS);
 575         }
 576         return (DDI_FAILURE);
 577 }