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 #pragma ident "%Z%%M% %I% %E% SMI" 41 42 #include "drmP.h" 43 #include "drm.h" 44 #include "drm_sarea.h" 45 46 int drm_debug_flag = 1; 47 48 #define DRIVER_IOCTL_COUNT 256 49 drm_ioctl_desc_t drm_ioctls[DRIVER_IOCTL_COUNT]; 50 51 void 52 drm_set_ioctl_desc(int n, drm_ioctl_t *func, int auth_needed, 53 int root_only, char *desc) 54 { 55 drm_ioctls[n].func = func; 56 drm_ioctls[n].auth_needed = auth_needed; 57 drm_ioctls[n].root_only = root_only; 58 drm_ioctls[n].desc = desc; 59 } 60 61 void 62 drm_init_ioctl_arrays(void) 63 { 64 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_VERSION), 65 drm_version, 0, 0, "drm_version"); 66 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE), 67 drm_getunique, 0, 0, "drm_getunique"); 68 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC), 69 drm_getmagic, 0, 0, "drm_getmagic"); 70 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID), 71 drm_irq_by_busid, 0, 1, "drm_irq_by_busid"); 72 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_GET_MAP), 73 drm_getmap, 0, 0, "drm_getmap"); 74 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT), 75 drm_getclient, 0, 0, "drm_getclient"); 76 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_GET_STATS), 77 drm_getstats, 0, 0, "drm_getstats"); 78 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION), 79 drm_setversion, 0, 1, "drm_setversion"); 80 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE), 81 drm_setunique, 1, 1, "drm_setunique"); 82 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_BLOCK), 83 drm_noop, 1, 1, "drm_ioctl_block"); 84 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK), 85 drm_noop, 1, 1, "DRM_IOCTL_UNBLOCK"); 86 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC), 87 drm_authmagic, 1, 1, "drm_authmagic"); 88 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP), 89 drm_addmap_ioctl, 1, 1, "drm_addmap_ioctl"); 90 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_RM_MAP), 91 drm_rmmap_ioctl, 1, 1, "drm_rmmap_ioctl"); 92 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX), 93 drm_setsareactx, 1, 1, "drm_setsareactx"); 94 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX), 95 drm_getsareactx, 1, 0, "drm_getsareactx"); 96 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX), 97 drm_addctx, 1, 1, "drm_addctx"); 98 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_RM_CTX), 99 drm_rmctx, 1, 1, "drm_rmctx"); 100 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX), 101 drm_modctx, 1, 1, "drm_modctx"); 102 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_GET_CTX), 103 drm_getctx, 1, 0, "drm_getctx"); 104 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX), 105 drm_switchctx, 1, 1, "drm_switchctx"); 106 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX), 107 drm_newctx, 1, 1, "drm_newctx"); 108 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_RES_CTX), 109 drm_resctx, 1, 0, "drm_resctx"); 110 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW), 111 drm_adddraw, 1, 1, "drm_adddraw"); 112 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW), 113 drm_rmdraw, 1, 1, "drm_rmdraw"); 114 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_LOCK), 115 drm_lock, 1, 0, "drm_lock"); 116 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_UNLOCK), 117 drm_unlock, 1, 0, "drm_unlock"); 118 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_FINISH), 119 drm_noop, 1, 0, "drm_noop"); 120 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS), 121 drm_addbufs_ioctl, 1, 1, "drm_addbufs_ioctl"); 122 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS), 123 drm_markbufs, 1, 1, "drm_markbufs"); 124 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS), 125 drm_infobufs, 1, 0, "drm_infobufs"); 126 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS), 127 drm_mapbufs, 1, 0, "drm_mapbufs"); 128 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS), 129 drm_freebufs, 1, 0, "drm_freebufs"); 130 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_DMA), 131 drm_dma, 1, 0, "drm_dma"); 132 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_CONTROL), 133 drm_control, 1, 1, "drm_control"); 134 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE), 135 drm_agp_acquire, 1, 1, "drm_agp_acquire"); 136 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE), 137 drm_agp_release, 1, 1, "drm_agp_release"); 138 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE), 139 drm_agp_enable, 1, 1, "drm_agp_enable"); 140 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO), 141 drm_agp_info, 1, 0, "drm_agp_info"); 142 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC), 143 drm_agp_alloc, 1, 1, "drm_agp_alloc"); 144 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE), 145 drm_agp_free, 1, 1, "drm_agp_free"); 146 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND), 147 drm_agp_bind, 1, 1, "drm_agp_bind"); 148 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND), 149 drm_agp_unbind, 1, 1, "drm_agp_unbind"); 150 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC), 151 drm_sg_alloc, 1, 1, "drm_sg_alloc"); 152 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_SG_FREE), 153 drm_sg_free, 1, 1, "drm_sg_free"); 154 drm_set_ioctl_desc(DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK), 155 drm_wait_vblank, 0, 0, "drm_wait_vblank"); 156 } 157 158 159 const char * 160 drm_find_description(int vendor, int device, drm_pci_id_list_t *idlist) 161 { 162 int i = 0; 163 for (i = 0; idlist[i].vendor != 0; i++) { 164 if ((idlist[i].vendor == vendor) && 165 (idlist[i].device == device)) { 166 return (idlist[i].name); 167 } 168 } 169 return ((char *)NULL); 170 } 171 172 static int 173 drm_firstopen(drm_device_t *dev) 174 { 175 int i; 176 int retval; 177 drm_local_map_t *map; 178 179 /* prebuild the SAREA */ 180 retval = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, 181 _DRM_CONTAINS_LOCK, &map); 182 if (retval != 0) { 183 DRM_ERROR("firstopen: failed to prebuild SAREA"); 184 return (retval); 185 } 186 187 if (dev->driver->use_agp) { 188 DRM_DEBUG("drm_firstopen: use_agp=%d", dev->driver->use_agp); 189 if (drm_device_is_agp(dev)) 190 dev->agp = drm_agp_init(dev); 191 if (dev->driver->require_agp && dev->agp == NULL) { 192 DRM_ERROR("couldn't initialize AGP"); 193 return (EIO); 194 } 195 } 196 197 if (dev->driver->firstopen) 198 retval = dev->driver->firstopen(dev); 199 200 if (retval != 0) { 201 DRM_ERROR("drm_firstopen: driver-specific firstopen failed"); 202 return (retval); 203 } 204 205 dev->buf_use = 0; 206 207 if (dev->driver->use_dma) { 208 i = drm_dma_setup(dev); 209 if (i != 0) 210 return (i); 211 } 212 dev->counters = 6; 213 dev->types[0] = _DRM_STAT_LOCK; 214 dev->types[1] = _DRM_STAT_OPENS; 215 dev->types[2] = _DRM_STAT_CLOSES; 216 dev->types[3] = _DRM_STAT_IOCTLS; 217 dev->types[4] = _DRM_STAT_LOCKS; 218 dev->types[5] = _DRM_STAT_UNLOCKS; 219 220 for (i = 0; i < DRM_ARRAY_SIZE(dev->counts); i++) 221 *(&dev->counts[i]) = 0; 222 223 for (i = 0; i < DRM_HASH_SIZE; i++) { 224 dev->magiclist[i].head = NULL; 225 dev->magiclist[i].tail = NULL; 226 } 227 228 dev->irq_enabled = 0; 229 dev->context_flag = 0; 230 dev->last_context = 0; 231 dev->if_version = 0; 232 233 return (0); 234 } 235 236 /* Free resources associated with the DRM on the last close. */ 237 static int 238 drm_lastclose(drm_device_t *dev) 239 { 240 drm_magic_entry_t *pt, *next; 241 drm_local_map_t *map, *mapsave; 242 int i; 243 244 DRM_SPINLOCK_ASSERT(&dev->dev_lock); 245 246 if (dev->driver->lastclose != NULL) 247 dev->driver->lastclose(dev); 248 249 if (dev->irq_enabled) 250 (void) drm_irq_uninstall(dev); 251 252 if (dev->unique) { 253 drm_free(dev->unique, dev->unique_len + 1, DRM_MEM_DRIVER); 254 dev->unique = NULL; 255 dev->unique_len = 0; 256 } 257 258 /* Clear pid list */ 259 for (i = 0; i < DRM_HASH_SIZE; i++) { 260 for (pt = dev->magiclist[i].head; pt; pt = next) { 261 next = pt->next; 262 drm_free(pt, sizeof (*pt), DRM_MEM_MAGIC); 263 } 264 dev->magiclist[i].head = dev->magiclist[i].tail = NULL; 265 } 266 267 /* Clear AGP information */ 268 if (dev->agp) { 269 drm_agp_mem_t *entry; 270 drm_agp_mem_t *nexte; 271 272 /* 273 * Remove AGP resources, but leave dev->agp 274 * intact until drm_cleanup is called. 275 */ 276 for (entry = dev->agp->memory; entry; entry = nexte) { 277 nexte = entry->next; 278 if (entry->bound) 279 (void) drm_agp_unbind_memory( 280 (unsigned long)entry->handle, dev); 281 (void) drm_agp_free_memory(entry->handle); 282 drm_free(entry, sizeof (*entry), DRM_MEM_AGPLISTS); 283 } 284 dev->agp->memory = NULL; 285 286 if (dev->agp->acquired) 287 (void) drm_agp_do_release(dev); 288 289 dev->agp->acquired = 0; 290 dev->agp->enabled = 0; 291 drm_agp_fini(dev); 292 } 293 294 if (dev->sg != NULL) { 295 drm_sg_mem_t *entry; 296 entry = dev->sg; 297 dev->sg = NULL; 298 drm_sg_cleanup(dev, entry); 299 } 300 301 302 /* Clean up maps that weren't set up by the driver. */ 303 TAILQ_FOREACH_SAFE(map, &dev->maplist, link, mapsave) { 304 if (!map->kernel_owned) 305 drm_rmmap(dev, map); 306 } 307 308 drm_dma_takedown(dev); 309 if (dev->lock.hw_lock) { 310 dev->lock.hw_lock = NULL; /* SHM removed */ 311 dev->lock.filp = NULL; 312 313 mutex_enter(&(dev->lock.lock_mutex)); 314 cv_broadcast(&(dev->lock.lock_cv)); 315 mutex_exit(&(dev->lock.lock_mutex)); 316 } 317 318 return (0); 319 } 320 321 static int 322 drm_load(drm_device_t *dev) 323 { 324 int retcode; 325 326 cv_init(&(dev->lock.lock_cv), NULL, CV_DRIVER, NULL); 327 mutex_init(&(dev->lock.lock_mutex), NULL, MUTEX_DRIVER, NULL); 328 mutex_init(&(dev->dev_lock), NULL, MUTEX_DRIVER, NULL); 329 mutex_init(&dev->drw_lock, NULL, MUTEX_DRIVER, NULL); 330 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 (drm_init_kstats(dev)) { 352 DRM_ERROR("drm_attach => drm_load: init kstats error"); 353 retcode = EFAULT; 354 goto error; 355 } 356 357 DRM_INFO("!drm: Initialized %s %d.%d.%d %s ", 358 dev->driver->driver_name, 359 dev->driver->driver_major, 360 dev->driver->driver_minor, 361 dev->driver->driver_patchlevel, 362 dev->driver->driver_date); 363 return (0); 364 365 error: 366 DRM_LOCK(); 367 (void) drm_lastclose(dev); 368 DRM_UNLOCK(); 369 cv_destroy(&(dev->lock.lock_cv)); 370 mutex_destroy(&(dev->lock.lock_mutex)); 371 mutex_destroy(&(dev->dev_lock)); 372 mutex_destroy(&dev->drw_lock); 373 374 return (retcode); 375 } 376 377 /* called when cleanup this module */ 378 static void 379 drm_unload(drm_device_t *dev) 380 { 381 drm_local_map_t *map; 382 383 drm_ctxbitmap_cleanup(dev); 384 385 DRM_LOCK(); 386 (void) drm_lastclose(dev); 387 DRM_UNLOCK(); 388 389 while ((map = TAILQ_FIRST(&dev->maplist)) != NULL) { 390 drm_rmmap(dev, map); 391 } 392 393 if (dev->driver->unload != NULL) 394 dev->driver->unload(dev); 395 396 drm_mem_uninit(); 397 cv_destroy(&dev->lock.lock_cv); 398 mutex_destroy(&dev->lock.lock_mutex); 399 mutex_destroy(&dev->dev_lock); 400 mutex_destroy(&dev->drw_lock); 401 } 402 403 404 /*ARGSUSED*/ 405 int 406 drm_open(drm_device_t *dev, drm_cminor_t *mp, int openflags, 407 int otyp, cred_t *credp) 408 { 409 int retcode; 410 411 retcode = drm_open_helper(dev, mp, openflags, otyp, credp); 412 413 if (!retcode) { 414 atomic_inc_32(&dev->counts[_DRM_STAT_OPENS]); 415 DRM_LOCK(); 416 if (!dev->open_count ++) 417 retcode = drm_firstopen(dev); 418 DRM_UNLOCK(); 419 } 420 421 return (retcode); 422 } 423 424 /*ARGSUSED*/ 425 int 426 drm_close(drm_device_t *dev, int minor, int flag, int otyp, 427 cred_t *credp) 428 { 429 drm_cminor_t *mp; 430 drm_file_t *fpriv; 431 int retcode = 0; 432 433 DRM_LOCK(); 434 mp = drm_find_file_by_minor(dev, minor); 435 if (!mp) { 436 DRM_UNLOCK(); 437 DRM_ERROR("drm_close: can't find authenticator"); 438 return (EACCES); 439 } 440 441 fpriv = mp->fpriv; 442 ASSERT(fpriv); 443 444 if (--fpriv->refs != 0) 445 goto done; 446 447 if (dev->driver->preclose != NULL) 448 dev->driver->preclose(dev, fpriv); 449 450 /* 451 * Begin inline drm_release 452 */ 453 DRM_DEBUG("drm_close :pid = %d , open_count = %d", 454 DRM_CURRENTPID, dev->open_count); 455 456 if (dev->lock.hw_lock && 457 _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) && 458 dev->lock.filp == fpriv) { 459 DRM_DEBUG("Process %d dead, freeing lock for context %d", 460 DRM_CURRENTPID, 461 _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); 462 if (dev->driver->reclaim_buffers_locked != NULL) 463 dev->driver->reclaim_buffers_locked(dev, fpriv); 464 (void) drm_lock_free(dev, &dev->lock.hw_lock->lock, 465 _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); 466 } else if (dev->driver->reclaim_buffers_locked != NULL && 467 dev->lock.hw_lock != NULL) { 468 DRM_ERROR("drm_close: " 469 "retake lock not implemented yet"); 470 } 471 472 if (dev->driver->use_dma) 473 drm_reclaim_buffers(dev, fpriv); 474 475 476 if (dev->driver->postclose != NULL) 477 dev->driver->postclose(dev, fpriv); 478 TAILQ_REMOVE(&dev->files, fpriv, link); 479 drm_free(fpriv, sizeof (*fpriv), DRM_MEM_FILES); 480 481 done: 482 atomic_inc_32(&dev->counts[_DRM_STAT_CLOSES]); 483 484 TAILQ_REMOVE(&dev->minordevs, mp, link); 485 drm_free(mp, sizeof (*mp), DRM_MEM_FILES); 486 487 if (--dev->open_count == 0) { 488 retcode = drm_lastclose(dev); 489 } 490 DRM_UNLOCK(); 491 492 return (retcode); 493 } 494 495 int 496 drm_attach(drm_device_t *dev) 497 { 498 drm_init_ioctl_arrays(); 499 return (drm_load(dev)); 500 } 501 502 int 503 drm_detach(drm_device_t *dev) 504 { 505 drm_unload(dev); 506 drm_fini_kstats(dev); 507 return (DDI_SUCCESS); 508 } 509 510 static int 511 drm_get_businfo(drm_device_t *dev) 512 { 513 dev->irq = pci_get_irq(dev); 514 if (dev->irq == -1) { 515 DRM_ERROR("drm_get_businfo: get irq error"); 516 return (DDI_FAILURE); 517 } 518 /* XXX Fix domain number (alpha hoses) */ 519 dev->pci_domain = 0; 520 if (pci_get_info(dev, &dev->pci_bus, 521 &dev->pci_slot, &dev->pci_func) != DDI_SUCCESS) { 522 DRM_ERROR("drm_get_businfo: get bus slot func error "); 523 return (DDI_FAILURE); 524 } 525 DRM_DEBUG("drm_get_businfo: pci bus: %d, pci slot :%d pci func %d", 526 dev->pci_bus, dev->pci_slot, dev->pci_func); 527 return (DDI_SUCCESS); 528 } 529 530 int 531 drm_probe(drm_device_t *dev, drm_pci_id_list_t *idlist) 532 { 533 const char *s = NULL; 534 int vendor, device; 535 536 vendor = pci_get_vendor(dev); 537 device = pci_get_device(dev); 538 539 s = drm_find_description(vendor, device, idlist); 540 if (s != NULL) { 541 dev->desc = s; 542 if (drm_get_businfo(dev) != DDI_SUCCESS) { 543 DRM_ERROR("drm_probe: drm get bus info error"); 544 return (DDI_FAILURE); 545 } 546 return (DDI_SUCCESS); 547 } 548 return (DDI_FAILURE); 549 } 550