1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Common misc module interfaces of DRM under Solaris 31 */ 32 33 /* 34 * This module calls into gfx and agpmaster misc modules respectively 35 * for generic graphics operations and AGP master device support. 36 */ 37 38 #include "drm_sunmod.h" 39 #include <sys/modctl.h> 40 #include <sys/kmem.h> 41 #include <vm/seg_kmem.h> 42 43 static struct modlmisc modlmisc = { 44 &mod_miscops, "DRM common interfaces %I%" 45 }; 46 47 static struct modlinkage modlinkage = { 48 MODREV_1, (void *)&modlmisc, NULL 49 }; 50 51 static drm_inst_list_t *drm_inst_head; 52 static kmutex_t drm_inst_list_lock; 53 54 static int drm_sun_open(dev_t *, int, int, cred_t *); 55 static int drm_sun_close(dev_t, int, int, cred_t *); 56 static int drm_sun_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 57 static int drm_sun_devmap(dev_t, devmap_cookie_t, offset_t, size_t, 58 size_t *, uint_t); 59 60 /* 61 * devmap callbacks for AGP and PCI GART 62 */ 63 static int drm_devmap_map(devmap_cookie_t, dev_t, 64 uint_t, offset_t, size_t, void **); 65 static int drm_devmap_dup(devmap_cookie_t, void *, 66 devmap_cookie_t, void **); 67 static void drm_devmap_unmap(devmap_cookie_t, void *, 68 offset_t, size_t, devmap_cookie_t, void **, devmap_cookie_t, void **); 69 70 static drm_inst_list_t *drm_supp_alloc_drv_entry(dev_info_t *); 71 static drm_inst_state_t *drm_sup_devt_to_state(dev_t); 72 static void drm_supp_free_drv_entry(dev_info_t *); 73 74 static struct devmap_callback_ctl drm_devmap_callbacks = { 75 DEVMAP_OPS_REV, /* devmap_rev */ 76 drm_devmap_map, /* devmap_map */ 77 NULL, /* devmap_access */ 78 drm_devmap_dup, /* devmap_dup */ 79 drm_devmap_unmap /* devmap_unmap */ 80 }; 81 82 /* 83 * Common device operations structure for all DRM drivers 84 */ 85 struct cb_ops drm_cb_ops = { 86 drm_sun_open, /* cb_open */ 87 drm_sun_close, /* cb_close */ 88 nodev, /* cb_strategy */ 89 nodev, /* cb_print */ 90 nodev, /* cb_dump */ 91 nodev, /* cb_read */ 92 nodev, /* cb_write */ 93 drm_sun_ioctl, /* cb_ioctl */ 94 drm_sun_devmap, /* cb_devmap */ 95 nodev, /* cb_mmap */ 96 NULL, /* cb_segmap */ 97 nochpoll, /* cb_chpoll */ 98 ddi_prop_op, /* cb_prop_op */ 99 0, /* cb_stream */ 100 D_NEW | D_MTSAFE |D_DEVMAP /* cb_flag */ 101 }; 102 103 104 int 105 _init(void) 106 { 107 int error; 108 109 if ((error = mod_install(&modlinkage)) != 0) { 110 return (error); 111 } 112 113 /* initialize the instance list lock */ 114 mutex_init(&drm_inst_list_lock, NULL, MUTEX_DRIVER, NULL); 115 return (0); 116 } 117 118 int 119 _fini(void) 120 { 121 int err; 122 123 if ((err = mod_remove(&modlinkage)) != 0) 124 return (err); 125 126 mutex_destroy(&drm_inst_list_lock); 127 return (0); 128 } 129 130 int 131 _info(struct modinfo *modinfop) 132 { 133 return (mod_info(&modlinkage, modinfop)); 134 } 135 136 void * 137 drm_supp_register(dev_info_t *dip, drm_device_t *dp) 138 { 139 int error; 140 char buf[80]; 141 int instance = ddi_get_instance(dip); 142 ddi_acc_handle_t pci_cfg_handle; 143 agp_master_softc_t *agpm; 144 drm_inst_state_t *mstate; 145 drm_inst_list_t *entry; 146 gfxp_vgatext_softc_ptr_t gfxp; 147 struct dev_ops *devop; 148 149 ASSERT(dip != NULL); 150 151 entry = drm_supp_alloc_drv_entry(dip); 152 if (entry == NULL) { 153 cmn_err(CE_WARN, "drm_supp_register: failed to get softstate"); 154 return (NULL); 155 } 156 mstate = &entry->disl_state; 157 158 /* 159 * DRM drivers are required to use common cb_ops 160 */ 161 devop = ddi_get_driver(dip); 162 if (devop->devo_cb_ops != &drm_cb_ops) { 163 devop->devo_cb_ops = &drm_cb_ops; 164 } 165 166 /* Generic graphics initialization */ 167 gfxp = gfxp_vgatext_softc_alloc(); 168 error = gfxp_vgatext_attach(dip, DDI_ATTACH, gfxp); 169 if (error != DDI_SUCCESS) { 170 DRM_ERROR("drm_supp_regiter: failed to init gfx"); 171 goto exit1; 172 } 173 174 /* create a minor node for common graphics ops */ 175 (void) sprintf(buf, "%s%d", GFX_NAME, instance); 176 error = ddi_create_minor_node(dip, buf, S_IFCHR, 177 INST2NODE0(instance), DDI_NT_DISPLAY, NULL); 178 if (error != DDI_SUCCESS) { 179 DRM_ERROR("drm_supp_regiter: " 180 "failed to create minor node for gfx"); 181 goto exit2; 182 } 183 184 /* setup mapping for later PCI config space access */ 185 error = pci_config_setup(dip, &pci_cfg_handle); 186 if (error != DDI_SUCCESS) { 187 DRM_ERROR("drm_supp_regiter: " 188 "PCI configuration space setup failed"); 189 goto exit2; 190 } 191 192 /* AGP master attach */ 193 agpm = NULL; 194 if (dp->driver->use_agp) { 195 DRM_DEBUG("drm_supp_regiter: driver use AGP\n"); 196 error = agpmaster_attach(dip, &agpm, 197 pci_cfg_handle, INST2NODE1(instance)); 198 if ((error != DDI_SUCCESS) && (dp->driver->require_agp)) { 199 DRM_ERROR("drm_supp_regiter: " 200 "AGP master support not available"); 201 goto exit3; 202 } 203 } 204 205 mutex_enter(&mstate->mis_lock); 206 mstate->mis_major = ddi_driver_major(dip); 207 mstate->mis_dip = dip; 208 mstate->mis_gfxp = gfxp; 209 mstate->mis_agpm = agpm; 210 mstate->mis_cfg_hdl = pci_cfg_handle; 211 mstate->mis_devp = dp; 212 mutex_exit(&mstate->mis_lock); 213 214 /* create minor node for DRM access */ 215 (void) sprintf(buf, "%s%d", DRM_DEVNODE, instance); 216 if (ddi_create_minor_node(dip, buf, S_IFCHR, 217 INST2NODE2(instance), DDI_NT_DISPLAY_DRM, 0)) { 218 DRM_ERROR("supp_regiter: faled to create minor node for drm"); 219 goto exit4; 220 } 221 222 return ((void *)mstate); 223 224 exit4: 225 if ((dp->driver->use_agp) && agpm) 226 agpmaster_detach(&agpm); 227 exit3: 228 pci_config_teardown(&pci_cfg_handle); 229 exit2: 230 gfxp_vgatext_detach(dip, DDI_DETACH, gfxp); 231 exit1: 232 gfxp_vgatext_softc_free(gfxp); 233 drm_supp_free_drv_entry(dip); 234 ddi_remove_minor_node(dip, NULL); 235 236 return (NULL); 237 } 238 239 240 int 241 drm_supp_unregister(void *handle) 242 { 243 drm_inst_list_t *list; 244 drm_inst_state_t *mstate; 245 246 list = (drm_inst_list_t *)handle; 247 mstate = &list->disl_state; 248 mutex_enter(&mstate->mis_lock); 249 250 /* AGP master detach */ 251 if (mstate->mis_agpm != NULL) 252 agpmaster_detach(&mstate->mis_agpm); 253 254 /* free PCI config access handle */ 255 if (mstate->mis_cfg_hdl) 256 pci_config_teardown(&mstate->mis_cfg_hdl); 257 258 /* graphics misc module detach */ 259 if (mstate->mis_gfxp) { 260 (void) gfxp_vgatext_detach(mstate->mis_dip, DDI_DETACH, 261 mstate->mis_gfxp); 262 gfxp_vgatext_softc_free(mstate->mis_gfxp); 263 } 264 265 mstate->mis_devp = NULL; 266 267 /* remove all minor nodes */ 268 ddi_remove_minor_node(mstate->mis_dip, NULL); 269 mutex_exit(&mstate->mis_lock); 270 drm_supp_free_drv_entry(mstate->mis_dip); 271 272 return (DDI_SUCCESS); 273 } 274 275 276 /*ARGSUSED*/ 277 static int 278 drm_sun_open(dev_t *devp, int flag, int otyp, cred_t *credp) 279 { 280 drm_inst_state_t *mstate; 281 drm_cminor_t *mp, *newp; 282 drm_device_t *dp; 283 minor_t minor; 284 int newminor; 285 int instance; 286 int err; 287 288 mstate = drm_sup_devt_to_state(*devp); 289 /* 290 * return ENXIO for deferred attach so that system can 291 * attach us again. 292 */ 293 if (mstate == NULL) 294 return (ENXIO); 295 296 /* 297 * The lest significant 15 bits are used for minor_number, and 298 * the mid 3 bits are used for instance number. All minor numbers 299 * are used as follows: 300 * 0 -- gfx 301 * 1 -- agpmaster 302 * 2 -- drm 303 * (3, MAX_CLONE_MINOR) -- drm minor node for clone open. 304 */ 305 minor = DEV2MINOR(*devp); 306 instance = DEV2INST(*devp); 307 ASSERT(minor <= MAX_CLONE_MINOR); 308 309 /* 310 * No operations for VGA & AGP mater devices, always return OK. 311 */ 312 if ((minor == GFX_MINOR) || (minor == AGPMASTER_MINOR)) 313 return (0); 314 315 /* 316 * From here, we start to process drm 317 */ 318 319 dp = mstate->mis_devp; 320 if (!dp) 321 return (ENXIO); 322 323 /* 324 * Drm driver implements a software lock to serialize access 325 * to graphics hardware based on per-process granulation. Before 326 * operating graphics hardware, all clients, including kernel 327 * and applications, must acquire this lock via DRM_IOCTL_LOCK 328 * ioctl, and release it via DRM_IOCTL_UNLOCK after finishing 329 * operations. Drm driver will grant r/w permission to the 330 * process which acquires this lock (Kernel is assumed to have 331 * process ID 0). 332 * 333 * A process might be terminated without releasing drm lock, in 334 * this case, drm driver is responsible for clearing the holding. 335 * To be informed of process exiting, drm driver uses clone open 336 * to guarantee that each call to open(9e) have one corresponding 337 * call to close(9e). In most cases, a process will close drm 338 * during process termination, so that drm driver could have a 339 * chance to release drm lock. 340 * 341 * In fact, a driver cannot know exactly when a process exits. 342 * Clone open doesn't address this issue completely: Because of 343 * inheritance, child processes inherit file descriptors from 344 * their parent. As a result, if the parent exits before its 345 * children, drm close(9e) entrypoint won't be called until all 346 * of its children terminate. 347 * 348 * Another issue brought up by inhertance is the process PID 349 * that calls the drm close() entry point may not be the same 350 * as the one who called open(). Per-process struct is allocated 351 * when a process first open() drm, and released when the process 352 * last close() drm. Since open()/close() may be not the same 353 * process, PID cannot be used for key to lookup per-process 354 * struct. So, we associate minor number with per-process struct 355 * during open()'ing, and find corresponding process struct 356 * via minor number when close() is called. 357 */ 358 newp = kmem_zalloc(sizeof (drm_cminor_t), KM_SLEEP); 359 mutex_enter(&dp->dev_lock); 360 for (newminor = DRM_MIN_CLONEMINOR; newminor < MAX_CLONE_MINOR; 361 newminor ++) { 362 TAILQ_FOREACH(mp, &dp->minordevs, link) { 363 if (mp->minor == newminor) 364 break; 365 } 366 if (mp == NULL) 367 goto gotminor; 368 } 369 370 mutex_exit(&dp->dev_lock); 371 return (EMFILE); 372 373 gotminor: 374 TAILQ_INSERT_TAIL(&dp->minordevs, newp, link); 375 newp->minor = newminor; 376 mutex_exit(&dp->dev_lock); 377 err = drm_open(dp, newp, flag, otyp, credp); 378 if (err) { 379 mutex_enter(&dp->dev_lock); 380 TAILQ_REMOVE(&dp->minordevs, newp, link); 381 (void) kmem_free(mp, sizeof (drm_cminor_t)); 382 mutex_exit(&dp->dev_lock); 383 384 return (err); 385 } 386 387 /* return a clone minor */ 388 newminor = newminor | (instance << NBITSMNODE); 389 *devp = makedevice(getmajor(*devp), newminor); 390 return (err); 391 } 392 393 /*ARGSUSED*/ 394 static int 395 drm_sun_close(dev_t dev, int flag, int otyp, cred_t *credp) 396 { 397 drm_inst_state_t *mstate; 398 drm_device_t *dp; 399 minor_t minor; 400 int ret; 401 402 mstate = drm_sup_devt_to_state(dev); 403 if (mstate == NULL) 404 return (EBADF); 405 406 minor = DEV2MINOR(dev); 407 ASSERT(minor <= MAX_CLONE_MINOR); 408 if ((minor == GFX_MINOR) || (minor == AGPMASTER_MINOR)) 409 return (0); 410 411 dp = mstate->mis_devp; 412 if (dp == NULL) { 413 DRM_ERROR("drm_sun_close: NULL soft state"); 414 return (ENXIO); 415 } 416 417 ret = drm_close(dp, minor, flag, otyp, credp); 418 419 return (ret); 420 } 421 422 /*ARGSUSED*/ 423 static int 424 drm_sun_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 425 cred_t *credp, int *rvalp) 426 { 427 extern drm_ioctl_desc_t drm_ioctls[]; 428 429 drm_inst_state_t *mstate; 430 drm_device_t *dp; 431 drm_ioctl_desc_t *ioctl; 432 drm_ioctl_t *func; 433 drm_file_t *fpriv; 434 minor_t minor; 435 int retval; 436 int nr; 437 438 if (cmd == VIS_GETIDENTIFIER) { 439 if (ddi_copyout(&text_ident, (void *)arg, 440 sizeof (struct vis_identifier), mode)) 441 return (EFAULT); 442 } 443 444 mstate = drm_sup_devt_to_state(dev); 445 if (mstate == NULL) { 446 return (EIO); 447 } 448 449 minor = DEV2MINOR(dev); 450 ASSERT(minor <= MAX_CLONE_MINOR); 451 switch (minor) { 452 case GFX_MINOR: 453 retval = gfxp_vgatext_ioctl(dev, cmd, arg, 454 mode, credp, rvalp, mstate->mis_gfxp); 455 return (retval); 456 457 case AGPMASTER_MINOR: 458 retval = agpmaster_ioctl(dev, cmd, arg, mode, 459 credp, rvalp, mstate->mis_agpm); 460 return (retval); 461 462 case DRM_MINOR: 463 default: /* DRM cloning minor nodes */ 464 break; 465 } 466 467 dp = mstate->mis_devp; 468 ASSERT(dp != NULL); 469 470 nr = DRM_IOCTL_NR(cmd); 471 ioctl = &drm_ioctls[nr]; 472 atomic_inc_32(&dp->counts[_DRM_STAT_IOCTLS]); 473 474 /* It's not a core DRM ioctl, try driver-specific. */ 475 if (ioctl->func == NULL && nr >= DRM_COMMAND_BASE) { 476 /* The array entries begin at DRM_COMMAND_BASE ioctl nr */ 477 nr -= DRM_COMMAND_BASE; 478 if (nr > dp->driver->max_driver_ioctl) { 479 DRM_ERROR("Bad driver ioctl number, 0x%x (of 0x%x)", 480 nr, dp->driver->max_driver_ioctl); 481 return (EINVAL); 482 } 483 ioctl = &dp->driver->driver_ioctls[nr]; 484 } 485 486 func = ioctl->func; 487 if (func == NULL) { 488 return (ENOTSUP); 489 } 490 491 mutex_enter(&dp->dev_lock); 492 fpriv = drm_find_file_by_proc(dp, credp); 493 mutex_exit(&dp->dev_lock); 494 if (fpriv == NULL) { 495 DRM_ERROR("drm_sun_ioctl : can't find authenticator"); 496 return (EACCES); 497 } 498 499 if (((ioctl->flags & DRM_ROOT_ONLY) && !DRM_SUSER(credp)) || 500 ((ioctl->flags & DRM_AUTH) && !fpriv->authenticated) || 501 ((ioctl->flags & DRM_MASTER) && !fpriv->master)) 502 return (EACCES); 503 504 retval = func(dp, arg, fpriv, mode); 505 506 return (retval); 507 } 508 509 /*ARGSUSED*/ 510 static int 511 drm_sun_devmap(dev_t dev, devmap_cookie_t dhp, offset_t offset, 512 size_t len, size_t *maplen, uint_t model) 513 { 514 extern int drm_get_pci_index_reg(dev_info_t *, uint_t, uint_t, off_t *); 515 516 drm_inst_state_t *mstate; 517 drm_device_t *dp; 518 ddi_umem_cookie_t cookie; 519 drm_local_map_t *map; 520 unsigned long aperbase; 521 u_offset_t handle; 522 offset_t koff; 523 caddr_t kva; 524 minor_t minor; 525 size_t length; 526 int ret; 527 528 static ddi_device_acc_attr_t dev_attr = { 529 DDI_DEVICE_ATTR_V0, 530 DDI_NEVERSWAP_ACC, 531 DDI_STRICTORDER_ACC, 532 }; 533 534 mstate = drm_sup_devt_to_state(dev); 535 if (mstate == NULL) 536 return (ENXIO); 537 538 minor = DEV2MINOR(dev); 539 switch (minor) { 540 case GFX_MINOR: 541 ret = gfxp_vgatext_devmap(dev, dhp, offset, len, maplen, model, 542 mstate->mis_gfxp); 543 return (ret); 544 545 case AGPMASTER_MINOR: 546 return (ENOTSUP); 547 548 case DRM_MINOR: 549 break; 550 551 default: 552 /* DRM cloning nodes */ 553 if (minor > MAX_CLONE_MINOR) 554 return (EBADF); 555 break; 556 } 557 558 559 dp = mstate->mis_devp; 560 if (dp == NULL) { 561 DRM_ERROR("drm_sun_devmap: NULL soft state"); 562 return (EINVAL); 563 } 564 565 /* 566 * We will solve 32-bit application on 64-bit kernel 567 * issue later, now, we just use low 32-bit 568 */ 569 handle = (u_offset_t)offset; 570 handle &= 0xffffffff; 571 mutex_enter(&dp->dev_lock); 572 TAILQ_FOREACH(map, &dp->maplist, link) { 573 if (handle == 574 ((u_offset_t)((uintptr_t)map->handle) & 0xffffffff)) 575 break; 576 } 577 578 /* 579 * Temporarily, because offset is phys_addr for register 580 * and framebuffer, is kernel virtual_addr for others 581 * Maybe we will use hash table to solve this issue later. 582 */ 583 if (map == NULL) { 584 TAILQ_FOREACH(map, &dp->maplist, link) { 585 if (handle == (map->offset & 0xffffffff)) 586 break; 587 } 588 } 589 590 if (map == NULL) { 591 u_offset_t tmp; 592 593 mutex_exit(&dp->dev_lock); 594 cmn_err(CE_WARN, "Can't find map, offset=0x%llx, len=%x\n", 595 offset, (int)len); 596 cmn_err(CE_WARN, "Current mapping:\n"); 597 TAILQ_FOREACH(map, &dp->maplist, link) { 598 tmp = (u_offset_t)((uintptr_t)map->handle) & 0xffffffff; 599 cmn_err(CE_WARN, "map(handle=0x%p, size=0x%lx,type=%d," 600 "offset=0x%lx), handle=%llx, tmp=%lld", map->handle, 601 map->size, map->type, map->offset, handle, tmp); 602 } 603 return (-1); 604 } 605 if (map->flags & _DRM_RESTRICTED) { 606 mutex_exit(&dp->dev_lock); 607 cmn_err(CE_WARN, "restricted map\n"); 608 return (-1); 609 } 610 611 mutex_exit(&dp->dev_lock); 612 switch (map->type) { 613 case _DRM_FRAME_BUFFER: 614 case _DRM_REGISTERS: 615 { 616 int regno; 617 off_t regoff; 618 619 regno = drm_get_pci_index_reg(dp->dip, 620 map->offset, (uint_t)len, ®off); 621 if (regno < 0) { 622 DRM_ERROR("devmap: failed to get register" 623 " offset=0x%llx, len=0x%x", handle, len); 624 return (EINVAL); 625 } 626 627 ret = devmap_devmem_setup(dhp, dp->dip, NULL, 628 regno, (offset_t)regoff, len, PROT_ALL, 629 0, &dev_attr); 630 if (ret != 0) { 631 *maplen = 0; 632 DRM_ERROR("devmap: failed, regno=%d,type=%d," 633 " handle=0x%x, offset=0x%llx, len=0x%x", 634 regno, map->type, handle, offset, len); 635 return (ret); 636 } 637 *maplen = len; 638 return (ret); 639 } 640 641 case _DRM_SHM: 642 if (map->drm_umem_cookie == NULL) 643 return (EINVAL); 644 length = ptob(btopr(map->size)); 645 ret = devmap_umem_setup(dhp, dp->dip, NULL, 646 map->drm_umem_cookie, 0, length, 647 PROT_ALL, IOMEM_DATA_CACHED, NULL); 648 if (ret != 0) { 649 *maplen = 0; 650 return (ret); 651 } 652 *maplen = length; 653 654 return (DDI_SUCCESS); 655 656 case _DRM_AGP: 657 if (dp->agp == NULL) { 658 cmn_err(CE_WARN, "drm_sun_devmap: attempted to mmap AGP" 659 "memory before AGP support is enabled"); 660 return (DDI_FAILURE); 661 } 662 663 aperbase = dp->agp->base; 664 koff = map->offset - aperbase; 665 length = ptob(btopr(len)); 666 kva = map->dev_addr; 667 cookie = gfxp_umem_cookie_init(kva, length); 668 if (cookie == NULL) { 669 cmn_err(CE_WARN, "devmap:failed to get umem_cookie"); 670 return (DDI_FAILURE); 671 } 672 673 if ((ret = devmap_umem_setup(dhp, dp->dip, 674 &drm_devmap_callbacks, cookie, 0, length, PROT_ALL, 675 IOMEM_DATA_UNCACHED | DEVMAP_ALLOW_REMAP, &dev_attr)) < 0) { 676 gfxp_umem_cookie_destroy(cookie); 677 cmn_err(CE_WARN, "devmap:failed, retval=%d", ret); 678 return (DDI_FAILURE); 679 } 680 *maplen = length; 681 break; 682 683 case _DRM_SCATTER_GATHER: 684 koff = map->offset - (unsigned long)(caddr_t)dp->sg->virtual; 685 kva = map->dev_addr + koff; 686 length = ptob(btopr(len)); 687 if (length > map->size) { 688 cmn_err(CE_WARN, "offset=0x%lx, virtual=0x%p," 689 "mapsize=0x%lx,len=0x%lx", map->offset, 690 dp->sg->virtual, map->size, len); 691 return (DDI_FAILURE); 692 } 693 cookie = gfxp_umem_cookie_init(kva, length); 694 if (cookie == NULL) { 695 cmn_err(CE_WARN, "devmap:failed to get umem_cookie"); 696 return (DDI_FAILURE); 697 } 698 ret = devmap_umem_setup(dhp, dp->dip, 699 &drm_devmap_callbacks, cookie, 0, length, PROT_ALL, 700 IOMEM_DATA_UNCACHED | DEVMAP_ALLOW_REMAP, &dev_attr); 701 if (ret != 0) { 702 cmn_err(CE_WARN, "sun_devmap: umem_setup fail"); 703 gfxp_umem_cookie_destroy(cookie); 704 return (DDI_FAILURE); 705 } 706 *maplen = length; 707 break; 708 709 default: 710 return (DDI_FAILURE); 711 } 712 return (DDI_SUCCESS); 713 714 } 715 716 /*ARGSUSED*/ 717 static int 718 drm_devmap_map(devmap_cookie_t dhc, dev_t dev, uint_t flags, 719 offset_t offset, size_t len, void **new_priv) 720 { 721 devmap_handle_t *dhp; 722 drm_inst_state_t *statep; 723 struct ddi_umem_cookie *cp; 724 725 statep = drm_sup_devt_to_state(dev); 726 ASSERT(statep != NULL); 727 728 /* 729 * This driver only supports MAP_SHARED, 730 * and doesn't support MAP_PRIVATE 731 */ 732 if (flags & MAP_PRIVATE) { 733 cmn_err(CE_WARN, "!DRM driver doesn't support MAP_PRIVATE"); 734 return (EINVAL); 735 } 736 737 mutex_enter(&statep->dis_ctxlock); 738 dhp = (devmap_handle_t *)dhc; 739 cp = (struct ddi_umem_cookie *)dhp->dh_cookie; 740 cp->cook_refcnt = 1; 741 mutex_exit(&statep->dis_ctxlock); 742 *new_priv = statep; 743 744 return (0); 745 } 746 747 /*ARGSUSED*/ 748 static void 749 drm_devmap_unmap(devmap_cookie_t dhc, void *pvtp, offset_t off, size_t len, 750 devmap_cookie_t new_dhp1, void **new_pvtp1, devmap_cookie_t new_dhp2, 751 void **new_pvtp2) 752 { 753 devmap_handle_t *dhp; 754 devmap_handle_t *ndhp; 755 drm_inst_state_t *statep; 756 struct ddi_umem_cookie *cp; 757 struct ddi_umem_cookie *ncp; 758 759 dhp = (devmap_handle_t *)dhc; 760 statep = (drm_inst_state_t *)pvtp; 761 762 mutex_enter(&statep->dis_ctxlock); 763 cp = (struct ddi_umem_cookie *)dhp->dh_cookie; 764 if (new_dhp1 != NULL) { 765 ndhp = (devmap_handle_t *)new_dhp1; 766 ncp = (struct ddi_umem_cookie *)ndhp->dh_cookie; 767 ncp->cook_refcnt ++; 768 *new_pvtp1 = statep; 769 ASSERT(ncp == cp); 770 } 771 772 if (new_dhp2 != NULL) { 773 ndhp = (devmap_handle_t *)new_dhp2; 774 ncp = (struct ddi_umem_cookie *)ndhp->dh_cookie; 775 ncp->cook_refcnt ++; 776 *new_pvtp2 = statep; 777 ASSERT(ncp == cp); 778 } 779 780 cp->cook_refcnt --; 781 if (cp->cook_refcnt == 0) { 782 gfxp_umem_cookie_destroy(dhp->dh_cookie); 783 dhp->dh_cookie = NULL; 784 } 785 mutex_exit(&statep->dis_ctxlock); 786 } 787 788 789 /*ARGSUSED*/ 790 static int 791 drm_devmap_dup(devmap_cookie_t dhc, void *pvtp, devmap_cookie_t new_dhc, 792 void **new_pvtp) 793 { 794 devmap_handle_t *dhp; 795 drm_inst_state_t *statep; 796 struct ddi_umem_cookie *cp; 797 798 statep = (drm_inst_state_t *)pvtp; 799 mutex_enter(&statep->dis_ctxlock); 800 dhp = (devmap_handle_t *)dhc; 801 cp = (struct ddi_umem_cookie *)dhp->dh_cookie; 802 cp->cook_refcnt ++; 803 mutex_exit(&statep->dis_ctxlock); 804 *new_pvtp = statep; 805 806 return (0); 807 } 808 809 int 810 drm_dev_to_instance(dev_t dev) 811 { 812 return (DEV2INST(dev)); 813 } 814 815 /* 816 * drm_supp_alloc_drv_entry() 817 * 818 * Description: 819 * Create a DRM entry and add it into the instance list (drm_inst_head). 820 * Note that we don't allow a duplicated entry 821 */ 822 static drm_inst_list_t * 823 drm_supp_alloc_drv_entry(dev_info_t *dip) 824 { 825 drm_inst_list_t **plist; 826 drm_inst_list_t *list; 827 drm_inst_list_t *entry; 828 829 /* protect the driver list */ 830 mutex_enter(&drm_inst_list_lock); 831 plist = &drm_inst_head; 832 list = *plist; 833 while (list) { 834 if (list->disl_state.mis_dip == dip) { 835 mutex_exit(&drm_inst_list_lock); 836 cmn_err(CE_WARN, "%s%d already registered", 837 ddi_driver_name(dip), ddi_get_instance(dip)); 838 return (NULL); 839 } 840 plist = &list->disl_next; 841 list = list->disl_next; 842 } 843 844 /* "dip" is not registered, create new one and add to list */ 845 entry = kmem_zalloc(sizeof (*entry), KM_SLEEP); 846 *plist = entry; 847 entry->disl_state.mis_dip = dip; 848 mutex_init(&entry->disl_state.mis_lock, NULL, MUTEX_DRIVER, NULL); 849 mutex_init(&entry->disl_state.dis_ctxlock, NULL, MUTEX_DRIVER, NULL); 850 mutex_exit(&drm_inst_list_lock); 851 852 return (entry); 853 854 } /* drm_supp_alloc_drv_entry */ 855 856 /* 857 * drm_supp_free_drv_entry() 858 */ 859 static void 860 drm_supp_free_drv_entry(dev_info_t *dip) 861 { 862 drm_inst_list_t *list; 863 drm_inst_list_t **plist; 864 drm_inst_state_t *mstate; 865 866 /* protect the driver list */ 867 mutex_enter(&drm_inst_list_lock); 868 plist = &drm_inst_head; 869 list = *plist; 870 while (list) { 871 if (list->disl_state.mis_dip == dip) { 872 *plist = list->disl_next; 873 mstate = &list->disl_state; 874 mutex_destroy(&mstate->mis_lock); 875 mutex_destroy(&mstate->dis_ctxlock); 876 kmem_free(list, sizeof (*list)); 877 mutex_exit(&drm_inst_list_lock); 878 return; 879 } 880 plist = &list->disl_next; 881 list = list->disl_next; 882 } 883 mutex_exit(&drm_inst_list_lock); 884 885 } /* drm_supp_free_drv_entry() */ 886 887 /* 888 * drm_sup_devt_to_state() 889 * 890 * description: 891 * Get the soft state of DRM instance by device number 892 */ 893 static drm_inst_state_t * 894 drm_sup_devt_to_state(dev_t dev) 895 { 896 drm_inst_list_t *list; 897 drm_inst_state_t *mstate; 898 major_t major = getmajor(dev); 899 int instance = DEV2INST(dev); 900 901 mutex_enter(&drm_inst_list_lock); 902 list = drm_inst_head; 903 while (list) { 904 mstate = &list->disl_state; 905 mutex_enter(&mstate->mis_lock); 906 907 if ((mstate->mis_major == major) && 908 (ddi_get_instance(mstate->mis_dip) == instance)) { 909 mutex_exit(&mstate->mis_lock); 910 mutex_exit(&drm_inst_list_lock); 911 return (mstate); 912 } 913 914 list = list->disl_next; 915 mutex_exit(&mstate->mis_lock); 916 } 917 918 mutex_exit(&drm_inst_list_lock); 919 return (NULL); 920 921 } /* drm_sup_devt_to_state() */ 922 923 int 924 drm_supp_get_irq(void *handle) 925 { 926 drm_inst_list_t *list; 927 drm_inst_state_t *mstate; 928 int irq; 929 930 list = (drm_inst_list_t *)handle; 931 mstate = &list->disl_state; 932 ASSERT(mstate != NULL); 933 irq = pci_config_get8(mstate->mis_cfg_hdl, PCI_CONF_ILINE); 934 return (irq); 935 } 936 937 int 938 drm_supp_device_capability(void *handle, int capid) 939 { 940 drm_inst_list_t *list; 941 drm_inst_state_t *mstate; 942 uint8_t cap = 0; 943 uint16_t caps_ptr; 944 945 list = (drm_inst_list_t *)handle; 946 mstate = &list->disl_state; 947 ASSERT(mstate != NULL); 948 949 /* has capabilities list ? */ 950 if ((pci_config_get16(mstate->mis_cfg_hdl, PCI_CONF_STAT) & 951 PCI_CONF_CAP_MASK) == 0) 952 return (NULL); 953 954 caps_ptr = pci_config_get8(mstate->mis_cfg_hdl, PCI_CONF_CAP_PTR); 955 while (caps_ptr != PCI_CAP_NEXT_PTR_NULL) { 956 cap = pci_config_get32(mstate->mis_cfg_hdl, caps_ptr); 957 if ((cap & PCI_CONF_CAPID_MASK) == capid) 958 return (cap); 959 caps_ptr = pci_config_get8(mstate->mis_cfg_hdl, 960 caps_ptr + PCI_CAP_NEXT_PTR); 961 } 962 963 return (0); 964 } 965