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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 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 * Layered driver support. 31 */ 32 33 #include <sys/atomic.h> 34 #include <sys/types.h> 35 #include <sys/t_lock.h> 36 #include <sys/param.h> 37 #include <sys/conf.h> 38 #include <sys/systm.h> 39 #include <sys/sysmacros.h> 40 #include <sys/buf.h> 41 #include <sys/cred.h> 42 #include <sys/uio.h> 43 #include <sys/vnode.h> 44 #include <sys/fs/snode.h> 45 #include <sys/open.h> 46 #include <sys/kmem.h> 47 #include <sys/file.h> 48 #include <sys/bootconf.h> 49 #include <sys/pathname.h> 50 #include <sys/bitmap.h> 51 #include <sys/stat.h> 52 #include <sys/dditypes.h> 53 #include <sys/ddi_impldefs.h> 54 #include <sys/ddi.h> 55 #include <sys/sunddi.h> 56 #include <sys/sunndi.h> 57 #include <sys/esunddi.h> 58 #include <sys/autoconf.h> 59 #include <sys/sunldi.h> 60 #include <sys/sunldi_impl.h> 61 #include <sys/errno.h> 62 #include <sys/debug.h> 63 #include <sys/modctl.h> 64 #include <sys/var.h> 65 #include <vm/seg_vn.h> 66 67 #include <sys/stropts.h> 68 #include <sys/strsubr.h> 69 #include <sys/socket.h> 70 #include <sys/socketvar.h> 71 #include <sys/kstr.h> 72 73 74 /* 75 * Define macros to manipulate snode, vnode, and open device flags 76 */ 77 #define VTYP_VALID(i) (((i) == VCHR) || ((i) == VBLK)) 78 #define VTYP_TO_OTYP(i) (((i) == VCHR) ? OTYP_CHR : OTYP_BLK) 79 #define VTYP_TO_STYP(i) (((i) == VCHR) ? S_IFCHR : S_IFBLK) 80 81 #define OTYP_VALID(i) (((i) == OTYP_CHR) || ((i) == OTYP_BLK)) 82 #define OTYP_TO_VTYP(i) (((i) == OTYP_CHR) ? VCHR : VBLK) 83 #define OTYP_TO_STYP(i) (((i) == OTYP_CHR) ? S_IFCHR : S_IFBLK) 84 85 #define STYP_VALID(i) (((i) == S_IFCHR) || ((i) == S_IFBLK)) 86 #define STYP_TO_VTYP(i) (((i) == S_IFCHR) ? VCHR : VBLK) 87 88 /* 89 * Define macros for accessing layered driver hash structures 90 */ 91 #define LH_HASH(vp) (handle_hash_func(vp) % LH_HASH_SZ) 92 #define LI_HASH(mid, dip, dev) (ident_hash_func(mid, dip, dev) % LI_HASH_SZ) 93 94 /* 95 * Define layered handle flags used in the lh_type field 96 */ 97 #define LH_STREAM (0x1) /* handle to a streams device */ 98 #define LH_CBDEV (0x2) /* handle to a char/block device */ 99 100 /* 101 * Define marco for devid property lookups 102 */ 103 #define DEVID_PROP_FLAGS (DDI_PROP_DONTPASS | \ 104 DDI_PROP_TYPE_STRING|DDI_PROP_CANSLEEP) 105 106 107 /* 108 * globals 109 */ 110 static kmutex_t ldi_ident_hash_lock[LI_HASH_SZ]; 111 static struct ldi_ident *ldi_ident_hash[LI_HASH_SZ]; 112 113 static kmutex_t ldi_handle_hash_lock[LH_HASH_SZ]; 114 static struct ldi_handle *ldi_handle_hash[LH_HASH_SZ]; 115 static size_t ldi_handle_hash_count; 116 117 void 118 ldi_init(void) 119 { 120 int i; 121 122 ldi_handle_hash_count = 0; 123 for (i = 0; i < LH_HASH_SZ; i++) { 124 mutex_init(&ldi_handle_hash_lock[i], NULL, MUTEX_DEFAULT, NULL); 125 ldi_handle_hash[i] = NULL; 126 } 127 for (i = 0; i < LI_HASH_SZ; i++) { 128 mutex_init(&ldi_ident_hash_lock[i], NULL, MUTEX_DEFAULT, NULL); 129 ldi_ident_hash[i] = NULL; 130 } 131 } 132 133 /* 134 * LDI ident manipulation functions 135 */ 136 static uint_t 137 ident_hash_func(modid_t modid, dev_info_t *dip, dev_t dev) 138 { 139 if (dip != NULL) { 140 uintptr_t k = (uintptr_t)dip; 141 k >>= (int)highbit(sizeof (struct dev_info)); 142 return ((uint_t)k); 143 } else if (dev != DDI_DEV_T_NONE) { 144 return (modid + getminor(dev) + getmajor(dev)); 145 } else { 146 return (modid); 147 } 148 } 149 150 static struct ldi_ident ** 151 ident_find_ref_nolock(modid_t modid, dev_info_t *dip, dev_t dev, major_t major) 152 { 153 struct ldi_ident **lipp = NULL; 154 uint_t index = LI_HASH(modid, dip, dev); 155 156 ASSERT(MUTEX_HELD(&ldi_ident_hash_lock[index])); 157 158 for (lipp = &(ldi_ident_hash[index]); 159 (*lipp != NULL); 160 lipp = &((*lipp)->li_next)) { 161 if (((*lipp)->li_modid == modid) && 162 ((*lipp)->li_major == major) && 163 ((*lipp)->li_dip == dip) && 164 ((*lipp)->li_dev == dev)) 165 break; 166 } 167 168 ASSERT(lipp != NULL); 169 return (lipp); 170 } 171 172 static struct ldi_ident * 173 ident_alloc(char *mod_name, dev_info_t *dip, dev_t dev, major_t major) 174 { 175 struct ldi_ident *lip, **lipp; 176 modid_t modid; 177 uint_t index; 178 179 ASSERT(mod_name != NULL); 180 181 /* get the module id */ 182 modid = mod_name_to_modid(mod_name); 183 ASSERT(modid != -1); 184 185 /* allocate a new ident in case we need it */ 186 lip = kmem_zalloc(sizeof (*lip), KM_SLEEP); 187 188 /* search the hash for a matching ident */ 189 index = LI_HASH(modid, dip, dev); 190 mutex_enter(&ldi_ident_hash_lock[index]); 191 lipp = ident_find_ref_nolock(modid, dip, dev, major); 192 193 if (*lipp != NULL) { 194 /* we found an indent in the hash */ 195 ASSERT(strcmp((*lipp)->li_modname, mod_name) == 0); 196 (*lipp)->li_ref++; 197 mutex_exit(&ldi_ident_hash_lock[index]); 198 kmem_free(lip, sizeof (struct ldi_ident)); 199 return (*lipp); 200 } 201 202 /* initialize the new ident */ 203 lip->li_next = NULL; 204 lip->li_ref = 1; 205 lip->li_modid = modid; 206 lip->li_major = major; 207 lip->li_dip = dip; 208 lip->li_dev = dev; 209 (void) strncpy(lip->li_modname, mod_name, sizeof (lip->li_modname) - 1); 210 211 /* add it to the ident hash */ 212 lip->li_next = ldi_ident_hash[index]; 213 ldi_ident_hash[index] = lip; 214 215 mutex_exit(&ldi_ident_hash_lock[index]); 216 return (lip); 217 } 218 219 static void 220 ident_hold(struct ldi_ident *lip) 221 { 222 uint_t index; 223 224 ASSERT(lip != NULL); 225 index = LI_HASH(lip->li_modid, lip->li_dip, lip->li_dev); 226 mutex_enter(&ldi_ident_hash_lock[index]); 227 ASSERT(lip->li_ref > 0); 228 lip->li_ref++; 229 mutex_exit(&ldi_ident_hash_lock[index]); 230 } 231 232 static void 233 ident_release(struct ldi_ident *lip) 234 { 235 struct ldi_ident **lipp; 236 uint_t index; 237 238 ASSERT(lip != NULL); 239 index = LI_HASH(lip->li_modid, lip->li_dip, lip->li_dev); 240 mutex_enter(&ldi_ident_hash_lock[index]); 241 242 ASSERT(lip->li_ref > 0); 243 if (--lip->li_ref > 0) { 244 /* there are more references to this ident */ 245 mutex_exit(&ldi_ident_hash_lock[index]); 246 return; 247 } 248 249 /* this was the last reference/open for this ident. free it. */ 250 lipp = ident_find_ref_nolock( 251 lip->li_modid, lip->li_dip, lip->li_dev, lip->li_major); 252 253 ASSERT((lipp != NULL) && (*lipp != NULL)); 254 *lipp = lip->li_next; 255 mutex_exit(&ldi_ident_hash_lock[index]); 256 kmem_free(lip, sizeof (struct ldi_ident)); 257 } 258 259 /* 260 * LDI handle manipulation functions 261 */ 262 static uint_t 263 handle_hash_func(void *vp) 264 { 265 uintptr_t k = (uintptr_t)vp; 266 k >>= (int)highbit(sizeof (vnode_t)); 267 return ((uint_t)k); 268 } 269 270 static struct ldi_handle ** 271 handle_find_ref_nolock(vnode_t *vp, struct ldi_ident *ident) 272 { 273 struct ldi_handle **lhpp = NULL; 274 uint_t index = LH_HASH(vp); 275 276 ASSERT(MUTEX_HELD(&ldi_handle_hash_lock[index])); 277 278 for (lhpp = &(ldi_handle_hash[index]); 279 (*lhpp != NULL); 280 lhpp = &((*lhpp)->lh_next)) { 281 if (((*lhpp)->lh_ident == ident) && 282 ((*lhpp)->lh_vp == vp)) 283 break; 284 } 285 286 ASSERT(lhpp != NULL); 287 return (lhpp); 288 } 289 290 static struct ldi_handle * 291 handle_find(vnode_t *vp, struct ldi_ident *ident) 292 { 293 struct ldi_handle **lhpp; 294 int index = LH_HASH(vp); 295 296 mutex_enter(&ldi_handle_hash_lock[index]); 297 lhpp = handle_find_ref_nolock(vp, ident); 298 mutex_exit(&ldi_handle_hash_lock[index]); 299 ASSERT(lhpp != NULL); 300 return (*lhpp); 301 } 302 303 static struct ldi_handle * 304 handle_alloc(vnode_t *vp, struct ldi_ident *ident) 305 { 306 struct ldi_handle *lhp, **lhpp; 307 uint_t index; 308 309 ASSERT((vp != NULL) && (ident != NULL)); 310 311 /* allocate a new handle in case we need it */ 312 lhp = kmem_zalloc(sizeof (*lhp), KM_SLEEP); 313 314 /* search the hash for a matching handle */ 315 index = LH_HASH(vp); 316 mutex_enter(&ldi_handle_hash_lock[index]); 317 lhpp = handle_find_ref_nolock(vp, ident); 318 319 if (*lhpp != NULL) { 320 /* we found a handle in the hash */ 321 (*lhpp)->lh_ref++; 322 mutex_exit(&ldi_handle_hash_lock[index]); 323 324 LDI_ALLOCFREE((CE_WARN, "ldi handle alloc: dup " 325 "lh=0x%p, ident=0x%p, vp=0x%p, drv=%s, minor=0x%x", 326 (void *)*lhpp, (void *)ident, (void *)vp, 327 mod_major_to_name(getmajor(vp->v_rdev)), 328 getminor(vp->v_rdev))); 329 330 kmem_free(lhp, sizeof (struct ldi_handle)); 331 return (*lhpp); 332 } 333 334 /* initialize the new handle */ 335 lhp->lh_ref = 1; 336 lhp->lh_vp = vp; 337 lhp->lh_ident = ident; 338 mutex_init(lhp->lh_lock, NULL, MUTEX_DEFAULT, NULL); 339 340 /* set the device type for this handle */ 341 lhp->lh_type = 0; 342 if (STREAMSTAB(getmajor(vp->v_rdev))) { 343 ASSERT(vp->v_type == VCHR); 344 lhp->lh_type |= LH_STREAM; 345 } else { 346 lhp->lh_type |= LH_CBDEV; 347 } 348 349 /* get holds on other objects */ 350 ident_hold(ident); 351 ASSERT(vp->v_count >= 1); 352 VN_HOLD(vp); 353 354 /* add it to the handle hash */ 355 lhp->lh_next = ldi_handle_hash[index]; 356 ldi_handle_hash[index] = lhp; 357 atomic_add_long(&ldi_handle_hash_count, 1); 358 359 LDI_ALLOCFREE((CE_WARN, "ldi handle alloc: new " 360 "lh=0x%p, ident=0x%p, vp=0x%p, drv=%s, minor=0x%x", 361 (void *)lhp, (void *)ident, (void *)vp, 362 mod_major_to_name(getmajor(vp->v_rdev)), 363 getminor(vp->v_rdev))); 364 365 mutex_exit(&ldi_handle_hash_lock[index]); 366 return (lhp); 367 } 368 369 static void 370 handle_release(struct ldi_handle *lhp) 371 { 372 struct ldi_handle **lhpp; 373 uint_t index; 374 375 ASSERT(lhp != NULL); 376 377 index = LH_HASH(lhp->lh_vp); 378 mutex_enter(&ldi_handle_hash_lock[index]); 379 380 LDI_ALLOCFREE((CE_WARN, "ldi handle release: " 381 "lh=0x%p, ident=0x%p, vp=0x%p, drv=%s, minor=0x%x", 382 (void *)lhp, (void *)lhp->lh_ident, (void *)lhp->lh_vp, 383 mod_major_to_name(getmajor(lhp->lh_vp->v_rdev)), 384 getminor(lhp->lh_vp->v_rdev))); 385 386 ASSERT(lhp->lh_ref > 0); 387 if (--lhp->lh_ref > 0) { 388 /* there are more references to this handle */ 389 mutex_exit(&ldi_handle_hash_lock[index]); 390 return; 391 } 392 393 /* this was the last reference/open for this handle. free it. */ 394 lhpp = handle_find_ref_nolock(lhp->lh_vp, lhp->lh_ident); 395 ASSERT((lhpp != NULL) && (*lhpp != NULL)); 396 *lhpp = lhp->lh_next; 397 atomic_add_long(&ldi_handle_hash_count, -1); 398 mutex_exit(&ldi_handle_hash_lock[index]); 399 400 VN_RELE(lhp->lh_vp); 401 ident_release(lhp->lh_ident); 402 mutex_destroy(lhp->lh_lock); 403 kmem_free(lhp, sizeof (struct ldi_handle)); 404 } 405 406 /* 407 * LDI event manipulation functions 408 */ 409 static void 410 handle_event_add(ldi_event_t *lep) 411 { 412 struct ldi_handle *lhp = lep->le_lhp; 413 414 ASSERT(lhp != NULL); 415 416 mutex_enter(lhp->lh_lock); 417 if (lhp->lh_events == NULL) { 418 lhp->lh_events = lep; 419 mutex_exit(lhp->lh_lock); 420 return; 421 } 422 423 lep->le_next = lhp->lh_events; 424 lhp->lh_events->le_prev = lep; 425 lhp->lh_events = lep; 426 mutex_exit(lhp->lh_lock); 427 } 428 429 static void 430 handle_event_remove(ldi_event_t *lep) 431 { 432 struct ldi_handle *lhp = lep->le_lhp; 433 434 ASSERT(lhp != NULL); 435 436 mutex_enter(lhp->lh_lock); 437 if (lep->le_prev) 438 lep->le_prev->le_next = lep->le_next; 439 if (lep->le_next) 440 lep->le_next->le_prev = lep->le_prev; 441 if (lhp->lh_events == lep) 442 lhp->lh_events = lep->le_next; 443 mutex_exit(lhp->lh_lock); 444 445 } 446 447 static void 448 i_ldi_callback(dev_info_t *dip, ddi_eventcookie_t event_cookie, 449 void *arg, void *bus_impldata) 450 { 451 ldi_event_t *lep = (ldi_event_t *)arg; 452 453 ASSERT(lep != NULL); 454 455 LDI_EVENTCB((CE_NOTE, "%s: dip=0x%p, " 456 "event_cookie=0x%p, ldi_eventp=0x%p", "i_ldi_callback", 457 (void *)dip, (void *)event_cookie, (void *)lep)); 458 459 lep->le_handler(lep->le_lhp, event_cookie, lep->le_arg, bus_impldata); 460 } 461 462 /* 463 * LDI open helper functions 464 */ 465 466 /* get a vnode to a device by dev_t and otyp */ 467 static int 468 ldi_vp_from_dev(dev_t dev, int otyp, vnode_t **vpp) 469 { 470 dev_info_t *dip; 471 vnode_t *vp; 472 473 /* sanity check required input parameters */ 474 if ((dev == DDI_DEV_T_NONE) || (!OTYP_VALID(otyp)) || (vpp == NULL)) 475 return (EINVAL); 476 477 if ((dip = e_ddi_hold_devi_by_dev(dev, 0)) == NULL) 478 return (ENODEV); 479 480 if (STREAMSTAB(getmajor(dev)) && (otyp != OTYP_CHR)) { 481 ddi_release_devi(dip); /* from e_ddi_hold_devi_by_dev */ 482 return (ENXIO); 483 } 484 485 vp = makespecvp(dev, OTYP_TO_VTYP(otyp)); 486 spec_assoc_vp_with_devi(vp, dip); 487 ddi_release_devi(dip); /* from e_ddi_hold_devi_by_dev */ 488 489 *vpp = vp; 490 return (0); 491 } 492 493 /* get a vnode to a device by pathname */ 494 static int 495 ldi_vp_from_name(char *path, vnode_t **vpp) 496 { 497 vnode_t *vp = NULL; 498 int ret; 499 500 /* sanity check required input parameters */ 501 if ((path == NULL) || (vpp == NULL)) 502 return (EINVAL); 503 504 if (modrootloaded) { 505 cred_t *saved_cred = curthread->t_cred; 506 507 /* we don't want lookupname to fail because of credentials */ 508 curthread->t_cred = kcred; 509 ret = lookupname(path, UIO_SYSSPACE, FOLLOW, NULLVPP, &vp); 510 curthread->t_cred = saved_cred; 511 512 if (ret == 0) { 513 if (!vn_matchops(vp, spec_getvnodeops()) || 514 !VTYP_VALID(vp->v_type)) { 515 VN_RELE(vp); 516 return (ENXIO); 517 } 518 } 519 } 520 521 if (vp == NULL) { 522 dev_info_t *dip; 523 dev_t dev; 524 int spec_type; 525 526 /* 527 * Root is not mounted, the minor node is not specified, 528 * or an OBP path has been specified. 529 */ 530 531 /* 532 * Determine if path can be pruned to produce an 533 * OBP or devfs path for resolve_pathname. 534 */ 535 if (strncmp(path, "/devices/", 9) == 0) 536 path += strlen("/devices"); 537 538 /* 539 * if no minor node was specified the DEFAULT minor node 540 * will be returned. if there is no DEFAULT minor node 541 * one will be fabricated of type S_IFCHR with the minor 542 * number equal to the instance number. 543 */ 544 ret = resolve_pathname(path, &dip, &dev, &spec_type); 545 if (ret != 0) 546 return (ENODEV); 547 548 ASSERT(STYP_VALID(spec_type)); 549 vp = makespecvp(dev, STYP_TO_VTYP(spec_type)); 550 spec_assoc_vp_with_devi(vp, dip); 551 ddi_release_devi(dip); 552 } 553 554 *vpp = vp; 555 return (0); 556 } 557 558 static int 559 ldi_devid_match(ddi_devid_t devid, dev_info_t *dip, dev_t dev) 560 { 561 char *devidstr; 562 ddi_prop_t *propp; 563 564 /* convert devid as a string property */ 565 if ((devidstr = ddi_devid_str_encode(devid, NULL)) == NULL) 566 return (0); 567 568 /* 569 * Search for the devid. For speed and ease in locking this 570 * code directly uses the property implementation. See 571 * ddi_common_devid_to_devlist() for a comment as to why. 572 */ 573 mutex_enter(&(DEVI(dip)->devi_lock)); 574 575 /* check if there is a DDI_DEV_T_NONE devid property */ 576 propp = i_ddi_prop_search(DDI_DEV_T_NONE, 577 DEVID_PROP_NAME, DEVID_PROP_FLAGS, &DEVI(dip)->devi_hw_prop_ptr); 578 if (propp != NULL) { 579 if (ddi_devid_str_compare(propp->prop_val, devidstr) == 0) { 580 /* a DDI_DEV_T_NONE devid exists and matchs */ 581 mutex_exit(&(DEVI(dip)->devi_lock)); 582 ddi_devid_str_free(devidstr); 583 return (1); 584 } else { 585 /* a DDI_DEV_T_NONE devid exists and doesn't match */ 586 mutex_exit(&(DEVI(dip)->devi_lock)); 587 ddi_devid_str_free(devidstr); 588 return (0); 589 } 590 } 591 592 /* check if there is a devt specific devid property */ 593 propp = i_ddi_prop_search(dev, 594 DEVID_PROP_NAME, DEVID_PROP_FLAGS, &(DEVI(dip)->devi_hw_prop_ptr)); 595 if (propp != NULL) { 596 if (ddi_devid_str_compare(propp->prop_val, devidstr) == 0) { 597 /* a devt specific devid exists and matchs */ 598 mutex_exit(&(DEVI(dip)->devi_lock)); 599 ddi_devid_str_free(devidstr); 600 return (1); 601 } else { 602 /* a devt specific devid exists and doesn't match */ 603 mutex_exit(&(DEVI(dip)->devi_lock)); 604 ddi_devid_str_free(devidstr); 605 return (0); 606 } 607 } 608 609 /* we didn't find any devids associated with the device */ 610 mutex_exit(&(DEVI(dip)->devi_lock)); 611 ddi_devid_str_free(devidstr); 612 return (0); 613 } 614 615 /* get a handle to a device by devid and minor name */ 616 static int 617 ldi_vp_from_devid(ddi_devid_t devid, char *minor_name, vnode_t **vpp) 618 { 619 dev_info_t *dip; 620 vnode_t *vp; 621 int ret, i, ndevs, styp; 622 dev_t dev, *devs; 623 624 /* sanity check required input parameters */ 625 if ((devid == NULL) || (minor_name == NULL) || (vpp == NULL)) 626 return (EINVAL); 627 628 ret = ddi_lyr_devid_to_devlist(devid, minor_name, &ndevs, &devs); 629 if ((ret != DDI_SUCCESS) || (ndevs <= 0)) 630 return (ENODEV); 631 632 for (i = 0; i < ndevs; i++) { 633 dev = devs[i]; 634 635 if ((dip = e_ddi_hold_devi_by_dev(dev, 0)) == NULL) 636 continue; 637 638 /* 639 * now we have to verify that the devid of the disk 640 * still matches what was requested. 641 * 642 * we have to do this because the devid could have 643 * changed between the call to ddi_lyr_devid_to_devlist() 644 * and e_ddi_hold_devi_by_dev(). this is because when 645 * ddi_lyr_devid_to_devlist() returns a list of devts 646 * there is no kind of hold on those devts so a device 647 * could have been replaced out from under us in the 648 * interim. 649 */ 650 if ((i_ddi_minorname_to_devtspectype(dip, minor_name, 651 NULL, &styp) == DDI_SUCCESS) && 652 ldi_devid_match(devid, dip, dev)) 653 break; 654 655 ddi_release_devi(dip); /* from e_ddi_hold_devi_by_dev() */ 656 } 657 658 ddi_lyr_free_devlist(devs, ndevs); 659 660 if (i == ndevs) 661 return (ENODEV); 662 663 ASSERT(STYP_VALID(styp)); 664 vp = makespecvp(dev, STYP_TO_VTYP(styp)); 665 spec_assoc_vp_with_devi(vp, dip); 666 ddi_release_devi(dip); /* from e_ddi_hold_devi_by_dev */ 667 668 *vpp = vp; 669 return (0); 670 } 671 672 /* given a vnode, open a device */ 673 static int 674 ldi_open_by_vp(vnode_t **vpp, int flag, cred_t *cr, 675 ldi_handle_t *lhp, struct ldi_ident *li) 676 { 677 struct ldi_handle *nlhp; 678 vnode_t *vp; 679 int err; 680 681 ASSERT((vpp != NULL) && (*vpp != NULL)); 682 ASSERT((lhp != NULL) && (li != NULL)); 683 684 vp = *vpp; 685 /* if the vnode passed in is not a device, then bail */ 686 if (!vn_matchops(vp, spec_getvnodeops()) || !VTYP_VALID(vp->v_type)) 687 return (ENXIO); 688 689 /* 690 * the caller may have specified a node that 691 * doesn't have cb_ops defined. the ldi doesn't yet 692 * support opening devices without a valid cb_ops. 693 */ 694 if (devopsp[getmajor(vp->v_rdev)]->devo_cb_ops == NULL) 695 return (ENXIO); 696 697 /* open the device */ 698 if ((err = VOP_OPEN(&vp, flag | FKLYR, cr)) != 0) 699 return (err); 700 701 /* possible clone open, make sure that we still have a spec node */ 702 ASSERT(vn_matchops(vp, spec_getvnodeops())); 703 704 nlhp = handle_alloc(vp, li); 705 706 if (vp != *vpp) { 707 /* 708 * allocating the layered handle took a new hold on the vnode 709 * so we can release the hold that was returned by the clone 710 * open 711 */ 712 LDI_OPENCLOSE((CE_WARN, "%s: lh=0x%p", 713 "ldi clone open", (void *)nlhp)); 714 } else { 715 LDI_OPENCLOSE((CE_WARN, "%s: lh=0x%p", 716 "ldi open", (void *)nlhp)); 717 } 718 719 /* Flush back any dirty pages associated with the device. */ 720 if (nlhp->lh_type & LH_CBDEV) { 721 vnode_t *cvp = common_specvp(nlhp->lh_vp); 722 dev_t dev = cvp->v_rdev; 723 724 (void) VOP_PUTPAGE(cvp, 0, 0, B_INVAL, kcred); 725 bflush(dev); 726 } 727 728 *vpp = vp; 729 *lhp = (ldi_handle_t)nlhp; 730 return (0); 731 } 732 733 /* Call a drivers prop_op(9E) interface */ 734 static int 735 i_ldi_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 736 int flags, char *name, caddr_t valuep, int *lengthp) 737 { 738 struct dev_ops *ops = NULL; 739 int res; 740 741 ASSERT((dip != NULL) && (name != NULL)); 742 ASSERT((prop_op == PROP_LEN) || (valuep != NULL)); 743 ASSERT(lengthp != NULL); 744 745 /* 746 * we can only be invoked after a driver has been opened and 747 * someone has a layered handle to it, so there had better be 748 * a valid ops vector. 749 */ 750 ops = DEVI(dip)->devi_ops; 751 ASSERT(ops && ops->devo_cb_ops); 752 753 /* 754 * Some nexus drivers incorrectly set cb_prop_op to nodev, 755 * nulldev or even NULL. 756 */ 757 if ((ops->devo_cb_ops->cb_prop_op == nodev) || 758 (ops->devo_cb_ops->cb_prop_op == nulldev) || 759 (ops->devo_cb_ops->cb_prop_op == NULL)) { 760 return (DDI_PROP_NOT_FOUND); 761 } 762 763 /* check if this is actually DDI_DEV_T_ANY query */ 764 if (flags & LDI_DEV_T_ANY) { 765 flags &= ~LDI_DEV_T_ANY; 766 dev = DDI_DEV_T_ANY; 767 } 768 769 res = cdev_prop_op(dev, dip, prop_op, flags, name, valuep, lengthp); 770 return (res); 771 } 772 773 static void 774 i_ldi_prop_op_free(struct prop_driver_data *pdd) 775 { 776 kmem_free(pdd, pdd->pdd_size); 777 } 778 779 static caddr_t 780 i_ldi_prop_op_alloc(int prop_len) 781 { 782 struct prop_driver_data *pdd; 783 int pdd_size; 784 785 pdd_size = sizeof (struct prop_driver_data) + prop_len; 786 pdd = kmem_alloc(pdd_size, KM_SLEEP); 787 pdd->pdd_size = pdd_size; 788 pdd->pdd_prop_free = i_ldi_prop_op_free; 789 return ((caddr_t)&pdd[1]); 790 } 791 792 /* 793 * i_ldi_prop_op_typed() is a wrapper for i_ldi_prop_op that is used 794 * by the typed ldi property lookup interfaces. 795 */ 796 static int 797 i_ldi_prop_op_typed(dev_t dev, dev_info_t *dip, int flags, char *name, 798 caddr_t *datap, int *lengthp, int elem_size) 799 { 800 caddr_t prop_val; 801 int prop_len, res; 802 803 ASSERT((dip != NULL) && (name != NULL)); 804 ASSERT((datap != NULL) && (lengthp != NULL)); 805 806 /* 807 * first call the drivers prop_op() interface to allow it 808 * it to override default property values. 809 */ 810 res = i_ldi_prop_op(dev, dip, PROP_LEN, 811 flags | DDI_PROP_DYNAMIC, name, NULL, &prop_len); 812 if (res != DDI_PROP_SUCCESS) 813 return (DDI_PROP_NOT_FOUND); 814 815 /* sanity check the property length */ 816 if (prop_len == 0) { 817 /* 818 * the ddi typed interfaces don't allow a drivers to 819 * create properties with a length of 0. so we should 820 * prevent drivers from returning 0 length dynamic 821 * properties for typed property lookups. 822 */ 823 return (DDI_PROP_NOT_FOUND); 824 } 825 826 /* sanity check the property length against the element size */ 827 if (elem_size && ((prop_len % elem_size) != 0)) 828 return (DDI_PROP_NOT_FOUND); 829 830 /* 831 * got it. now allocate a prop_driver_data struct so that the 832 * user can free the property via ddi_prop_free(). 833 */ 834 prop_val = i_ldi_prop_op_alloc(prop_len); 835 836 /* lookup the property again, this time get the value */ 837 res = i_ldi_prop_op(dev, dip, PROP_LEN_AND_VAL_BUF, 838 flags | DDI_PROP_DYNAMIC, name, prop_val, &prop_len); 839 if (res != DDI_PROP_SUCCESS) { 840 ddi_prop_free(prop_val); 841 return (DDI_PROP_NOT_FOUND); 842 } 843 844 /* sanity check the property length */ 845 if (prop_len == 0) { 846 ddi_prop_free(prop_val); 847 return (DDI_PROP_NOT_FOUND); 848 } 849 850 /* sanity check the property length against the element size */ 851 if (elem_size && ((prop_len % elem_size) != 0)) { 852 ddi_prop_free(prop_val); 853 return (DDI_PROP_NOT_FOUND); 854 } 855 856 /* 857 * return the prop_driver_data struct and, optionally, the length 858 * of the data. 859 */ 860 *datap = prop_val; 861 *lengthp = prop_len; 862 863 return (DDI_PROP_SUCCESS); 864 } 865 866 /* 867 * i_check_string looks at a string property and makes sure its 868 * a valid null terminated string 869 */ 870 static int 871 i_check_string(char *str, int prop_len) 872 { 873 int i; 874 875 ASSERT(str != NULL); 876 877 for (i = 0; i < prop_len; i++) { 878 if (str[i] == '\0') 879 return (0); 880 } 881 return (1); 882 } 883 884 /* 885 * i_pack_string_array takes a a string array property that is represented 886 * as a concatination of strings (with the NULL character included for 887 * each string) and converts it into a format that can be returned by 888 * ldi_prop_lookup_string_array. 889 */ 890 static int 891 i_pack_string_array(char *str_concat, int prop_len, 892 char ***str_arrayp, int *nelemp) 893 { 894 int i, nelem, pack_size; 895 char **str_array, *strptr; 896 897 /* 898 * first we need to sanity check the input string array. 899 * in essence this can be done my making sure that the last 900 * character of the array passed in is null. (meaning the last 901 * string in the array is NULL terminated. 902 */ 903 if (str_concat[prop_len - 1] != '\0') 904 return (1); 905 906 /* now let's count the number of strings in the array */ 907 for (nelem = i = 0; i < prop_len; i++) 908 if (str_concat[i] == '\0') 909 nelem++; 910 ASSERT(nelem >= 1); 911 912 /* now let's allocate memory for the new packed property */ 913 pack_size = (sizeof (char *) * (nelem + 1)) + prop_len; 914 str_array = (char **)i_ldi_prop_op_alloc(pack_size); 915 916 /* let's copy the actual string data into the new property */ 917 strptr = (char *)&(str_array[nelem + 1]); 918 bcopy(str_concat, strptr, prop_len); 919 920 /* now initialize the string array pointers */ 921 for (i = 0; i < nelem; i++) { 922 str_array[i] = strptr; 923 strptr += strlen(strptr) + 1; 924 } 925 str_array[nelem] = NULL; 926 927 /* set the return values */ 928 *str_arrayp = str_array; 929 *nelemp = nelem; 930 931 return (0); 932 } 933 934 935 /* 936 * LDI Project private device usage interfaces 937 */ 938 939 /* 940 * Get a count of how many devices are currentl open by different consumers 941 */ 942 int 943 ldi_usage_count() 944 { 945 return (ldi_handle_hash_count); 946 } 947 948 static void 949 ldi_usage_walker_tgt_helper(ldi_usage_t *ldi_usage, vnode_t *vp) 950 { 951 dev_info_t *dip; 952 dev_t dev; 953 954 ASSERT(STYP_VALID(VTYP_TO_STYP(vp->v_type))); 955 956 /* get the target devt */ 957 dev = vp->v_rdev; 958 959 /* try to get the target dip */ 960 dip = VTOCS(vp)->s_dip; 961 if (dip != NULL) { 962 e_ddi_hold_devi(dip); 963 } else if (dev != DDI_DEV_T_NONE) { 964 dip = e_ddi_hold_devi_by_dev(dev, 0); 965 } 966 967 /* set the target information */ 968 ldi_usage->tgt_name = mod_major_to_name(getmajor(dev)); 969 ldi_usage->tgt_modid = mod_name_to_modid(ldi_usage->tgt_name); 970 ldi_usage->tgt_devt = dev; 971 ldi_usage->tgt_spec_type = VTYP_TO_STYP(vp->v_type); 972 ldi_usage->tgt_dip = dip; 973 } 974 975 976 static int 977 ldi_usage_walker_helper(struct ldi_ident *lip, vnode_t *vp, 978 void *arg, int (*callback)(const ldi_usage_t *, void *)) 979 { 980 ldi_usage_t ldi_usage; 981 struct devnames *dnp; 982 dev_info_t *dip; 983 major_t major; 984 dev_t dev; 985 int ret = LDI_USAGE_CONTINUE; 986 987 /* set the target device information */ 988 ldi_usage_walker_tgt_helper(&ldi_usage, vp); 989 990 /* get the source devt */ 991 dev = lip->li_dev; 992 993 /* try to get the source dip */ 994 dip = lip->li_dip; 995 if (dip != NULL) { 996 e_ddi_hold_devi(dip); 997 } else if (dev != DDI_DEV_T_NONE) { 998 dip = e_ddi_hold_devi_by_dev(dev, 0); 999 } 1000 1001 /* set the valid source information */ 1002 ldi_usage.src_modid = lip->li_modid; 1003 ldi_usage.src_name = lip->li_modname; 1004 ldi_usage.src_devt = dev; 1005 ldi_usage.src_dip = dip; 1006 1007 /* 1008 * if the source ident represents either: 1009 * 1010 * - a kernel module (and not a device or device driver) 1011 * - a device node 1012 * 1013 * then we currently have all the info we need to report the 1014 * usage information so invoke the callback function. 1015 */ 1016 if (((lip->li_major == -1) && (dev == DDI_DEV_T_NONE)) || 1017 (dip != NULL)) { 1018 ret = callback(&ldi_usage, arg); 1019 if (dip != NULL) 1020 ddi_release_devi(dip); 1021 if (ldi_usage.tgt_dip != NULL) 1022 ddi_release_devi(ldi_usage.tgt_dip); 1023 return (ret); 1024 } 1025 1026 /* 1027 * now this is kinda gross. 1028 * 1029 * what we do here is attempt to associate every device instance 1030 * of the source driver on the system with the open target driver. 1031 * we do this because we don't know which instance of the device 1032 * could potentially access the lower device so we assume that all 1033 * the instances could access it. 1034 * 1035 * there are two ways we could have gotten here: 1036 * 1037 * 1) this layered ident represents one created using only a 1038 * major number or a driver module name. this means that when 1039 * it was created we could not associate it with a particular 1040 * dev_t or device instance. 1041 * 1042 * when could this possibly happen you ask? 1043 * 1044 * a perfect example of this is streams persistent links. 1045 * when a persistant streams link is formed we can't associate 1046 * the lower device stream with any particular upper device 1047 * stream or instance. this is because any particular upper 1048 * device stream could be closed, then another could be 1049 * opened with a different dev_t and device instance, and it 1050 * would still have access to the lower linked stream. 1051 * 1052 * since any instance of the upper streams driver could 1053 * potentially access the lower stream whenever it wants, 1054 * we represent that here by associating the opened lower 1055 * device with every existing device instance of the upper 1056 * streams driver. 1057 * 1058 * 2) This case should really never happen but we'll include it 1059 * for completeness. 1060 * 1061 * it's possible that we could have gotten here because we 1062 * have a dev_t for the upper device but we couldn't find a 1063 * dip associated with that dev_t. 1064 * 1065 * the only types of devices that have dev_t without an 1066 * associated dip are unbound DLPIv2 network devices. These 1067 * types of devices exist to be able to attach a stream to any 1068 * instance of a hardware network device. since these types of 1069 * devices are usually hardware devices they should never 1070 * really have other devices open. 1071 */ 1072 if (dev != DDI_DEV_T_NONE) 1073 major = getmajor(dev); 1074 else 1075 major = lip->li_major; 1076 1077 ASSERT((major >= 0) && (major < devcnt)); 1078 1079 dnp = &devnamesp[major]; 1080 LOCK_DEV_OPS(&dnp->dn_lock); 1081 dip = dnp->dn_head; 1082 while ((dip) && (ret == LDI_USAGE_CONTINUE)) { 1083 e_ddi_hold_devi(dip); 1084 UNLOCK_DEV_OPS(&dnp->dn_lock); 1085 1086 /* set the source dip */ 1087 ldi_usage.src_dip = dip; 1088 1089 /* invoke the callback function */ 1090 ret = callback(&ldi_usage, arg); 1091 1092 LOCK_DEV_OPS(&dnp->dn_lock); 1093 ddi_release_devi(dip); 1094 dip = ddi_get_next(dip); 1095 } 1096 UNLOCK_DEV_OPS(&dnp->dn_lock); 1097 1098 /* if there was a target dip, release it */ 1099 if (ldi_usage.tgt_dip != NULL) 1100 ddi_release_devi(ldi_usage.tgt_dip); 1101 1102 return (ret); 1103 } 1104 1105 /* 1106 * ldi_usage_walker() - this walker reports LDI kernel device usage 1107 * information via the callback() callback function. the LDI keeps track 1108 * of what devices are being accessed in its own internal data structures. 1109 * this function walks those data structures to determine device usage. 1110 */ 1111 void 1112 ldi_usage_walker(void *arg, int (*callback)(const ldi_usage_t *, void *)) 1113 { 1114 struct ldi_handle *lhp; 1115 struct ldi_ident *lip; 1116 vnode_t *vp; 1117 int i; 1118 int ret = LDI_USAGE_CONTINUE; 1119 1120 for (i = 0; i < LH_HASH_SZ; i++) { 1121 mutex_enter(&ldi_handle_hash_lock[i]); 1122 1123 lhp = ldi_handle_hash[i]; 1124 while ((lhp != NULL) && (ret == LDI_USAGE_CONTINUE)) { 1125 lip = lhp->lh_ident; 1126 vp = lhp->lh_vp; 1127 1128 /* invoke the devinfo callback function */ 1129 ret = ldi_usage_walker_helper(lip, vp, arg, callback); 1130 1131 lhp = lhp->lh_next; 1132 } 1133 mutex_exit(&ldi_handle_hash_lock[i]); 1134 1135 if (ret != LDI_USAGE_CONTINUE) 1136 break; 1137 } 1138 } 1139 1140 /* 1141 * LDI Project private interfaces (streams linking interfaces) 1142 * 1143 * Streams supports a type of built in device layering via linking. 1144 * Certain types of streams drivers can be streams multiplexors. 1145 * A streams multiplexor supports the I_LINK/I_PLINK operation. 1146 * These operations allows other streams devices to be linked under the 1147 * multiplexor. By definition all streams multiplexors are devices 1148 * so this linking is a type of device layering where the multiplexor 1149 * device is layered on top of the device linked below it. 1150 */ 1151 1152 /* 1153 * ldi_mlink_lh() is invoked when streams are linked using LDI handles. 1154 * It is not used for normal I_LINKs and I_PLINKs using file descriptors. 1155 * 1156 * The streams framework keeps track of links via the file_t of the lower 1157 * stream. The LDI keeps track of devices using a vnode. In the case 1158 * of a streams link created via an LDI handle, fnk_lh() allocates 1159 * a file_t that the streams framework can use to track the linkage. 1160 */ 1161 int 1162 ldi_mlink_lh(vnode_t *vp, int cmd, intptr_t arg, cred_t *crp, int *rvalp) 1163 { 1164 struct ldi_handle *lhp = (struct ldi_handle *)arg; 1165 vnode_t *vpdown; 1166 file_t *fpdown; 1167 int err; 1168 1169 if (lhp == NULL) 1170 return (EINVAL); 1171 1172 vpdown = lhp->lh_vp; 1173 ASSERT(vn_matchops(vpdown, spec_getvnodeops())); 1174 ASSERT(cmd == _I_PLINK_LH); 1175 1176 /* 1177 * create a new lower vnode and a file_t that points to it, 1178 * streams linking requires a file_t. falloc() returns with 1179 * fpdown locked. 1180 */ 1181 VN_HOLD(vpdown); 1182 (void) falloc(vpdown, FREAD|FWRITE, &fpdown, NULL); 1183 mutex_exit(&fpdown->f_tlock); 1184 1185 /* try to establish the link */ 1186 err = mlink_file(vp, I_PLINK, fpdown, crp, rvalp, 1); 1187 1188 if (err != 0) { 1189 /* the link failed, free the file_t and release the vnode */ 1190 mutex_enter(&fpdown->f_tlock); 1191 unfalloc(fpdown); 1192 VN_RELE(vpdown); 1193 } 1194 1195 return (err); 1196 } 1197 1198 /* 1199 * ldi_mlink_fp() is invoked for all successfull streams linkages created 1200 * via I_LINK and I_PLINK. ldi_mlink_fp() records the linkage information 1201 * in its internal state so that the devinfo snapshot code has some 1202 * observability into streams device linkage information. 1203 */ 1204 void 1205 ldi_mlink_fp(struct stdata *stp, file_t *fpdown, int lhlink, int type) 1206 { 1207 vnode_t *vp = fpdown->f_vnode; 1208 struct snode *sp, *csp; 1209 ldi_ident_t li; 1210 major_t major; 1211 int ret; 1212 1213 /* if the lower stream is not a device then return */ 1214 if (!vn_matchops(vp, spec_getvnodeops())) 1215 return; 1216 1217 ASSERT(!servicing_interrupt()); 1218 1219 LDI_STREAMS_LNK((CE_NOTE, "%s: linking streams " 1220 "stp=0x%p, fpdown=0x%p", "ldi_mlink_fp", 1221 (void *)stp, (void *)fpdown)); 1222 1223 sp = VTOS(vp); 1224 csp = VTOS(sp->s_commonvp); 1225 1226 /* check if this was a plink via a layered handle */ 1227 if (lhlink) { 1228 /* 1229 * increment the common snode s_count. 1230 * 1231 * this is done because after the link operation there 1232 * are two ways that s_count can be decremented. 1233 * 1234 * when the layered handle used to create the link is 1235 * closed, spec_close() is called and it will decrement 1236 * s_count in the common snode. if we don't increment 1237 * s_count here then this could cause spec_close() to 1238 * actually close the device while it's still linked 1239 * under a multiplexer. 1240 * 1241 * also, when the lower stream is unlinked, closef() is 1242 * called for the file_t associated with this snode. 1243 * closef() will call spec_close(), which will decrement 1244 * s_count. if we dont't increment s_count here then this 1245 * could cause spec_close() to actually close the device 1246 * while there may still be valid layered handles 1247 * pointing to it. 1248 */ 1249 mutex_enter(&csp->s_lock); 1250 ASSERT(csp->s_count >= 1); 1251 csp->s_count++; 1252 mutex_exit(&csp->s_lock); 1253 1254 /* 1255 * decrement the f_count. 1256 * this is done because the layered driver framework does 1257 * not actually cache a copy of the file_t allocated to 1258 * do the link. this is done here instead of in ldi_mlink_lh() 1259 * because there is a window in ldi_mlink_lh() between where 1260 * milnk_file() returns and we would decrement the f_count 1261 * when the stream could be unlinked. 1262 */ 1263 mutex_enter(&fpdown->f_tlock); 1264 fpdown->f_count--; 1265 mutex_exit(&fpdown->f_tlock); 1266 } 1267 1268 /* 1269 * NOTE: here we rely on the streams subsystem not allowing 1270 * a stream to be multiplexed more than once. if this 1271 * changes, we break. 1272 * 1273 * mark the snode/stream as multiplexed 1274 */ 1275 mutex_enter(&sp->s_lock); 1276 ASSERT(!(sp->s_flag & SMUXED)); 1277 sp->s_flag |= SMUXED; 1278 mutex_exit(&sp->s_lock); 1279 1280 /* get a layered ident for the upper stream */ 1281 if (type == LINKNORMAL) { 1282 /* 1283 * if the link is not persistant then we can associate 1284 * the upper stream with a dev_t. this is because the 1285 * upper stream is associated with a vnode, which is 1286 * associated with a dev_t and this binding can't change 1287 * during the life of the stream. since the link isn't 1288 * persistant once the stream is destroyed the link is 1289 * destroyed. so the dev_t will be valid for the life 1290 * of the link. 1291 */ 1292 ret = ldi_ident_from_stream(getendq(stp->sd_wrq), &li); 1293 } else { 1294 /* 1295 * if the link is persistant we can only associate the 1296 * link with a driver (and not a dev_t.) this is 1297 * because subsequent opens of the upper device may result 1298 * in a different stream (and dev_t) having access to 1299 * the lower stream. 1300 * 1301 * for example, if the upper stream is closed after the 1302 * persistant link operation is compleated, a subsequent 1303 * open of the upper device will create a new stream which 1304 * may have a different dev_t and an unlink operation 1305 * can be performed using this new upper stream. 1306 */ 1307 ASSERT(type == LINKPERSIST); 1308 major = getmajor(stp->sd_vnode->v_rdev); 1309 ret = ldi_ident_from_major(major, &li); 1310 } 1311 1312 ASSERT(ret == 0); 1313 (void) handle_alloc(vp, (struct ldi_ident *)li); 1314 ldi_ident_release(li); 1315 } 1316 1317 void 1318 ldi_munlink_fp(struct stdata *stp, file_t *fpdown, int type) 1319 { 1320 struct ldi_handle *lhp; 1321 vnode_t *vp = (vnode_t *)fpdown->f_vnode; 1322 struct snode *sp; 1323 ldi_ident_t li; 1324 major_t major; 1325 int ret; 1326 1327 /* if the lower stream is not a device then return */ 1328 if (!vn_matchops(vp, spec_getvnodeops())) 1329 return; 1330 1331 ASSERT(!servicing_interrupt()); 1332 ASSERT((type == LINKNORMAL) || (type == LINKPERSIST)); 1333 1334 LDI_STREAMS_LNK((CE_NOTE, "%s: unlinking streams " 1335 "stp=0x%p, fpdown=0x%p", "ldi_munlink_fp", 1336 (void *)stp, (void *)fpdown)); 1337 1338 /* 1339 * NOTE: here we rely on the streams subsystem not allowing 1340 * a stream to be multiplexed more than once. if this 1341 * changes, we break. 1342 * 1343 * mark the snode/stream as not multiplexed 1344 */ 1345 sp = VTOS(vp); 1346 mutex_enter(&sp->s_lock); 1347 ASSERT(sp->s_flag & SMUXED); 1348 sp->s_flag &= ~SMUXED; 1349 mutex_exit(&sp->s_lock); 1350 1351 /* 1352 * clear the owner for this snode 1353 * see the comment in ldi_mlink_fp() for information about how 1354 * the ident is allocated 1355 */ 1356 if (type == LINKNORMAL) { 1357 ret = ldi_ident_from_stream(getendq(stp->sd_wrq), &li); 1358 } else { 1359 ASSERT(type == LINKPERSIST); 1360 major = getmajor(stp->sd_vnode->v_rdev); 1361 ret = ldi_ident_from_major(major, &li); 1362 } 1363 1364 ASSERT(ret == 0); 1365 lhp = handle_find(vp, (struct ldi_ident *)li); 1366 handle_release(lhp); 1367 ldi_ident_release(li); 1368 } 1369 1370 /* 1371 * LDI Consolidation private interfaces 1372 */ 1373 int 1374 ldi_ident_from_mod(struct modlinkage *modlp, ldi_ident_t *lip) 1375 { 1376 struct modctl *modp; 1377 major_t major; 1378 char *name; 1379 1380 if ((modlp == NULL) || (lip == NULL)) 1381 return (EINVAL); 1382 1383 ASSERT(!servicing_interrupt()); 1384 1385 modp = mod_getctl(modlp); 1386 if (modp == NULL) 1387 return (EINVAL); 1388 name = modp->mod_modname; 1389 if (name == NULL) 1390 return (EINVAL); 1391 major = mod_name_to_major(name); 1392 1393 *lip = (ldi_ident_t)ident_alloc(name, NULL, DDI_DEV_T_NONE, major); 1394 1395 LDI_ALLOCFREE((CE_WARN, "%s: li=0x%p, mod=%s", 1396 "ldi_ident_from_mod", (void *)*lip, name)); 1397 1398 return (0); 1399 } 1400 1401 ldi_ident_t 1402 ldi_ident_from_anon() 1403 { 1404 ldi_ident_t lip; 1405 1406 ASSERT(!servicing_interrupt()); 1407 1408 lip = (ldi_ident_t)ident_alloc("genunix", NULL, DDI_DEV_T_NONE, -1); 1409 1410 LDI_ALLOCFREE((CE_WARN, "%s: li=0x%p, mod=%s", 1411 "ldi_ident_from_anon", (void *)lip, "genunix")); 1412 1413 return (lip); 1414 } 1415 1416 1417 /* 1418 * LDI Public interfaces 1419 */ 1420 int 1421 ldi_ident_from_stream(struct queue *sq, ldi_ident_t *lip) 1422 { 1423 struct stdata *stp; 1424 dev_t dev; 1425 char *name; 1426 1427 if ((sq == NULL) || (lip == NULL)) 1428 return (EINVAL); 1429 1430 ASSERT(!servicing_interrupt()); 1431 1432 stp = sq->q_stream; 1433 if (!vn_matchops(stp->sd_vnode, spec_getvnodeops())) 1434 return (EINVAL); 1435 1436 dev = stp->sd_vnode->v_rdev; 1437 name = mod_major_to_name(getmajor(dev)); 1438 if (name == NULL) 1439 return (EINVAL); 1440 *lip = (ldi_ident_t)ident_alloc(name, NULL, dev, -1); 1441 1442 LDI_ALLOCFREE((CE_WARN, 1443 "%s: li=0x%p, mod=%s, minor=0x%x, stp=0x%p", 1444 "ldi_ident_from_stream", (void *)*lip, name, getminor(dev), 1445 (void *)stp)); 1446 1447 return (0); 1448 } 1449 1450 int 1451 ldi_ident_from_dev(dev_t dev, ldi_ident_t *lip) 1452 { 1453 char *name; 1454 1455 if (lip == NULL) 1456 return (EINVAL); 1457 1458 ASSERT(!servicing_interrupt()); 1459 1460 name = mod_major_to_name(getmajor(dev)); 1461 if (name == NULL) 1462 return (EINVAL); 1463 *lip = (ldi_ident_t)ident_alloc(name, NULL, dev, -1); 1464 1465 LDI_ALLOCFREE((CE_WARN, 1466 "%s: li=0x%p, mod=%s, minor=0x%x", 1467 "ldi_ident_from_dev", (void *)*lip, name, getminor(dev))); 1468 1469 return (0); 1470 } 1471 1472 int 1473 ldi_ident_from_dip(dev_info_t *dip, ldi_ident_t *lip) 1474 { 1475 struct dev_info *devi = (struct dev_info *)dip; 1476 char *name; 1477 1478 if ((dip == NULL) || (lip == NULL)) 1479 return (EINVAL); 1480 1481 ASSERT(!servicing_interrupt()); 1482 1483 name = mod_major_to_name(devi->devi_major); 1484 if (name == NULL) 1485 return (EINVAL); 1486 *lip = (ldi_ident_t)ident_alloc(name, dip, DDI_DEV_T_NONE, -1); 1487 1488 LDI_ALLOCFREE((CE_WARN, 1489 "%s: li=0x%p, mod=%s, dip=0x%p", 1490 "ldi_ident_from_dip", (void *)*lip, name, (void *)devi)); 1491 1492 return (0); 1493 } 1494 1495 int 1496 ldi_ident_from_major(major_t major, ldi_ident_t *lip) 1497 { 1498 char *name; 1499 1500 if (lip == NULL) 1501 return (EINVAL); 1502 1503 ASSERT(!servicing_interrupt()); 1504 1505 name = mod_major_to_name(major); 1506 if (name == NULL) 1507 return (EINVAL); 1508 *lip = (ldi_ident_t)ident_alloc(name, NULL, DDI_DEV_T_NONE, major); 1509 1510 LDI_ALLOCFREE((CE_WARN, 1511 "%s: li=0x%p, mod=%s", 1512 "ldi_ident_from_major", (void *)*lip, name)); 1513 1514 return (0); 1515 } 1516 1517 void 1518 ldi_ident_release(ldi_ident_t li) 1519 { 1520 struct ldi_ident *ident = (struct ldi_ident *)li; 1521 char *name; 1522 1523 if (li == NULL) 1524 return; 1525 1526 ASSERT(!servicing_interrupt()); 1527 1528 name = ident->li_modname; 1529 1530 LDI_ALLOCFREE((CE_WARN, 1531 "%s: li=0x%p, mod=%s", 1532 "ldi_ident_release", (void *)li, name)); 1533 1534 ident_release((struct ldi_ident *)li); 1535 } 1536 1537 /* get a handle to a device by dev_t and otyp */ 1538 int 1539 ldi_open_by_dev(dev_t *devp, int otyp, int flag, cred_t *cr, 1540 ldi_handle_t *lhp, ldi_ident_t li) 1541 { 1542 struct ldi_ident *lip = (struct ldi_ident *)li; 1543 int ret; 1544 vnode_t *vp; 1545 1546 /* sanity check required input parameters */ 1547 if ((devp == NULL) || (!OTYP_VALID(otyp)) || (cr == NULL) || 1548 (lhp == NULL) || (lip == NULL)) 1549 return (EINVAL); 1550 1551 ASSERT(!servicing_interrupt()); 1552 1553 if ((ret = ldi_vp_from_dev(*devp, otyp, &vp)) != 0) 1554 return (ret); 1555 1556 if ((ret = ldi_open_by_vp(&vp, flag, cr, lhp, lip)) == 0) { 1557 *devp = vp->v_rdev; 1558 } 1559 VN_RELE(vp); 1560 1561 return (ret); 1562 } 1563 1564 /* get a handle to a device by pathname */ 1565 int 1566 ldi_open_by_name(char *pathname, int flag, cred_t *cr, 1567 ldi_handle_t *lhp, ldi_ident_t li) 1568 { 1569 struct ldi_ident *lip = (struct ldi_ident *)li; 1570 int ret; 1571 vnode_t *vp; 1572 1573 /* sanity check required input parameters */ 1574 if ((pathname == NULL) || (*pathname != '/') || 1575 (cr == NULL) || (lhp == NULL) || (lip == NULL)) 1576 return (EINVAL); 1577 1578 ASSERT(!servicing_interrupt()); 1579 1580 if ((ret = ldi_vp_from_name(pathname, &vp)) != 0) 1581 return (ret); 1582 1583 ret = ldi_open_by_vp(&vp, flag, cr, lhp, lip); 1584 VN_RELE(vp); 1585 1586 return (ret); 1587 } 1588 1589 /* get a handle to a device by devid and minor_name */ 1590 int 1591 ldi_open_by_devid(ddi_devid_t devid, char *minor_name, 1592 int flag, cred_t *cr, ldi_handle_t *lhp, ldi_ident_t li) 1593 { 1594 struct ldi_ident *lip = (struct ldi_ident *)li; 1595 int ret; 1596 vnode_t *vp; 1597 1598 /* sanity check required input parameters */ 1599 if ((minor_name == NULL) || (cr == NULL) || 1600 (lhp == NULL) || (lip == NULL)) 1601 return (EINVAL); 1602 1603 ASSERT(!servicing_interrupt()); 1604 1605 if ((ret = ldi_vp_from_devid(devid, minor_name, &vp)) != 0) 1606 return (ret); 1607 1608 ret = ldi_open_by_vp(&vp, flag, cr, lhp, lip); 1609 VN_RELE(vp); 1610 1611 return (ret); 1612 } 1613 1614 int 1615 ldi_close(ldi_handle_t lh, int flag, cred_t *cr) 1616 { 1617 struct ldi_handle *handlep = (struct ldi_handle *)lh; 1618 struct ldi_event *lep; 1619 int err = 0; 1620 1621 if (lh == NULL) 1622 return (EINVAL); 1623 1624 ASSERT(!servicing_interrupt()); 1625 1626 /* Flush back any dirty pages associated with the device. */ 1627 if (handlep->lh_type & LH_CBDEV) { 1628 vnode_t *cvp = common_specvp(handlep->lh_vp); 1629 dev_t dev = cvp->v_rdev; 1630 1631 (void) VOP_PUTPAGE(cvp, 0, 0, B_INVAL, kcred); 1632 bflush(dev); 1633 } 1634 1635 /* 1636 * Any event handlers should have been unregistered by the 1637 * time ldi_close() is called. If they haven't then it's a 1638 * bug. 1639 * 1640 * In a debug kernel we'll panic to make the problem obvious. 1641 */ 1642 ASSERT(handlep->lh_events == NULL); 1643 1644 /* 1645 * On a production kernel we'll "do the right thing" (unregister 1646 * the event handlers) and then complain about having to do the 1647 * work ourselves. 1648 */ 1649 while ((lep = handlep->lh_events) != NULL) { 1650 err = 1; 1651 (void) ldi_remove_event_handler(lh, (ldi_callback_id_t)lep); 1652 } 1653 if (err) { 1654 struct ldi_ident *lip = handlep->lh_ident; 1655 ASSERT(lip != NULL); 1656 cmn_err(CE_NOTE, "ldi err: %s " 1657 "failed to unregister layered event handlers before " 1658 "closing devices", lip->li_modname); 1659 } 1660 1661 /* do a layered close on the device */ 1662 err = VOP_CLOSE(handlep->lh_vp, flag | FKLYR, 1, (offset_t)0, cr); 1663 1664 LDI_OPENCLOSE((CE_WARN, "%s: lh=0x%p", "ldi close", (void *)lh)); 1665 1666 /* 1667 * Free the handle even if the device close failed. why? 1668 * 1669 * If the device close failed we can't really make assumptions 1670 * about the devices state so we shouldn't allow access to the 1671 * device via this handle any more. If the device consumer wants 1672 * to access the device again they should open it again. 1673 * 1674 * This is the same way file/device close failures are handled 1675 * in other places like spec_close() and closeandsetf(). 1676 */ 1677 handle_release(handlep); 1678 return (err); 1679 } 1680 1681 int 1682 ldi_read(ldi_handle_t lh, struct uio *uiop, cred_t *credp) 1683 { 1684 struct ldi_handle *handlep = (struct ldi_handle *)lh; 1685 vnode_t *vp; 1686 dev_t dev; 1687 int ret; 1688 1689 if (lh == NULL) 1690 return (EINVAL); 1691 1692 vp = handlep->lh_vp; 1693 dev = vp->v_rdev; 1694 if (handlep->lh_type & LH_CBDEV) { 1695 ret = cdev_read(dev, uiop, credp); 1696 } else if (handlep->lh_type & LH_STREAM) { 1697 ret = strread(vp, uiop, credp); 1698 } else { 1699 return (ENOTSUP); 1700 } 1701 return (ret); 1702 } 1703 1704 int 1705 ldi_write(ldi_handle_t lh, struct uio *uiop, cred_t *credp) 1706 { 1707 struct ldi_handle *handlep = (struct ldi_handle *)lh; 1708 vnode_t *vp; 1709 dev_t dev; 1710 int ret; 1711 1712 if (lh == NULL) 1713 return (EINVAL); 1714 1715 vp = handlep->lh_vp; 1716 dev = vp->v_rdev; 1717 if (handlep->lh_type & LH_CBDEV) { 1718 ret = cdev_write(dev, uiop, credp); 1719 } else if (handlep->lh_type & LH_STREAM) { 1720 ret = strwrite(vp, uiop, credp); 1721 } else { 1722 return (ENOTSUP); 1723 } 1724 return (ret); 1725 } 1726 1727 int 1728 ldi_get_size(ldi_handle_t lh, uint64_t *sizep) 1729 { 1730 int otyp; 1731 uint_t value; 1732 int64_t drv_prop64; 1733 struct ldi_handle *handlep = (struct ldi_handle *)lh; 1734 1735 1736 if ((lh == NULL) || (sizep == NULL)) 1737 return (DDI_FAILURE); 1738 1739 if (handlep->lh_type & LH_STREAM) 1740 return (DDI_FAILURE); 1741 1742 /* 1743 * Determine device type (char or block). 1744 * Character devices support Size/size 1745 * property value. Block devices may support 1746 * Nblocks/nblocks or Size/size property value. 1747 */ 1748 if ((ldi_get_otyp(lh, &otyp)) != 0) 1749 return (DDI_FAILURE); 1750 1751 if (otyp == OTYP_BLK) { 1752 if (ldi_prop_exists(lh, 1753 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "Nblocks")) { 1754 1755 drv_prop64 = ldi_prop_get_int64(lh, 1756 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 1757 "Nblocks", 0); 1758 *sizep = (uint64_t)ldbtob((uint64_t)drv_prop64); 1759 return (DDI_SUCCESS); 1760 } 1761 1762 if (ldi_prop_exists(lh, 1763 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "nblocks")) { 1764 1765 value = ldi_prop_get_int(lh, 1766 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 1767 "nblocks", 0); 1768 *sizep = (uint64_t)ldbtob(value); 1769 return (DDI_SUCCESS); 1770 } 1771 } 1772 1773 if (ldi_prop_exists(lh, 1774 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "Size")) { 1775 1776 drv_prop64 = ldi_prop_get_int64(lh, 1777 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "Size", 0); 1778 *sizep = (uint64_t)drv_prop64; 1779 return (DDI_SUCCESS); 1780 } 1781 1782 if (ldi_prop_exists(lh, 1783 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "size")) { 1784 1785 value = ldi_prop_get_int(lh, 1786 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "size", 0); 1787 *sizep = (uint64_t)value; 1788 return (DDI_SUCCESS); 1789 } 1790 1791 /* unable to determine device size */ 1792 return (DDI_FAILURE); 1793 } 1794 1795 int 1796 ldi_ioctl(ldi_handle_t lh, int cmd, intptr_t arg, int mode, 1797 cred_t *cr, int *rvalp) 1798 { 1799 struct ldi_handle *handlep = (struct ldi_handle *)lh; 1800 vnode_t *vp; 1801 dev_t dev; 1802 int ret, copymode; 1803 1804 if (lh == NULL) 1805 return (EINVAL); 1806 1807 /* 1808 * if the data pointed to by arg is located in the kernel then 1809 * make sure the FNATIVE flag is set. 1810 */ 1811 if (mode & FKIOCTL) 1812 mode = (mode & ~FMODELS) | FNATIVE | FKIOCTL; 1813 1814 vp = handlep->lh_vp; 1815 dev = vp->v_rdev; 1816 if (handlep->lh_type & LH_CBDEV) { 1817 ret = cdev_ioctl(dev, cmd, arg, mode, cr, rvalp); 1818 } else if (handlep->lh_type & LH_STREAM) { 1819 copymode = (mode & FKIOCTL) ? K_TO_K : U_TO_K; 1820 1821 /* 1822 * if we get an I_PLINK from within the kernel the 1823 * arg is a layered handle pointer instead of 1824 * a file descriptor, so we translate this ioctl 1825 * into a private one that can handle this. 1826 */ 1827 if ((mode & FKIOCTL) && (cmd == I_PLINK)) 1828 cmd = _I_PLINK_LH; 1829 1830 ret = strioctl(vp, cmd, arg, mode, copymode, cr, rvalp); 1831 } else { 1832 return (ENOTSUP); 1833 } 1834 1835 return (ret); 1836 } 1837 1838 int 1839 ldi_poll(ldi_handle_t lh, short events, int anyyet, short *reventsp, 1840 struct pollhead **phpp) 1841 { 1842 struct ldi_handle *handlep = (struct ldi_handle *)lh; 1843 vnode_t *vp; 1844 dev_t dev; 1845 int ret; 1846 1847 if (lh == NULL) 1848 return (EINVAL); 1849 1850 vp = handlep->lh_vp; 1851 dev = vp->v_rdev; 1852 if (handlep->lh_type & LH_CBDEV) { 1853 ret = cdev_poll(dev, events, anyyet, reventsp, phpp); 1854 } else if (handlep->lh_type & LH_STREAM) { 1855 ret = strpoll(vp->v_stream, events, anyyet, reventsp, phpp); 1856 } else { 1857 return (ENOTSUP); 1858 } 1859 1860 return (ret); 1861 } 1862 1863 int 1864 ldi_prop_op(ldi_handle_t lh, ddi_prop_op_t prop_op, 1865 int flags, char *name, caddr_t valuep, int *length) 1866 { 1867 struct ldi_handle *handlep = (struct ldi_handle *)lh; 1868 dev_t dev; 1869 dev_info_t *dip; 1870 int ret; 1871 struct snode *csp; 1872 1873 if ((lh == NULL) || (name == NULL) || (strlen(name) == 0)) 1874 return (DDI_PROP_INVAL_ARG); 1875 1876 if ((prop_op != PROP_LEN) && (valuep == NULL)) 1877 return (DDI_PROP_INVAL_ARG); 1878 1879 if (length == NULL) 1880 return (DDI_PROP_INVAL_ARG); 1881 1882 /* 1883 * try to find the associated dip, 1884 * this places a hold on the driver 1885 */ 1886 dev = handlep->lh_vp->v_rdev; 1887 1888 csp = VTOCS(handlep->lh_vp); 1889 mutex_enter(&csp->s_lock); 1890 if ((dip = csp->s_dip) != NULL) 1891 e_ddi_hold_devi(dip); 1892 mutex_exit(&csp->s_lock); 1893 if (dip == NULL) 1894 dip = e_ddi_hold_devi_by_dev(dev, 0); 1895 1896 if (dip == NULL) 1897 return (DDI_PROP_NOT_FOUND); 1898 1899 ret = i_ldi_prop_op(dev, dip, prop_op, flags, name, valuep, length); 1900 ddi_release_devi(dip); 1901 1902 return (ret); 1903 } 1904 1905 int 1906 ldi_strategy(ldi_handle_t lh, struct buf *bp) 1907 { 1908 struct ldi_handle *handlep = (struct ldi_handle *)lh; 1909 dev_t dev; 1910 1911 if ((lh == NULL) || (bp == NULL)) 1912 return (EINVAL); 1913 1914 /* this entry point is only supported for cb devices */ 1915 dev = handlep->lh_vp->v_rdev; 1916 if (!(handlep->lh_type & LH_CBDEV)) 1917 return (ENOTSUP); 1918 1919 bp->b_edev = dev; 1920 bp->b_dev = cmpdev(dev); 1921 return (bdev_strategy(bp)); 1922 } 1923 1924 int 1925 ldi_dump(ldi_handle_t lh, caddr_t addr, daddr_t blkno, int nblk) 1926 { 1927 struct ldi_handle *handlep = (struct ldi_handle *)lh; 1928 dev_t dev; 1929 1930 if (lh == NULL) 1931 return (EINVAL); 1932 1933 /* this entry point is only supported for cb devices */ 1934 dev = handlep->lh_vp->v_rdev; 1935 if (!(handlep->lh_type & LH_CBDEV)) 1936 return (ENOTSUP); 1937 1938 return (bdev_dump(dev, addr, blkno, nblk)); 1939 } 1940 1941 int 1942 ldi_devmap(ldi_handle_t lh, devmap_cookie_t dhp, offset_t off, 1943 size_t len, size_t *maplen, uint_t model) 1944 { 1945 struct ldi_handle *handlep = (struct ldi_handle *)lh; 1946 dev_t dev; 1947 1948 if (lh == NULL) 1949 return (EINVAL); 1950 1951 /* this entry point is only supported for cb devices */ 1952 dev = handlep->lh_vp->v_rdev; 1953 if (!(handlep->lh_type & LH_CBDEV)) 1954 return (ENOTSUP); 1955 1956 return (cdev_devmap(dev, dhp, off, len, maplen, model)); 1957 } 1958 1959 int 1960 ldi_aread(ldi_handle_t lh, struct aio_req *aio_reqp, cred_t *cr) 1961 { 1962 struct ldi_handle *handlep = (struct ldi_handle *)lh; 1963 dev_t dev; 1964 struct cb_ops *cb; 1965 1966 if (lh == NULL) 1967 return (EINVAL); 1968 1969 /* this entry point is only supported for cb devices */ 1970 if (!(handlep->lh_type & LH_CBDEV)) 1971 return (ENOTSUP); 1972 1973 /* 1974 * Kaio is only supported on block devices. 1975 */ 1976 dev = handlep->lh_vp->v_rdev; 1977 cb = devopsp[getmajor(dev)]->devo_cb_ops; 1978 if (cb->cb_strategy == nodev || cb->cb_strategy == NULL) 1979 return (ENOTSUP); 1980 1981 if (cb->cb_aread == NULL) 1982 return (ENOTSUP); 1983 1984 return (cb->cb_aread(dev, aio_reqp, cr)); 1985 } 1986 1987 int 1988 ldi_awrite(ldi_handle_t lh, struct aio_req *aio_reqp, cred_t *cr) 1989 { 1990 struct ldi_handle *handlep = (struct ldi_handle *)lh; 1991 struct cb_ops *cb; 1992 dev_t dev; 1993 1994 if (lh == NULL) 1995 return (EINVAL); 1996 1997 /* this entry point is only supported for cb devices */ 1998 if (!(handlep->lh_type & LH_CBDEV)) 1999 return (ENOTSUP); 2000 2001 /* 2002 * Kaio is only supported on block devices. 2003 */ 2004 dev = handlep->lh_vp->v_rdev; 2005 cb = devopsp[getmajor(dev)]->devo_cb_ops; 2006 if (cb->cb_strategy == nodev || cb->cb_strategy == NULL) 2007 return (ENOTSUP); 2008 2009 if (cb->cb_awrite == NULL) 2010 return (ENOTSUP); 2011 2012 return (cb->cb_awrite(dev, aio_reqp, cr)); 2013 } 2014 2015 int 2016 ldi_putmsg(ldi_handle_t lh, mblk_t *smp) 2017 { 2018 struct ldi_handle *handlep = (struct ldi_handle *)lh; 2019 int ret; 2020 2021 if ((lh == NULL) || (smp == NULL)) 2022 return (EINVAL); 2023 2024 if (!(handlep->lh_type & LH_STREAM)) { 2025 freemsg(smp); 2026 return (ENOTSUP); 2027 } 2028 2029 /* Send message while honoring flow control */ 2030 ret = kstrputmsg(handlep->lh_vp, smp, NULL, 0, 0, 2031 MSG_BAND | MSG_HOLDSIG | MSG_IGNERROR, 0); 2032 2033 return (ret); 2034 } 2035 2036 int 2037 ldi_getmsg(ldi_handle_t lh, mblk_t **rmp, timestruc_t *timeo) 2038 { 2039 struct ldi_handle *handlep = (struct ldi_handle *)lh; 2040 clock_t timout; /* milliseconds */ 2041 uchar_t pri; 2042 rval_t rval; 2043 int ret, pflag; 2044 2045 2046 if (lh == NULL) 2047 return (EINVAL); 2048 2049 if (!(handlep->lh_type & LH_STREAM)) 2050 return (ENOTSUP); 2051 2052 /* Convert from nanoseconds to milliseconds */ 2053 if (timeo != NULL) { 2054 timout = timeo->tv_sec * 1000 + timeo->tv_nsec / 1000000; 2055 if (timout > INT_MAX) 2056 return (EINVAL); 2057 } else 2058 timout = -1; 2059 2060 /* Wait for timeout millseconds for a message */ 2061 pflag = MSG_ANY; 2062 pri = 0; 2063 *rmp = NULL; 2064 ret = kstrgetmsg(handlep->lh_vp, 2065 rmp, NULL, &pri, &pflag, timout, &rval); 2066 return (ret); 2067 } 2068 2069 int 2070 ldi_get_dev(ldi_handle_t lh, dev_t *devp) 2071 { 2072 struct ldi_handle *handlep = (struct ldi_handle *)lh; 2073 2074 if ((lh == NULL) || (devp == NULL)) 2075 return (EINVAL); 2076 2077 *devp = handlep->lh_vp->v_rdev; 2078 return (0); 2079 } 2080 2081 int 2082 ldi_get_otyp(ldi_handle_t lh, int *otyp) 2083 { 2084 struct ldi_handle *handlep = (struct ldi_handle *)lh; 2085 2086 if ((lh == NULL) || (otyp == NULL)) 2087 return (EINVAL); 2088 2089 *otyp = VTYP_TO_OTYP(handlep->lh_vp->v_type); 2090 return (0); 2091 } 2092 2093 int 2094 ldi_get_devid(ldi_handle_t lh, ddi_devid_t *devid) 2095 { 2096 struct ldi_handle *handlep = (struct ldi_handle *)lh; 2097 int ret; 2098 dev_t dev; 2099 2100 if ((lh == NULL) || (devid == NULL)) 2101 return (EINVAL); 2102 2103 dev = handlep->lh_vp->v_rdev; 2104 2105 ret = ddi_lyr_get_devid(dev, devid); 2106 if (ret != DDI_SUCCESS) 2107 return (ENOTSUP); 2108 2109 return (0); 2110 } 2111 2112 int 2113 ldi_get_minor_name(ldi_handle_t lh, char **minor_name) 2114 { 2115 struct ldi_handle *handlep = (struct ldi_handle *)lh; 2116 int ret, otyp; 2117 dev_t dev; 2118 2119 if ((lh == NULL) || (minor_name == NULL)) 2120 return (EINVAL); 2121 2122 dev = handlep->lh_vp->v_rdev; 2123 otyp = VTYP_TO_OTYP(handlep->lh_vp->v_type); 2124 2125 ret = ddi_lyr_get_minor_name(dev, OTYP_TO_STYP(otyp), minor_name); 2126 if (ret != DDI_SUCCESS) 2127 return (ENOTSUP); 2128 2129 return (0); 2130 } 2131 2132 int 2133 ldi_prop_lookup_int_array(ldi_handle_t lh, 2134 uint_t flags, char *name, int **data, uint_t *nelements) 2135 { 2136 struct ldi_handle *handlep = (struct ldi_handle *)lh; 2137 dev_info_t *dip; 2138 dev_t dev; 2139 int res; 2140 struct snode *csp; 2141 2142 if ((lh == NULL) || (name == NULL) || (strlen(name) == 0)) 2143 return (DDI_PROP_INVAL_ARG); 2144 2145 dev = handlep->lh_vp->v_rdev; 2146 2147 csp = VTOCS(handlep->lh_vp); 2148 mutex_enter(&csp->s_lock); 2149 if ((dip = csp->s_dip) != NULL) 2150 e_ddi_hold_devi(dip); 2151 mutex_exit(&csp->s_lock); 2152 if (dip == NULL) 2153 dip = e_ddi_hold_devi_by_dev(dev, 0); 2154 2155 if (dip == NULL) { 2156 flags |= DDI_UNBND_DLPI2; 2157 } else if (flags & LDI_DEV_T_ANY) { 2158 flags &= ~LDI_DEV_T_ANY; 2159 dev = DDI_DEV_T_ANY; 2160 } 2161 2162 if (dip != NULL) { 2163 int *prop_val, prop_len; 2164 2165 res = i_ldi_prop_op_typed(dev, dip, flags, name, 2166 (caddr_t *)&prop_val, &prop_len, sizeof (int)); 2167 2168 /* if we got it then return it */ 2169 if (res == DDI_PROP_SUCCESS) { 2170 *nelements = prop_len / sizeof (int); 2171 *data = prop_val; 2172 2173 ddi_release_devi(dip); 2174 return (res); 2175 } 2176 } 2177 2178 /* call the normal property interfaces */ 2179 res = ddi_prop_lookup_int_array(dev, dip, flags, 2180 name, data, nelements); 2181 2182 if (dip != NULL) 2183 ddi_release_devi(dip); 2184 2185 return (res); 2186 } 2187 2188 int 2189 ldi_prop_lookup_int64_array(ldi_handle_t lh, 2190 uint_t flags, char *name, int64_t **data, uint_t *nelements) 2191 { 2192 struct ldi_handle *handlep = (struct ldi_handle *)lh; 2193 dev_info_t *dip; 2194 dev_t dev; 2195 int res; 2196 struct snode *csp; 2197 2198 if ((lh == NULL) || (name == NULL) || (strlen(name) == 0)) 2199 return (DDI_PROP_INVAL_ARG); 2200 2201 dev = handlep->lh_vp->v_rdev; 2202 2203 csp = VTOCS(handlep->lh_vp); 2204 mutex_enter(&csp->s_lock); 2205 if ((dip = csp->s_dip) != NULL) 2206 e_ddi_hold_devi(dip); 2207 mutex_exit(&csp->s_lock); 2208 if (dip == NULL) 2209 dip = e_ddi_hold_devi_by_dev(dev, 0); 2210 2211 if (dip == NULL) { 2212 flags |= DDI_UNBND_DLPI2; 2213 } else if (flags & LDI_DEV_T_ANY) { 2214 flags &= ~LDI_DEV_T_ANY; 2215 dev = DDI_DEV_T_ANY; 2216 } 2217 2218 if (dip != NULL) { 2219 int64_t *prop_val; 2220 int prop_len; 2221 2222 res = i_ldi_prop_op_typed(dev, dip, flags, name, 2223 (caddr_t *)&prop_val, &prop_len, sizeof (int64_t)); 2224 2225 /* if we got it then return it */ 2226 if (res == DDI_PROP_SUCCESS) { 2227 *nelements = prop_len / sizeof (int64_t); 2228 *data = prop_val; 2229 2230 ddi_release_devi(dip); 2231 return (res); 2232 } 2233 } 2234 2235 /* call the normal property interfaces */ 2236 res = ddi_prop_lookup_int64_array(dev, dip, flags, 2237 name, data, nelements); 2238 2239 if (dip != NULL) 2240 ddi_release_devi(dip); 2241 2242 return (res); 2243 } 2244 2245 int 2246 ldi_prop_lookup_string_array(ldi_handle_t lh, 2247 uint_t flags, char *name, char ***data, uint_t *nelements) 2248 { 2249 struct ldi_handle *handlep = (struct ldi_handle *)lh; 2250 dev_info_t *dip; 2251 dev_t dev; 2252 int res; 2253 struct snode *csp; 2254 2255 if ((lh == NULL) || (name == NULL) || (strlen(name) == 0)) 2256 return (DDI_PROP_INVAL_ARG); 2257 2258 dev = handlep->lh_vp->v_rdev; 2259 2260 csp = VTOCS(handlep->lh_vp); 2261 mutex_enter(&csp->s_lock); 2262 if ((dip = csp->s_dip) != NULL) 2263 e_ddi_hold_devi(dip); 2264 mutex_exit(&csp->s_lock); 2265 if (dip == NULL) 2266 dip = e_ddi_hold_devi_by_dev(dev, 0); 2267 2268 if (dip == NULL) { 2269 flags |= DDI_UNBND_DLPI2; 2270 } else if (flags & LDI_DEV_T_ANY) { 2271 flags &= ~LDI_DEV_T_ANY; 2272 dev = DDI_DEV_T_ANY; 2273 } 2274 2275 if (dip != NULL) { 2276 char *prop_val; 2277 int prop_len; 2278 2279 res = i_ldi_prop_op_typed(dev, dip, flags, name, 2280 (caddr_t *)&prop_val, &prop_len, 0); 2281 2282 /* if we got it then return it */ 2283 if (res == DDI_PROP_SUCCESS) { 2284 char **str_array; 2285 int nelem; 2286 2287 /* 2288 * pack the returned string array into the format 2289 * our callers expect 2290 */ 2291 if (i_pack_string_array(prop_val, prop_len, 2292 &str_array, &nelem) == 0) { 2293 2294 *data = str_array; 2295 *nelements = nelem; 2296 2297 ddi_prop_free(prop_val); 2298 ddi_release_devi(dip); 2299 return (res); 2300 } 2301 2302 /* 2303 * the format of the returned property must have 2304 * been bad so throw it out 2305 */ 2306 ddi_prop_free(prop_val); 2307 } 2308 } 2309 2310 /* call the normal property interfaces */ 2311 res = ddi_prop_lookup_string_array(dev, dip, flags, 2312 name, data, nelements); 2313 2314 if (dip != NULL) 2315 ddi_release_devi(dip); 2316 2317 return (res); 2318 } 2319 2320 int 2321 ldi_prop_lookup_string(ldi_handle_t lh, 2322 uint_t flags, char *name, char **data) 2323 { 2324 struct ldi_handle *handlep = (struct ldi_handle *)lh; 2325 dev_info_t *dip; 2326 dev_t dev; 2327 int res; 2328 struct snode *csp; 2329 2330 if ((lh == NULL) || (name == NULL) || (strlen(name) == 0)) 2331 return (DDI_PROP_INVAL_ARG); 2332 2333 dev = handlep->lh_vp->v_rdev; 2334 2335 csp = VTOCS(handlep->lh_vp); 2336 mutex_enter(&csp->s_lock); 2337 if ((dip = csp->s_dip) != NULL) 2338 e_ddi_hold_devi(dip); 2339 mutex_exit(&csp->s_lock); 2340 if (dip == NULL) 2341 dip = e_ddi_hold_devi_by_dev(dev, 0); 2342 2343 if (dip == NULL) { 2344 flags |= DDI_UNBND_DLPI2; 2345 } else if (flags & LDI_DEV_T_ANY) { 2346 flags &= ~LDI_DEV_T_ANY; 2347 dev = DDI_DEV_T_ANY; 2348 } 2349 2350 if (dip != NULL) { 2351 char *prop_val; 2352 int prop_len; 2353 2354 res = i_ldi_prop_op_typed(dev, dip, flags, name, 2355 (caddr_t *)&prop_val, &prop_len, 0); 2356 2357 /* if we got it then return it */ 2358 if (res == DDI_PROP_SUCCESS) { 2359 /* 2360 * sanity check the vaule returned. 2361 */ 2362 if (i_check_string(prop_val, prop_len)) { 2363 ddi_prop_free(prop_val); 2364 } else { 2365 *data = prop_val; 2366 ddi_release_devi(dip); 2367 return (res); 2368 } 2369 } 2370 } 2371 2372 /* call the normal property interfaces */ 2373 res = ddi_prop_lookup_string(dev, dip, flags, name, data); 2374 2375 if (dip != NULL) 2376 ddi_release_devi(dip); 2377 2378 #ifdef DEBUG 2379 if (res == DDI_PROP_SUCCESS) { 2380 /* 2381 * keep ourselves honest 2382 * make sure the framework returns strings in the 2383 * same format as we're demanding from drivers. 2384 */ 2385 struct prop_driver_data *pdd; 2386 int pdd_prop_size; 2387 2388 pdd = ((struct prop_driver_data *)(*data)) - 1; 2389 pdd_prop_size = pdd->pdd_size - 2390 sizeof (struct prop_driver_data); 2391 ASSERT(i_check_string(*data, pdd_prop_size) == 0); 2392 } 2393 #endif /* DEBUG */ 2394 2395 return (res); 2396 } 2397 2398 int 2399 ldi_prop_lookup_byte_array(ldi_handle_t lh, 2400 uint_t flags, char *name, uchar_t **data, uint_t *nelements) 2401 { 2402 struct ldi_handle *handlep = (struct ldi_handle *)lh; 2403 dev_info_t *dip; 2404 dev_t dev; 2405 int res; 2406 struct snode *csp; 2407 2408 if ((lh == NULL) || (name == NULL) || (strlen(name) == 0)) 2409 return (DDI_PROP_INVAL_ARG); 2410 2411 dev = handlep->lh_vp->v_rdev; 2412 2413 csp = VTOCS(handlep->lh_vp); 2414 mutex_enter(&csp->s_lock); 2415 if ((dip = csp->s_dip) != NULL) 2416 e_ddi_hold_devi(dip); 2417 mutex_exit(&csp->s_lock); 2418 if (dip == NULL) 2419 dip = e_ddi_hold_devi_by_dev(dev, 0); 2420 2421 if (dip == NULL) { 2422 flags |= DDI_UNBND_DLPI2; 2423 } else if (flags & LDI_DEV_T_ANY) { 2424 flags &= ~LDI_DEV_T_ANY; 2425 dev = DDI_DEV_T_ANY; 2426 } 2427 2428 if (dip != NULL) { 2429 uchar_t *prop_val; 2430 int prop_len; 2431 2432 res = i_ldi_prop_op_typed(dev, dip, flags, name, 2433 (caddr_t *)&prop_val, &prop_len, sizeof (uchar_t)); 2434 2435 /* if we got it then return it */ 2436 if (res == DDI_PROP_SUCCESS) { 2437 *nelements = prop_len / sizeof (uchar_t); 2438 *data = prop_val; 2439 2440 ddi_release_devi(dip); 2441 return (res); 2442 } 2443 } 2444 2445 /* call the normal property interfaces */ 2446 res = ddi_prop_lookup_byte_array(dev, dip, flags, 2447 name, data, nelements); 2448 2449 if (dip != NULL) 2450 ddi_release_devi(dip); 2451 2452 return (res); 2453 } 2454 2455 int 2456 ldi_prop_get_int(ldi_handle_t lh, 2457 uint_t flags, char *name, int defvalue) 2458 { 2459 struct ldi_handle *handlep = (struct ldi_handle *)lh; 2460 dev_info_t *dip; 2461 dev_t dev; 2462 int res; 2463 struct snode *csp; 2464 2465 if ((lh == NULL) || (name == NULL) || (strlen(name) == 0)) 2466 return (defvalue); 2467 2468 dev = handlep->lh_vp->v_rdev; 2469 2470 csp = VTOCS(handlep->lh_vp); 2471 mutex_enter(&csp->s_lock); 2472 if ((dip = csp->s_dip) != NULL) 2473 e_ddi_hold_devi(dip); 2474 mutex_exit(&csp->s_lock); 2475 if (dip == NULL) 2476 dip = e_ddi_hold_devi_by_dev(dev, 0); 2477 2478 if (dip == NULL) { 2479 flags |= DDI_UNBND_DLPI2; 2480 } else if (flags & LDI_DEV_T_ANY) { 2481 flags &= ~LDI_DEV_T_ANY; 2482 dev = DDI_DEV_T_ANY; 2483 } 2484 2485 if (dip != NULL) { 2486 int prop_val; 2487 int prop_len; 2488 2489 /* 2490 * first call the drivers prop_op interface to allow it 2491 * it to override default property values. 2492 */ 2493 prop_len = sizeof (int); 2494 res = i_ldi_prop_op(dev, dip, PROP_LEN_AND_VAL_BUF, 2495 flags | DDI_PROP_DYNAMIC, name, 2496 (caddr_t)&prop_val, &prop_len); 2497 2498 /* if we got it then return it */ 2499 if ((res == DDI_PROP_SUCCESS) && 2500 (prop_len == sizeof (int))) { 2501 res = prop_val; 2502 ddi_release_devi(dip); 2503 return (res); 2504 } 2505 } 2506 2507 /* call the normal property interfaces */ 2508 res = ddi_prop_get_int(dev, dip, flags, name, defvalue); 2509 2510 if (dip != NULL) 2511 ddi_release_devi(dip); 2512 2513 return (res); 2514 } 2515 2516 int64_t 2517 ldi_prop_get_int64(ldi_handle_t lh, 2518 uint_t flags, char *name, int64_t defvalue) 2519 { 2520 struct ldi_handle *handlep = (struct ldi_handle *)lh; 2521 dev_info_t *dip; 2522 dev_t dev; 2523 int64_t res; 2524 struct snode *csp; 2525 2526 if ((lh == NULL) || (name == NULL) || (strlen(name) == 0)) 2527 return (defvalue); 2528 2529 dev = handlep->lh_vp->v_rdev; 2530 2531 csp = VTOCS(handlep->lh_vp); 2532 mutex_enter(&csp->s_lock); 2533 if ((dip = csp->s_dip) != NULL) 2534 e_ddi_hold_devi(dip); 2535 mutex_exit(&csp->s_lock); 2536 if (dip == NULL) 2537 dip = e_ddi_hold_devi_by_dev(dev, 0); 2538 2539 if (dip == NULL) { 2540 flags |= DDI_UNBND_DLPI2; 2541 } else if (flags & LDI_DEV_T_ANY) { 2542 flags &= ~LDI_DEV_T_ANY; 2543 dev = DDI_DEV_T_ANY; 2544 } 2545 2546 if (dip != NULL) { 2547 int64_t prop_val; 2548 int prop_len; 2549 2550 /* 2551 * first call the drivers prop_op interface to allow it 2552 * it to override default property values. 2553 */ 2554 prop_len = sizeof (int64_t); 2555 res = i_ldi_prop_op(dev, dip, PROP_LEN_AND_VAL_BUF, 2556 flags | DDI_PROP_DYNAMIC, name, 2557 (caddr_t)&prop_val, &prop_len); 2558 2559 /* if we got it then return it */ 2560 if ((res == DDI_PROP_SUCCESS) && 2561 (prop_len == sizeof (int64_t))) { 2562 res = prop_val; 2563 ddi_release_devi(dip); 2564 return (res); 2565 } 2566 } 2567 2568 /* call the normal property interfaces */ 2569 res = ddi_prop_get_int64(dev, dip, flags, name, defvalue); 2570 2571 if (dip != NULL) 2572 ddi_release_devi(dip); 2573 2574 return (res); 2575 } 2576 2577 int 2578 ldi_prop_exists(ldi_handle_t lh, uint_t flags, char *name) 2579 { 2580 struct ldi_handle *handlep = (struct ldi_handle *)lh; 2581 dev_info_t *dip; 2582 dev_t dev; 2583 int res, prop_len; 2584 struct snode *csp; 2585 2586 if ((lh == NULL) || (name == NULL) || (strlen(name) == 0)) 2587 return (0); 2588 2589 dev = handlep->lh_vp->v_rdev; 2590 2591 csp = VTOCS(handlep->lh_vp); 2592 mutex_enter(&csp->s_lock); 2593 if ((dip = csp->s_dip) != NULL) 2594 e_ddi_hold_devi(dip); 2595 mutex_exit(&csp->s_lock); 2596 if (dip == NULL) 2597 dip = e_ddi_hold_devi_by_dev(dev, 0); 2598 2599 /* if NULL dip, prop does NOT exist */ 2600 if (dip == NULL) 2601 return (0); 2602 2603 if (flags & LDI_DEV_T_ANY) { 2604 flags &= ~LDI_DEV_T_ANY; 2605 dev = DDI_DEV_T_ANY; 2606 } 2607 2608 /* 2609 * first call the drivers prop_op interface to allow it 2610 * it to override default property values. 2611 */ 2612 res = i_ldi_prop_op(dev, dip, PROP_LEN, 2613 flags | DDI_PROP_DYNAMIC, name, NULL, &prop_len); 2614 2615 if (res == DDI_PROP_SUCCESS) { 2616 ddi_release_devi(dip); 2617 return (1); 2618 } 2619 2620 /* call the normal property interfaces */ 2621 res = ddi_prop_exists(dev, dip, flags, name); 2622 2623 ddi_release_devi(dip); 2624 return (res); 2625 } 2626 2627 int 2628 ldi_get_eventcookie(ldi_handle_t lh, char *name, ddi_eventcookie_t *ecp) 2629 { 2630 struct ldi_handle *handlep = (struct ldi_handle *)lh; 2631 dev_info_t *dip; 2632 dev_t dev; 2633 int res; 2634 struct snode *csp; 2635 2636 if ((lh == NULL) || (name == NULL) || 2637 (strlen(name) == 0) || (ecp == NULL)) { 2638 return (DDI_FAILURE); 2639 } 2640 2641 ASSERT(!servicing_interrupt()); 2642 2643 dev = handlep->lh_vp->v_rdev; 2644 2645 csp = VTOCS(handlep->lh_vp); 2646 mutex_enter(&csp->s_lock); 2647 if ((dip = csp->s_dip) != NULL) 2648 e_ddi_hold_devi(dip); 2649 mutex_exit(&csp->s_lock); 2650 if (dip == NULL) 2651 dip = e_ddi_hold_devi_by_dev(dev, 0); 2652 2653 if (dip == NULL) 2654 return (DDI_FAILURE); 2655 2656 LDI_EVENTCB((CE_NOTE, "%s: event_name=%s, " 2657 "dip=0x%p, event_cookiep=0x%p", "ldi_get_eventcookie", 2658 name, (void *)dip, (void *)ecp)); 2659 2660 res = ddi_get_eventcookie(dip, name, ecp); 2661 2662 ddi_release_devi(dip); 2663 return (res); 2664 } 2665 2666 int 2667 ldi_add_event_handler(ldi_handle_t lh, ddi_eventcookie_t ec, 2668 void (*handler)(ldi_handle_t, ddi_eventcookie_t, void *, void *), 2669 void *arg, ldi_callback_id_t *id) 2670 { 2671 struct ldi_handle *handlep = (struct ldi_handle *)lh; 2672 struct ldi_event *lep; 2673 dev_info_t *dip; 2674 dev_t dev; 2675 int res; 2676 struct snode *csp; 2677 2678 if ((lh == NULL) || (ec == NULL) || (handler == NULL) || (id == NULL)) 2679 return (DDI_FAILURE); 2680 2681 ASSERT(!servicing_interrupt()); 2682 2683 dev = handlep->lh_vp->v_rdev; 2684 2685 csp = VTOCS(handlep->lh_vp); 2686 mutex_enter(&csp->s_lock); 2687 if ((dip = csp->s_dip) != NULL) 2688 e_ddi_hold_devi(dip); 2689 mutex_exit(&csp->s_lock); 2690 if (dip == NULL) 2691 dip = e_ddi_hold_devi_by_dev(dev, 0); 2692 2693 if (dip == NULL) 2694 return (DDI_FAILURE); 2695 2696 lep = kmem_zalloc(sizeof (struct ldi_event), KM_SLEEP); 2697 lep->le_lhp = handlep; 2698 lep->le_arg = arg; 2699 lep->le_handler = handler; 2700 2701 if ((res = ddi_add_event_handler(dip, ec, i_ldi_callback, 2702 (void *)lep, &lep->le_id)) != DDI_SUCCESS) { 2703 LDI_EVENTCB((CE_WARN, "%s: unable to add" 2704 "event callback", "ldi_add_event_handler")); 2705 ddi_release_devi(dip); 2706 kmem_free(lep, sizeof (struct ldi_event)); 2707 return (res); 2708 } 2709 2710 *id = (ldi_callback_id_t)lep; 2711 2712 LDI_EVENTCB((CE_NOTE, "%s: dip=0x%p, event=0x%p, " 2713 "ldi_eventp=0x%p, cb_id=0x%p", "ldi_add_event_handler", 2714 (void *)dip, (void *)ec, (void *)lep, (void *)id)); 2715 2716 handle_event_add(lep); 2717 ddi_release_devi(dip); 2718 return (res); 2719 } 2720 2721 int 2722 ldi_remove_event_handler(ldi_handle_t lh, ldi_callback_id_t id) 2723 { 2724 ldi_event_t *lep = (ldi_event_t *)id; 2725 int res; 2726 2727 if ((lh == NULL) || (id == NULL)) 2728 return (DDI_FAILURE); 2729 2730 ASSERT(!servicing_interrupt()); 2731 2732 if ((res = ddi_remove_event_handler(lep->le_id)) 2733 != DDI_SUCCESS) { 2734 LDI_EVENTCB((CE_WARN, "%s: unable to remove " 2735 "event callback", "ldi_remove_event_handler")); 2736 return (res); 2737 } 2738 2739 handle_event_remove(lep); 2740 kmem_free(lep, sizeof (struct ldi_event)); 2741 return (res); 2742 } 2743