xref: /illumos-gate/usr/src/uts/common/os/driver_lyr.c (revision 7c478bd9)
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