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