xref: /illumos-gate/usr/src/uts/common/os/sunddi.c (revision 00277c9e43668ff248a12ee635ce125957750373)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright 2012 Garrett D'Amore <garrett@damore.org>.  All rights reserved.
25  */
26 
27 #include <sys/note.h>
28 #include <sys/types.h>
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/buf.h>
32 #include <sys/uio.h>
33 #include <sys/cred.h>
34 #include <sys/poll.h>
35 #include <sys/mman.h>
36 #include <sys/kmem.h>
37 #include <sys/model.h>
38 #include <sys/file.h>
39 #include <sys/proc.h>
40 #include <sys/open.h>
41 #include <sys/user.h>
42 #include <sys/t_lock.h>
43 #include <sys/vm.h>
44 #include <sys/stat.h>
45 #include <vm/hat.h>
46 #include <vm/seg.h>
47 #include <vm/seg_vn.h>
48 #include <vm/seg_dev.h>
49 #include <vm/as.h>
50 #include <sys/cmn_err.h>
51 #include <sys/cpuvar.h>
52 #include <sys/debug.h>
53 #include <sys/autoconf.h>
54 #include <sys/sunddi.h>
55 #include <sys/esunddi.h>
56 #include <sys/sunndi.h>
57 #include <sys/kstat.h>
58 #include <sys/conf.h>
59 #include <sys/ddi_impldefs.h>	/* include implementation structure defs */
60 #include <sys/ndi_impldefs.h>	/* include prototypes */
61 #include <sys/ddi_periodic.h>
62 #include <sys/hwconf.h>
63 #include <sys/pathname.h>
64 #include <sys/modctl.h>
65 #include <sys/epm.h>
66 #include <sys/devctl.h>
67 #include <sys/callb.h>
68 #include <sys/cladm.h>
69 #include <sys/sysevent.h>
70 #include <sys/dacf_impl.h>
71 #include <sys/ddidevmap.h>
72 #include <sys/bootconf.h>
73 #include <sys/disp.h>
74 #include <sys/atomic.h>
75 #include <sys/promif.h>
76 #include <sys/instance.h>
77 #include <sys/sysevent/eventdefs.h>
78 #include <sys/task.h>
79 #include <sys/project.h>
80 #include <sys/taskq.h>
81 #include <sys/devpolicy.h>
82 #include <sys/ctype.h>
83 #include <net/if.h>
84 #include <sys/rctl.h>
85 #include <sys/zone.h>
86 #include <sys/clock_impl.h>
87 #include <sys/ddi.h>
88 #include <sys/modhash.h>
89 #include <sys/sunldi_impl.h>
90 #include <sys/fs/dv_node.h>
91 #include <sys/fs/snode.h>
92 
93 extern	pri_t	minclsyspri;
94 
95 extern	rctl_hndl_t rc_project_locked_mem;
96 extern	rctl_hndl_t rc_zone_locked_mem;
97 
98 #ifdef DEBUG
99 static int sunddi_debug = 0;
100 #endif /* DEBUG */
101 
102 /* ddi_umem_unlock miscellaneous */
103 
104 static	void	i_ddi_umem_unlock_thread_start(void);
105 
106 static	kmutex_t	ddi_umem_unlock_mutex; /* unlock list mutex */
107 static	kcondvar_t	ddi_umem_unlock_cv; /* unlock list block/unblock */
108 static	kthread_t	*ddi_umem_unlock_thread;
109 /*
110  * The ddi_umem_unlock FIFO list.  NULL head pointer indicates empty list.
111  */
112 static	struct	ddi_umem_cookie *ddi_umem_unlock_head = NULL;
113 static	struct	ddi_umem_cookie *ddi_umem_unlock_tail = NULL;
114 
115 /*
116  * DDI(Sun) Function and flag definitions:
117  */
118 
119 #if defined(__x86)
120 /*
121  * Used to indicate which entries were chosen from a range.
122  */
123 char	*chosen_reg = "chosen-reg";
124 #endif
125 
126 /*
127  * Function used to ring system console bell
128  */
129 void (*ddi_console_bell_func)(clock_t duration);
130 
131 /*
132  * Creating register mappings and handling interrupts:
133  */
134 
135 /*
136  * Generic ddi_map: Call parent to fulfill request...
137  */
138 
139 int
140 ddi_map(dev_info_t *dp, ddi_map_req_t *mp, off_t offset,
141     off_t len, caddr_t *addrp)
142 {
143 	dev_info_t *pdip;
144 
145 	ASSERT(dp);
146 	pdip = (dev_info_t *)DEVI(dp)->devi_parent;
147 	return ((DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)(pdip,
148 	    dp, mp, offset, len, addrp));
149 }
150 
151 /*
152  * ddi_apply_range: (Called by nexi only.)
153  * Apply ranges in parent node dp, to child regspec rp...
154  */
155 
156 int
157 ddi_apply_range(dev_info_t *dp, dev_info_t *rdip, struct regspec *rp)
158 {
159 	return (i_ddi_apply_range(dp, rdip, rp));
160 }
161 
162 int
163 ddi_map_regs(dev_info_t *dip, uint_t rnumber, caddr_t *kaddrp, off_t offset,
164     off_t len)
165 {
166 	ddi_map_req_t mr;
167 #if defined(__x86)
168 	struct {
169 		int	bus;
170 		int	addr;
171 		int	size;
172 	} reg, *reglist;
173 	uint_t	length;
174 	int	rc;
175 
176 	/*
177 	 * get the 'registers' or the 'reg' property.
178 	 * We look up the reg property as an array of
179 	 * int's.
180 	 */
181 	rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
182 	    DDI_PROP_DONTPASS, "registers", (int **)&reglist, &length);
183 	if (rc != DDI_PROP_SUCCESS)
184 		rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
185 		    DDI_PROP_DONTPASS, "reg", (int **)&reglist, &length);
186 	if (rc == DDI_PROP_SUCCESS) {
187 		/*
188 		 * point to the required entry.
189 		 */
190 		reg = reglist[rnumber];
191 		reg.addr += offset;
192 		if (len != 0)
193 			reg.size = len;
194 		/*
195 		 * make a new property containing ONLY the required tuple.
196 		 */
197 		if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
198 		    chosen_reg, (int *)&reg, (sizeof (reg)/sizeof (int)))
199 		    != DDI_PROP_SUCCESS) {
200 			cmn_err(CE_WARN, "%s%d: cannot create '%s' "
201 			    "property", DEVI(dip)->devi_name,
202 			    DEVI(dip)->devi_instance, chosen_reg);
203 		}
204 		/*
205 		 * free the memory allocated by
206 		 * ddi_prop_lookup_int_array ().
207 		 */
208 		ddi_prop_free((void *)reglist);
209 	}
210 #endif
211 	mr.map_op = DDI_MO_MAP_LOCKED;
212 	mr.map_type = DDI_MT_RNUMBER;
213 	mr.map_obj.rnumber = rnumber;
214 	mr.map_prot = PROT_READ | PROT_WRITE;
215 	mr.map_flags = DDI_MF_KERNEL_MAPPING;
216 	mr.map_handlep = NULL;
217 	mr.map_vers = DDI_MAP_VERSION;
218 
219 	/*
220 	 * Call my parent to map in my regs.
221 	 */
222 
223 	return (ddi_map(dip, &mr, offset, len, kaddrp));
224 }
225 
226 void
227 ddi_unmap_regs(dev_info_t *dip, uint_t rnumber, caddr_t *kaddrp, off_t offset,
228     off_t len)
229 {
230 	ddi_map_req_t mr;
231 
232 	mr.map_op = DDI_MO_UNMAP;
233 	mr.map_type = DDI_MT_RNUMBER;
234 	mr.map_flags = DDI_MF_KERNEL_MAPPING;
235 	mr.map_prot = PROT_READ | PROT_WRITE;	/* who cares? */
236 	mr.map_obj.rnumber = rnumber;
237 	mr.map_handlep = NULL;
238 	mr.map_vers = DDI_MAP_VERSION;
239 
240 	/*
241 	 * Call my parent to unmap my regs.
242 	 */
243 
244 	(void) ddi_map(dip, &mr, offset, len, kaddrp);
245 	*kaddrp = (caddr_t)0;
246 #if defined(__x86)
247 	(void) ddi_prop_remove(DDI_DEV_T_NONE, dip, chosen_reg);
248 #endif
249 }
250 
251 int
252 ddi_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
253 	off_t offset, off_t len, caddr_t *vaddrp)
254 {
255 	return (i_ddi_bus_map(dip, rdip, mp, offset, len, vaddrp));
256 }
257 
258 /*
259  * nullbusmap:	The/DDI default bus_map entry point for nexi
260  *		not conforming to the reg/range paradigm (i.e. scsi, etc.)
261  *		with no HAT/MMU layer to be programmed at this level.
262  *
263  *		If the call is to map by rnumber, return an error,
264  *		otherwise pass anything else up the tree to my parent.
265  */
266 int
267 nullbusmap(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
268 	off_t offset, off_t len, caddr_t *vaddrp)
269 {
270 	_NOTE(ARGUNUSED(rdip))
271 	if (mp->map_type == DDI_MT_RNUMBER)
272 		return (DDI_ME_UNSUPPORTED);
273 
274 	return (ddi_map(dip, mp, offset, len, vaddrp));
275 }
276 
277 /*
278  * ddi_rnumber_to_regspec: Not for use by leaf drivers.
279  *			   Only for use by nexi using the reg/range paradigm.
280  */
281 struct regspec *
282 ddi_rnumber_to_regspec(dev_info_t *dip, int rnumber)
283 {
284 	return (i_ddi_rnumber_to_regspec(dip, rnumber));
285 }
286 
287 
288 /*
289  * Note that we allow the dip to be nil because we may be called
290  * prior even to the instantiation of the devinfo tree itself - all
291  * regular leaf and nexus drivers should always use a non-nil dip!
292  *
293  * We treat peek in a somewhat cavalier fashion .. assuming that we'll
294  * simply get a synchronous fault as soon as we touch a missing address.
295  *
296  * Poke is rather more carefully handled because we might poke to a write
297  * buffer, "succeed", then only find some time later that we got an
298  * asynchronous fault that indicated that the address we were writing to
299  * was not really backed by hardware.
300  */
301 
302 static int
303 i_ddi_peekpoke(dev_info_t *devi, ddi_ctl_enum_t cmd, size_t size,
304     void *addr, void *value_p)
305 {
306 	union {
307 		uint64_t	u64;
308 		uint32_t	u32;
309 		uint16_t	u16;
310 		uint8_t		u8;
311 	} peekpoke_value;
312 
313 	peekpoke_ctlops_t peekpoke_args;
314 	uint64_t dummy_result;
315 	int rval;
316 
317 	/* Note: size is assumed to be correct;  it is not checked. */
318 	peekpoke_args.size = size;
319 	peekpoke_args.dev_addr = (uintptr_t)addr;
320 	peekpoke_args.handle = NULL;
321 	peekpoke_args.repcount = 1;
322 	peekpoke_args.flags = 0;
323 
324 	if (cmd == DDI_CTLOPS_POKE) {
325 		switch (size) {
326 		case sizeof (uint8_t):
327 			peekpoke_value.u8 = *(uint8_t *)value_p;
328 			break;
329 		case sizeof (uint16_t):
330 			peekpoke_value.u16 = *(uint16_t *)value_p;
331 			break;
332 		case sizeof (uint32_t):
333 			peekpoke_value.u32 = *(uint32_t *)value_p;
334 			break;
335 		case sizeof (uint64_t):
336 			peekpoke_value.u64 = *(uint64_t *)value_p;
337 			break;
338 		}
339 	}
340 
341 	peekpoke_args.host_addr = (uintptr_t)&peekpoke_value.u64;
342 
343 	if (devi != NULL)
344 		rval = ddi_ctlops(devi, devi, cmd, &peekpoke_args,
345 		    &dummy_result);
346 	else
347 		rval = peekpoke_mem(cmd, &peekpoke_args);
348 
349 	/*
350 	 * A NULL value_p is permitted by ddi_peek(9F); discard the result.
351 	 */
352 	if ((cmd == DDI_CTLOPS_PEEK) & (value_p != NULL)) {
353 		switch (size) {
354 		case sizeof (uint8_t):
355 			*(uint8_t *)value_p = peekpoke_value.u8;
356 			break;
357 		case sizeof (uint16_t):
358 			*(uint16_t *)value_p = peekpoke_value.u16;
359 			break;
360 		case sizeof (uint32_t):
361 			*(uint32_t *)value_p = peekpoke_value.u32;
362 			break;
363 		case sizeof (uint64_t):
364 			*(uint64_t *)value_p = peekpoke_value.u64;
365 			break;
366 		}
367 	}
368 
369 	return (rval);
370 }
371 
372 /*
373  * Keep ddi_peek() and ddi_poke() in case 3rd parties are calling this.
374  * they shouldn't be, but the 9f manpage kind of pseudo exposes it.
375  */
376 int
377 ddi_peek(dev_info_t *devi, size_t size, void *addr, void *value_p)
378 {
379 	switch (size) {
380 	case sizeof (uint8_t):
381 	case sizeof (uint16_t):
382 	case sizeof (uint32_t):
383 	case sizeof (uint64_t):
384 		break;
385 	default:
386 		return (DDI_FAILURE);
387 	}
388 
389 	return (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, size, addr, value_p));
390 }
391 
392 int
393 ddi_poke(dev_info_t *devi, size_t size, void *addr, void *value_p)
394 {
395 	switch (size) {
396 	case sizeof (uint8_t):
397 	case sizeof (uint16_t):
398 	case sizeof (uint32_t):
399 	case sizeof (uint64_t):
400 		break;
401 	default:
402 		return (DDI_FAILURE);
403 	}
404 
405 	return (i_ddi_peekpoke(devi, DDI_CTLOPS_POKE, size, addr, value_p));
406 }
407 
408 int
409 ddi_peek8(dev_info_t *dip, int8_t *addr, int8_t *val_p)
410 {
411 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
412 	    val_p));
413 }
414 
415 int
416 ddi_peek16(dev_info_t *dip, int16_t *addr, int16_t *val_p)
417 {
418 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
419 	    val_p));
420 }
421 
422 int
423 ddi_peek32(dev_info_t *dip, int32_t *addr, int32_t *val_p)
424 {
425 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
426 	    val_p));
427 }
428 
429 int
430 ddi_peek64(dev_info_t *dip, int64_t *addr, int64_t *val_p)
431 {
432 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
433 	    val_p));
434 }
435 
436 
437 /*
438  * We need to separate the old interfaces from the new ones and leave them
439  * in here for a while. Previous versions of the OS defined the new interfaces
440  * to the old interfaces. This way we can fix things up so that we can
441  * eventually remove these interfaces.
442  * e.g. A 3rd party module/driver using ddi_peek8 and built against S10
443  * or earlier will actually have a reference to ddi_peekc in the binary.
444  */
445 #ifdef _ILP32
446 int
447 ddi_peekc(dev_info_t *dip, int8_t *addr, int8_t *val_p)
448 {
449 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
450 	    val_p));
451 }
452 
453 int
454 ddi_peeks(dev_info_t *dip, int16_t *addr, int16_t *val_p)
455 {
456 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
457 	    val_p));
458 }
459 
460 int
461 ddi_peekl(dev_info_t *dip, int32_t *addr, int32_t *val_p)
462 {
463 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
464 	    val_p));
465 }
466 
467 int
468 ddi_peekd(dev_info_t *dip, int64_t *addr, int64_t *val_p)
469 {
470 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
471 	    val_p));
472 }
473 #endif /* _ILP32 */
474 
475 int
476 ddi_poke8(dev_info_t *dip, int8_t *addr, int8_t val)
477 {
478 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
479 }
480 
481 int
482 ddi_poke16(dev_info_t *dip, int16_t *addr, int16_t val)
483 {
484 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
485 }
486 
487 int
488 ddi_poke32(dev_info_t *dip, int32_t *addr, int32_t val)
489 {
490 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
491 }
492 
493 int
494 ddi_poke64(dev_info_t *dip, int64_t *addr, int64_t val)
495 {
496 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
497 }
498 
499 /*
500  * We need to separate the old interfaces from the new ones and leave them
501  * in here for a while. Previous versions of the OS defined the new interfaces
502  * to the old interfaces. This way we can fix things up so that we can
503  * eventually remove these interfaces.
504  * e.g. A 3rd party module/driver using ddi_poke8 and built against S10
505  * or earlier will actually have a reference to ddi_pokec in the binary.
506  */
507 #ifdef _ILP32
508 int
509 ddi_pokec(dev_info_t *dip, int8_t *addr, int8_t val)
510 {
511 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
512 }
513 
514 int
515 ddi_pokes(dev_info_t *dip, int16_t *addr, int16_t val)
516 {
517 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
518 }
519 
520 int
521 ddi_pokel(dev_info_t *dip, int32_t *addr, int32_t val)
522 {
523 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
524 }
525 
526 int
527 ddi_poked(dev_info_t *dip, int64_t *addr, int64_t val)
528 {
529 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
530 }
531 #endif /* _ILP32 */
532 
533 /*
534  * ddi_peekpokeio() is used primarily by the mem drivers for moving
535  * data to and from uio structures via peek and poke.  Note that we
536  * use "internal" routines ddi_peek and ddi_poke to make this go
537  * slightly faster, avoiding the call overhead ..
538  */
539 int
540 ddi_peekpokeio(dev_info_t *devi, struct uio *uio, enum uio_rw rw,
541     caddr_t addr, size_t len, uint_t xfersize)
542 {
543 	int64_t	ibuffer;
544 	int8_t w8;
545 	size_t sz;
546 	int o;
547 
548 	if (xfersize > sizeof (long))
549 		xfersize = sizeof (long);
550 
551 	while (len != 0) {
552 		if ((len | (uintptr_t)addr) & 1) {
553 			sz = sizeof (int8_t);
554 			if (rw == UIO_WRITE) {
555 				if ((o = uwritec(uio)) == -1)
556 					return (DDI_FAILURE);
557 				if (ddi_poke8(devi, (int8_t *)addr,
558 				    (int8_t)o) != DDI_SUCCESS)
559 					return (DDI_FAILURE);
560 			} else {
561 				if (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, sz,
562 				    (int8_t *)addr, &w8) != DDI_SUCCESS)
563 					return (DDI_FAILURE);
564 				if (ureadc(w8, uio))
565 					return (DDI_FAILURE);
566 			}
567 		} else {
568 			switch (xfersize) {
569 			case sizeof (int64_t):
570 				if (((len | (uintptr_t)addr) &
571 				    (sizeof (int64_t) - 1)) == 0) {
572 					sz = xfersize;
573 					break;
574 				}
575 				/*FALLTHROUGH*/
576 			case sizeof (int32_t):
577 				if (((len | (uintptr_t)addr) &
578 				    (sizeof (int32_t) - 1)) == 0) {
579 					sz = xfersize;
580 					break;
581 				}
582 				/*FALLTHROUGH*/
583 			default:
584 				/*
585 				 * This still assumes that we might have an
586 				 * I/O bus out there that permits 16-bit
587 				 * transfers (and that it would be upset by
588 				 * 32-bit transfers from such locations).
589 				 */
590 				sz = sizeof (int16_t);
591 				break;
592 			}
593 
594 			if (rw == UIO_READ) {
595 				if (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, sz,
596 				    addr, &ibuffer) != DDI_SUCCESS)
597 					return (DDI_FAILURE);
598 			}
599 
600 			if (uiomove(&ibuffer, sz, rw, uio))
601 				return (DDI_FAILURE);
602 
603 			if (rw == UIO_WRITE) {
604 				if (i_ddi_peekpoke(devi, DDI_CTLOPS_POKE, sz,
605 				    addr, &ibuffer) != DDI_SUCCESS)
606 					return (DDI_FAILURE);
607 			}
608 		}
609 		addr += sz;
610 		len -= sz;
611 	}
612 	return (DDI_SUCCESS);
613 }
614 
615 /*
616  * These routines are used by drivers that do layered ioctls
617  * On sparc, they're implemented in assembler to avoid spilling
618  * register windows in the common (copyin) case ..
619  */
620 #if !defined(__sparc)
621 int
622 ddi_copyin(const void *buf, void *kernbuf, size_t size, int flags)
623 {
624 	if (flags & FKIOCTL)
625 		return (kcopy(buf, kernbuf, size) ? -1 : 0);
626 	return (copyin(buf, kernbuf, size));
627 }
628 
629 int
630 ddi_copyout(const void *buf, void *kernbuf, size_t size, int flags)
631 {
632 	if (flags & FKIOCTL)
633 		return (kcopy(buf, kernbuf, size) ? -1 : 0);
634 	return (copyout(buf, kernbuf, size));
635 }
636 #endif	/* !__sparc */
637 
638 /*
639  * Conversions in nexus pagesize units.  We don't duplicate the
640  * 'nil dip' semantics of peek/poke because btopr/btop/ptob are DDI/DKI
641  * routines anyway.
642  */
643 unsigned long
644 ddi_btop(dev_info_t *dip, unsigned long bytes)
645 {
646 	unsigned long pages;
647 
648 	(void) ddi_ctlops(dip, dip, DDI_CTLOPS_BTOP, &bytes, &pages);
649 	return (pages);
650 }
651 
652 unsigned long
653 ddi_btopr(dev_info_t *dip, unsigned long bytes)
654 {
655 	unsigned long pages;
656 
657 	(void) ddi_ctlops(dip, dip, DDI_CTLOPS_BTOPR, &bytes, &pages);
658 	return (pages);
659 }
660 
661 unsigned long
662 ddi_ptob(dev_info_t *dip, unsigned long pages)
663 {
664 	unsigned long bytes;
665 
666 	(void) ddi_ctlops(dip, dip, DDI_CTLOPS_PTOB, &pages, &bytes);
667 	return (bytes);
668 }
669 
670 unsigned int
671 ddi_enter_critical(void)
672 {
673 	return ((uint_t)spl7());
674 }
675 
676 void
677 ddi_exit_critical(unsigned int spl)
678 {
679 	splx((int)spl);
680 }
681 
682 /*
683  * Nexus ctlops punter
684  */
685 
686 #if !defined(__sparc)
687 /*
688  * Request bus_ctl parent to handle a bus_ctl request
689  *
690  * (The sparc version is in sparc_ddi.s)
691  */
692 int
693 ddi_ctlops(dev_info_t *d, dev_info_t *r, ddi_ctl_enum_t op, void *a, void *v)
694 {
695 	int (*fp)();
696 
697 	if (!d || !r)
698 		return (DDI_FAILURE);
699 
700 	if ((d = (dev_info_t *)DEVI(d)->devi_bus_ctl) == NULL)
701 		return (DDI_FAILURE);
702 
703 	fp = DEVI(d)->devi_ops->devo_bus_ops->bus_ctl;
704 	return ((*fp)(d, r, op, a, v));
705 }
706 
707 #endif
708 
709 /*
710  * DMA/DVMA setup
711  */
712 
713 #if defined(__sparc)
714 static ddi_dma_lim_t standard_limits = {
715 	(uint_t)0,	/* addr_t dlim_addr_lo */
716 	(uint_t)-1,	/* addr_t dlim_addr_hi */
717 	(uint_t)-1,	/* uint_t dlim_cntr_max */
718 	(uint_t)1,	/* uint_t dlim_burstsizes */
719 	(uint_t)1,	/* uint_t dlim_minxfer */
720 	0		/* uint_t dlim_dmaspeed */
721 };
722 #elif defined(__x86)
723 static ddi_dma_lim_t standard_limits = {
724 	(uint_t)0,		/* addr_t dlim_addr_lo */
725 	(uint_t)0xffffff,	/* addr_t dlim_addr_hi */
726 	(uint_t)0,		/* uint_t dlim_cntr_max */
727 	(uint_t)0x00000001,	/* uint_t dlim_burstsizes */
728 	(uint_t)DMA_UNIT_8,	/* uint_t dlim_minxfer */
729 	(uint_t)0,		/* uint_t dlim_dmaspeed */
730 	(uint_t)0x86<<24+0,	/* uint_t dlim_version */
731 	(uint_t)0xffff,		/* uint_t dlim_adreg_max */
732 	(uint_t)0xffff,		/* uint_t dlim_ctreg_max */
733 	(uint_t)512,		/* uint_t dlim_granular */
734 	(int)1,			/* int dlim_sgllen */
735 	(uint_t)0xffffffff	/* uint_t dlim_reqsizes */
736 };
737 
738 #endif
739 
740 #if !defined(__sparc)
741 /*
742  * Request bus_dma_ctl parent to fiddle with a dma request.
743  *
744  * (The sparc version is in sparc_subr.s)
745  */
746 int
747 ddi_dma_mctl(dev_info_t *dip, dev_info_t *rdip,
748     ddi_dma_handle_t handle, enum ddi_dma_ctlops request,
749     off_t *offp, size_t *lenp, caddr_t *objp, uint_t flags)
750 {
751 	int (*fp)();
752 
753 	if (dip != ddi_root_node())
754 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_ctl;
755 	fp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_ctl;
756 	return ((*fp) (dip, rdip, handle, request, offp, lenp, objp, flags));
757 }
758 #endif
759 
760 /*
761  * For all DMA control functions, call the DMA control
762  * routine and return status.
763  *
764  * Just plain assume that the parent is to be called.
765  * If a nexus driver or a thread outside the framework
766  * of a nexus driver or a leaf driver calls these functions,
767  * it is up to them to deal with the fact that the parent's
768  * bus_dma_ctl function will be the first one called.
769  */
770 
771 #define	HD	((ddi_dma_impl_t *)h)->dmai_rdip
772 
773 /*
774  * This routine is left in place to satisfy link dependencies
775  * for any 3rd party nexus drivers that rely on it.  It is never
776  * called, though.
777  */
778 /*ARGSUSED*/
779 int
780 ddi_dma_map(dev_info_t *dip, dev_info_t *rdip,
781 	struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep)
782 {
783 	return (DDI_FAILURE);
784 }
785 
786 #if !defined(__sparc)
787 
788 /*
789  * The SPARC versions of these routines are done in assembler to
790  * save register windows, so they're in sparc_subr.s.
791  */
792 
793 int
794 ddi_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr,
795     int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep)
796 {
797 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_attr_t *,
798 	    int (*)(caddr_t), caddr_t, ddi_dma_handle_t *);
799 
800 	if (dip != ddi_root_node())
801 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl;
802 
803 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_allochdl;
804 	return ((*funcp)(dip, rdip, attr, waitfp, arg, handlep));
805 }
806 
807 int
808 ddi_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handlep)
809 {
810 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t);
811 
812 	if (dip != ddi_root_node())
813 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl;
814 
815 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_freehdl;
816 	return ((*funcp)(dip, rdip, handlep));
817 }
818 
819 int
820 ddi_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
821     ddi_dma_handle_t handle, struct ddi_dma_req *dmareq,
822     ddi_dma_cookie_t *cp, uint_t *ccountp)
823 {
824 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t,
825 	    struct ddi_dma_req *, ddi_dma_cookie_t *, uint_t *);
826 
827 	if (dip != ddi_root_node())
828 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_bindhdl;
829 
830 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_bindhdl;
831 	return ((*funcp)(dip, rdip, handle, dmareq, cp, ccountp));
832 }
833 
834 int
835 ddi_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
836     ddi_dma_handle_t handle)
837 {
838 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t);
839 
840 	if (dip != ddi_root_node())
841 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl;
842 
843 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_unbindhdl;
844 	return ((*funcp)(dip, rdip, handle));
845 }
846 
847 
848 int
849 ddi_dma_flush(dev_info_t *dip, dev_info_t *rdip,
850     ddi_dma_handle_t handle, off_t off, size_t len,
851     uint_t cache_flags)
852 {
853 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t,
854 	    off_t, size_t, uint_t);
855 
856 	if (dip != ddi_root_node())
857 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush;
858 
859 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_flush;
860 	return ((*funcp)(dip, rdip, handle, off, len, cache_flags));
861 }
862 
863 int
864 ddi_dma_win(dev_info_t *dip, dev_info_t *rdip,
865     ddi_dma_handle_t handle, uint_t win, off_t *offp,
866     size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp)
867 {
868 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t,
869 	    uint_t, off_t *, size_t *, ddi_dma_cookie_t *, uint_t *);
870 
871 	if (dip != ddi_root_node())
872 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_win;
873 
874 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_win;
875 	return ((*funcp)(dip, rdip, handle, win, offp, lenp,
876 	    cookiep, ccountp));
877 }
878 
879 int
880 ddi_dma_sync(ddi_dma_handle_t h, off_t o, size_t l, uint_t whom)
881 {
882 	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)h;
883 	dev_info_t *dip, *rdip;
884 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t, off_t,
885 	    size_t, uint_t);
886 
887 	/*
888 	 * the DMA nexus driver will set DMP_NOSYNC if the
889 	 * platform does not require any sync operation. For
890 	 * example if the memory is uncached or consistent
891 	 * and without any I/O write buffers involved.
892 	 */
893 	if ((hp->dmai_rflags & DMP_NOSYNC) == DMP_NOSYNC)
894 		return (DDI_SUCCESS);
895 
896 	dip = rdip = hp->dmai_rdip;
897 	if (dip != ddi_root_node())
898 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush;
899 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_flush;
900 	return ((*funcp)(dip, rdip, h, o, l, whom));
901 }
902 
903 int
904 ddi_dma_unbind_handle(ddi_dma_handle_t h)
905 {
906 	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)h;
907 	dev_info_t *dip, *rdip;
908 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t);
909 
910 	dip = rdip = hp->dmai_rdip;
911 	if (dip != ddi_root_node())
912 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl;
913 	funcp = DEVI(rdip)->devi_bus_dma_unbindfunc;
914 	return ((*funcp)(dip, rdip, h));
915 }
916 
917 #endif	/* !__sparc */
918 
919 /*
920  * DMA burst sizes, and transfer minimums
921  */
922 
923 int
924 ddi_dma_burstsizes(ddi_dma_handle_t handle)
925 {
926 	ddi_dma_impl_t *dimp = (ddi_dma_impl_t *)handle;
927 
928 	if (!dimp)
929 		return (0);
930 	else
931 		return (dimp->dmai_burstsizes);
932 }
933 
934 int
935 ddi_iomin(dev_info_t *a, int i, int stream)
936 {
937 	int r;
938 
939 	/*
940 	 * Make sure that the initial value is sane
941 	 */
942 	if (i & (i - 1))
943 		return (0);
944 	if (i == 0)
945 		i = (stream) ? 4 : 1;
946 
947 	r = ddi_ctlops(a, a,
948 	    DDI_CTLOPS_IOMIN, (void *)(uintptr_t)stream, (void *)&i);
949 	if (r != DDI_SUCCESS || (i & (i - 1)))
950 		return (0);
951 	return (i);
952 }
953 
954 /*
955  * Given two DMA attribute structures, apply the attributes
956  * of one to the other, following the rules of attributes
957  * and the wishes of the caller.
958  *
959  * The rules of DMA attribute structures are that you cannot
960  * make things *less* restrictive as you apply one set
961  * of attributes to another.
962  *
963  */
964 void
965 ddi_dma_attr_merge(ddi_dma_attr_t *attr, ddi_dma_attr_t *mod)
966 {
967 	attr->dma_attr_addr_lo =
968 	    MAX(attr->dma_attr_addr_lo, mod->dma_attr_addr_lo);
969 	attr->dma_attr_addr_hi =
970 	    MIN(attr->dma_attr_addr_hi, mod->dma_attr_addr_hi);
971 	attr->dma_attr_count_max =
972 	    MIN(attr->dma_attr_count_max, mod->dma_attr_count_max);
973 	attr->dma_attr_align =
974 	    MAX(attr->dma_attr_align,  mod->dma_attr_align);
975 	attr->dma_attr_burstsizes =
976 	    (uint_t)(attr->dma_attr_burstsizes & mod->dma_attr_burstsizes);
977 	attr->dma_attr_minxfer =
978 	    maxbit(attr->dma_attr_minxfer, mod->dma_attr_minxfer);
979 	attr->dma_attr_maxxfer =
980 	    MIN(attr->dma_attr_maxxfer, mod->dma_attr_maxxfer);
981 	attr->dma_attr_seg = MIN(attr->dma_attr_seg, mod->dma_attr_seg);
982 	attr->dma_attr_sgllen = MIN((uint_t)attr->dma_attr_sgllen,
983 	    (uint_t)mod->dma_attr_sgllen);
984 	attr->dma_attr_granular =
985 	    MAX(attr->dma_attr_granular, mod->dma_attr_granular);
986 }
987 
988 /*
989  * mmap/segmap interface:
990  */
991 
992 /*
993  * ddi_segmap:		setup the default segment driver. Calls the drivers
994  *			XXmmap routine to validate the range to be mapped.
995  *			Return ENXIO of the range is not valid.  Create
996  *			a seg_dev segment that contains all of the
997  *			necessary information and will reference the
998  *			default segment driver routines. It returns zero
999  *			on success or non-zero on failure.
1000  */
1001 int
1002 ddi_segmap(dev_t dev, off_t offset, struct as *asp, caddr_t *addrp, off_t len,
1003     uint_t prot, uint_t maxprot, uint_t flags, cred_t *credp)
1004 {
1005 	extern int spec_segmap(dev_t, off_t, struct as *, caddr_t *,
1006 	    off_t, uint_t, uint_t, uint_t, struct cred *);
1007 
1008 	return (spec_segmap(dev, offset, asp, addrp, len,
1009 	    prot, maxprot, flags, credp));
1010 }
1011 
1012 /*
1013  * ddi_map_fault:	Resolve mappings at fault time.  Used by segment
1014  *			drivers. Allows each successive parent to resolve
1015  *			address translations and add its mappings to the
1016  *			mapping list supplied in the page structure. It
1017  *			returns zero on success	or non-zero on failure.
1018  */
1019 
1020 int
1021 ddi_map_fault(dev_info_t *dip, struct hat *hat, struct seg *seg,
1022     caddr_t addr, struct devpage *dp, pfn_t pfn, uint_t prot, uint_t lock)
1023 {
1024 	return (i_ddi_map_fault(dip, dip, hat, seg, addr, dp, pfn, prot, lock));
1025 }
1026 
1027 /*
1028  * ddi_device_mapping_check:	Called from ddi_segmap_setup.
1029  *	Invokes platform specific DDI to determine whether attributes specified
1030  *	in attr(9s) are	valid for the region of memory that will be made
1031  *	available for direct access to user process via the mmap(2) system call.
1032  */
1033 int
1034 ddi_device_mapping_check(dev_t dev, ddi_device_acc_attr_t *accattrp,
1035     uint_t rnumber, uint_t *hat_flags)
1036 {
1037 	ddi_acc_handle_t handle;
1038 	ddi_map_req_t mr;
1039 	ddi_acc_hdl_t *hp;
1040 	int result;
1041 	dev_info_t *dip;
1042 
1043 	/*
1044 	 * we use e_ddi_hold_devi_by_dev to search for the devi.  We
1045 	 * release it immediately since it should already be held by
1046 	 * a devfs vnode.
1047 	 */
1048 	if ((dip =
1049 	    e_ddi_hold_devi_by_dev(dev, E_DDI_HOLD_DEVI_NOATTACH)) == NULL)
1050 		return (-1);
1051 	ddi_release_devi(dip);		/* for e_ddi_hold_devi_by_dev() */
1052 
1053 	/*
1054 	 * Allocate and initialize the common elements of data
1055 	 * access handle.
1056 	 */
1057 	handle = impl_acc_hdl_alloc(KM_SLEEP, NULL);
1058 	if (handle == NULL)
1059 		return (-1);
1060 
1061 	hp = impl_acc_hdl_get(handle);
1062 	hp->ah_vers = VERS_ACCHDL;
1063 	hp->ah_dip = dip;
1064 	hp->ah_rnumber = rnumber;
1065 	hp->ah_offset = 0;
1066 	hp->ah_len = 0;
1067 	hp->ah_acc = *accattrp;
1068 
1069 	/*
1070 	 * Set up the mapping request and call to parent.
1071 	 */
1072 	mr.map_op = DDI_MO_MAP_HANDLE;
1073 	mr.map_type = DDI_MT_RNUMBER;
1074 	mr.map_obj.rnumber = rnumber;
1075 	mr.map_prot = PROT_READ | PROT_WRITE;
1076 	mr.map_flags = DDI_MF_KERNEL_MAPPING;
1077 	mr.map_handlep = hp;
1078 	mr.map_vers = DDI_MAP_VERSION;
1079 	result = ddi_map(dip, &mr, 0, 0, NULL);
1080 
1081 	/*
1082 	 * Region must be mappable, pick up flags from the framework.
1083 	 */
1084 	*hat_flags = hp->ah_hat_flags;
1085 
1086 	impl_acc_hdl_free(handle);
1087 
1088 	/*
1089 	 * check for end result.
1090 	 */
1091 	if (result != DDI_SUCCESS)
1092 		return (-1);
1093 	return (0);
1094 }
1095 
1096 
1097 /*
1098  * Property functions:	 See also, ddipropdefs.h.
1099  *
1100  * These functions are the framework for the property functions,
1101  * i.e. they support software defined properties.  All implementation
1102  * specific property handling (i.e.: self-identifying devices and
1103  * PROM defined properties are handled in the implementation specific
1104  * functions (defined in ddi_implfuncs.h).
1105  */
1106 
1107 /*
1108  * nopropop:	Shouldn't be called, right?
1109  */
1110 int
1111 nopropop(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
1112     char *name, caddr_t valuep, int *lengthp)
1113 {
1114 	_NOTE(ARGUNUSED(dev, dip, prop_op, mod_flags, name, valuep, lengthp))
1115 	return (DDI_PROP_NOT_FOUND);
1116 }
1117 
1118 #ifdef	DDI_PROP_DEBUG
1119 int ddi_prop_debug_flag = 0;
1120 
1121 int
1122 ddi_prop_debug(int enable)
1123 {
1124 	int prev = ddi_prop_debug_flag;
1125 
1126 	if ((enable != 0) || (prev != 0))
1127 		printf("ddi_prop_debug: debugging %s\n",
1128 		    enable ? "enabled" : "disabled");
1129 	ddi_prop_debug_flag = enable;
1130 	return (prev);
1131 }
1132 
1133 #endif	/* DDI_PROP_DEBUG */
1134 
1135 /*
1136  * Search a property list for a match, if found return pointer
1137  * to matching prop struct, else return NULL.
1138  */
1139 
1140 ddi_prop_t *
1141 i_ddi_prop_search(dev_t dev, char *name, uint_t flags, ddi_prop_t **list_head)
1142 {
1143 	ddi_prop_t	*propp;
1144 
1145 	/*
1146 	 * find the property in child's devinfo:
1147 	 * Search order defined by this search function is first matching
1148 	 * property with input dev == DDI_DEV_T_ANY matching any dev or
1149 	 * dev == propp->prop_dev, name == propp->name, and the correct
1150 	 * data type as specified in the flags.  If a DDI_DEV_T_NONE dev
1151 	 * value made it this far then it implies a DDI_DEV_T_ANY search.
1152 	 */
1153 	if (dev == DDI_DEV_T_NONE)
1154 		dev = DDI_DEV_T_ANY;
1155 
1156 	for (propp = *list_head; propp != NULL; propp = propp->prop_next)  {
1157 
1158 		if (!DDI_STRSAME(propp->prop_name, name))
1159 			continue;
1160 
1161 		if ((dev != DDI_DEV_T_ANY) && (propp->prop_dev != dev))
1162 			continue;
1163 
1164 		if (((propp->prop_flags & flags) & DDI_PROP_TYPE_MASK) == 0)
1165 			continue;
1166 
1167 		return (propp);
1168 	}
1169 
1170 	return ((ddi_prop_t *)0);
1171 }
1172 
1173 /*
1174  * Search for property within devnames structures
1175  */
1176 ddi_prop_t *
1177 i_ddi_search_global_prop(dev_t dev, char *name, uint_t flags)
1178 {
1179 	major_t		major;
1180 	struct devnames	*dnp;
1181 	ddi_prop_t	*propp;
1182 
1183 	/*
1184 	 * Valid dev_t value is needed to index into the
1185 	 * correct devnames entry, therefore a dev_t
1186 	 * value of DDI_DEV_T_ANY is not appropriate.
1187 	 */
1188 	ASSERT(dev != DDI_DEV_T_ANY);
1189 	if (dev == DDI_DEV_T_ANY) {
1190 		return ((ddi_prop_t *)0);
1191 	}
1192 
1193 	major = getmajor(dev);
1194 	dnp = &(devnamesp[major]);
1195 
1196 	if (dnp->dn_global_prop_ptr == NULL)
1197 		return ((ddi_prop_t *)0);
1198 
1199 	LOCK_DEV_OPS(&dnp->dn_lock);
1200 
1201 	for (propp = dnp->dn_global_prop_ptr->prop_list;
1202 	    propp != NULL;
1203 	    propp = (ddi_prop_t *)propp->prop_next) {
1204 
1205 		if (!DDI_STRSAME(propp->prop_name, name))
1206 			continue;
1207 
1208 		if ((!(flags & DDI_PROP_ROOTNEX_GLOBAL)) &&
1209 		    (!(flags & LDI_DEV_T_ANY)) && (propp->prop_dev != dev))
1210 			continue;
1211 
1212 		if (((propp->prop_flags & flags) & DDI_PROP_TYPE_MASK) == 0)
1213 			continue;
1214 
1215 		/* Property found, return it */
1216 		UNLOCK_DEV_OPS(&dnp->dn_lock);
1217 		return (propp);
1218 	}
1219 
1220 	UNLOCK_DEV_OPS(&dnp->dn_lock);
1221 	return ((ddi_prop_t *)0);
1222 }
1223 
1224 static char prop_no_mem_msg[] = "can't allocate memory for ddi property <%s>";
1225 
1226 /*
1227  * ddi_prop_search_global:
1228  *	Search the global property list within devnames
1229  *	for the named property.  Return the encoded value.
1230  */
1231 static int
1232 i_ddi_prop_search_global(dev_t dev, uint_t flags, char *name,
1233     void *valuep, uint_t *lengthp)
1234 {
1235 	ddi_prop_t	*propp;
1236 	caddr_t		buffer;
1237 
1238 	propp =  i_ddi_search_global_prop(dev, name, flags);
1239 
1240 	/* Property NOT found, bail */
1241 	if (propp == (ddi_prop_t *)0)
1242 		return (DDI_PROP_NOT_FOUND);
1243 
1244 	if (propp->prop_flags & DDI_PROP_UNDEF_IT)
1245 		return (DDI_PROP_UNDEFINED);
1246 
1247 	if ((buffer = kmem_alloc(propp->prop_len,
1248 	    (flags & DDI_PROP_CANSLEEP) ? KM_SLEEP : KM_NOSLEEP)) == NULL) {
1249 		cmn_err(CE_CONT, prop_no_mem_msg, name);
1250 		return (DDI_PROP_NO_MEMORY);
1251 	}
1252 
1253 	/*
1254 	 * Return the encoded data
1255 	 */
1256 	*(caddr_t *)valuep = buffer;
1257 	*lengthp = propp->prop_len;
1258 	bcopy(propp->prop_val, buffer, propp->prop_len);
1259 
1260 	return (DDI_PROP_SUCCESS);
1261 }
1262 
1263 /*
1264  * ddi_prop_search_common:	Lookup and return the encoded value
1265  */
1266 int
1267 ddi_prop_search_common(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1268     uint_t flags, char *name, void *valuep, uint_t *lengthp)
1269 {
1270 	ddi_prop_t	*propp;
1271 	int		i;
1272 	caddr_t		buffer;
1273 	caddr_t		prealloc = NULL;
1274 	int		plength = 0;
1275 	dev_info_t	*pdip;
1276 	int		(*bop)();
1277 
1278 	/*CONSTANTCONDITION*/
1279 	while (1)  {
1280 
1281 		mutex_enter(&(DEVI(dip)->devi_lock));
1282 
1283 
1284 		/*
1285 		 * find the property in child's devinfo:
1286 		 * Search order is:
1287 		 *	1. driver defined properties
1288 		 *	2. system defined properties
1289 		 *	3. driver global properties
1290 		 *	4. boot defined properties
1291 		 */
1292 
1293 		propp = i_ddi_prop_search(dev, name, flags,
1294 		    &(DEVI(dip)->devi_drv_prop_ptr));
1295 		if (propp == NULL)  {
1296 			propp = i_ddi_prop_search(dev, name, flags,
1297 			    &(DEVI(dip)->devi_sys_prop_ptr));
1298 		}
1299 		if ((propp == NULL) && DEVI(dip)->devi_global_prop_list) {
1300 			propp = i_ddi_prop_search(dev, name, flags,
1301 			    &DEVI(dip)->devi_global_prop_list->prop_list);
1302 		}
1303 
1304 		if (propp == NULL)  {
1305 			propp = i_ddi_prop_search(dev, name, flags,
1306 			    &(DEVI(dip)->devi_hw_prop_ptr));
1307 		}
1308 
1309 		/*
1310 		 * Software property found?
1311 		 */
1312 		if (propp != (ddi_prop_t *)0)	{
1313 
1314 			/*
1315 			 * If explicit undefine, return now.
1316 			 */
1317 			if (propp->prop_flags & DDI_PROP_UNDEF_IT) {
1318 				mutex_exit(&(DEVI(dip)->devi_lock));
1319 				if (prealloc)
1320 					kmem_free(prealloc, plength);
1321 				return (DDI_PROP_UNDEFINED);
1322 			}
1323 
1324 			/*
1325 			 * If we only want to know if it exists, return now
1326 			 */
1327 			if (prop_op == PROP_EXISTS) {
1328 				mutex_exit(&(DEVI(dip)->devi_lock));
1329 				ASSERT(prealloc == NULL);
1330 				return (DDI_PROP_SUCCESS);
1331 			}
1332 
1333 			/*
1334 			 * If length only request or prop length == 0,
1335 			 * service request and return now.
1336 			 */
1337 			if ((prop_op == PROP_LEN) ||(propp->prop_len == 0)) {
1338 				*lengthp = propp->prop_len;
1339 
1340 				/*
1341 				 * if prop_op is PROP_LEN_AND_VAL_ALLOC
1342 				 * that means prop_len is 0, so set valuep
1343 				 * also to NULL
1344 				 */
1345 				if (prop_op == PROP_LEN_AND_VAL_ALLOC)
1346 					*(caddr_t *)valuep = NULL;
1347 
1348 				mutex_exit(&(DEVI(dip)->devi_lock));
1349 				if (prealloc)
1350 					kmem_free(prealloc, plength);
1351 				return (DDI_PROP_SUCCESS);
1352 			}
1353 
1354 			/*
1355 			 * If LEN_AND_VAL_ALLOC and the request can sleep,
1356 			 * drop the mutex, allocate the buffer, and go
1357 			 * through the loop again.  If we already allocated
1358 			 * the buffer, and the size of the property changed,
1359 			 * keep trying...
1360 			 */
1361 			if ((prop_op == PROP_LEN_AND_VAL_ALLOC) &&
1362 			    (flags & DDI_PROP_CANSLEEP))  {
1363 				if (prealloc && (propp->prop_len != plength)) {
1364 					kmem_free(prealloc, plength);
1365 					prealloc = NULL;
1366 				}
1367 				if (prealloc == NULL)  {
1368 					plength = propp->prop_len;
1369 					mutex_exit(&(DEVI(dip)->devi_lock));
1370 					prealloc = kmem_alloc(plength,
1371 					    KM_SLEEP);
1372 					continue;
1373 				}
1374 			}
1375 
1376 			/*
1377 			 * Allocate buffer, if required.  Either way,
1378 			 * set `buffer' variable.
1379 			 */
1380 			i = *lengthp;			/* Get callers length */
1381 			*lengthp = propp->prop_len;	/* Set callers length */
1382 
1383 			switch (prop_op) {
1384 
1385 			case PROP_LEN_AND_VAL_ALLOC:
1386 
1387 				if (prealloc == NULL) {
1388 					buffer = kmem_alloc(propp->prop_len,
1389 					    KM_NOSLEEP);
1390 				} else {
1391 					buffer = prealloc;
1392 				}
1393 
1394 				if (buffer == NULL)  {
1395 					mutex_exit(&(DEVI(dip)->devi_lock));
1396 					cmn_err(CE_CONT, prop_no_mem_msg, name);
1397 					return (DDI_PROP_NO_MEMORY);
1398 				}
1399 				/* Set callers buf ptr */
1400 				*(caddr_t *)valuep = buffer;
1401 				break;
1402 
1403 			case PROP_LEN_AND_VAL_BUF:
1404 
1405 				if (propp->prop_len > (i)) {
1406 					mutex_exit(&(DEVI(dip)->devi_lock));
1407 					return (DDI_PROP_BUF_TOO_SMALL);
1408 				}
1409 
1410 				buffer = valuep;  /* Get callers buf ptr */
1411 				break;
1412 
1413 			default:
1414 				break;
1415 			}
1416 
1417 			/*
1418 			 * Do the copy.
1419 			 */
1420 			bcopy(propp->prop_val, buffer, propp->prop_len);
1421 			mutex_exit(&(DEVI(dip)->devi_lock));
1422 			return (DDI_PROP_SUCCESS);
1423 		}
1424 
1425 		mutex_exit(&(DEVI(dip)->devi_lock));
1426 		if (prealloc)
1427 			kmem_free(prealloc, plength);
1428 		prealloc = NULL;
1429 
1430 		/*
1431 		 * Prop not found, call parent bus_ops to deal with possible
1432 		 * h/w layer (possible PROM defined props, etc.) and to
1433 		 * possibly ascend the hierarchy, if allowed by flags.
1434 		 */
1435 		pdip = (dev_info_t *)DEVI(dip)->devi_parent;
1436 
1437 		/*
1438 		 * One last call for the root driver PROM props?
1439 		 */
1440 		if (dip == ddi_root_node())  {
1441 			return (ddi_bus_prop_op(dev, dip, dip, prop_op,
1442 			    flags, name, valuep, (int *)lengthp));
1443 		}
1444 
1445 		/*
1446 		 * We may have been called to check for properties
1447 		 * within a single devinfo node that has no parent -
1448 		 * see make_prop()
1449 		 */
1450 		if (pdip == NULL) {
1451 			ASSERT((flags &
1452 			    (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM)) ==
1453 			    (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM));
1454 			return (DDI_PROP_NOT_FOUND);
1455 		}
1456 
1457 		/*
1458 		 * Instead of recursing, we do iterative calls up the tree.
1459 		 * As a bit of optimization, skip the bus_op level if the
1460 		 * node is a s/w node and if the parent's bus_prop_op function
1461 		 * is `ddi_bus_prop_op', because we know that in this case,
1462 		 * this function does nothing.
1463 		 *
1464 		 * 4225415: If the parent isn't attached, or the child
1465 		 * hasn't been named by the parent yet, use the default
1466 		 * ddi_bus_prop_op as a proxy for the parent.  This
1467 		 * allows property lookups in any child/parent state to
1468 		 * include 'prom' and inherited properties, even when
1469 		 * there are no drivers attached to the child or parent.
1470 		 */
1471 
1472 		bop = ddi_bus_prop_op;
1473 		if (i_ddi_devi_attached(pdip) &&
1474 		    (i_ddi_node_state(dip) >= DS_INITIALIZED))
1475 			bop = DEVI(pdip)->devi_ops->devo_bus_ops->bus_prop_op;
1476 
1477 		i = DDI_PROP_NOT_FOUND;
1478 
1479 		if ((bop != ddi_bus_prop_op) || ndi_dev_is_prom_node(dip)) {
1480 			i = (*bop)(dev, pdip, dip, prop_op,
1481 			    flags | DDI_PROP_DONTPASS,
1482 			    name, valuep, lengthp);
1483 		}
1484 
1485 		if ((flags & DDI_PROP_DONTPASS) ||
1486 		    (i != DDI_PROP_NOT_FOUND))
1487 			return (i);
1488 
1489 		dip = pdip;
1490 	}
1491 	/*NOTREACHED*/
1492 }
1493 
1494 
1495 /*
1496  * ddi_prop_op: The basic property operator for drivers.
1497  *
1498  * In ddi_prop_op, the type of valuep is interpreted based on prop_op:
1499  *
1500  *	prop_op			valuep
1501  *	------			------
1502  *
1503  *	PROP_LEN		<unused>
1504  *
1505  *	PROP_LEN_AND_VAL_BUF	Pointer to callers buffer
1506  *
1507  *	PROP_LEN_AND_VAL_ALLOC	Address of callers pointer (will be set to
1508  *				address of allocated buffer, if successful)
1509  */
1510 int
1511 ddi_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
1512     char *name, caddr_t valuep, int *lengthp)
1513 {
1514 	int	i;
1515 
1516 	ASSERT((mod_flags & DDI_PROP_TYPE_MASK) == 0);
1517 
1518 	/*
1519 	 * If this was originally an LDI prop lookup then we bail here.
1520 	 * The reason is that the LDI property lookup interfaces first call
1521 	 * a drivers prop_op() entry point to allow it to override
1522 	 * properties.  But if we've made it here, then the driver hasn't
1523 	 * overriden any properties.  We don't want to continue with the
1524 	 * property search here because we don't have any type inforamtion.
1525 	 * When we return failure, the LDI interfaces will then proceed to
1526 	 * call the typed property interfaces to look up the property.
1527 	 */
1528 	if (mod_flags & DDI_PROP_DYNAMIC)
1529 		return (DDI_PROP_NOT_FOUND);
1530 
1531 	/*
1532 	 * check for pre-typed property consumer asking for typed property:
1533 	 * see e_ddi_getprop_int64.
1534 	 */
1535 	if (mod_flags & DDI_PROP_CONSUMER_TYPED)
1536 		mod_flags |= DDI_PROP_TYPE_INT64;
1537 	mod_flags |= DDI_PROP_TYPE_ANY;
1538 
1539 	i = ddi_prop_search_common(dev, dip, prop_op,
1540 	    mod_flags, name, valuep, (uint_t *)lengthp);
1541 	if (i == DDI_PROP_FOUND_1275)
1542 		return (DDI_PROP_SUCCESS);
1543 	return (i);
1544 }
1545 
1546 /*
1547  * ddi_prop_op_nblocks_blksize: The basic property operator for drivers that
1548  * maintain size in number of blksize blocks.  Provides a dynamic property
1549  * implementation for size oriented properties based on nblocks64 and blksize
1550  * values passed in by the driver.  Fallback to ddi_prop_op if the nblocks64
1551  * is too large.  This interface should not be used with a nblocks64 that
1552  * represents the driver's idea of how to represent unknown, if nblocks is
1553  * unknown use ddi_prop_op.
1554  */
1555 int
1556 ddi_prop_op_nblocks_blksize(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1557     int mod_flags, char *name, caddr_t valuep, int *lengthp,
1558     uint64_t nblocks64, uint_t blksize)
1559 {
1560 	uint64_t size64;
1561 	int	blkshift;
1562 
1563 	/* convert block size to shift value */
1564 	ASSERT(BIT_ONLYONESET(blksize));
1565 	blkshift = highbit(blksize) - 1;
1566 
1567 	/*
1568 	 * There is no point in supporting nblocks64 values that don't have
1569 	 * an accurate uint64_t byte count representation.
1570 	 */
1571 	if (nblocks64 >= (UINT64_MAX >> blkshift))
1572 		return (ddi_prop_op(dev, dip, prop_op, mod_flags,
1573 		    name, valuep, lengthp));
1574 
1575 	size64 = nblocks64 << blkshift;
1576 	return (ddi_prop_op_size_blksize(dev, dip, prop_op, mod_flags,
1577 	    name, valuep, lengthp, size64, blksize));
1578 }
1579 
1580 /*
1581  * ddi_prop_op_nblocks: ddi_prop_op_nblocks_blksize with DEV_BSIZE blksize.
1582  */
1583 int
1584 ddi_prop_op_nblocks(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1585     int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t nblocks64)
1586 {
1587 	return (ddi_prop_op_nblocks_blksize(dev, dip, prop_op,
1588 	    mod_flags, name, valuep, lengthp, nblocks64, DEV_BSIZE));
1589 }
1590 
1591 /*
1592  * ddi_prop_op_size_blksize: The basic property operator for block drivers that
1593  * maintain size in bytes. Provides a of dynamic property implementation for
1594  * size oriented properties based on size64 value and blksize passed in by the
1595  * driver.  Fallback to ddi_prop_op if the size64 is too large. This interface
1596  * should not be used with a size64 that represents the driver's idea of how
1597  * to represent unknown, if size is unknown use ddi_prop_op.
1598  *
1599  * NOTE: the legacy "nblocks"/"size" properties are treated as 32-bit unsigned
1600  * integers. While the most likely interface to request them ([bc]devi_size)
1601  * is declared int (signed) there is no enforcement of this, which means we
1602  * can't enforce limitations here without risking regression.
1603  */
1604 int
1605 ddi_prop_op_size_blksize(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1606     int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t size64,
1607     uint_t blksize)
1608 {
1609 	uint64_t nblocks64;
1610 	int	callers_length;
1611 	caddr_t	buffer;
1612 	int	blkshift;
1613 
1614 	/*
1615 	 * This is a kludge to support capture of size(9P) pure dynamic
1616 	 * properties in snapshots for non-cmlb code (without exposing
1617 	 * i_ddi_prop_dyn changes). When everyone uses cmlb, this code
1618 	 * should be removed.
1619 	 */
1620 	if (i_ddi_prop_dyn_driver_get(dip) == NULL) {
1621 		static i_ddi_prop_dyn_t prop_dyn_size[] = {
1622 		    {"Size",		DDI_PROP_TYPE_INT64,	S_IFCHR},
1623 		    {"Nblocks",		DDI_PROP_TYPE_INT64,	S_IFBLK},
1624 		    {NULL}
1625 		};
1626 		i_ddi_prop_dyn_driver_set(dip, prop_dyn_size);
1627 	}
1628 
1629 	/* convert block size to shift value */
1630 	ASSERT(BIT_ONLYONESET(blksize));
1631 	blkshift = highbit(blksize) - 1;
1632 
1633 	/* compute DEV_BSIZE nblocks value */
1634 	nblocks64 = size64 >> blkshift;
1635 
1636 	/* get callers length, establish length of our dynamic properties */
1637 	callers_length = *lengthp;
1638 
1639 	if (strcmp(name, "Nblocks") == 0)
1640 		*lengthp = sizeof (uint64_t);
1641 	else if (strcmp(name, "Size") == 0)
1642 		*lengthp = sizeof (uint64_t);
1643 	else if ((strcmp(name, "nblocks") == 0) && (nblocks64 < UINT_MAX))
1644 		*lengthp = sizeof (uint32_t);
1645 	else if ((strcmp(name, "size") == 0) && (size64 < UINT_MAX))
1646 		*lengthp = sizeof (uint32_t);
1647 	else if ((strcmp(name, "blksize") == 0) && (blksize < UINT_MAX))
1648 		*lengthp = sizeof (uint32_t);
1649 	else {
1650 		/* fallback to ddi_prop_op */
1651 		return (ddi_prop_op(dev, dip, prop_op, mod_flags,
1652 		    name, valuep, lengthp));
1653 	}
1654 
1655 	/* service request for the length of the property */
1656 	if (prop_op == PROP_LEN)
1657 		return (DDI_PROP_SUCCESS);
1658 
1659 	switch (prop_op) {
1660 	case PROP_LEN_AND_VAL_ALLOC:
1661 		if ((buffer = kmem_alloc(*lengthp,
1662 		    (mod_flags & DDI_PROP_CANSLEEP) ?
1663 		    KM_SLEEP : KM_NOSLEEP)) == NULL)
1664 			return (DDI_PROP_NO_MEMORY);
1665 
1666 		*(caddr_t *)valuep = buffer;	/* set callers buf ptr */
1667 		break;
1668 
1669 	case PROP_LEN_AND_VAL_BUF:
1670 		/* the length of the property and the request must match */
1671 		if (callers_length != *lengthp)
1672 			return (DDI_PROP_INVAL_ARG);
1673 
1674 		buffer = valuep;		/* get callers buf ptr */
1675 		break;
1676 
1677 	default:
1678 		return (DDI_PROP_INVAL_ARG);
1679 	}
1680 
1681 	/* transfer the value into the buffer */
1682 	if (strcmp(name, "Nblocks") == 0)
1683 		*((uint64_t *)buffer) = nblocks64;
1684 	else if (strcmp(name, "Size") == 0)
1685 		*((uint64_t *)buffer) = size64;
1686 	else if (strcmp(name, "nblocks") == 0)
1687 		*((uint32_t *)buffer) = (uint32_t)nblocks64;
1688 	else if (strcmp(name, "size") == 0)
1689 		*((uint32_t *)buffer) = (uint32_t)size64;
1690 	else if (strcmp(name, "blksize") == 0)
1691 		*((uint32_t *)buffer) = (uint32_t)blksize;
1692 	return (DDI_PROP_SUCCESS);
1693 }
1694 
1695 /*
1696  * ddi_prop_op_size: ddi_prop_op_size_blksize with DEV_BSIZE block size.
1697  */
1698 int
1699 ddi_prop_op_size(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1700     int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t size64)
1701 {
1702 	return (ddi_prop_op_size_blksize(dev, dip, prop_op,
1703 	    mod_flags, name, valuep, lengthp, size64, DEV_BSIZE));
1704 }
1705 
1706 /*
1707  * Variable length props...
1708  */
1709 
1710 /*
1711  * ddi_getlongprop:	Get variable length property len+val into a buffer
1712  *		allocated by property provider via kmem_alloc. Requester
1713  *		is responsible for freeing returned property via kmem_free.
1714  *
1715  *	Arguments:
1716  *
1717  *	dev_t:	Input:	dev_t of property.
1718  *	dip:	Input:	dev_info_t pointer of child.
1719  *	flags:	Input:	Possible flag modifiers are:
1720  *		DDI_PROP_DONTPASS:	Don't pass to parent if prop not found.
1721  *		DDI_PROP_CANSLEEP:	Memory allocation may sleep.
1722  *	name:	Input:	name of property.
1723  *	valuep:	Output:	Addr of callers buffer pointer.
1724  *	lengthp:Output:	*lengthp will contain prop length on exit.
1725  *
1726  *	Possible Returns:
1727  *
1728  *		DDI_PROP_SUCCESS:	Prop found and returned.
1729  *		DDI_PROP_NOT_FOUND:	Prop not found
1730  *		DDI_PROP_UNDEFINED:	Prop explicitly undefined.
1731  *		DDI_PROP_NO_MEMORY:	Prop found, but unable to alloc mem.
1732  */
1733 
1734 int
1735 ddi_getlongprop(dev_t dev, dev_info_t *dip, int flags,
1736     char *name, caddr_t valuep, int *lengthp)
1737 {
1738 	return (ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_ALLOC,
1739 	    flags, name, valuep, lengthp));
1740 }
1741 
1742 /*
1743  *
1744  * ddi_getlongprop_buf:		Get long prop into pre-allocated callers
1745  *				buffer. (no memory allocation by provider).
1746  *
1747  *	dev_t:	Input:	dev_t of property.
1748  *	dip:	Input:	dev_info_t pointer of child.
1749  *	flags:	Input:	DDI_PROP_DONTPASS or NULL
1750  *	name:	Input:	name of property
1751  *	valuep:	Input:	ptr to callers buffer.
1752  *	lengthp:I/O:	ptr to length of callers buffer on entry,
1753  *			actual length of property on exit.
1754  *
1755  *	Possible returns:
1756  *
1757  *		DDI_PROP_SUCCESS	Prop found and returned
1758  *		DDI_PROP_NOT_FOUND	Prop not found
1759  *		DDI_PROP_UNDEFINED	Prop explicitly undefined.
1760  *		DDI_PROP_BUF_TOO_SMALL	Prop found, callers buf too small,
1761  *					no value returned, but actual prop
1762  *					length returned in *lengthp
1763  *
1764  */
1765 
1766 int
1767 ddi_getlongprop_buf(dev_t dev, dev_info_t *dip, int flags,
1768     char *name, caddr_t valuep, int *lengthp)
1769 {
1770 	return (ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_BUF,
1771 	    flags, name, valuep, lengthp));
1772 }
1773 
1774 /*
1775  * Integer/boolean sized props.
1776  *
1777  * Call is value only... returns found boolean or int sized prop value or
1778  * defvalue if prop not found or is wrong length or is explicitly undefined.
1779  * Only flag is DDI_PROP_DONTPASS...
1780  *
1781  * By convention, this interface returns boolean (0) sized properties
1782  * as value (int)1.
1783  *
1784  * This never returns an error, if property not found or specifically
1785  * undefined, the input `defvalue' is returned.
1786  */
1787 
1788 int
1789 ddi_getprop(dev_t dev, dev_info_t *dip, int flags, char *name, int defvalue)
1790 {
1791 	int	propvalue = defvalue;
1792 	int	proplength = sizeof (int);
1793 	int	error;
1794 
1795 	error = ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_BUF,
1796 	    flags, name, (caddr_t)&propvalue, &proplength);
1797 
1798 	if ((error == DDI_PROP_SUCCESS) && (proplength == 0))
1799 		propvalue = 1;
1800 
1801 	return (propvalue);
1802 }
1803 
1804 /*
1805  * Get prop length interface: flags are 0 or DDI_PROP_DONTPASS
1806  * if returns DDI_PROP_SUCCESS, length returned in *lengthp.
1807  */
1808 
1809 int
1810 ddi_getproplen(dev_t dev, dev_info_t *dip, int flags, char *name, int *lengthp)
1811 {
1812 	return (ddi_prop_op(dev, dip, PROP_LEN, flags, name, NULL, lengthp));
1813 }
1814 
1815 /*
1816  * Allocate a struct prop_driver_data, along with 'size' bytes
1817  * for decoded property data.  This structure is freed by
1818  * calling ddi_prop_free(9F).
1819  */
1820 static void *
1821 ddi_prop_decode_alloc(size_t size, void (*prop_free)(struct prop_driver_data *))
1822 {
1823 	struct prop_driver_data *pdd;
1824 
1825 	/*
1826 	 * Allocate a structure with enough memory to store the decoded data.
1827 	 */
1828 	pdd = kmem_zalloc(sizeof (struct prop_driver_data) + size, KM_SLEEP);
1829 	pdd->pdd_size = (sizeof (struct prop_driver_data) + size);
1830 	pdd->pdd_prop_free = prop_free;
1831 
1832 	/*
1833 	 * Return a pointer to the location to put the decoded data.
1834 	 */
1835 	return ((void *)((caddr_t)pdd + sizeof (struct prop_driver_data)));
1836 }
1837 
1838 /*
1839  * Allocated the memory needed to store the encoded data in the property
1840  * handle.
1841  */
1842 static int
1843 ddi_prop_encode_alloc(prop_handle_t *ph, size_t size)
1844 {
1845 	/*
1846 	 * If size is zero, then set data to NULL and size to 0.  This
1847 	 * is a boolean property.
1848 	 */
1849 	if (size == 0) {
1850 		ph->ph_size = 0;
1851 		ph->ph_data = NULL;
1852 		ph->ph_cur_pos = NULL;
1853 		ph->ph_save_pos = NULL;
1854 	} else {
1855 		if (ph->ph_flags == DDI_PROP_DONTSLEEP) {
1856 			ph->ph_data = kmem_zalloc(size, KM_NOSLEEP);
1857 			if (ph->ph_data == NULL)
1858 				return (DDI_PROP_NO_MEMORY);
1859 		} else
1860 			ph->ph_data = kmem_zalloc(size, KM_SLEEP);
1861 		ph->ph_size = size;
1862 		ph->ph_cur_pos = ph->ph_data;
1863 		ph->ph_save_pos = ph->ph_data;
1864 	}
1865 	return (DDI_PROP_SUCCESS);
1866 }
1867 
1868 /*
1869  * Free the space allocated by the lookup routines.  Each lookup routine
1870  * returns a pointer to the decoded data to the driver.  The driver then
1871  * passes this pointer back to us.  This data actually lives in a struct
1872  * prop_driver_data.  We use negative indexing to find the beginning of
1873  * the structure and then free the entire structure using the size and
1874  * the free routine stored in the structure.
1875  */
1876 void
1877 ddi_prop_free(void *datap)
1878 {
1879 	struct prop_driver_data *pdd;
1880 
1881 	/*
1882 	 * Get the structure
1883 	 */
1884 	pdd = (struct prop_driver_data *)
1885 	    ((caddr_t)datap - sizeof (struct prop_driver_data));
1886 	/*
1887 	 * Call the free routine to free it
1888 	 */
1889 	(*pdd->pdd_prop_free)(pdd);
1890 }
1891 
1892 /*
1893  * Free the data associated with an array of ints,
1894  * allocated with ddi_prop_decode_alloc().
1895  */
1896 static void
1897 ddi_prop_free_ints(struct prop_driver_data *pdd)
1898 {
1899 	kmem_free(pdd, pdd->pdd_size);
1900 }
1901 
1902 /*
1903  * Free a single string property or a single string contained within
1904  * the argv style return value of an array of strings.
1905  */
1906 static void
1907 ddi_prop_free_string(struct prop_driver_data *pdd)
1908 {
1909 	kmem_free(pdd, pdd->pdd_size);
1910 
1911 }
1912 
1913 /*
1914  * Free an array of strings.
1915  */
1916 static void
1917 ddi_prop_free_strings(struct prop_driver_data *pdd)
1918 {
1919 	kmem_free(pdd, pdd->pdd_size);
1920 }
1921 
1922 /*
1923  * Free the data associated with an array of bytes.
1924  */
1925 static void
1926 ddi_prop_free_bytes(struct prop_driver_data *pdd)
1927 {
1928 	kmem_free(pdd, pdd->pdd_size);
1929 }
1930 
1931 /*
1932  * Reset the current location pointer in the property handle to the
1933  * beginning of the data.
1934  */
1935 void
1936 ddi_prop_reset_pos(prop_handle_t *ph)
1937 {
1938 	ph->ph_cur_pos = ph->ph_data;
1939 	ph->ph_save_pos = ph->ph_data;
1940 }
1941 
1942 /*
1943  * Restore the current location pointer in the property handle to the
1944  * saved position.
1945  */
1946 void
1947 ddi_prop_save_pos(prop_handle_t *ph)
1948 {
1949 	ph->ph_save_pos = ph->ph_cur_pos;
1950 }
1951 
1952 /*
1953  * Save the location that the current location pointer is pointing to..
1954  */
1955 void
1956 ddi_prop_restore_pos(prop_handle_t *ph)
1957 {
1958 	ph->ph_cur_pos = ph->ph_save_pos;
1959 }
1960 
1961 /*
1962  * Property encode/decode functions
1963  */
1964 
1965 /*
1966  * Decode a single integer property
1967  */
1968 static int
1969 ddi_prop_fm_decode_int(prop_handle_t *ph, void *data, uint_t *nelements)
1970 {
1971 	int	i;
1972 	int	tmp;
1973 
1974 	/*
1975 	 * If there is nothing to decode return an error
1976 	 */
1977 	if (ph->ph_size == 0)
1978 		return (DDI_PROP_END_OF_DATA);
1979 
1980 	/*
1981 	 * Decode the property as a single integer and return it
1982 	 * in data if we were able to decode it.
1983 	 */
1984 	i = DDI_PROP_INT(ph, DDI_PROP_CMD_DECODE, &tmp);
1985 	if (i < DDI_PROP_RESULT_OK) {
1986 		switch (i) {
1987 		case DDI_PROP_RESULT_EOF:
1988 			return (DDI_PROP_END_OF_DATA);
1989 
1990 		case DDI_PROP_RESULT_ERROR:
1991 			return (DDI_PROP_CANNOT_DECODE);
1992 		}
1993 	}
1994 
1995 	*(int *)data = tmp;
1996 	*nelements = 1;
1997 	return (DDI_PROP_SUCCESS);
1998 }
1999 
2000 /*
2001  * Decode a single 64 bit integer property
2002  */
2003 static int
2004 ddi_prop_fm_decode_int64(prop_handle_t *ph, void *data, uint_t *nelements)
2005 {
2006 	int	i;
2007 	int64_t	tmp;
2008 
2009 	/*
2010 	 * If there is nothing to decode return an error
2011 	 */
2012 	if (ph->ph_size == 0)
2013 		return (DDI_PROP_END_OF_DATA);
2014 
2015 	/*
2016 	 * Decode the property as a single integer and return it
2017 	 * in data if we were able to decode it.
2018 	 */
2019 	i = DDI_PROP_INT64(ph, DDI_PROP_CMD_DECODE, &tmp);
2020 	if (i < DDI_PROP_RESULT_OK) {
2021 		switch (i) {
2022 		case DDI_PROP_RESULT_EOF:
2023 			return (DDI_PROP_END_OF_DATA);
2024 
2025 		case DDI_PROP_RESULT_ERROR:
2026 			return (DDI_PROP_CANNOT_DECODE);
2027 		}
2028 	}
2029 
2030 	*(int64_t *)data = tmp;
2031 	*nelements = 1;
2032 	return (DDI_PROP_SUCCESS);
2033 }
2034 
2035 /*
2036  * Decode an array of integers property
2037  */
2038 static int
2039 ddi_prop_fm_decode_ints(prop_handle_t *ph, void *data, uint_t *nelements)
2040 {
2041 	int	i;
2042 	int	cnt = 0;
2043 	int	*tmp;
2044 	int	*intp;
2045 	int	n;
2046 
2047 	/*
2048 	 * Figure out how many array elements there are by going through the
2049 	 * data without decoding it first and counting.
2050 	 */
2051 	for (;;) {
2052 		i = DDI_PROP_INT(ph, DDI_PROP_CMD_SKIP, NULL);
2053 		if (i < 0)
2054 			break;
2055 		cnt++;
2056 	}
2057 
2058 	/*
2059 	 * If there are no elements return an error
2060 	 */
2061 	if (cnt == 0)
2062 		return (DDI_PROP_END_OF_DATA);
2063 
2064 	/*
2065 	 * If we cannot skip through the data, we cannot decode it
2066 	 */
2067 	if (i == DDI_PROP_RESULT_ERROR)
2068 		return (DDI_PROP_CANNOT_DECODE);
2069 
2070 	/*
2071 	 * Reset the data pointer to the beginning of the encoded data
2072 	 */
2073 	ddi_prop_reset_pos(ph);
2074 
2075 	/*
2076 	 * Allocated memory to store the decoded value in.
2077 	 */
2078 	intp = ddi_prop_decode_alloc((cnt * sizeof (int)),
2079 	    ddi_prop_free_ints);
2080 
2081 	/*
2082 	 * Decode each element and place it in the space we just allocated
2083 	 */
2084 	tmp = intp;
2085 	for (n = 0; n < cnt; n++, tmp++) {
2086 		i = DDI_PROP_INT(ph, DDI_PROP_CMD_DECODE, tmp);
2087 		if (i < DDI_PROP_RESULT_OK) {
2088 			/*
2089 			 * Free the space we just allocated
2090 			 * and return an error.
2091 			 */
2092 			ddi_prop_free(intp);
2093 			switch (i) {
2094 			case DDI_PROP_RESULT_EOF:
2095 				return (DDI_PROP_END_OF_DATA);
2096 
2097 			case DDI_PROP_RESULT_ERROR:
2098 				return (DDI_PROP_CANNOT_DECODE);
2099 			}
2100 		}
2101 	}
2102 
2103 	*nelements = cnt;
2104 	*(int **)data = intp;
2105 
2106 	return (DDI_PROP_SUCCESS);
2107 }
2108 
2109 /*
2110  * Decode a 64 bit integer array property
2111  */
2112 static int
2113 ddi_prop_fm_decode_int64_array(prop_handle_t *ph, void *data, uint_t *nelements)
2114 {
2115 	int	i;
2116 	int	n;
2117 	int	cnt = 0;
2118 	int64_t	*tmp;
2119 	int64_t	*intp;
2120 
2121 	/*
2122 	 * Count the number of array elements by going
2123 	 * through the data without decoding it.
2124 	 */
2125 	for (;;) {
2126 		i = DDI_PROP_INT64(ph, DDI_PROP_CMD_SKIP, NULL);
2127 		if (i < 0)
2128 			break;
2129 		cnt++;
2130 	}
2131 
2132 	/*
2133 	 * If there are no elements return an error
2134 	 */
2135 	if (cnt == 0)
2136 		return (DDI_PROP_END_OF_DATA);
2137 
2138 	/*
2139 	 * If we cannot skip through the data, we cannot decode it
2140 	 */
2141 	if (i == DDI_PROP_RESULT_ERROR)
2142 		return (DDI_PROP_CANNOT_DECODE);
2143 
2144 	/*
2145 	 * Reset the data pointer to the beginning of the encoded data
2146 	 */
2147 	ddi_prop_reset_pos(ph);
2148 
2149 	/*
2150 	 * Allocate memory to store the decoded value.
2151 	 */
2152 	intp = ddi_prop_decode_alloc((cnt * sizeof (int64_t)),
2153 	    ddi_prop_free_ints);
2154 
2155 	/*
2156 	 * Decode each element and place it in the space allocated
2157 	 */
2158 	tmp = intp;
2159 	for (n = 0; n < cnt; n++, tmp++) {
2160 		i = DDI_PROP_INT64(ph, DDI_PROP_CMD_DECODE, tmp);
2161 		if (i < DDI_PROP_RESULT_OK) {
2162 			/*
2163 			 * Free the space we just allocated
2164 			 * and return an error.
2165 			 */
2166 			ddi_prop_free(intp);
2167 			switch (i) {
2168 			case DDI_PROP_RESULT_EOF:
2169 				return (DDI_PROP_END_OF_DATA);
2170 
2171 			case DDI_PROP_RESULT_ERROR:
2172 				return (DDI_PROP_CANNOT_DECODE);
2173 			}
2174 		}
2175 	}
2176 
2177 	*nelements = cnt;
2178 	*(int64_t **)data = intp;
2179 
2180 	return (DDI_PROP_SUCCESS);
2181 }
2182 
2183 /*
2184  * Encode an array of integers property (Can be one element)
2185  */
2186 int
2187 ddi_prop_fm_encode_ints(prop_handle_t *ph, void *data, uint_t nelements)
2188 {
2189 	int	i;
2190 	int	*tmp;
2191 	int	cnt;
2192 	int	size;
2193 
2194 	/*
2195 	 * If there is no data, we cannot do anything
2196 	 */
2197 	if (nelements == 0)
2198 		return (DDI_PROP_CANNOT_ENCODE);
2199 
2200 	/*
2201 	 * Get the size of an encoded int.
2202 	 */
2203 	size = DDI_PROP_INT(ph, DDI_PROP_CMD_GET_ESIZE, NULL);
2204 
2205 	if (size < DDI_PROP_RESULT_OK) {
2206 		switch (size) {
2207 		case DDI_PROP_RESULT_EOF:
2208 			return (DDI_PROP_END_OF_DATA);
2209 
2210 		case DDI_PROP_RESULT_ERROR:
2211 			return (DDI_PROP_CANNOT_ENCODE);
2212 		}
2213 	}
2214 
2215 	/*
2216 	 * Allocate space in the handle to store the encoded int.
2217 	 */
2218 	if (ddi_prop_encode_alloc(ph, size * nelements) !=
2219 	    DDI_PROP_SUCCESS)
2220 		return (DDI_PROP_NO_MEMORY);
2221 
2222 	/*
2223 	 * Encode the array of ints.
2224 	 */
2225 	tmp = (int *)data;
2226 	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
2227 		i = DDI_PROP_INT(ph, DDI_PROP_CMD_ENCODE, tmp);
2228 		if (i < DDI_PROP_RESULT_OK) {
2229 			switch (i) {
2230 			case DDI_PROP_RESULT_EOF:
2231 				return (DDI_PROP_END_OF_DATA);
2232 
2233 			case DDI_PROP_RESULT_ERROR:
2234 				return (DDI_PROP_CANNOT_ENCODE);
2235 			}
2236 		}
2237 	}
2238 
2239 	return (DDI_PROP_SUCCESS);
2240 }
2241 
2242 
2243 /*
2244  * Encode a 64 bit integer array property
2245  */
2246 int
2247 ddi_prop_fm_encode_int64(prop_handle_t *ph, void *data, uint_t nelements)
2248 {
2249 	int i;
2250 	int cnt;
2251 	int size;
2252 	int64_t *tmp;
2253 
2254 	/*
2255 	 * If there is no data, we cannot do anything
2256 	 */
2257 	if (nelements == 0)
2258 		return (DDI_PROP_CANNOT_ENCODE);
2259 
2260 	/*
2261 	 * Get the size of an encoded 64 bit int.
2262 	 */
2263 	size = DDI_PROP_INT64(ph, DDI_PROP_CMD_GET_ESIZE, NULL);
2264 
2265 	if (size < DDI_PROP_RESULT_OK) {
2266 		switch (size) {
2267 		case DDI_PROP_RESULT_EOF:
2268 			return (DDI_PROP_END_OF_DATA);
2269 
2270 		case DDI_PROP_RESULT_ERROR:
2271 			return (DDI_PROP_CANNOT_ENCODE);
2272 		}
2273 	}
2274 
2275 	/*
2276 	 * Allocate space in the handle to store the encoded int.
2277 	 */
2278 	if (ddi_prop_encode_alloc(ph, size * nelements) !=
2279 	    DDI_PROP_SUCCESS)
2280 		return (DDI_PROP_NO_MEMORY);
2281 
2282 	/*
2283 	 * Encode the array of ints.
2284 	 */
2285 	tmp = (int64_t *)data;
2286 	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
2287 		i = DDI_PROP_INT64(ph, DDI_PROP_CMD_ENCODE, tmp);
2288 		if (i < DDI_PROP_RESULT_OK) {
2289 			switch (i) {
2290 			case DDI_PROP_RESULT_EOF:
2291 				return (DDI_PROP_END_OF_DATA);
2292 
2293 			case DDI_PROP_RESULT_ERROR:
2294 				return (DDI_PROP_CANNOT_ENCODE);
2295 			}
2296 		}
2297 	}
2298 
2299 	return (DDI_PROP_SUCCESS);
2300 }
2301 
2302 /*
2303  * Decode a single string property
2304  */
2305 static int
2306 ddi_prop_fm_decode_string(prop_handle_t *ph, void *data, uint_t *nelements)
2307 {
2308 	char		*tmp;
2309 	char		*str;
2310 	int		i;
2311 	int		size;
2312 
2313 	/*
2314 	 * If there is nothing to decode return an error
2315 	 */
2316 	if (ph->ph_size == 0)
2317 		return (DDI_PROP_END_OF_DATA);
2318 
2319 	/*
2320 	 * Get the decoded size of the encoded string.
2321 	 */
2322 	size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL);
2323 	if (size < DDI_PROP_RESULT_OK) {
2324 		switch (size) {
2325 		case DDI_PROP_RESULT_EOF:
2326 			return (DDI_PROP_END_OF_DATA);
2327 
2328 		case DDI_PROP_RESULT_ERROR:
2329 			return (DDI_PROP_CANNOT_DECODE);
2330 		}
2331 	}
2332 
2333 	/*
2334 	 * Allocated memory to store the decoded value in.
2335 	 */
2336 	str = ddi_prop_decode_alloc((size_t)size, ddi_prop_free_string);
2337 
2338 	ddi_prop_reset_pos(ph);
2339 
2340 	/*
2341 	 * Decode the str and place it in the space we just allocated
2342 	 */
2343 	tmp = str;
2344 	i = DDI_PROP_STR(ph, DDI_PROP_CMD_DECODE, tmp);
2345 	if (i < DDI_PROP_RESULT_OK) {
2346 		/*
2347 		 * Free the space we just allocated
2348 		 * and return an error.
2349 		 */
2350 		ddi_prop_free(str);
2351 		switch (i) {
2352 		case DDI_PROP_RESULT_EOF:
2353 			return (DDI_PROP_END_OF_DATA);
2354 
2355 		case DDI_PROP_RESULT_ERROR:
2356 			return (DDI_PROP_CANNOT_DECODE);
2357 		}
2358 	}
2359 
2360 	*(char **)data = str;
2361 	*nelements = 1;
2362 
2363 	return (DDI_PROP_SUCCESS);
2364 }
2365 
2366 /*
2367  * Decode an array of strings.
2368  */
2369 int
2370 ddi_prop_fm_decode_strings(prop_handle_t *ph, void *data, uint_t *nelements)
2371 {
2372 	int		cnt = 0;
2373 	char		**strs;
2374 	char		**tmp;
2375 	char		*ptr;
2376 	int		i;
2377 	int		n;
2378 	int		size;
2379 	size_t		nbytes;
2380 
2381 	/*
2382 	 * Figure out how many array elements there are by going through the
2383 	 * data without decoding it first and counting.
2384 	 */
2385 	for (;;) {
2386 		i = DDI_PROP_STR(ph, DDI_PROP_CMD_SKIP, NULL);
2387 		if (i < 0)
2388 			break;
2389 		cnt++;
2390 	}
2391 
2392 	/*
2393 	 * If there are no elements return an error
2394 	 */
2395 	if (cnt == 0)
2396 		return (DDI_PROP_END_OF_DATA);
2397 
2398 	/*
2399 	 * If we cannot skip through the data, we cannot decode it
2400 	 */
2401 	if (i == DDI_PROP_RESULT_ERROR)
2402 		return (DDI_PROP_CANNOT_DECODE);
2403 
2404 	/*
2405 	 * Reset the data pointer to the beginning of the encoded data
2406 	 */
2407 	ddi_prop_reset_pos(ph);
2408 
2409 	/*
2410 	 * Figure out how much memory we need for the sum total
2411 	 */
2412 	nbytes = (cnt + 1) * sizeof (char *);
2413 
2414 	for (n = 0; n < cnt; n++) {
2415 		/*
2416 		 * Get the decoded size of the current encoded string.
2417 		 */
2418 		size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL);
2419 		if (size < DDI_PROP_RESULT_OK) {
2420 			switch (size) {
2421 			case DDI_PROP_RESULT_EOF:
2422 				return (DDI_PROP_END_OF_DATA);
2423 
2424 			case DDI_PROP_RESULT_ERROR:
2425 				return (DDI_PROP_CANNOT_DECODE);
2426 			}
2427 		}
2428 
2429 		nbytes += size;
2430 	}
2431 
2432 	/*
2433 	 * Allocate memory in which to store the decoded strings.
2434 	 */
2435 	strs = ddi_prop_decode_alloc(nbytes, ddi_prop_free_strings);
2436 
2437 	/*
2438 	 * Set up pointers for each string by figuring out yet
2439 	 * again how long each string is.
2440 	 */
2441 	ddi_prop_reset_pos(ph);
2442 	ptr = (caddr_t)strs + ((cnt + 1) * sizeof (char *));
2443 	for (tmp = strs, n = 0; n < cnt; n++, tmp++) {
2444 		/*
2445 		 * Get the decoded size of the current encoded string.
2446 		 */
2447 		size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL);
2448 		if (size < DDI_PROP_RESULT_OK) {
2449 			ddi_prop_free(strs);
2450 			switch (size) {
2451 			case DDI_PROP_RESULT_EOF:
2452 				return (DDI_PROP_END_OF_DATA);
2453 
2454 			case DDI_PROP_RESULT_ERROR:
2455 				return (DDI_PROP_CANNOT_DECODE);
2456 			}
2457 		}
2458 
2459 		*tmp = ptr;
2460 		ptr += size;
2461 	}
2462 
2463 	/*
2464 	 * String array is terminated by a NULL
2465 	 */
2466 	*tmp = NULL;
2467 
2468 	/*
2469 	 * Finally, we can decode each string
2470 	 */
2471 	ddi_prop_reset_pos(ph);
2472 	for (tmp = strs, n = 0; n < cnt; n++, tmp++) {
2473 		i = DDI_PROP_STR(ph, DDI_PROP_CMD_DECODE, *tmp);
2474 		if (i < DDI_PROP_RESULT_OK) {
2475 			/*
2476 			 * Free the space we just allocated
2477 			 * and return an error
2478 			 */
2479 			ddi_prop_free(strs);
2480 			switch (i) {
2481 			case DDI_PROP_RESULT_EOF:
2482 				return (DDI_PROP_END_OF_DATA);
2483 
2484 			case DDI_PROP_RESULT_ERROR:
2485 				return (DDI_PROP_CANNOT_DECODE);
2486 			}
2487 		}
2488 	}
2489 
2490 	*(char ***)data = strs;
2491 	*nelements = cnt;
2492 
2493 	return (DDI_PROP_SUCCESS);
2494 }
2495 
2496 /*
2497  * Encode a string.
2498  */
2499 int
2500 ddi_prop_fm_encode_string(prop_handle_t *ph, void *data, uint_t nelements)
2501 {
2502 	char		**tmp;
2503 	int		size;
2504 	int		i;
2505 
2506 	/*
2507 	 * If there is no data, we cannot do anything
2508 	 */
2509 	if (nelements == 0)
2510 		return (DDI_PROP_CANNOT_ENCODE);
2511 
2512 	/*
2513 	 * Get the size of the encoded string.
2514 	 */
2515 	tmp = (char **)data;
2516 	size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_ESIZE, *tmp);
2517 	if (size < DDI_PROP_RESULT_OK) {
2518 		switch (size) {
2519 		case DDI_PROP_RESULT_EOF:
2520 			return (DDI_PROP_END_OF_DATA);
2521 
2522 		case DDI_PROP_RESULT_ERROR:
2523 			return (DDI_PROP_CANNOT_ENCODE);
2524 		}
2525 	}
2526 
2527 	/*
2528 	 * Allocate space in the handle to store the encoded string.
2529 	 */
2530 	if (ddi_prop_encode_alloc(ph, size) != DDI_PROP_SUCCESS)
2531 		return (DDI_PROP_NO_MEMORY);
2532 
2533 	ddi_prop_reset_pos(ph);
2534 
2535 	/*
2536 	 * Encode the string.
2537 	 */
2538 	tmp = (char **)data;
2539 	i = DDI_PROP_STR(ph, DDI_PROP_CMD_ENCODE, *tmp);
2540 	if (i < DDI_PROP_RESULT_OK) {
2541 		switch (i) {
2542 		case DDI_PROP_RESULT_EOF:
2543 			return (DDI_PROP_END_OF_DATA);
2544 
2545 		case DDI_PROP_RESULT_ERROR:
2546 			return (DDI_PROP_CANNOT_ENCODE);
2547 		}
2548 	}
2549 
2550 	return (DDI_PROP_SUCCESS);
2551 }
2552 
2553 
2554 /*
2555  * Encode an array of strings.
2556  */
2557 int
2558 ddi_prop_fm_encode_strings(prop_handle_t *ph, void *data, uint_t nelements)
2559 {
2560 	int		cnt = 0;
2561 	char		**tmp;
2562 	int		size;
2563 	uint_t		total_size;
2564 	int		i;
2565 
2566 	/*
2567 	 * If there is no data, we cannot do anything
2568 	 */
2569 	if (nelements == 0)
2570 		return (DDI_PROP_CANNOT_ENCODE);
2571 
2572 	/*
2573 	 * Get the total size required to encode all the strings.
2574 	 */
2575 	total_size = 0;
2576 	tmp = (char **)data;
2577 	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
2578 		size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_ESIZE, *tmp);
2579 		if (size < DDI_PROP_RESULT_OK) {
2580 			switch (size) {
2581 			case DDI_PROP_RESULT_EOF:
2582 				return (DDI_PROP_END_OF_DATA);
2583 
2584 			case DDI_PROP_RESULT_ERROR:
2585 				return (DDI_PROP_CANNOT_ENCODE);
2586 			}
2587 		}
2588 		total_size += (uint_t)size;
2589 	}
2590 
2591 	/*
2592 	 * Allocate space in the handle to store the encoded strings.
2593 	 */
2594 	if (ddi_prop_encode_alloc(ph, total_size) != DDI_PROP_SUCCESS)
2595 		return (DDI_PROP_NO_MEMORY);
2596 
2597 	ddi_prop_reset_pos(ph);
2598 
2599 	/*
2600 	 * Encode the array of strings.
2601 	 */
2602 	tmp = (char **)data;
2603 	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
2604 		i = DDI_PROP_STR(ph, DDI_PROP_CMD_ENCODE, *tmp);
2605 		if (i < DDI_PROP_RESULT_OK) {
2606 			switch (i) {
2607 			case DDI_PROP_RESULT_EOF:
2608 				return (DDI_PROP_END_OF_DATA);
2609 
2610 			case DDI_PROP_RESULT_ERROR:
2611 				return (DDI_PROP_CANNOT_ENCODE);
2612 			}
2613 		}
2614 	}
2615 
2616 	return (DDI_PROP_SUCCESS);
2617 }
2618 
2619 
2620 /*
2621  * Decode an array of bytes.
2622  */
2623 static int
2624 ddi_prop_fm_decode_bytes(prop_handle_t *ph, void *data, uint_t *nelements)
2625 {
2626 	uchar_t		*tmp;
2627 	int		nbytes;
2628 	int		i;
2629 
2630 	/*
2631 	 * If there are no elements return an error
2632 	 */
2633 	if (ph->ph_size == 0)
2634 		return (DDI_PROP_END_OF_DATA);
2635 
2636 	/*
2637 	 * Get the size of the encoded array of bytes.
2638 	 */
2639 	nbytes = DDI_PROP_BYTES(ph, DDI_PROP_CMD_GET_DSIZE,
2640 	    data, ph->ph_size);
2641 	if (nbytes < DDI_PROP_RESULT_OK) {
2642 		switch (nbytes) {
2643 		case DDI_PROP_RESULT_EOF:
2644 			return (DDI_PROP_END_OF_DATA);
2645 
2646 		case DDI_PROP_RESULT_ERROR:
2647 			return (DDI_PROP_CANNOT_DECODE);
2648 		}
2649 	}
2650 
2651 	/*
2652 	 * Allocated memory to store the decoded value in.
2653 	 */
2654 	tmp = ddi_prop_decode_alloc(nbytes, ddi_prop_free_bytes);
2655 
2656 	/*
2657 	 * Decode each element and place it in the space we just allocated
2658 	 */
2659 	i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_DECODE, tmp, nbytes);
2660 	if (i < DDI_PROP_RESULT_OK) {
2661 		/*
2662 		 * Free the space we just allocated
2663 		 * and return an error
2664 		 */
2665 		ddi_prop_free(tmp);
2666 		switch (i) {
2667 		case DDI_PROP_RESULT_EOF:
2668 			return (DDI_PROP_END_OF_DATA);
2669 
2670 		case DDI_PROP_RESULT_ERROR:
2671 			return (DDI_PROP_CANNOT_DECODE);
2672 		}
2673 	}
2674 
2675 	*(uchar_t **)data = tmp;
2676 	*nelements = nbytes;
2677 
2678 	return (DDI_PROP_SUCCESS);
2679 }
2680 
2681 /*
2682  * Encode an array of bytes.
2683  */
2684 int
2685 ddi_prop_fm_encode_bytes(prop_handle_t *ph, void *data, uint_t nelements)
2686 {
2687 	int		size;
2688 	int		i;
2689 
2690 	/*
2691 	 * If there are no elements, then this is a boolean property,
2692 	 * so just create a property handle with no data and return.
2693 	 */
2694 	if (nelements == 0) {
2695 		(void) ddi_prop_encode_alloc(ph, 0);
2696 		return (DDI_PROP_SUCCESS);
2697 	}
2698 
2699 	/*
2700 	 * Get the size of the encoded array of bytes.
2701 	 */
2702 	size = DDI_PROP_BYTES(ph, DDI_PROP_CMD_GET_ESIZE, (uchar_t *)data,
2703 	    nelements);
2704 	if (size < DDI_PROP_RESULT_OK) {
2705 		switch (size) {
2706 		case DDI_PROP_RESULT_EOF:
2707 			return (DDI_PROP_END_OF_DATA);
2708 
2709 		case DDI_PROP_RESULT_ERROR:
2710 			return (DDI_PROP_CANNOT_DECODE);
2711 		}
2712 	}
2713 
2714 	/*
2715 	 * Allocate space in the handle to store the encoded bytes.
2716 	 */
2717 	if (ddi_prop_encode_alloc(ph, (uint_t)size) != DDI_PROP_SUCCESS)
2718 		return (DDI_PROP_NO_MEMORY);
2719 
2720 	/*
2721 	 * Encode the array of bytes.
2722 	 */
2723 	i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_ENCODE, (uchar_t *)data,
2724 	    nelements);
2725 	if (i < DDI_PROP_RESULT_OK) {
2726 		switch (i) {
2727 		case DDI_PROP_RESULT_EOF:
2728 			return (DDI_PROP_END_OF_DATA);
2729 
2730 		case DDI_PROP_RESULT_ERROR:
2731 			return (DDI_PROP_CANNOT_ENCODE);
2732 		}
2733 	}
2734 
2735 	return (DDI_PROP_SUCCESS);
2736 }
2737 
2738 /*
2739  * OBP 1275 integer, string and byte operators.
2740  *
2741  * DDI_PROP_CMD_DECODE:
2742  *
2743  *	DDI_PROP_RESULT_ERROR:		cannot decode the data
2744  *	DDI_PROP_RESULT_EOF:		end of data
2745  *	DDI_PROP_OK:			data was decoded
2746  *
2747  * DDI_PROP_CMD_ENCODE:
2748  *
2749  *	DDI_PROP_RESULT_ERROR:		cannot encode the data
2750  *	DDI_PROP_RESULT_EOF:		end of data
2751  *	DDI_PROP_OK:			data was encoded
2752  *
2753  * DDI_PROP_CMD_SKIP:
2754  *
2755  *	DDI_PROP_RESULT_ERROR:		cannot skip the data
2756  *	DDI_PROP_RESULT_EOF:		end of data
2757  *	DDI_PROP_OK:			data was skipped
2758  *
2759  * DDI_PROP_CMD_GET_ESIZE:
2760  *
2761  *	DDI_PROP_RESULT_ERROR:		cannot get encoded size
2762  *	DDI_PROP_RESULT_EOF:		end of data
2763  *	> 0:				the encoded size
2764  *
2765  * DDI_PROP_CMD_GET_DSIZE:
2766  *
2767  *	DDI_PROP_RESULT_ERROR:		cannot get decoded size
2768  *	DDI_PROP_RESULT_EOF:		end of data
2769  *	> 0:				the decoded size
2770  */
2771 
2772 /*
2773  * OBP 1275 integer operator
2774  *
2775  * OBP properties are a byte stream of data, so integers may not be
2776  * properly aligned.  Therefore we need to copy them one byte at a time.
2777  */
2778 int
2779 ddi_prop_1275_int(prop_handle_t *ph, uint_t cmd, int *data)
2780 {
2781 	int	i;
2782 
2783 	switch (cmd) {
2784 	case DDI_PROP_CMD_DECODE:
2785 		/*
2786 		 * Check that there is encoded data
2787 		 */
2788 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0)
2789 			return (DDI_PROP_RESULT_ERROR);
2790 		if (ph->ph_flags & PH_FROM_PROM) {
2791 			i = MIN(ph->ph_size, PROP_1275_INT_SIZE);
2792 			if ((int *)ph->ph_cur_pos > ((int *)ph->ph_data +
2793 			    ph->ph_size - i))
2794 				return (DDI_PROP_RESULT_ERROR);
2795 		} else {
2796 			if (ph->ph_size < sizeof (int) ||
2797 			    ((int *)ph->ph_cur_pos > ((int *)ph->ph_data +
2798 			    ph->ph_size - sizeof (int))))
2799 				return (DDI_PROP_RESULT_ERROR);
2800 		}
2801 
2802 		/*
2803 		 * Copy the integer, using the implementation-specific
2804 		 * copy function if the property is coming from the PROM.
2805 		 */
2806 		if (ph->ph_flags & PH_FROM_PROM) {
2807 			*data = impl_ddi_prop_int_from_prom(
2808 			    (uchar_t *)ph->ph_cur_pos,
2809 			    (ph->ph_size < PROP_1275_INT_SIZE) ?
2810 			    ph->ph_size : PROP_1275_INT_SIZE);
2811 		} else {
2812 			bcopy(ph->ph_cur_pos, data, sizeof (int));
2813 		}
2814 
2815 		/*
2816 		 * Move the current location to the start of the next
2817 		 * bit of undecoded data.
2818 		 */
2819 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
2820 		    PROP_1275_INT_SIZE;
2821 		return (DDI_PROP_RESULT_OK);
2822 
2823 	case DDI_PROP_CMD_ENCODE:
2824 		/*
2825 		 * Check that there is room to encoded the data
2826 		 */
2827 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
2828 		    ph->ph_size < PROP_1275_INT_SIZE ||
2829 		    ((int *)ph->ph_cur_pos > ((int *)ph->ph_data +
2830 		    ph->ph_size - sizeof (int))))
2831 			return (DDI_PROP_RESULT_ERROR);
2832 
2833 		/*
2834 		 * Encode the integer into the byte stream one byte at a
2835 		 * time.
2836 		 */
2837 		bcopy(data, ph->ph_cur_pos, sizeof (int));
2838 
2839 		/*
2840 		 * Move the current location to the start of the next bit of
2841 		 * space where we can store encoded data.
2842 		 */
2843 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE;
2844 		return (DDI_PROP_RESULT_OK);
2845 
2846 	case DDI_PROP_CMD_SKIP:
2847 		/*
2848 		 * Check that there is encoded data
2849 		 */
2850 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
2851 		    ph->ph_size < PROP_1275_INT_SIZE)
2852 			return (DDI_PROP_RESULT_ERROR);
2853 
2854 
2855 		if ((caddr_t)ph->ph_cur_pos ==
2856 		    (caddr_t)ph->ph_data + ph->ph_size) {
2857 			return (DDI_PROP_RESULT_EOF);
2858 		} else if ((caddr_t)ph->ph_cur_pos >
2859 		    (caddr_t)ph->ph_data + ph->ph_size) {
2860 			return (DDI_PROP_RESULT_EOF);
2861 		}
2862 
2863 		/*
2864 		 * Move the current location to the start of the next bit of
2865 		 * undecoded data.
2866 		 */
2867 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE;
2868 		return (DDI_PROP_RESULT_OK);
2869 
2870 	case DDI_PROP_CMD_GET_ESIZE:
2871 		/*
2872 		 * Return the size of an encoded integer on OBP
2873 		 */
2874 		return (PROP_1275_INT_SIZE);
2875 
2876 	case DDI_PROP_CMD_GET_DSIZE:
2877 		/*
2878 		 * Return the size of a decoded integer on the system.
2879 		 */
2880 		return (sizeof (int));
2881 
2882 	default:
2883 #ifdef DEBUG
2884 		panic("ddi_prop_1275_int: %x impossible", cmd);
2885 		/*NOTREACHED*/
2886 #else
2887 		return (DDI_PROP_RESULT_ERROR);
2888 #endif	/* DEBUG */
2889 	}
2890 }
2891 
2892 /*
2893  * 64 bit integer operator.
2894  *
2895  * This is an extension, defined by Sun, to the 1275 integer
2896  * operator.  This routine handles the encoding/decoding of
2897  * 64 bit integer properties.
2898  */
2899 int
2900 ddi_prop_int64_op(prop_handle_t *ph, uint_t cmd, int64_t *data)
2901 {
2902 
2903 	switch (cmd) {
2904 	case DDI_PROP_CMD_DECODE:
2905 		/*
2906 		 * Check that there is encoded data
2907 		 */
2908 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0)
2909 			return (DDI_PROP_RESULT_ERROR);
2910 		if (ph->ph_flags & PH_FROM_PROM) {
2911 			return (DDI_PROP_RESULT_ERROR);
2912 		} else {
2913 			if (ph->ph_size < sizeof (int64_t) ||
2914 			    ((int64_t *)ph->ph_cur_pos >
2915 			    ((int64_t *)ph->ph_data +
2916 			    ph->ph_size - sizeof (int64_t))))
2917 				return (DDI_PROP_RESULT_ERROR);
2918 		}
2919 		/*
2920 		 * Copy the integer, using the implementation-specific
2921 		 * copy function if the property is coming from the PROM.
2922 		 */
2923 		if (ph->ph_flags & PH_FROM_PROM) {
2924 			return (DDI_PROP_RESULT_ERROR);
2925 		} else {
2926 			bcopy(ph->ph_cur_pos, data, sizeof (int64_t));
2927 		}
2928 
2929 		/*
2930 		 * Move the current location to the start of the next
2931 		 * bit of undecoded data.
2932 		 */
2933 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
2934 		    sizeof (int64_t);
2935 			return (DDI_PROP_RESULT_OK);
2936 
2937 	case DDI_PROP_CMD_ENCODE:
2938 		/*
2939 		 * Check that there is room to encoded the data
2940 		 */
2941 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
2942 		    ph->ph_size < sizeof (int64_t) ||
2943 		    ((int64_t *)ph->ph_cur_pos > ((int64_t *)ph->ph_data +
2944 		    ph->ph_size - sizeof (int64_t))))
2945 			return (DDI_PROP_RESULT_ERROR);
2946 
2947 		/*
2948 		 * Encode the integer into the byte stream one byte at a
2949 		 * time.
2950 		 */
2951 		bcopy(data, ph->ph_cur_pos, sizeof (int64_t));
2952 
2953 		/*
2954 		 * Move the current location to the start of the next bit of
2955 		 * space where we can store encoded data.
2956 		 */
2957 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
2958 		    sizeof (int64_t);
2959 		return (DDI_PROP_RESULT_OK);
2960 
2961 	case DDI_PROP_CMD_SKIP:
2962 		/*
2963 		 * Check that there is encoded data
2964 		 */
2965 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
2966 		    ph->ph_size < sizeof (int64_t))
2967 			return (DDI_PROP_RESULT_ERROR);
2968 
2969 		if ((caddr_t)ph->ph_cur_pos ==
2970 		    (caddr_t)ph->ph_data + ph->ph_size) {
2971 			return (DDI_PROP_RESULT_EOF);
2972 		} else if ((caddr_t)ph->ph_cur_pos >
2973 		    (caddr_t)ph->ph_data + ph->ph_size) {
2974 			return (DDI_PROP_RESULT_EOF);
2975 		}
2976 
2977 		/*
2978 		 * Move the current location to the start of
2979 		 * the next bit of undecoded data.
2980 		 */
2981 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
2982 		    sizeof (int64_t);
2983 			return (DDI_PROP_RESULT_OK);
2984 
2985 	case DDI_PROP_CMD_GET_ESIZE:
2986 		/*
2987 		 * Return the size of an encoded integer on OBP
2988 		 */
2989 		return (sizeof (int64_t));
2990 
2991 	case DDI_PROP_CMD_GET_DSIZE:
2992 		/*
2993 		 * Return the size of a decoded integer on the system.
2994 		 */
2995 		return (sizeof (int64_t));
2996 
2997 	default:
2998 #ifdef DEBUG
2999 		panic("ddi_prop_int64_op: %x impossible", cmd);
3000 		/*NOTREACHED*/
3001 #else
3002 		return (DDI_PROP_RESULT_ERROR);
3003 #endif  /* DEBUG */
3004 	}
3005 }
3006 
3007 /*
3008  * OBP 1275 string operator.
3009  *
3010  * OBP strings are NULL terminated.
3011  */
3012 int
3013 ddi_prop_1275_string(prop_handle_t *ph, uint_t cmd, char *data)
3014 {
3015 	int	n;
3016 	char	*p;
3017 	char	*end;
3018 
3019 	switch (cmd) {
3020 	case DDI_PROP_CMD_DECODE:
3021 		/*
3022 		 * Check that there is encoded data
3023 		 */
3024 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0) {
3025 			return (DDI_PROP_RESULT_ERROR);
3026 		}
3027 
3028 		/*
3029 		 * Match DDI_PROP_CMD_GET_DSIZE logic for when to stop and
3030 		 * how to NULL terminate result.
3031 		 */
3032 		p = (char *)ph->ph_cur_pos;
3033 		end = (char *)ph->ph_data + ph->ph_size;
3034 		if (p >= end)
3035 			return (DDI_PROP_RESULT_EOF);
3036 
3037 		while (p < end) {
3038 			*data++ = *p;
3039 			if (*p++ == 0) {	/* NULL from OBP */
3040 				ph->ph_cur_pos = p;
3041 				return (DDI_PROP_RESULT_OK);
3042 			}
3043 		}
3044 
3045 		/*
3046 		 * If OBP did not NULL terminate string, which happens
3047 		 * (at least) for 'true'/'false' boolean values, account for
3048 		 * the space and store null termination on decode.
3049 		 */
3050 		ph->ph_cur_pos = p;
3051 		*data = 0;
3052 		return (DDI_PROP_RESULT_OK);
3053 
3054 	case DDI_PROP_CMD_ENCODE:
3055 		/*
3056 		 * Check that there is room to encoded the data
3057 		 */
3058 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0) {
3059 			return (DDI_PROP_RESULT_ERROR);
3060 		}
3061 
3062 		n = strlen(data) + 1;
3063 		if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
3064 		    ph->ph_size - n)) {
3065 			return (DDI_PROP_RESULT_ERROR);
3066 		}
3067 
3068 		/*
3069 		 * Copy the NULL terminated string
3070 		 */
3071 		bcopy(data, ph->ph_cur_pos, n);
3072 
3073 		/*
3074 		 * Move the current location to the start of the next bit of
3075 		 * space where we can store encoded data.
3076 		 */
3077 		ph->ph_cur_pos = (char *)ph->ph_cur_pos + n;
3078 		return (DDI_PROP_RESULT_OK);
3079 
3080 	case DDI_PROP_CMD_SKIP:
3081 		/*
3082 		 * Check that there is encoded data
3083 		 */
3084 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0) {
3085 			return (DDI_PROP_RESULT_ERROR);
3086 		}
3087 
3088 		/*
3089 		 * Return the string length plus one for the NULL
3090 		 * We know the size of the property, we need to
3091 		 * ensure that the string is properly formatted,
3092 		 * since we may be looking up random OBP data.
3093 		 */
3094 		p = (char *)ph->ph_cur_pos;
3095 		end = (char *)ph->ph_data + ph->ph_size;
3096 		if (p >= end)
3097 			return (DDI_PROP_RESULT_EOF);
3098 
3099 		while (p < end) {
3100 			if (*p++ == 0) {	/* NULL from OBP */
3101 				ph->ph_cur_pos = p;
3102 				return (DDI_PROP_RESULT_OK);
3103 			}
3104 		}
3105 
3106 		/*
3107 		 * Accommodate the fact that OBP does not always NULL
3108 		 * terminate strings.
3109 		 */
3110 		ph->ph_cur_pos = p;
3111 		return (DDI_PROP_RESULT_OK);
3112 
3113 	case DDI_PROP_CMD_GET_ESIZE:
3114 		/*
3115 		 * Return the size of the encoded string on OBP.
3116 		 */
3117 		return (strlen(data) + 1);
3118 
3119 	case DDI_PROP_CMD_GET_DSIZE:
3120 		/*
3121 		 * Return the string length plus one for the NULL.
3122 		 * We know the size of the property, we need to
3123 		 * ensure that the string is properly formatted,
3124 		 * since we may be looking up random OBP data.
3125 		 */
3126 		p = (char *)ph->ph_cur_pos;
3127 		end = (char *)ph->ph_data + ph->ph_size;
3128 		if (p >= end)
3129 			return (DDI_PROP_RESULT_EOF);
3130 
3131 		for (n = 0; p < end; n++) {
3132 			if (*p++ == 0) {	/* NULL from OBP */
3133 				ph->ph_cur_pos = p;
3134 				return (n + 1);
3135 			}
3136 		}
3137 
3138 		/*
3139 		 * If OBP did not NULL terminate string, which happens for
3140 		 * 'true'/'false' boolean values, account for the space
3141 		 * to store null termination here.
3142 		 */
3143 		ph->ph_cur_pos = p;
3144 		return (n + 1);
3145 
3146 	default:
3147 #ifdef DEBUG
3148 		panic("ddi_prop_1275_string: %x impossible", cmd);
3149 		/*NOTREACHED*/
3150 #else
3151 		return (DDI_PROP_RESULT_ERROR);
3152 #endif	/* DEBUG */
3153 	}
3154 }
3155 
3156 /*
3157  * OBP 1275 byte operator
3158  *
3159  * Caller must specify the number of bytes to get.  OBP encodes bytes
3160  * as a byte so there is a 1-to-1 translation.
3161  */
3162 int
3163 ddi_prop_1275_bytes(prop_handle_t *ph, uint_t cmd, uchar_t *data,
3164 	uint_t nelements)
3165 {
3166 	switch (cmd) {
3167 	case DDI_PROP_CMD_DECODE:
3168 		/*
3169 		 * Check that there is encoded data
3170 		 */
3171 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
3172 		    ph->ph_size < nelements ||
3173 		    ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
3174 		    ph->ph_size - nelements)))
3175 			return (DDI_PROP_RESULT_ERROR);
3176 
3177 		/*
3178 		 * Copy out the bytes
3179 		 */
3180 		bcopy(ph->ph_cur_pos, data, nelements);
3181 
3182 		/*
3183 		 * Move the current location
3184 		 */
3185 		ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements;
3186 		return (DDI_PROP_RESULT_OK);
3187 
3188 	case DDI_PROP_CMD_ENCODE:
3189 		/*
3190 		 * Check that there is room to encode the data
3191 		 */
3192 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
3193 		    ph->ph_size < nelements ||
3194 		    ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
3195 		    ph->ph_size - nelements)))
3196 			return (DDI_PROP_RESULT_ERROR);
3197 
3198 		/*
3199 		 * Copy in the bytes
3200 		 */
3201 		bcopy(data, ph->ph_cur_pos, nelements);
3202 
3203 		/*
3204 		 * Move the current location to the start of the next bit of
3205 		 * space where we can store encoded data.
3206 		 */
3207 		ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements;
3208 		return (DDI_PROP_RESULT_OK);
3209 
3210 	case DDI_PROP_CMD_SKIP:
3211 		/*
3212 		 * Check that there is encoded data
3213 		 */
3214 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
3215 		    ph->ph_size < nelements)
3216 			return (DDI_PROP_RESULT_ERROR);
3217 
3218 		if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
3219 		    ph->ph_size - nelements))
3220 			return (DDI_PROP_RESULT_EOF);
3221 
3222 		/*
3223 		 * Move the current location
3224 		 */
3225 		ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements;
3226 		return (DDI_PROP_RESULT_OK);
3227 
3228 	case DDI_PROP_CMD_GET_ESIZE:
3229 		/*
3230 		 * The size in bytes of the encoded size is the
3231 		 * same as the decoded size provided by the caller.
3232 		 */
3233 		return (nelements);
3234 
3235 	case DDI_PROP_CMD_GET_DSIZE:
3236 		/*
3237 		 * Just return the number of bytes specified by the caller.
3238 		 */
3239 		return (nelements);
3240 
3241 	default:
3242 #ifdef DEBUG
3243 		panic("ddi_prop_1275_bytes: %x impossible", cmd);
3244 		/*NOTREACHED*/
3245 #else
3246 		return (DDI_PROP_RESULT_ERROR);
3247 #endif	/* DEBUG */
3248 	}
3249 }
3250 
3251 /*
3252  * Used for properties that come from the OBP, hardware configuration files,
3253  * or that are created by calls to ddi_prop_update(9F).
3254  */
3255 static struct prop_handle_ops prop_1275_ops = {
3256 	ddi_prop_1275_int,
3257 	ddi_prop_1275_string,
3258 	ddi_prop_1275_bytes,
3259 	ddi_prop_int64_op
3260 };
3261 
3262 
3263 /*
3264  * Interface to create/modify a managed property on child's behalf...
3265  * Flags interpreted are:
3266  *	DDI_PROP_CANSLEEP:	Allow memory allocation to sleep.
3267  *	DDI_PROP_SYSTEM_DEF:	Manipulate system list rather than driver list.
3268  *
3269  * Use same dev_t when modifying or undefining a property.
3270  * Search for properties with DDI_DEV_T_ANY to match first named
3271  * property on the list.
3272  *
3273  * Properties are stored LIFO and subsequently will match the first
3274  * `matching' instance.
3275  */
3276 
3277 /*
3278  * ddi_prop_add:	Add a software defined property
3279  */
3280 
3281 /*
3282  * define to get a new ddi_prop_t.
3283  * km_flags are KM_SLEEP or KM_NOSLEEP.
3284  */
3285 
3286 #define	DDI_NEW_PROP_T(km_flags)	\
3287 	(kmem_zalloc(sizeof (ddi_prop_t), km_flags))
3288 
3289 static int
3290 ddi_prop_add(dev_t dev, dev_info_t *dip, int flags,
3291     char *name, caddr_t value, int length)
3292 {
3293 	ddi_prop_t	*new_propp, *propp;
3294 	ddi_prop_t	**list_head = &(DEVI(dip)->devi_drv_prop_ptr);
3295 	int		km_flags = KM_NOSLEEP;
3296 	int		name_buf_len;
3297 
3298 	/*
3299 	 * If dev_t is DDI_DEV_T_ANY or name's length is zero return error.
3300 	 */
3301 
3302 	if (dev == DDI_DEV_T_ANY || name == (char *)0 || strlen(name) == 0)
3303 		return (DDI_PROP_INVAL_ARG);
3304 
3305 	if (flags & DDI_PROP_CANSLEEP)
3306 		km_flags = KM_SLEEP;
3307 
3308 	if (flags & DDI_PROP_SYSTEM_DEF)
3309 		list_head = &(DEVI(dip)->devi_sys_prop_ptr);
3310 	else if (flags & DDI_PROP_HW_DEF)
3311 		list_head = &(DEVI(dip)->devi_hw_prop_ptr);
3312 
3313 	if ((new_propp = DDI_NEW_PROP_T(km_flags)) == NULL)  {
3314 		cmn_err(CE_CONT, prop_no_mem_msg, name);
3315 		return (DDI_PROP_NO_MEMORY);
3316 	}
3317 
3318 	/*
3319 	 * If dev is major number 0, then we need to do a ddi_name_to_major
3320 	 * to get the real major number for the device.  This needs to be
3321 	 * done because some drivers need to call ddi_prop_create in their
3322 	 * attach routines but they don't have a dev.  By creating the dev
3323 	 * ourself if the major number is 0, drivers will not have to know what
3324 	 * their major number.	They can just create a dev with major number
3325 	 * 0 and pass it in.  For device 0, we will be doing a little extra
3326 	 * work by recreating the same dev that we already have, but its the
3327 	 * price you pay :-).
3328 	 *
3329 	 * This fixes bug #1098060.
3330 	 */
3331 	if (getmajor(dev) == DDI_MAJOR_T_UNKNOWN) {
3332 		new_propp->prop_dev =
3333 		    makedevice(ddi_name_to_major(DEVI(dip)->devi_binding_name),
3334 		    getminor(dev));
3335 	} else
3336 		new_propp->prop_dev = dev;
3337 
3338 	/*
3339 	 * Allocate space for property name and copy it in...
3340 	 */
3341 
3342 	name_buf_len = strlen(name) + 1;
3343 	new_propp->prop_name = kmem_alloc(name_buf_len, km_flags);
3344 	if (new_propp->prop_name == 0)	{
3345 		kmem_free(new_propp, sizeof (ddi_prop_t));
3346 		cmn_err(CE_CONT, prop_no_mem_msg, name);
3347 		return (DDI_PROP_NO_MEMORY);
3348 	}
3349 	bcopy(name, new_propp->prop_name, name_buf_len);
3350 
3351 	/*
3352 	 * Set the property type
3353 	 */
3354 	new_propp->prop_flags = flags & DDI_PROP_TYPE_MASK;
3355 
3356 	/*
3357 	 * Set length and value ONLY if not an explicit property undefine:
3358 	 * NOTE: value and length are zero for explicit undefines.
3359 	 */
3360 
3361 	if (flags & DDI_PROP_UNDEF_IT) {
3362 		new_propp->prop_flags |= DDI_PROP_UNDEF_IT;
3363 	} else {
3364 		if ((new_propp->prop_len = length) != 0) {
3365 			new_propp->prop_val = kmem_alloc(length, km_flags);
3366 			if (new_propp->prop_val == 0)  {
3367 				kmem_free(new_propp->prop_name, name_buf_len);
3368 				kmem_free(new_propp, sizeof (ddi_prop_t));
3369 				cmn_err(CE_CONT, prop_no_mem_msg, name);
3370 				return (DDI_PROP_NO_MEMORY);
3371 			}
3372 			bcopy(value, new_propp->prop_val, length);
3373 		}
3374 	}
3375 
3376 	/*
3377 	 * Link property into beginning of list. (Properties are LIFO order.)
3378 	 */
3379 
3380 	mutex_enter(&(DEVI(dip)->devi_lock));
3381 	propp = *list_head;
3382 	new_propp->prop_next = propp;
3383 	*list_head = new_propp;
3384 	mutex_exit(&(DEVI(dip)->devi_lock));
3385 	return (DDI_PROP_SUCCESS);
3386 }
3387 
3388 
3389 /*
3390  * ddi_prop_change:	Modify a software managed property value
3391  *
3392  *			Set new length and value if found.
3393  *			returns DDI_PROP_INVAL_ARG if dev is DDI_DEV_T_ANY or
3394  *			input name is the NULL string.
3395  *			returns DDI_PROP_NO_MEMORY if unable to allocate memory
3396  *
3397  *			Note: an undef can be modified to be a define,
3398  *			(you can't go the other way.)
3399  */
3400 
3401 static int
3402 ddi_prop_change(dev_t dev, dev_info_t *dip, int flags,
3403     char *name, caddr_t value, int length)
3404 {
3405 	ddi_prop_t	*propp;
3406 	ddi_prop_t	**ppropp;
3407 	caddr_t		p = NULL;
3408 
3409 	if ((dev == DDI_DEV_T_ANY) || (name == NULL) || (strlen(name) == 0))
3410 		return (DDI_PROP_INVAL_ARG);
3411 
3412 	/*
3413 	 * Preallocate buffer, even if we don't need it...
3414 	 */
3415 	if (length != 0)  {
3416 		p = kmem_alloc(length, (flags & DDI_PROP_CANSLEEP) ?
3417 		    KM_SLEEP : KM_NOSLEEP);
3418 		if (p == NULL)	{
3419 			cmn_err(CE_CONT, prop_no_mem_msg, name);
3420 			return (DDI_PROP_NO_MEMORY);
3421 		}
3422 	}
3423 
3424 	/*
3425 	 * If the dev_t value contains DDI_MAJOR_T_UNKNOWN for the major
3426 	 * number, a real dev_t value should be created based upon the dip's
3427 	 * binding driver.  See ddi_prop_add...
3428 	 */
3429 	if (getmajor(dev) == DDI_MAJOR_T_UNKNOWN)
3430 		dev = makedevice(
3431 		    ddi_name_to_major(DEVI(dip)->devi_binding_name),
3432 		    getminor(dev));
3433 
3434 	/*
3435 	 * Check to see if the property exists.  If so we modify it.
3436 	 * Else we create it by calling ddi_prop_add().
3437 	 */
3438 	mutex_enter(&(DEVI(dip)->devi_lock));
3439 	ppropp = &DEVI(dip)->devi_drv_prop_ptr;
3440 	if (flags & DDI_PROP_SYSTEM_DEF)
3441 		ppropp = &DEVI(dip)->devi_sys_prop_ptr;
3442 	else if (flags & DDI_PROP_HW_DEF)
3443 		ppropp = &DEVI(dip)->devi_hw_prop_ptr;
3444 
3445 	if ((propp = i_ddi_prop_search(dev, name, flags, ppropp)) != NULL) {
3446 		/*
3447 		 * Need to reallocate buffer?  If so, do it
3448 		 * carefully (reuse same space if new prop
3449 		 * is same size and non-NULL sized).
3450 		 */
3451 		if (length != 0)
3452 			bcopy(value, p, length);
3453 
3454 		if (propp->prop_len != 0)
3455 			kmem_free(propp->prop_val, propp->prop_len);
3456 
3457 		propp->prop_len = length;
3458 		propp->prop_val = p;
3459 		propp->prop_flags &= ~DDI_PROP_UNDEF_IT;
3460 		mutex_exit(&(DEVI(dip)->devi_lock));
3461 		return (DDI_PROP_SUCCESS);
3462 	}
3463 
3464 	mutex_exit(&(DEVI(dip)->devi_lock));
3465 	if (length != 0)
3466 		kmem_free(p, length);
3467 
3468 	return (ddi_prop_add(dev, dip, flags, name, value, length));
3469 }
3470 
3471 /*
3472  * Common update routine used to update and encode a property.	Creates
3473  * a property handle, calls the property encode routine, figures out if
3474  * the property already exists and updates if it does.	Otherwise it
3475  * creates if it does not exist.
3476  */
3477 int
3478 ddi_prop_update_common(dev_t match_dev, dev_info_t *dip, int flags,
3479     char *name, void *data, uint_t nelements,
3480     int (*prop_create)(prop_handle_t *, void *data, uint_t nelements))
3481 {
3482 	prop_handle_t	ph;
3483 	int		rval;
3484 	uint_t		ourflags;
3485 
3486 	/*
3487 	 * If dev_t is DDI_DEV_T_ANY or name's length is zero,
3488 	 * return error.
3489 	 */
3490 	if (match_dev == DDI_DEV_T_ANY || name == NULL || strlen(name) == 0)
3491 		return (DDI_PROP_INVAL_ARG);
3492 
3493 	/*
3494 	 * Create the handle
3495 	 */
3496 	ph.ph_data = NULL;
3497 	ph.ph_cur_pos = NULL;
3498 	ph.ph_save_pos = NULL;
3499 	ph.ph_size = 0;
3500 	ph.ph_ops = &prop_1275_ops;
3501 
3502 	/*
3503 	 * ourflags:
3504 	 * For compatibility with the old interfaces.  The old interfaces
3505 	 * didn't sleep by default and slept when the flag was set.  These
3506 	 * interfaces to the opposite.	So the old interfaces now set the
3507 	 * DDI_PROP_DONTSLEEP flag by default which tells us not to sleep.
3508 	 *
3509 	 * ph.ph_flags:
3510 	 * Blocked data or unblocked data allocation
3511 	 * for ph.ph_data in ddi_prop_encode_alloc()
3512 	 */
3513 	if (flags & DDI_PROP_DONTSLEEP) {
3514 		ourflags = flags;
3515 		ph.ph_flags = DDI_PROP_DONTSLEEP;
3516 	} else {
3517 		ourflags = flags | DDI_PROP_CANSLEEP;
3518 		ph.ph_flags = DDI_PROP_CANSLEEP;
3519 	}
3520 
3521 	/*
3522 	 * Encode the data and store it in the property handle by
3523 	 * calling the prop_encode routine.
3524 	 */
3525 	if ((rval = (*prop_create)(&ph, data, nelements)) !=
3526 	    DDI_PROP_SUCCESS) {
3527 		if (rval == DDI_PROP_NO_MEMORY)
3528 			cmn_err(CE_CONT, prop_no_mem_msg, name);
3529 		if (ph.ph_size != 0)
3530 			kmem_free(ph.ph_data, ph.ph_size);
3531 		return (rval);
3532 	}
3533 
3534 	/*
3535 	 * The old interfaces use a stacking approach to creating
3536 	 * properties.	If we are being called from the old interfaces,
3537 	 * the DDI_PROP_STACK_CREATE flag will be set, so we just do a
3538 	 * create without checking.
3539 	 */
3540 	if (flags & DDI_PROP_STACK_CREATE) {
3541 		rval = ddi_prop_add(match_dev, dip,
3542 		    ourflags, name, ph.ph_data, ph.ph_size);
3543 	} else {
3544 		rval = ddi_prop_change(match_dev, dip,
3545 		    ourflags, name, ph.ph_data, ph.ph_size);
3546 	}
3547 
3548 	/*
3549 	 * Free the encoded data allocated in the prop_encode routine.
3550 	 */
3551 	if (ph.ph_size != 0)
3552 		kmem_free(ph.ph_data, ph.ph_size);
3553 
3554 	return (rval);
3555 }
3556 
3557 
3558 /*
3559  * ddi_prop_create:	Define a managed property:
3560  *			See above for details.
3561  */
3562 
3563 int
3564 ddi_prop_create(dev_t dev, dev_info_t *dip, int flag,
3565     char *name, caddr_t value, int length)
3566 {
3567 	if (!(flag & DDI_PROP_CANSLEEP)) {
3568 		flag |= DDI_PROP_DONTSLEEP;
3569 #ifdef DDI_PROP_DEBUG
3570 		if (length != 0)
3571 			cmn_err(CE_NOTE, "!ddi_prop_create: interface obsolete,"
3572 			    "use ddi_prop_update (prop = %s, node = %s%d)",
3573 			    name, ddi_driver_name(dip), ddi_get_instance(dip));
3574 #endif /* DDI_PROP_DEBUG */
3575 	}
3576 	flag &= ~DDI_PROP_SYSTEM_DEF;
3577 	flag |= DDI_PROP_STACK_CREATE | DDI_PROP_TYPE_ANY;
3578 	return (ddi_prop_update_common(dev, dip, flag, name,
3579 	    value, length, ddi_prop_fm_encode_bytes));
3580 }
3581 
3582 int
3583 e_ddi_prop_create(dev_t dev, dev_info_t *dip, int flag,
3584     char *name, caddr_t value, int length)
3585 {
3586 	if (!(flag & DDI_PROP_CANSLEEP))
3587 		flag |= DDI_PROP_DONTSLEEP;
3588 	flag |= DDI_PROP_SYSTEM_DEF | DDI_PROP_STACK_CREATE | DDI_PROP_TYPE_ANY;
3589 	return (ddi_prop_update_common(dev, dip, flag,
3590 	    name, value, length, ddi_prop_fm_encode_bytes));
3591 }
3592 
3593 int
3594 ddi_prop_modify(dev_t dev, dev_info_t *dip, int flag,
3595     char *name, caddr_t value, int length)
3596 {
3597 	ASSERT((flag & DDI_PROP_TYPE_MASK) == 0);
3598 
3599 	/*
3600 	 * If dev_t is DDI_DEV_T_ANY or name's length is zero,
3601 	 * return error.
3602 	 */
3603 	if (dev == DDI_DEV_T_ANY || name == NULL || strlen(name) == 0)
3604 		return (DDI_PROP_INVAL_ARG);
3605 
3606 	if (!(flag & DDI_PROP_CANSLEEP))
3607 		flag |= DDI_PROP_DONTSLEEP;
3608 	flag &= ~DDI_PROP_SYSTEM_DEF;
3609 	if (ddi_prop_exists(dev, dip, (flag | DDI_PROP_NOTPROM), name) == 0)
3610 		return (DDI_PROP_NOT_FOUND);
3611 
3612 	return (ddi_prop_update_common(dev, dip,
3613 	    (flag | DDI_PROP_TYPE_BYTE), name,
3614 	    value, length, ddi_prop_fm_encode_bytes));
3615 }
3616 
3617 int
3618 e_ddi_prop_modify(dev_t dev, dev_info_t *dip, int flag,
3619     char *name, caddr_t value, int length)
3620 {
3621 	ASSERT((flag & DDI_PROP_TYPE_MASK) == 0);
3622 
3623 	/*
3624 	 * If dev_t is DDI_DEV_T_ANY or name's length is zero,
3625 	 * return error.
3626 	 */
3627 	if (dev == DDI_DEV_T_ANY || name == NULL || strlen(name) == 0)
3628 		return (DDI_PROP_INVAL_ARG);
3629 
3630 	if (ddi_prop_exists(dev, dip, (flag | DDI_PROP_SYSTEM_DEF), name) == 0)
3631 		return (DDI_PROP_NOT_FOUND);
3632 
3633 	if (!(flag & DDI_PROP_CANSLEEP))
3634 		flag |= DDI_PROP_DONTSLEEP;
3635 	return (ddi_prop_update_common(dev, dip,
3636 	    (flag | DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_BYTE),
3637 	    name, value, length, ddi_prop_fm_encode_bytes));
3638 }
3639 
3640 
3641 /*
3642  * Common lookup routine used to lookup and decode a property.
3643  * Creates a property handle, searches for the raw encoded data,
3644  * fills in the handle, and calls the property decode functions
3645  * passed in.
3646  *
3647  * This routine is not static because ddi_bus_prop_op() which lives in
3648  * ddi_impl.c calls it.  No driver should be calling this routine.
3649  */
3650 int
3651 ddi_prop_lookup_common(dev_t match_dev, dev_info_t *dip,
3652     uint_t flags, char *name, void *data, uint_t *nelements,
3653     int (*prop_decoder)(prop_handle_t *, void *data, uint_t *nelements))
3654 {
3655 	int		rval;
3656 	uint_t		ourflags;
3657 	prop_handle_t	ph;
3658 
3659 	if ((match_dev == DDI_DEV_T_NONE) ||
3660 	    (name == NULL) || (strlen(name) == 0))
3661 		return (DDI_PROP_INVAL_ARG);
3662 
3663 	ourflags = (flags & DDI_PROP_DONTSLEEP) ? flags :
3664 	    flags | DDI_PROP_CANSLEEP;
3665 
3666 	/*
3667 	 * Get the encoded data
3668 	 */
3669 	bzero(&ph, sizeof (prop_handle_t));
3670 
3671 	if ((flags & DDI_UNBND_DLPI2) || (flags & DDI_PROP_ROOTNEX_GLOBAL)) {
3672 		/*
3673 		 * For rootnex and unbound dlpi style-2 devices, index into
3674 		 * the devnames' array and search the global
3675 		 * property list.
3676 		 */
3677 		ourflags &= ~DDI_UNBND_DLPI2;
3678 		rval = i_ddi_prop_search_global(match_dev,
3679 		    ourflags, name, &ph.ph_data, &ph.ph_size);
3680 	} else {
3681 		rval = ddi_prop_search_common(match_dev, dip,
3682 		    PROP_LEN_AND_VAL_ALLOC, ourflags, name,
3683 		    &ph.ph_data, &ph.ph_size);
3684 
3685 	}
3686 
3687 	if (rval != DDI_PROP_SUCCESS && rval != DDI_PROP_FOUND_1275) {
3688 		ASSERT(ph.ph_data == NULL);
3689 		ASSERT(ph.ph_size == 0);
3690 		return (rval);
3691 	}
3692 
3693 	/*
3694 	 * If the encoded data came from a OBP or software
3695 	 * use the 1275 OBP decode/encode routines.
3696 	 */
3697 	ph.ph_cur_pos = ph.ph_data;
3698 	ph.ph_save_pos = ph.ph_data;
3699 	ph.ph_ops = &prop_1275_ops;
3700 	ph.ph_flags = (rval == DDI_PROP_FOUND_1275) ? PH_FROM_PROM : 0;
3701 
3702 	rval = (*prop_decoder)(&ph, data, nelements);
3703 
3704 	/*
3705 	 * Free the encoded data
3706 	 */
3707 	if (ph.ph_size != 0)
3708 		kmem_free(ph.ph_data, ph.ph_size);
3709 
3710 	return (rval);
3711 }
3712 
3713 /*
3714  * Lookup and return an array of composite properties.  The driver must
3715  * provide the decode routine.
3716  */
3717 int
3718 ddi_prop_lookup(dev_t match_dev, dev_info_t *dip,
3719     uint_t flags, char *name, void *data, uint_t *nelements,
3720     int (*prop_decoder)(prop_handle_t *, void *data, uint_t *nelements))
3721 {
3722 	return (ddi_prop_lookup_common(match_dev, dip,
3723 	    (flags | DDI_PROP_TYPE_COMPOSITE), name,
3724 	    data, nelements, prop_decoder));
3725 }
3726 
3727 /*
3728  * Return 1 if a property exists (no type checking done).
3729  * Return 0 if it does not exist.
3730  */
3731 int
3732 ddi_prop_exists(dev_t match_dev, dev_info_t *dip, uint_t flags, char *name)
3733 {
3734 	int	i;
3735 	uint_t	x = 0;
3736 
3737 	i = ddi_prop_search_common(match_dev, dip, PROP_EXISTS,
3738 	    flags | DDI_PROP_TYPE_MASK, name, NULL, &x);
3739 	return (i == DDI_PROP_SUCCESS || i == DDI_PROP_FOUND_1275);
3740 }
3741 
3742 
3743 /*
3744  * Update an array of composite properties.  The driver must
3745  * provide the encode routine.
3746  */
3747 int
3748 ddi_prop_update(dev_t match_dev, dev_info_t *dip,
3749     char *name, void *data, uint_t nelements,
3750     int (*prop_create)(prop_handle_t *, void *data, uint_t nelements))
3751 {
3752 	return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_COMPOSITE,
3753 	    name, data, nelements, prop_create));
3754 }
3755 
3756 /*
3757  * Get a single integer or boolean property and return it.
3758  * If the property does not exists, or cannot be decoded,
3759  * then return the defvalue passed in.
3760  *
3761  * This routine always succeeds.
3762  */
3763 int
3764 ddi_prop_get_int(dev_t match_dev, dev_info_t *dip, uint_t flags,
3765     char *name, int defvalue)
3766 {
3767 	int	data;
3768 	uint_t	nelements;
3769 	int	rval;
3770 
3771 	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3772 	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
3773 #ifdef DEBUG
3774 		if (dip != NULL) {
3775 			cmn_err(CE_WARN, "ddi_prop_get_int: invalid flag"
3776 			    " 0x%x (prop = %s, node = %s%d)", flags,
3777 			    name, ddi_driver_name(dip), ddi_get_instance(dip));
3778 		}
3779 #endif /* DEBUG */
3780 		flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3781 		    LDI_DEV_T_ANY | DDI_UNBND_DLPI2;
3782 	}
3783 
3784 	if ((rval = ddi_prop_lookup_common(match_dev, dip,
3785 	    (flags | DDI_PROP_TYPE_INT), name, &data, &nelements,
3786 	    ddi_prop_fm_decode_int)) != DDI_PROP_SUCCESS) {
3787 		if (rval == DDI_PROP_END_OF_DATA)
3788 			data = 1;
3789 		else
3790 			data = defvalue;
3791 	}
3792 	return (data);
3793 }
3794 
3795 /*
3796  * Get a single 64 bit integer or boolean property and return it.
3797  * If the property does not exists, or cannot be decoded,
3798  * then return the defvalue passed in.
3799  *
3800  * This routine always succeeds.
3801  */
3802 int64_t
3803 ddi_prop_get_int64(dev_t match_dev, dev_info_t *dip, uint_t flags,
3804     char *name, int64_t defvalue)
3805 {
3806 	int64_t	data;
3807 	uint_t	nelements;
3808 	int	rval;
3809 
3810 	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3811 	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
3812 #ifdef DEBUG
3813 		if (dip != NULL) {
3814 			cmn_err(CE_WARN, "ddi_prop_get_int64: invalid flag"
3815 			    " 0x%x (prop = %s, node = %s%d)", flags,
3816 			    name, ddi_driver_name(dip), ddi_get_instance(dip));
3817 		}
3818 #endif /* DEBUG */
3819 		return (DDI_PROP_INVAL_ARG);
3820 	}
3821 
3822 	if ((rval = ddi_prop_lookup_common(match_dev, dip,
3823 	    (flags | DDI_PROP_TYPE_INT64 | DDI_PROP_NOTPROM),
3824 	    name, &data, &nelements, ddi_prop_fm_decode_int64))
3825 	    != DDI_PROP_SUCCESS) {
3826 		if (rval == DDI_PROP_END_OF_DATA)
3827 			data = 1;
3828 		else
3829 			data = defvalue;
3830 	}
3831 	return (data);
3832 }
3833 
3834 /*
3835  * Get an array of integer property
3836  */
3837 int
3838 ddi_prop_lookup_int_array(dev_t match_dev, dev_info_t *dip, uint_t flags,
3839     char *name, int **data, uint_t *nelements)
3840 {
3841 	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3842 	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
3843 #ifdef DEBUG
3844 		if (dip != NULL) {
3845 			cmn_err(CE_WARN, "ddi_prop_lookup_int_array: "
3846 			    "invalid flag 0x%x (prop = %s, node = %s%d)",
3847 			    flags, name, ddi_driver_name(dip),
3848 			    ddi_get_instance(dip));
3849 		}
3850 #endif /* DEBUG */
3851 		flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3852 		    LDI_DEV_T_ANY | DDI_UNBND_DLPI2;
3853 	}
3854 
3855 	return (ddi_prop_lookup_common(match_dev, dip,
3856 	    (flags | DDI_PROP_TYPE_INT), name, data,
3857 	    nelements, ddi_prop_fm_decode_ints));
3858 }
3859 
3860 /*
3861  * Get an array of 64 bit integer properties
3862  */
3863 int
3864 ddi_prop_lookup_int64_array(dev_t match_dev, dev_info_t *dip, uint_t flags,
3865     char *name, int64_t **data, uint_t *nelements)
3866 {
3867 	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3868 	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
3869 #ifdef DEBUG
3870 		if (dip != NULL) {
3871 			cmn_err(CE_WARN, "ddi_prop_lookup_int64_array: "
3872 			    "invalid flag 0x%x (prop = %s, node = %s%d)",
3873 			    flags, name, ddi_driver_name(dip),
3874 			    ddi_get_instance(dip));
3875 		}
3876 #endif /* DEBUG */
3877 		return (DDI_PROP_INVAL_ARG);
3878 	}
3879 
3880 	return (ddi_prop_lookup_common(match_dev, dip,
3881 	    (flags | DDI_PROP_TYPE_INT64 | DDI_PROP_NOTPROM),
3882 	    name, data, nelements, ddi_prop_fm_decode_int64_array));
3883 }
3884 
3885 /*
3886  * Update a single integer property.  If the property exists on the drivers
3887  * property list it updates, else it creates it.
3888  */
3889 int
3890 ddi_prop_update_int(dev_t match_dev, dev_info_t *dip,
3891     char *name, int data)
3892 {
3893 	return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_INT,
3894 	    name, &data, 1, ddi_prop_fm_encode_ints));
3895 }
3896 
3897 /*
3898  * Update a single 64 bit integer property.
3899  * Update the driver property list if it exists, else create it.
3900  */
3901 int
3902 ddi_prop_update_int64(dev_t match_dev, dev_info_t *dip,
3903     char *name, int64_t data)
3904 {
3905 	return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_INT64,
3906 	    name, &data, 1, ddi_prop_fm_encode_int64));
3907 }
3908 
3909 int
3910 e_ddi_prop_update_int(dev_t match_dev, dev_info_t *dip,
3911     char *name, int data)
3912 {
3913 	return (ddi_prop_update_common(match_dev, dip,
3914 	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_INT,
3915 	    name, &data, 1, ddi_prop_fm_encode_ints));
3916 }
3917 
3918 int
3919 e_ddi_prop_update_int64(dev_t match_dev, dev_info_t *dip,
3920     char *name, int64_t data)
3921 {
3922 	return (ddi_prop_update_common(match_dev, dip,
3923 	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_INT64,
3924 	    name, &data, 1, ddi_prop_fm_encode_int64));
3925 }
3926 
3927 /*
3928  * Update an array of integer property.  If the property exists on the drivers
3929  * property list it updates, else it creates it.
3930  */
3931 int
3932 ddi_prop_update_int_array(dev_t match_dev, dev_info_t *dip,
3933     char *name, int *data, uint_t nelements)
3934 {
3935 	return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_INT,
3936 	    name, data, nelements, ddi_prop_fm_encode_ints));
3937 }
3938 
3939 /*
3940  * Update an array of 64 bit integer properties.
3941  * Update the driver property list if it exists, else create it.
3942  */
3943 int
3944 ddi_prop_update_int64_array(dev_t match_dev, dev_info_t *dip,
3945     char *name, int64_t *data, uint_t nelements)
3946 {
3947 	return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_INT64,
3948 	    name, data, nelements, ddi_prop_fm_encode_int64));
3949 }
3950 
3951 int
3952 e_ddi_prop_update_int64_array(dev_t match_dev, dev_info_t *dip,
3953     char *name, int64_t *data, uint_t nelements)
3954 {
3955 	return (ddi_prop_update_common(match_dev, dip,
3956 	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_INT64,
3957 	    name, data, nelements, ddi_prop_fm_encode_int64));
3958 }
3959 
3960 int
3961 e_ddi_prop_update_int_array(dev_t match_dev, dev_info_t *dip,
3962     char *name, int *data, uint_t nelements)
3963 {
3964 	return (ddi_prop_update_common(match_dev, dip,
3965 	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_INT,
3966 	    name, data, nelements, ddi_prop_fm_encode_ints));
3967 }
3968 
3969 /*
3970  * Get a single string property.
3971  */
3972 int
3973 ddi_prop_lookup_string(dev_t match_dev, dev_info_t *dip, uint_t flags,
3974     char *name, char **data)
3975 {
3976 	uint_t x;
3977 
3978 	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3979 	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
3980 #ifdef DEBUG
3981 		if (dip != NULL) {
3982 			cmn_err(CE_WARN, "%s: invalid flag 0x%x "
3983 			    "(prop = %s, node = %s%d); invalid bits ignored",
3984 			    "ddi_prop_lookup_string", flags, name,
3985 			    ddi_driver_name(dip), ddi_get_instance(dip));
3986 		}
3987 #endif /* DEBUG */
3988 		flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3989 		    LDI_DEV_T_ANY | DDI_UNBND_DLPI2;
3990 	}
3991 
3992 	return (ddi_prop_lookup_common(match_dev, dip,
3993 	    (flags | DDI_PROP_TYPE_STRING), name, data,
3994 	    &x, ddi_prop_fm_decode_string));
3995 }
3996 
3997 /*
3998  * Get an array of strings property.
3999  */
4000 int
4001 ddi_prop_lookup_string_array(dev_t match_dev, dev_info_t *dip, uint_t flags,
4002     char *name, char ***data, uint_t *nelements)
4003 {
4004 	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
4005 	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
4006 #ifdef DEBUG
4007 		if (dip != NULL) {
4008 			cmn_err(CE_WARN, "ddi_prop_lookup_string_array: "
4009 			    "invalid flag 0x%x (prop = %s, node = %s%d)",
4010 			    flags, name, ddi_driver_name(dip),
4011 			    ddi_get_instance(dip));
4012 		}
4013 #endif /* DEBUG */
4014 		flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
4015 		    LDI_DEV_T_ANY | DDI_UNBND_DLPI2;
4016 	}
4017 
4018 	return (ddi_prop_lookup_common(match_dev, dip,
4019 	    (flags | DDI_PROP_TYPE_STRING), name, data,
4020 	    nelements, ddi_prop_fm_decode_strings));
4021 }
4022 
4023 /*
4024  * Update a single string property.
4025  */
4026 int
4027 ddi_prop_update_string(dev_t match_dev, dev_info_t *dip,
4028     char *name, char *data)
4029 {
4030 	return (ddi_prop_update_common(match_dev, dip,
4031 	    DDI_PROP_TYPE_STRING, name, &data, 1,
4032 	    ddi_prop_fm_encode_string));
4033 }
4034 
4035 int
4036 e_ddi_prop_update_string(dev_t match_dev, dev_info_t *dip,
4037     char *name, char *data)
4038 {
4039 	return (ddi_prop_update_common(match_dev, dip,
4040 	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_STRING,
4041 	    name, &data, 1, ddi_prop_fm_encode_string));
4042 }
4043 
4044 
4045 /*
4046  * Update an array of strings property.
4047  */
4048 int
4049 ddi_prop_update_string_array(dev_t match_dev, dev_info_t *dip,
4050     char *name, char **data, uint_t nelements)
4051 {
4052 	return (ddi_prop_update_common(match_dev, dip,
4053 	    DDI_PROP_TYPE_STRING, name, data, nelements,
4054 	    ddi_prop_fm_encode_strings));
4055 }
4056 
4057 int
4058 e_ddi_prop_update_string_array(dev_t match_dev, dev_info_t *dip,
4059     char *name, char **data, uint_t nelements)
4060 {
4061 	return (ddi_prop_update_common(match_dev, dip,
4062 	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_STRING,
4063 	    name, data, nelements,
4064 	    ddi_prop_fm_encode_strings));
4065 }
4066 
4067 
4068 /*
4069  * Get an array of bytes property.
4070  */
4071 int
4072 ddi_prop_lookup_byte_array(dev_t match_dev, dev_info_t *dip, uint_t flags,
4073     char *name, uchar_t **data, uint_t *nelements)
4074 {
4075 	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
4076 	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
4077 #ifdef DEBUG
4078 		if (dip != NULL) {
4079 			cmn_err(CE_WARN, "ddi_prop_lookup_byte_array: "
4080 			    " invalid flag 0x%x (prop = %s, node = %s%d)",
4081 			    flags, name, ddi_driver_name(dip),
4082 			    ddi_get_instance(dip));
4083 		}
4084 #endif /* DEBUG */
4085 		flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
4086 		    LDI_DEV_T_ANY | DDI_UNBND_DLPI2;
4087 	}
4088 
4089 	return (ddi_prop_lookup_common(match_dev, dip,
4090 	    (flags | DDI_PROP_TYPE_BYTE), name, data,
4091 	    nelements, ddi_prop_fm_decode_bytes));
4092 }
4093 
4094 /*
4095  * Update an array of bytes property.
4096  */
4097 int
4098 ddi_prop_update_byte_array(dev_t match_dev, dev_info_t *dip,
4099     char *name, uchar_t *data, uint_t nelements)
4100 {
4101 	if (nelements == 0)
4102 		return (DDI_PROP_INVAL_ARG);
4103 
4104 	return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_BYTE,
4105 	    name, data, nelements, ddi_prop_fm_encode_bytes));
4106 }
4107 
4108 
4109 int
4110 e_ddi_prop_update_byte_array(dev_t match_dev, dev_info_t *dip,
4111     char *name, uchar_t *data, uint_t nelements)
4112 {
4113 	if (nelements == 0)
4114 		return (DDI_PROP_INVAL_ARG);
4115 
4116 	return (ddi_prop_update_common(match_dev, dip,
4117 	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_BYTE,
4118 	    name, data, nelements, ddi_prop_fm_encode_bytes));
4119 }
4120 
4121 
4122 /*
4123  * ddi_prop_remove_common:	Undefine a managed property:
4124  *			Input dev_t must match dev_t when defined.
4125  *			Returns DDI_PROP_NOT_FOUND, possibly.
4126  *			DDI_PROP_INVAL_ARG is also possible if dev is
4127  *			DDI_DEV_T_ANY or incoming name is the NULL string.
4128  */
4129 int
4130 ddi_prop_remove_common(dev_t dev, dev_info_t *dip, char *name, int flag)
4131 {
4132 	ddi_prop_t	**list_head = &(DEVI(dip)->devi_drv_prop_ptr);
4133 	ddi_prop_t	*propp;
4134 	ddi_prop_t	*lastpropp = NULL;
4135 
4136 	if ((dev == DDI_DEV_T_ANY) || (name == (char *)0) ||
4137 	    (strlen(name) == 0)) {
4138 		return (DDI_PROP_INVAL_ARG);
4139 	}
4140 
4141 	if (flag & DDI_PROP_SYSTEM_DEF)
4142 		list_head = &(DEVI(dip)->devi_sys_prop_ptr);
4143 	else if (flag & DDI_PROP_HW_DEF)
4144 		list_head = &(DEVI(dip)->devi_hw_prop_ptr);
4145 
4146 	mutex_enter(&(DEVI(dip)->devi_lock));
4147 
4148 	for (propp = *list_head; propp != NULL; propp = propp->prop_next)  {
4149 		if (DDI_STRSAME(propp->prop_name, name) &&
4150 		    (dev == propp->prop_dev)) {
4151 			/*
4152 			 * Unlink this propp allowing for it to
4153 			 * be first in the list:
4154 			 */
4155 
4156 			if (lastpropp == NULL)
4157 				*list_head = propp->prop_next;
4158 			else
4159 				lastpropp->prop_next = propp->prop_next;
4160 
4161 			mutex_exit(&(DEVI(dip)->devi_lock));
4162 
4163 			/*
4164 			 * Free memory and return...
4165 			 */
4166 			kmem_free(propp->prop_name,
4167 			    strlen(propp->prop_name) + 1);
4168 			if (propp->prop_len != 0)
4169 				kmem_free(propp->prop_val, propp->prop_len);
4170 			kmem_free(propp, sizeof (ddi_prop_t));
4171 			return (DDI_PROP_SUCCESS);
4172 		}
4173 		lastpropp = propp;
4174 	}
4175 	mutex_exit(&(DEVI(dip)->devi_lock));
4176 	return (DDI_PROP_NOT_FOUND);
4177 }
4178 
4179 int
4180 ddi_prop_remove(dev_t dev, dev_info_t *dip, char *name)
4181 {
4182 	return (ddi_prop_remove_common(dev, dip, name, 0));
4183 }
4184 
4185 int
4186 e_ddi_prop_remove(dev_t dev, dev_info_t *dip, char *name)
4187 {
4188 	return (ddi_prop_remove_common(dev, dip, name, DDI_PROP_SYSTEM_DEF));
4189 }
4190 
4191 /*
4192  * e_ddi_prop_list_delete: remove a list of properties
4193  *	Note that the caller needs to provide the required protection
4194  *	(eg. devi_lock if these properties are still attached to a devi)
4195  */
4196 void
4197 e_ddi_prop_list_delete(ddi_prop_t *props)
4198 {
4199 	i_ddi_prop_list_delete(props);
4200 }
4201 
4202 /*
4203  * ddi_prop_remove_all_common:
4204  *	Used before unloading a driver to remove
4205  *	all properties. (undefines all dev_t's props.)
4206  *	Also removes `explicitly undefined' props.
4207  *	No errors possible.
4208  */
4209 void
4210 ddi_prop_remove_all_common(dev_info_t *dip, int flag)
4211 {
4212 	ddi_prop_t	**list_head;
4213 
4214 	mutex_enter(&(DEVI(dip)->devi_lock));
4215 	if (flag & DDI_PROP_SYSTEM_DEF) {
4216 		list_head = &(DEVI(dip)->devi_sys_prop_ptr);
4217 	} else if (flag & DDI_PROP_HW_DEF) {
4218 		list_head = &(DEVI(dip)->devi_hw_prop_ptr);
4219 	} else {
4220 		list_head = &(DEVI(dip)->devi_drv_prop_ptr);
4221 	}
4222 	i_ddi_prop_list_delete(*list_head);
4223 	*list_head = NULL;
4224 	mutex_exit(&(DEVI(dip)->devi_lock));
4225 }
4226 
4227 
4228 /*
4229  * ddi_prop_remove_all:		Remove all driver prop definitions.
4230  */
4231 
4232 void
4233 ddi_prop_remove_all(dev_info_t *dip)
4234 {
4235 	i_ddi_prop_dyn_driver_set(dip, NULL);
4236 	ddi_prop_remove_all_common(dip, 0);
4237 }
4238 
4239 /*
4240  * e_ddi_prop_remove_all:	Remove all system prop definitions.
4241  */
4242 
4243 void
4244 e_ddi_prop_remove_all(dev_info_t *dip)
4245 {
4246 	ddi_prop_remove_all_common(dip, (int)DDI_PROP_SYSTEM_DEF);
4247 }
4248 
4249 
4250 /*
4251  * ddi_prop_undefine:	Explicitly undefine a property.  Property
4252  *			searches which match this property return
4253  *			the error code DDI_PROP_UNDEFINED.
4254  *
4255  *			Use ddi_prop_remove to negate effect of
4256  *			ddi_prop_undefine
4257  *
4258  *			See above for error returns.
4259  */
4260 
4261 int
4262 ddi_prop_undefine(dev_t dev, dev_info_t *dip, int flag, char *name)
4263 {
4264 	if (!(flag & DDI_PROP_CANSLEEP))
4265 		flag |= DDI_PROP_DONTSLEEP;
4266 	flag |= DDI_PROP_STACK_CREATE | DDI_PROP_UNDEF_IT | DDI_PROP_TYPE_ANY;
4267 	return (ddi_prop_update_common(dev, dip, flag,
4268 	    name, NULL, 0, ddi_prop_fm_encode_bytes));
4269 }
4270 
4271 int
4272 e_ddi_prop_undefine(dev_t dev, dev_info_t *dip, int flag, char *name)
4273 {
4274 	if (!(flag & DDI_PROP_CANSLEEP))
4275 		flag |= DDI_PROP_DONTSLEEP;
4276 	flag |= DDI_PROP_SYSTEM_DEF | DDI_PROP_STACK_CREATE |
4277 	    DDI_PROP_UNDEF_IT | DDI_PROP_TYPE_ANY;
4278 	return (ddi_prop_update_common(dev, dip, flag,
4279 	    name, NULL, 0, ddi_prop_fm_encode_bytes));
4280 }
4281 
4282 /*
4283  * Support for gathering dynamic properties in devinfo snapshot.
4284  */
4285 void
4286 i_ddi_prop_dyn_driver_set(dev_info_t *dip, i_ddi_prop_dyn_t *dp)
4287 {
4288 	DEVI(dip)->devi_prop_dyn_driver = dp;
4289 }
4290 
4291 i_ddi_prop_dyn_t *
4292 i_ddi_prop_dyn_driver_get(dev_info_t *dip)
4293 {
4294 	return (DEVI(dip)->devi_prop_dyn_driver);
4295 }
4296 
4297 void
4298 i_ddi_prop_dyn_parent_set(dev_info_t *dip, i_ddi_prop_dyn_t *dp)
4299 {
4300 	DEVI(dip)->devi_prop_dyn_parent = dp;
4301 }
4302 
4303 i_ddi_prop_dyn_t *
4304 i_ddi_prop_dyn_parent_get(dev_info_t *dip)
4305 {
4306 	return (DEVI(dip)->devi_prop_dyn_parent);
4307 }
4308 
4309 void
4310 i_ddi_prop_dyn_cache_invalidate(dev_info_t *dip, i_ddi_prop_dyn_t *dp)
4311 {
4312 	/* for now we invalidate the entire cached snapshot */
4313 	if (dip && dp)
4314 		i_ddi_di_cache_invalidate();
4315 }
4316 
4317 /* ARGSUSED */
4318 void
4319 ddi_prop_cache_invalidate(dev_t dev, dev_info_t *dip, char *name, int flags)
4320 {
4321 	/* for now we invalidate the entire cached snapshot */
4322 	i_ddi_di_cache_invalidate();
4323 }
4324 
4325 
4326 /*
4327  * Code to search hardware layer (PROM), if it exists, on behalf of child.
4328  *
4329  * if input dip != child_dip, then call is on behalf of child
4330  * to search PROM, do it via ddi_prop_search_common() and ascend only
4331  * if allowed.
4332  *
4333  * if input dip == ch_dip (child_dip), call is on behalf of root driver,
4334  * to search for PROM defined props only.
4335  *
4336  * Note that the PROM search is done only if the requested dev
4337  * is either DDI_DEV_T_ANY or DDI_DEV_T_NONE. PROM properties
4338  * have no associated dev, thus are automatically associated with
4339  * DDI_DEV_T_NONE.
4340  *
4341  * Modifying flag DDI_PROP_NOTPROM inhibits the search in the h/w layer.
4342  *
4343  * Returns DDI_PROP_FOUND_1275 if found to indicate to framework
4344  * that the property resides in the prom.
4345  */
4346 int
4347 impl_ddi_bus_prop_op(dev_t dev, dev_info_t *dip, dev_info_t *ch_dip,
4348     ddi_prop_op_t prop_op, int mod_flags,
4349     char *name, caddr_t valuep, int *lengthp)
4350 {
4351 	int	len;
4352 	caddr_t buffer;
4353 
4354 	/*
4355 	 * If requested dev is DDI_DEV_T_NONE or DDI_DEV_T_ANY, then
4356 	 * look in caller's PROM if it's a self identifying device...
4357 	 *
4358 	 * Note that this is very similar to ddi_prop_op, but we
4359 	 * search the PROM instead of the s/w defined properties,
4360 	 * and we are called on by the parent driver to do this for
4361 	 * the child.
4362 	 */
4363 
4364 	if (((dev == DDI_DEV_T_NONE) || (dev == DDI_DEV_T_ANY)) &&
4365 	    ndi_dev_is_prom_node(ch_dip) &&
4366 	    ((mod_flags & DDI_PROP_NOTPROM) == 0)) {
4367 		len = prom_getproplen((pnode_t)DEVI(ch_dip)->devi_nodeid, name);
4368 		if (len == -1) {
4369 			return (DDI_PROP_NOT_FOUND);
4370 		}
4371 
4372 		/*
4373 		 * If exists only request, we're done
4374 		 */
4375 		if (prop_op == PROP_EXISTS) {
4376 			return (DDI_PROP_FOUND_1275);
4377 		}
4378 
4379 		/*
4380 		 * If length only request or prop length == 0, get out
4381 		 */
4382 		if ((prop_op == PROP_LEN) || (len == 0)) {
4383 			*lengthp = len;
4384 			return (DDI_PROP_FOUND_1275);
4385 		}
4386 
4387 		/*
4388 		 * Allocate buffer if required... (either way `buffer'
4389 		 * is receiving address).
4390 		 */
4391 
4392 		switch (prop_op) {
4393 
4394 		case PROP_LEN_AND_VAL_ALLOC:
4395 
4396 			buffer = kmem_alloc((size_t)len,
4397 			    mod_flags & DDI_PROP_CANSLEEP ?
4398 			    KM_SLEEP : KM_NOSLEEP);
4399 			if (buffer == NULL) {
4400 				return (DDI_PROP_NO_MEMORY);
4401 			}
4402 			*(caddr_t *)valuep = buffer;
4403 			break;
4404 
4405 		case PROP_LEN_AND_VAL_BUF:
4406 
4407 			if (len > (*lengthp)) {
4408 				*lengthp = len;
4409 				return (DDI_PROP_BUF_TOO_SMALL);
4410 			}
4411 
4412 			buffer = valuep;
4413 			break;
4414 
4415 		default:
4416 			break;
4417 		}
4418 
4419 		/*
4420 		 * Call the PROM function to do the copy.
4421 		 */
4422 		(void) prom_getprop((pnode_t)DEVI(ch_dip)->devi_nodeid,
4423 		    name, buffer);
4424 
4425 		*lengthp = len; /* return the actual length to the caller */
4426 		(void) impl_fix_props(dip, ch_dip, name, len, buffer);
4427 		return (DDI_PROP_FOUND_1275);
4428 	}
4429 
4430 	return (DDI_PROP_NOT_FOUND);
4431 }
4432 
4433 /*
4434  * The ddi_bus_prop_op default bus nexus prop op function.
4435  *
4436  * Code to search hardware layer (PROM), if it exists,
4437  * on behalf of child, then, if appropriate, ascend and check
4438  * my own software defined properties...
4439  */
4440 int
4441 ddi_bus_prop_op(dev_t dev, dev_info_t *dip, dev_info_t *ch_dip,
4442     ddi_prop_op_t prop_op, int mod_flags,
4443     char *name, caddr_t valuep, int *lengthp)
4444 {
4445 	int	error;
4446 
4447 	error = impl_ddi_bus_prop_op(dev, dip, ch_dip, prop_op, mod_flags,
4448 	    name, valuep, lengthp);
4449 
4450 	if (error == DDI_PROP_SUCCESS || error == DDI_PROP_FOUND_1275 ||
4451 	    error == DDI_PROP_BUF_TOO_SMALL)
4452 		return (error);
4453 
4454 	if (error == DDI_PROP_NO_MEMORY) {
4455 		cmn_err(CE_CONT, prop_no_mem_msg, name);
4456 		return (DDI_PROP_NO_MEMORY);
4457 	}
4458 
4459 	/*
4460 	 * Check the 'options' node as a last resort
4461 	 */
4462 	if ((mod_flags & DDI_PROP_DONTPASS) != 0)
4463 		return (DDI_PROP_NOT_FOUND);
4464 
4465 	if (ch_dip == ddi_root_node())	{
4466 		/*
4467 		 * As a last resort, when we've reached
4468 		 * the top and still haven't found the
4469 		 * property, see if the desired property
4470 		 * is attached to the options node.
4471 		 *
4472 		 * The options dip is attached right after boot.
4473 		 */
4474 		ASSERT(options_dip != NULL);
4475 		/*
4476 		 * Force the "don't pass" flag to *just* see
4477 		 * what the options node has to offer.
4478 		 */
4479 		return (ddi_prop_search_common(dev, options_dip, prop_op,
4480 		    mod_flags|DDI_PROP_DONTPASS, name, valuep,
4481 		    (uint_t *)lengthp));
4482 	}
4483 
4484 	/*
4485 	 * Otherwise, continue search with parent's s/w defined properties...
4486 	 * NOTE: Using `dip' in following call increments the level.
4487 	 */
4488 
4489 	return (ddi_prop_search_common(dev, dip, prop_op, mod_flags,
4490 	    name, valuep, (uint_t *)lengthp));
4491 }
4492 
4493 /*
4494  * External property functions used by other parts of the kernel...
4495  */
4496 
4497 /*
4498  * e_ddi_getlongprop: See comments for ddi_get_longprop.
4499  */
4500 
4501 int
4502 e_ddi_getlongprop(dev_t dev, vtype_t type, char *name, int flags,
4503     caddr_t valuep, int *lengthp)
4504 {
4505 	_NOTE(ARGUNUSED(type))
4506 	dev_info_t *devi;
4507 	ddi_prop_op_t prop_op = PROP_LEN_AND_VAL_ALLOC;
4508 	int error;
4509 
4510 	if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL)
4511 		return (DDI_PROP_NOT_FOUND);
4512 
4513 	error = cdev_prop_op(dev, devi, prop_op, flags, name, valuep, lengthp);
4514 	ddi_release_devi(devi);
4515 	return (error);
4516 }
4517 
4518 /*
4519  * e_ddi_getlongprop_buf:	See comments for ddi_getlongprop_buf.
4520  */
4521 
4522 int
4523 e_ddi_getlongprop_buf(dev_t dev, vtype_t type, char *name, int flags,
4524     caddr_t valuep, int *lengthp)
4525 {
4526 	_NOTE(ARGUNUSED(type))
4527 	dev_info_t *devi;
4528 	ddi_prop_op_t prop_op = PROP_LEN_AND_VAL_BUF;
4529 	int error;
4530 
4531 	if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL)
4532 		return (DDI_PROP_NOT_FOUND);
4533 
4534 	error = cdev_prop_op(dev, devi, prop_op, flags, name, valuep, lengthp);
4535 	ddi_release_devi(devi);
4536 	return (error);
4537 }
4538 
4539 /*
4540  * e_ddi_getprop:	See comments for ddi_getprop.
4541  */
4542 int
4543 e_ddi_getprop(dev_t dev, vtype_t type, char *name, int flags, int defvalue)
4544 {
4545 	_NOTE(ARGUNUSED(type))
4546 	dev_info_t *devi;
4547 	ddi_prop_op_t prop_op = PROP_LEN_AND_VAL_BUF;
4548 	int	propvalue = defvalue;
4549 	int	proplength = sizeof (int);
4550 	int	error;
4551 
4552 	if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL)
4553 		return (defvalue);
4554 
4555 	error = cdev_prop_op(dev, devi, prop_op,
4556 	    flags, name, (caddr_t)&propvalue, &proplength);
4557 	ddi_release_devi(devi);
4558 
4559 	if ((error == DDI_PROP_SUCCESS) && (proplength == 0))
4560 		propvalue = 1;
4561 
4562 	return (propvalue);
4563 }
4564 
4565 /*
4566  * e_ddi_getprop_int64:
4567  *
4568  * This is a typed interfaces, but predates typed properties. With the
4569  * introduction of typed properties the framework tries to ensure
4570  * consistent use of typed interfaces. This is why TYPE_INT64 is not
4571  * part of TYPE_ANY.  E_ddi_getprop_int64 is a special case where a
4572  * typed interface invokes legacy (non-typed) interfaces:
4573  * cdev_prop_op(), prop_op(9E), ddi_prop_op(9F)).  In this case the
4574  * fact that TYPE_INT64 is not part of TYPE_ANY matters.  To support
4575  * this type of lookup as a single operation we invoke the legacy
4576  * non-typed interfaces with the special CONSUMER_TYPED bit set. The
4577  * framework ddi_prop_op(9F) implementation is expected to check for
4578  * CONSUMER_TYPED and, if set, expand type bits beyond TYPE_ANY
4579  * (currently TYPE_INT64).
4580  */
4581 int64_t
4582 e_ddi_getprop_int64(dev_t dev, vtype_t type, char *name,
4583     int flags, int64_t defvalue)
4584 {
4585 	_NOTE(ARGUNUSED(type))
4586 	dev_info_t	*devi;
4587 	ddi_prop_op_t	prop_op = PROP_LEN_AND_VAL_BUF;
4588 	int64_t		propvalue = defvalue;
4589 	int		proplength = sizeof (propvalue);
4590 	int		error;
4591 
4592 	if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL)
4593 		return (defvalue);
4594 
4595 	error = cdev_prop_op(dev, devi, prop_op, flags |
4596 	    DDI_PROP_CONSUMER_TYPED, name, (caddr_t)&propvalue, &proplength);
4597 	ddi_release_devi(devi);
4598 
4599 	if ((error == DDI_PROP_SUCCESS) && (proplength == 0))
4600 		propvalue = 1;
4601 
4602 	return (propvalue);
4603 }
4604 
4605 /*
4606  * e_ddi_getproplen:	See comments for ddi_getproplen.
4607  */
4608 int
4609 e_ddi_getproplen(dev_t dev, vtype_t type, char *name, int flags, int *lengthp)
4610 {
4611 	_NOTE(ARGUNUSED(type))
4612 	dev_info_t *devi;
4613 	ddi_prop_op_t prop_op = PROP_LEN;
4614 	int error;
4615 
4616 	if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL)
4617 		return (DDI_PROP_NOT_FOUND);
4618 
4619 	error = cdev_prop_op(dev, devi, prop_op, flags, name, NULL, lengthp);
4620 	ddi_release_devi(devi);
4621 	return (error);
4622 }
4623 
4624 /*
4625  * Routines to get at elements of the dev_info structure
4626  */
4627 
4628 /*
4629  * ddi_binding_name: Return the driver binding name of the devinfo node
4630  *		This is the name the OS used to bind the node to a driver.
4631  */
4632 char *
4633 ddi_binding_name(dev_info_t *dip)
4634 {
4635 	return (DEVI(dip)->devi_binding_name);
4636 }
4637 
4638 /*
4639  * ddi_driver_major: Return the major number of the driver that
4640  *	the supplied devinfo is bound to.  If not yet bound,
4641  *	DDI_MAJOR_T_NONE.
4642  *
4643  * When used by the driver bound to 'devi', this
4644  * function will reliably return the driver major number.
4645  * Other ways of determining the driver major number, such as
4646  *	major = ddi_name_to_major(ddi_get_name(devi));
4647  *	major = ddi_name_to_major(ddi_binding_name(devi));
4648  * can return a different result as the driver/alias binding
4649  * can change dynamically, and thus should be avoided.
4650  */
4651 major_t
4652 ddi_driver_major(dev_info_t *devi)
4653 {
4654 	return (DEVI(devi)->devi_major);
4655 }
4656 
4657 /*
4658  * ddi_driver_name: Return the normalized driver name. this is the
4659  *		actual driver name
4660  */
4661 const char *
4662 ddi_driver_name(dev_info_t *devi)
4663 {
4664 	major_t major;
4665 
4666 	if ((major = ddi_driver_major(devi)) != DDI_MAJOR_T_NONE)
4667 		return (ddi_major_to_name(major));
4668 
4669 	return (ddi_node_name(devi));
4670 }
4671 
4672 /*
4673  * i_ddi_set_binding_name:	Set binding name.
4674  *
4675  *	Set the binding name to the given name.
4676  *	This routine is for use by the ddi implementation, not by drivers.
4677  */
4678 void
4679 i_ddi_set_binding_name(dev_info_t *dip, char *name)
4680 {
4681 	DEVI(dip)->devi_binding_name = name;
4682 
4683 }
4684 
4685 /*
4686  * ddi_get_name: A synonym of ddi_binding_name() ... returns a name
4687  * the implementation has used to bind the node to a driver.
4688  */
4689 char *
4690 ddi_get_name(dev_info_t *dip)
4691 {
4692 	return (DEVI(dip)->devi_binding_name);
4693 }
4694 
4695 /*
4696  * ddi_node_name: Return the name property of the devinfo node
4697  *		This may differ from ddi_binding_name if the node name
4698  *		does not define a binding to a driver (i.e. generic names).
4699  */
4700 char *
4701 ddi_node_name(dev_info_t *dip)
4702 {
4703 	return (DEVI(dip)->devi_node_name);
4704 }
4705 
4706 
4707 /*
4708  * ddi_get_nodeid:	Get nodeid stored in dev_info structure.
4709  */
4710 int
4711 ddi_get_nodeid(dev_info_t *dip)
4712 {
4713 	return (DEVI(dip)->devi_nodeid);
4714 }
4715 
4716 int
4717 ddi_get_instance(dev_info_t *dip)
4718 {
4719 	return (DEVI(dip)->devi_instance);
4720 }
4721 
4722 struct dev_ops *
4723 ddi_get_driver(dev_info_t *dip)
4724 {
4725 	return (DEVI(dip)->devi_ops);
4726 }
4727 
4728 void
4729 ddi_set_driver(dev_info_t *dip, struct dev_ops *devo)
4730 {
4731 	DEVI(dip)->devi_ops = devo;
4732 }
4733 
4734 /*
4735  * ddi_set_driver_private/ddi_get_driver_private:
4736  * Get/set device driver private data in devinfo.
4737  */
4738 void
4739 ddi_set_driver_private(dev_info_t *dip, void *data)
4740 {
4741 	DEVI(dip)->devi_driver_data = data;
4742 }
4743 
4744 void *
4745 ddi_get_driver_private(dev_info_t *dip)
4746 {
4747 	return (DEVI(dip)->devi_driver_data);
4748 }
4749 
4750 /*
4751  * ddi_get_parent, ddi_get_child, ddi_get_next_sibling
4752  */
4753 
4754 dev_info_t *
4755 ddi_get_parent(dev_info_t *dip)
4756 {
4757 	return ((dev_info_t *)DEVI(dip)->devi_parent);
4758 }
4759 
4760 dev_info_t *
4761 ddi_get_child(dev_info_t *dip)
4762 {
4763 	return ((dev_info_t *)DEVI(dip)->devi_child);
4764 }
4765 
4766 dev_info_t *
4767 ddi_get_next_sibling(dev_info_t *dip)
4768 {
4769 	return ((dev_info_t *)DEVI(dip)->devi_sibling);
4770 }
4771 
4772 dev_info_t *
4773 ddi_get_next(dev_info_t *dip)
4774 {
4775 	return ((dev_info_t *)DEVI(dip)->devi_next);
4776 }
4777 
4778 void
4779 ddi_set_next(dev_info_t *dip, dev_info_t *nextdip)
4780 {
4781 	DEVI(dip)->devi_next = DEVI(nextdip);
4782 }
4783 
4784 /*
4785  * ddi_root_node:		Return root node of devinfo tree
4786  */
4787 
4788 dev_info_t *
4789 ddi_root_node(void)
4790 {
4791 	extern dev_info_t *top_devinfo;
4792 
4793 	return (top_devinfo);
4794 }
4795 
4796 /*
4797  * Miscellaneous functions:
4798  */
4799 
4800 /*
4801  * Implementation specific hooks
4802  */
4803 
4804 void
4805 ddi_report_dev(dev_info_t *d)
4806 {
4807 	char *b;
4808 
4809 	(void) ddi_ctlops(d, d, DDI_CTLOPS_REPORTDEV, (void *)0, (void *)0);
4810 
4811 	/*
4812 	 * If this devinfo node has cb_ops, it's implicitly accessible from
4813 	 * userland, so we print its full name together with the instance
4814 	 * number 'abbreviation' that the driver may use internally.
4815 	 */
4816 	if (DEVI(d)->devi_ops->devo_cb_ops != (struct cb_ops *)0 &&
4817 	    (b = kmem_zalloc(MAXPATHLEN, KM_NOSLEEP))) {
4818 		cmn_err(CE_CONT, "?%s%d is %s\n",
4819 		    ddi_driver_name(d), ddi_get_instance(d),
4820 		    ddi_pathname(d, b));
4821 		kmem_free(b, MAXPATHLEN);
4822 	}
4823 }
4824 
4825 /*
4826  * ddi_ctlops() is described in the assembler not to buy a new register
4827  * window when it's called and can reduce cost in climbing the device tree
4828  * without using the tail call optimization.
4829  */
4830 int
4831 ddi_dev_regsize(dev_info_t *dev, uint_t rnumber, off_t *result)
4832 {
4833 	int ret;
4834 
4835 	ret = ddi_ctlops(dev, dev, DDI_CTLOPS_REGSIZE,
4836 	    (void *)&rnumber, (void *)result);
4837 
4838 	return (ret == DDI_SUCCESS ? DDI_SUCCESS : DDI_FAILURE);
4839 }
4840 
4841 int
4842 ddi_dev_nregs(dev_info_t *dev, int *result)
4843 {
4844 	return (ddi_ctlops(dev, dev, DDI_CTLOPS_NREGS, 0, (void *)result));
4845 }
4846 
4847 int
4848 ddi_dev_is_sid(dev_info_t *d)
4849 {
4850 	return (ddi_ctlops(d, d, DDI_CTLOPS_SIDDEV, (void *)0, (void *)0));
4851 }
4852 
4853 int
4854 ddi_slaveonly(dev_info_t *d)
4855 {
4856 	return (ddi_ctlops(d, d, DDI_CTLOPS_SLAVEONLY, (void *)0, (void *)0));
4857 }
4858 
4859 int
4860 ddi_dev_affinity(dev_info_t *a, dev_info_t *b)
4861 {
4862 	return (ddi_ctlops(a, a, DDI_CTLOPS_AFFINITY, (void *)b, (void *)0));
4863 }
4864 
4865 int
4866 ddi_streams_driver(dev_info_t *dip)
4867 {
4868 	if (i_ddi_devi_attached(dip) &&
4869 	    (DEVI(dip)->devi_ops->devo_cb_ops != NULL) &&
4870 	    (DEVI(dip)->devi_ops->devo_cb_ops->cb_str != NULL))
4871 		return (DDI_SUCCESS);
4872 	return (DDI_FAILURE);
4873 }
4874 
4875 /*
4876  * callback free list
4877  */
4878 
4879 static int ncallbacks;
4880 static int nc_low = 170;
4881 static int nc_med = 512;
4882 static int nc_high = 2048;
4883 static struct ddi_callback *callbackq;
4884 static struct ddi_callback *callbackqfree;
4885 
4886 /*
4887  * set/run callback lists
4888  */
4889 struct	cbstats	{
4890 	kstat_named_t	cb_asked;
4891 	kstat_named_t	cb_new;
4892 	kstat_named_t	cb_run;
4893 	kstat_named_t	cb_delete;
4894 	kstat_named_t	cb_maxreq;
4895 	kstat_named_t	cb_maxlist;
4896 	kstat_named_t	cb_alloc;
4897 	kstat_named_t	cb_runouts;
4898 	kstat_named_t	cb_L2;
4899 	kstat_named_t	cb_grow;
4900 } cbstats = {
4901 	{"asked",	KSTAT_DATA_UINT32},
4902 	{"new",		KSTAT_DATA_UINT32},
4903 	{"run",		KSTAT_DATA_UINT32},
4904 	{"delete",	KSTAT_DATA_UINT32},
4905 	{"maxreq",	KSTAT_DATA_UINT32},
4906 	{"maxlist",	KSTAT_DATA_UINT32},
4907 	{"alloc",	KSTAT_DATA_UINT32},
4908 	{"runouts",	KSTAT_DATA_UINT32},
4909 	{"L2",		KSTAT_DATA_UINT32},
4910 	{"grow",	KSTAT_DATA_UINT32},
4911 };
4912 
4913 #define	nc_asked	cb_asked.value.ui32
4914 #define	nc_new		cb_new.value.ui32
4915 #define	nc_run		cb_run.value.ui32
4916 #define	nc_delete	cb_delete.value.ui32
4917 #define	nc_maxreq	cb_maxreq.value.ui32
4918 #define	nc_maxlist	cb_maxlist.value.ui32
4919 #define	nc_alloc	cb_alloc.value.ui32
4920 #define	nc_runouts	cb_runouts.value.ui32
4921 #define	nc_L2		cb_L2.value.ui32
4922 #define	nc_grow		cb_grow.value.ui32
4923 
4924 static kmutex_t ddi_callback_mutex;
4925 
4926 /*
4927  * callbacks are handled using a L1/L2 cache. The L1 cache
4928  * comes out of kmem_cache_alloc and can expand/shrink dynamically. If
4929  * we can't get callbacks from the L1 cache [because pageout is doing
4930  * I/O at the time freemem is 0], we allocate callbacks out of the
4931  * L2 cache. The L2 cache is static and depends on the memory size.
4932  * [We might also count the number of devices at probe time and
4933  * allocate one structure per device and adjust for deferred attach]
4934  */
4935 void
4936 impl_ddi_callback_init(void)
4937 {
4938 	int	i;
4939 	uint_t	physmegs;
4940 	kstat_t	*ksp;
4941 
4942 	physmegs = physmem >> (20 - PAGESHIFT);
4943 	if (physmegs < 48) {
4944 		ncallbacks = nc_low;
4945 	} else if (physmegs < 128) {
4946 		ncallbacks = nc_med;
4947 	} else {
4948 		ncallbacks = nc_high;
4949 	}
4950 
4951 	/*
4952 	 * init free list
4953 	 */
4954 	callbackq = kmem_zalloc(
4955 	    ncallbacks * sizeof (struct ddi_callback), KM_SLEEP);
4956 	for (i = 0; i < ncallbacks-1; i++)
4957 		callbackq[i].c_nfree = &callbackq[i+1];
4958 	callbackqfree = callbackq;
4959 
4960 	/* init kstats */
4961 	if (ksp = kstat_create("unix", 0, "cbstats", "misc", KSTAT_TYPE_NAMED,
4962 	    sizeof (cbstats) / sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL)) {
4963 		ksp->ks_data = (void *) &cbstats;
4964 		kstat_install(ksp);
4965 	}
4966 
4967 }
4968 
4969 static void
4970 callback_insert(int (*funcp)(caddr_t), caddr_t arg, uintptr_t *listid,
4971 	int count)
4972 {
4973 	struct ddi_callback *list, *marker, *new;
4974 	size_t size = sizeof (struct ddi_callback);
4975 
4976 	list = marker = (struct ddi_callback *)*listid;
4977 	while (list != NULL) {
4978 		if (list->c_call == funcp && list->c_arg == arg) {
4979 			list->c_count += count;
4980 			return;
4981 		}
4982 		marker = list;
4983 		list = list->c_nlist;
4984 	}
4985 	new = kmem_alloc(size, KM_NOSLEEP);
4986 	if (new == NULL) {
4987 		new = callbackqfree;
4988 		if (new == NULL) {
4989 			new = kmem_alloc_tryhard(sizeof (struct ddi_callback),
4990 			    &size, KM_NOSLEEP | KM_PANIC);
4991 			cbstats.nc_grow++;
4992 		} else {
4993 			callbackqfree = new->c_nfree;
4994 			cbstats.nc_L2++;
4995 		}
4996 	}
4997 	if (marker != NULL) {
4998 		marker->c_nlist = new;
4999 	} else {
5000 		*listid = (uintptr_t)new;
5001 	}
5002 	new->c_size = size;
5003 	new->c_nlist = NULL;
5004 	new->c_call = funcp;
5005 	new->c_arg = arg;
5006 	new->c_count = count;
5007 	cbstats.nc_new++;
5008 	cbstats.nc_alloc++;
5009 	if (cbstats.nc_alloc > cbstats.nc_maxlist)
5010 		cbstats.nc_maxlist = cbstats.nc_alloc;
5011 }
5012 
5013 void
5014 ddi_set_callback(int (*funcp)(caddr_t), caddr_t arg, uintptr_t *listid)
5015 {
5016 	mutex_enter(&ddi_callback_mutex);
5017 	cbstats.nc_asked++;
5018 	if ((cbstats.nc_asked - cbstats.nc_run) > cbstats.nc_maxreq)
5019 		cbstats.nc_maxreq = (cbstats.nc_asked - cbstats.nc_run);
5020 	(void) callback_insert(funcp, arg, listid, 1);
5021 	mutex_exit(&ddi_callback_mutex);
5022 }
5023 
5024 static void
5025 real_callback_run(void *Queue)
5026 {
5027 	int (*funcp)(caddr_t);
5028 	caddr_t arg;
5029 	int count, rval;
5030 	uintptr_t *listid;
5031 	struct ddi_callback *list, *marker;
5032 	int check_pending = 1;
5033 	int pending = 0;
5034 
5035 	do {
5036 		mutex_enter(&ddi_callback_mutex);
5037 		listid = Queue;
5038 		list = (struct ddi_callback *)*listid;
5039 		if (list == NULL) {
5040 			mutex_exit(&ddi_callback_mutex);
5041 			return;
5042 		}
5043 		if (check_pending) {
5044 			marker = list;
5045 			while (marker != NULL) {
5046 				pending += marker->c_count;
5047 				marker = marker->c_nlist;
5048 			}
5049 			check_pending = 0;
5050 		}
5051 		ASSERT(pending > 0);
5052 		ASSERT(list->c_count > 0);
5053 		funcp = list->c_call;
5054 		arg = list->c_arg;
5055 		count = list->c_count;
5056 		*(uintptr_t *)Queue = (uintptr_t)list->c_nlist;
5057 		if (list >= &callbackq[0] &&
5058 		    list <= &callbackq[ncallbacks-1]) {
5059 			list->c_nfree = callbackqfree;
5060 			callbackqfree = list;
5061 		} else
5062 			kmem_free(list, list->c_size);
5063 
5064 		cbstats.nc_delete++;
5065 		cbstats.nc_alloc--;
5066 		mutex_exit(&ddi_callback_mutex);
5067 
5068 		do {
5069 			if ((rval = (*funcp)(arg)) == 0) {
5070 				pending -= count;
5071 				mutex_enter(&ddi_callback_mutex);
5072 				(void) callback_insert(funcp, arg, listid,
5073 				    count);
5074 				cbstats.nc_runouts++;
5075 			} else {
5076 				pending--;
5077 				mutex_enter(&ddi_callback_mutex);
5078 				cbstats.nc_run++;
5079 			}
5080 			mutex_exit(&ddi_callback_mutex);
5081 		} while (rval != 0 && (--count > 0));
5082 	} while (pending > 0);
5083 }
5084 
5085 void
5086 ddi_run_callback(uintptr_t *listid)
5087 {
5088 	softcall(real_callback_run, listid);
5089 }
5090 
5091 /*
5092  * ddi_periodic_t
5093  * ddi_periodic_add(void (*func)(void *), void *arg, hrtime_t interval,
5094  *     int level)
5095  *
5096  * INTERFACE LEVEL
5097  *      Solaris DDI specific (Solaris DDI)
5098  *
5099  * PARAMETERS
5100  *      func: the callback function
5101  *
5102  *            The callback function will be invoked. The function is invoked
5103  *            in kernel context if the argument level passed is the zero.
5104  *            Otherwise it's invoked in interrupt context at the specified
5105  *            level.
5106  *
5107  *       arg: the argument passed to the callback function
5108  *
5109  *  interval: interval time
5110  *
5111  *    level : callback interrupt level
5112  *
5113  *            If the value is the zero, the callback function is invoked
5114  *            in kernel context. If the value is more than the zero, but
5115  *            less than or equal to ten, the callback function is invoked in
5116  *            interrupt context at the specified interrupt level, which may
5117  *            be used for real time applications.
5118  *
5119  *            This value must be in range of 0-10, which can be a numeric
5120  *            number or a pre-defined macro (DDI_IPL_0, ... , DDI_IPL_10).
5121  *
5122  * DESCRIPTION
5123  *      ddi_periodic_add(9F) schedules the specified function to be
5124  *      periodically invoked in the interval time.
5125  *
5126  *      As well as timeout(9F), the exact time interval over which the function
5127  *      takes effect cannot be guaranteed, but the value given is a close
5128  *      approximation.
5129  *
5130  *      Drivers waiting on behalf of processes with real-time constraints must
5131  *      pass non-zero value with the level argument to ddi_periodic_add(9F).
5132  *
5133  * RETURN VALUES
5134  *      ddi_periodic_add(9F) returns a non-zero opaque value (ddi_periodic_t),
5135  *      which must be used for ddi_periodic_delete(9F) to specify the request.
5136  *
5137  * CONTEXT
5138  *      ddi_periodic_add(9F) can be called in user or kernel context, but
5139  *      it cannot be called in interrupt context, which is different from
5140  *      timeout(9F).
5141  */
5142 ddi_periodic_t
5143 ddi_periodic_add(void (*func)(void *), void *arg, hrtime_t interval, int level)
5144 {
5145 	/*
5146 	 * Sanity check of the argument level.
5147 	 */
5148 	if (level < DDI_IPL_0 || level > DDI_IPL_10)
5149 		cmn_err(CE_PANIC,
5150 		    "ddi_periodic_add: invalid interrupt level (%d).", level);
5151 
5152 	/*
5153 	 * Sanity check of the context. ddi_periodic_add() cannot be
5154 	 * called in either interrupt context or high interrupt context.
5155 	 */
5156 	if (servicing_interrupt())
5157 		cmn_err(CE_PANIC,
5158 		    "ddi_periodic_add: called in (high) interrupt context.");
5159 
5160 	return ((ddi_periodic_t)i_timeout(func, arg, interval, level));
5161 }
5162 
5163 /*
5164  * void
5165  * ddi_periodic_delete(ddi_periodic_t req)
5166  *
5167  * INTERFACE LEVEL
5168  *     Solaris DDI specific (Solaris DDI)
5169  *
5170  * PARAMETERS
5171  *     req: ddi_periodic_t opaque value ddi_periodic_add(9F) returned
5172  *     previously.
5173  *
5174  * DESCRIPTION
5175  *     ddi_periodic_delete(9F) cancels the ddi_periodic_add(9F) request
5176  *     previously requested.
5177  *
5178  *     ddi_periodic_delete(9F) will not return until the pending request
5179  *     is canceled or executed.
5180  *
5181  *     As well as untimeout(9F), calling ddi_periodic_delete(9F) for a
5182  *     timeout which is either running on another CPU, or has already
5183  *     completed causes no problems. However, unlike untimeout(9F), there is
5184  *     no restrictions on the lock which might be held across the call to
5185  *     ddi_periodic_delete(9F).
5186  *
5187  *     Drivers should be structured with the understanding that the arrival of
5188  *     both an interrupt and a timeout for that interrupt can occasionally
5189  *     occur, in either order.
5190  *
5191  * CONTEXT
5192  *     ddi_periodic_delete(9F) can be called in user or kernel context, but
5193  *     it cannot be called in interrupt context, which is different from
5194  *     untimeout(9F).
5195  */
5196 void
5197 ddi_periodic_delete(ddi_periodic_t req)
5198 {
5199 	/*
5200 	 * Sanity check of the context. ddi_periodic_delete() cannot be
5201 	 * called in either interrupt context or high interrupt context.
5202 	 */
5203 	if (servicing_interrupt())
5204 		cmn_err(CE_PANIC,
5205 		    "ddi_periodic_delete: called in (high) interrupt context.");
5206 
5207 	i_untimeout((timeout_t)req);
5208 }
5209 
5210 dev_info_t *
5211 nodevinfo(dev_t dev, int otyp)
5212 {
5213 	_NOTE(ARGUNUSED(dev, otyp))
5214 	return ((dev_info_t *)0);
5215 }
5216 
5217 /*
5218  * A driver should support its own getinfo(9E) entry point. This function
5219  * is provided as a convenience for ON drivers that don't expect their
5220  * getinfo(9E) entry point to be called. A driver that uses this must not
5221  * call ddi_create_minor_node.
5222  */
5223 int
5224 ddi_no_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
5225 {
5226 	_NOTE(ARGUNUSED(dip, infocmd, arg, result))
5227 	return (DDI_FAILURE);
5228 }
5229 
5230 /*
5231  * A driver should support its own getinfo(9E) entry point. This function
5232  * is provided as a convenience for ON drivers that where the minor number
5233  * is the instance. Drivers that do not have 1:1 mapping must implement
5234  * their own getinfo(9E) function.
5235  */
5236 int
5237 ddi_getinfo_1to1(dev_info_t *dip, ddi_info_cmd_t infocmd,
5238     void *arg, void **result)
5239 {
5240 	_NOTE(ARGUNUSED(dip))
5241 	int	instance;
5242 
5243 	if (infocmd != DDI_INFO_DEVT2INSTANCE)
5244 		return (DDI_FAILURE);
5245 
5246 	instance = getminor((dev_t)(uintptr_t)arg);
5247 	*result = (void *)(uintptr_t)instance;
5248 	return (DDI_SUCCESS);
5249 }
5250 
5251 int
5252 ddifail(dev_info_t *devi, ddi_attach_cmd_t cmd)
5253 {
5254 	_NOTE(ARGUNUSED(devi, cmd))
5255 	return (DDI_FAILURE);
5256 }
5257 
5258 int
5259 ddi_no_dma_map(dev_info_t *dip, dev_info_t *rdip,
5260     struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep)
5261 {
5262 	_NOTE(ARGUNUSED(dip, rdip, dmareqp, handlep))
5263 	return (DDI_DMA_NOMAPPING);
5264 }
5265 
5266 int
5267 ddi_no_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr,
5268     int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep)
5269 {
5270 	_NOTE(ARGUNUSED(dip, rdip, attr, waitfp, arg, handlep))
5271 	return (DDI_DMA_BADATTR);
5272 }
5273 
5274 int
5275 ddi_no_dma_freehdl(dev_info_t *dip, dev_info_t *rdip,
5276     ddi_dma_handle_t handle)
5277 {
5278 	_NOTE(ARGUNUSED(dip, rdip, handle))
5279 	return (DDI_FAILURE);
5280 }
5281 
5282 int
5283 ddi_no_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
5284     ddi_dma_handle_t handle, struct ddi_dma_req *dmareq,
5285     ddi_dma_cookie_t *cp, uint_t *ccountp)
5286 {
5287 	_NOTE(ARGUNUSED(dip, rdip, handle, dmareq, cp, ccountp))
5288 	return (DDI_DMA_NOMAPPING);
5289 }
5290 
5291 int
5292 ddi_no_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
5293     ddi_dma_handle_t handle)
5294 {
5295 	_NOTE(ARGUNUSED(dip, rdip, handle))
5296 	return (DDI_FAILURE);
5297 }
5298 
5299 int
5300 ddi_no_dma_flush(dev_info_t *dip, dev_info_t *rdip,
5301     ddi_dma_handle_t handle, off_t off, size_t len,
5302     uint_t cache_flags)
5303 {
5304 	_NOTE(ARGUNUSED(dip, rdip, handle, off, len, cache_flags))
5305 	return (DDI_FAILURE);
5306 }
5307 
5308 int
5309 ddi_no_dma_win(dev_info_t *dip, dev_info_t *rdip,
5310     ddi_dma_handle_t handle, uint_t win, off_t *offp,
5311     size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp)
5312 {
5313 	_NOTE(ARGUNUSED(dip, rdip, handle, win, offp, lenp, cookiep, ccountp))
5314 	return (DDI_FAILURE);
5315 }
5316 
5317 int
5318 ddi_no_dma_mctl(dev_info_t *dip, dev_info_t *rdip,
5319     ddi_dma_handle_t handle, enum ddi_dma_ctlops request,
5320     off_t *offp, size_t *lenp, caddr_t *objp, uint_t flags)
5321 {
5322 	_NOTE(ARGUNUSED(dip, rdip, handle, request, offp, lenp, objp, flags))
5323 	return (DDI_FAILURE);
5324 }
5325 
5326 void
5327 ddivoid(void)
5328 {}
5329 
5330 int
5331 nochpoll(dev_t dev, short events, int anyyet, short *reventsp,
5332     struct pollhead **pollhdrp)
5333 {
5334 	_NOTE(ARGUNUSED(dev, events, anyyet, reventsp, pollhdrp))
5335 	return (ENXIO);
5336 }
5337 
5338 cred_t *
5339 ddi_get_cred(void)
5340 {
5341 	return (CRED());
5342 }
5343 
5344 clock_t
5345 ddi_get_lbolt(void)
5346 {
5347 	return ((clock_t)lbolt_hybrid());
5348 }
5349 
5350 int64_t
5351 ddi_get_lbolt64(void)
5352 {
5353 	return (lbolt_hybrid());
5354 }
5355 
5356 time_t
5357 ddi_get_time(void)
5358 {
5359 	time_t	now;
5360 
5361 	if ((now = gethrestime_sec()) == 0) {
5362 		timestruc_t ts;
5363 		mutex_enter(&tod_lock);
5364 		ts = tod_get();
5365 		mutex_exit(&tod_lock);
5366 		return (ts.tv_sec);
5367 	} else {
5368 		return (now);
5369 	}
5370 }
5371 
5372 pid_t
5373 ddi_get_pid(void)
5374 {
5375 	return (ttoproc(curthread)->p_pid);
5376 }
5377 
5378 kt_did_t
5379 ddi_get_kt_did(void)
5380 {
5381 	return (curthread->t_did);
5382 }
5383 
5384 /*
5385  * This function returns B_TRUE if the caller can reasonably expect that a call
5386  * to cv_wait_sig(9F), cv_timedwait_sig(9F), or qwait_sig(9F) could be awakened
5387  * by user-level signal.  If it returns B_FALSE, then the caller should use
5388  * other means to make certain that the wait will not hang "forever."
5389  *
5390  * It does not check the signal mask, nor for reception of any particular
5391  * signal.
5392  *
5393  * Currently, a thread can receive a signal if it's not a kernel thread and it
5394  * is not in the middle of exit(2) tear-down.  Threads that are in that
5395  * tear-down effectively convert cv_wait_sig to cv_wait, cv_timedwait_sig to
5396  * cv_timedwait, and qwait_sig to qwait.
5397  */
5398 boolean_t
5399 ddi_can_receive_sig(void)
5400 {
5401 	proc_t *pp;
5402 
5403 	if (curthread->t_proc_flag & TP_LWPEXIT)
5404 		return (B_FALSE);
5405 	if ((pp = ttoproc(curthread)) == NULL)
5406 		return (B_FALSE);
5407 	return (pp->p_as != &kas);
5408 }
5409 
5410 /*
5411  * Swap bytes in 16-bit [half-]words
5412  */
5413 void
5414 swab(void *src, void *dst, size_t nbytes)
5415 {
5416 	uchar_t *pf = (uchar_t *)src;
5417 	uchar_t *pt = (uchar_t *)dst;
5418 	uchar_t tmp;
5419 	int nshorts;
5420 
5421 	nshorts = nbytes >> 1;
5422 
5423 	while (--nshorts >= 0) {
5424 		tmp = *pf++;
5425 		*pt++ = *pf++;
5426 		*pt++ = tmp;
5427 	}
5428 }
5429 
5430 static void
5431 ddi_append_minor_node(dev_info_t *ddip, struct ddi_minor_data *dmdp)
5432 {
5433 	int			circ;
5434 	struct ddi_minor_data	*dp;
5435 
5436 	ndi_devi_enter(ddip, &circ);
5437 	if ((dp = DEVI(ddip)->devi_minor) == (struct ddi_minor_data *)NULL) {
5438 		DEVI(ddip)->devi_minor = dmdp;
5439 	} else {
5440 		while (dp->next != (struct ddi_minor_data *)NULL)
5441 			dp = dp->next;
5442 		dp->next = dmdp;
5443 	}
5444 	ndi_devi_exit(ddip, circ);
5445 }
5446 
5447 /*
5448  * Part of the obsolete SunCluster DDI Hooks.
5449  * Keep for binary compatibility
5450  */
5451 minor_t
5452 ddi_getiminor(dev_t dev)
5453 {
5454 	return (getminor(dev));
5455 }
5456 
5457 static int
5458 i_log_devfs_minor_create(dev_info_t *dip, char *minor_name)
5459 {
5460 	int se_flag;
5461 	int kmem_flag;
5462 	int se_err;
5463 	char *pathname, *class_name;
5464 	sysevent_t *ev = NULL;
5465 	sysevent_id_t eid;
5466 	sysevent_value_t se_val;
5467 	sysevent_attr_list_t *ev_attr_list = NULL;
5468 
5469 	/* determine interrupt context */
5470 	se_flag = (servicing_interrupt()) ? SE_NOSLEEP : SE_SLEEP;
5471 	kmem_flag = (se_flag == SE_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
5472 
5473 	i_ddi_di_cache_invalidate();
5474 
5475 #ifdef DEBUG
5476 	if ((se_flag == SE_NOSLEEP) && sunddi_debug) {
5477 		cmn_err(CE_CONT, "ddi_create_minor_node: called from "
5478 		    "interrupt level by driver %s",
5479 		    ddi_driver_name(dip));
5480 	}
5481 #endif /* DEBUG */
5482 
5483 	ev = sysevent_alloc(EC_DEVFS, ESC_DEVFS_MINOR_CREATE, EP_DDI, se_flag);
5484 	if (ev == NULL) {
5485 		goto fail;
5486 	}
5487 
5488 	pathname = kmem_alloc(MAXPATHLEN, kmem_flag);
5489 	if (pathname == NULL) {
5490 		sysevent_free(ev);
5491 		goto fail;
5492 	}
5493 
5494 	(void) ddi_pathname(dip, pathname);
5495 	ASSERT(strlen(pathname));
5496 	se_val.value_type = SE_DATA_TYPE_STRING;
5497 	se_val.value.sv_string = pathname;
5498 	if (sysevent_add_attr(&ev_attr_list, DEVFS_PATHNAME,
5499 	    &se_val, se_flag) != 0) {
5500 		kmem_free(pathname, MAXPATHLEN);
5501 		sysevent_free(ev);
5502 		goto fail;
5503 	}
5504 	kmem_free(pathname, MAXPATHLEN);
5505 
5506 	/* add the device class attribute */
5507 	if ((class_name = i_ddi_devi_class(dip)) != NULL) {
5508 		se_val.value_type = SE_DATA_TYPE_STRING;
5509 		se_val.value.sv_string = class_name;
5510 		if (sysevent_add_attr(&ev_attr_list,
5511 		    DEVFS_DEVI_CLASS, &se_val, SE_SLEEP) != 0) {
5512 			sysevent_free_attr(ev_attr_list);
5513 			goto fail;
5514 		}
5515 	}
5516 
5517 	/*
5518 	 * allow for NULL minor names
5519 	 */
5520 	if (minor_name != NULL) {
5521 		se_val.value.sv_string = minor_name;
5522 		if (sysevent_add_attr(&ev_attr_list, DEVFS_MINOR_NAME,
5523 		    &se_val, se_flag) != 0) {
5524 			sysevent_free_attr(ev_attr_list);
5525 			sysevent_free(ev);
5526 			goto fail;
5527 		}
5528 	}
5529 
5530 	if (sysevent_attach_attributes(ev, ev_attr_list) != 0) {
5531 		sysevent_free_attr(ev_attr_list);
5532 		sysevent_free(ev);
5533 		goto fail;
5534 	}
5535 
5536 	if ((se_err = log_sysevent(ev, se_flag, &eid)) != 0) {
5537 		if (se_err == SE_NO_TRANSPORT) {
5538 			cmn_err(CE_WARN, "/devices or /dev may not be current "
5539 			    "for driver %s (%s). Run devfsadm -i %s",
5540 			    ddi_driver_name(dip), "syseventd not responding",
5541 			    ddi_driver_name(dip));
5542 		} else {
5543 			sysevent_free(ev);
5544 			goto fail;
5545 		}
5546 	}
5547 
5548 	sysevent_free(ev);
5549 	return (DDI_SUCCESS);
5550 fail:
5551 	cmn_err(CE_WARN, "/devices or /dev may not be current "
5552 	    "for driver %s. Run devfsadm -i %s",
5553 	    ddi_driver_name(dip), ddi_driver_name(dip));
5554 	return (DDI_SUCCESS);
5555 }
5556 
5557 /*
5558  * failing to remove a minor node is not of interest
5559  * therefore we do not generate an error message
5560  */
5561 static int
5562 i_log_devfs_minor_remove(dev_info_t *dip, char *minor_name)
5563 {
5564 	char *pathname, *class_name;
5565 	sysevent_t *ev;
5566 	sysevent_id_t eid;
5567 	sysevent_value_t se_val;
5568 	sysevent_attr_list_t *ev_attr_list = NULL;
5569 
5570 	/*
5571 	 * only log ddi_remove_minor_node() calls outside the scope
5572 	 * of attach/detach reconfigurations and when the dip is
5573 	 * still initialized.
5574 	 */
5575 	if (DEVI_IS_ATTACHING(dip) || DEVI_IS_DETACHING(dip) ||
5576 	    (i_ddi_node_state(dip) < DS_INITIALIZED)) {
5577 		return (DDI_SUCCESS);
5578 	}
5579 
5580 	i_ddi_di_cache_invalidate();
5581 
5582 	ev = sysevent_alloc(EC_DEVFS, ESC_DEVFS_MINOR_REMOVE, EP_DDI, SE_SLEEP);
5583 	if (ev == NULL) {
5584 		return (DDI_SUCCESS);
5585 	}
5586 
5587 	pathname = kmem_alloc(MAXPATHLEN, KM_SLEEP);
5588 	if (pathname == NULL) {
5589 		sysevent_free(ev);
5590 		return (DDI_SUCCESS);
5591 	}
5592 
5593 	(void) ddi_pathname(dip, pathname);
5594 	ASSERT(strlen(pathname));
5595 	se_val.value_type = SE_DATA_TYPE_STRING;
5596 	se_val.value.sv_string = pathname;
5597 	if (sysevent_add_attr(&ev_attr_list, DEVFS_PATHNAME,
5598 	    &se_val, SE_SLEEP) != 0) {
5599 		kmem_free(pathname, MAXPATHLEN);
5600 		sysevent_free(ev);
5601 		return (DDI_SUCCESS);
5602 	}
5603 
5604 	kmem_free(pathname, MAXPATHLEN);
5605 
5606 	/*
5607 	 * allow for NULL minor names
5608 	 */
5609 	if (minor_name != NULL) {
5610 		se_val.value.sv_string = minor_name;
5611 		if (sysevent_add_attr(&ev_attr_list, DEVFS_MINOR_NAME,
5612 		    &se_val, SE_SLEEP) != 0) {
5613 			sysevent_free_attr(ev_attr_list);
5614 			goto fail;
5615 		}
5616 	}
5617 
5618 	if ((class_name = i_ddi_devi_class(dip)) != NULL) {
5619 		/* add the device class, driver name and instance attributes */
5620 
5621 		se_val.value_type = SE_DATA_TYPE_STRING;
5622 		se_val.value.sv_string = class_name;
5623 		if (sysevent_add_attr(&ev_attr_list,
5624 		    DEVFS_DEVI_CLASS, &se_val, SE_SLEEP) != 0) {
5625 			sysevent_free_attr(ev_attr_list);
5626 			goto fail;
5627 		}
5628 
5629 		se_val.value_type = SE_DATA_TYPE_STRING;
5630 		se_val.value.sv_string = (char *)ddi_driver_name(dip);
5631 		if (sysevent_add_attr(&ev_attr_list,
5632 		    DEVFS_DRIVER_NAME, &se_val, SE_SLEEP) != 0) {
5633 			sysevent_free_attr(ev_attr_list);
5634 			goto fail;
5635 		}
5636 
5637 		se_val.value_type = SE_DATA_TYPE_INT32;
5638 		se_val.value.sv_int32 = ddi_get_instance(dip);
5639 		if (sysevent_add_attr(&ev_attr_list,
5640 		    DEVFS_INSTANCE, &se_val, SE_SLEEP) != 0) {
5641 			sysevent_free_attr(ev_attr_list);
5642 			goto fail;
5643 		}
5644 
5645 	}
5646 
5647 	if (sysevent_attach_attributes(ev, ev_attr_list) != 0) {
5648 		sysevent_free_attr(ev_attr_list);
5649 	} else {
5650 		(void) log_sysevent(ev, SE_SLEEP, &eid);
5651 	}
5652 fail:
5653 	sysevent_free(ev);
5654 	return (DDI_SUCCESS);
5655 }
5656 
5657 /*
5658  * Derive the device class of the node.
5659  * Device class names aren't defined yet. Until this is done we use
5660  * devfs event subclass names as device class names.
5661  */
5662 static int
5663 derive_devi_class(dev_info_t *dip, char *node_type, int flag)
5664 {
5665 	int rv = DDI_SUCCESS;
5666 
5667 	if (i_ddi_devi_class(dip) == NULL) {
5668 		if (strncmp(node_type, DDI_NT_BLOCK,
5669 		    sizeof (DDI_NT_BLOCK) - 1) == 0 &&
5670 		    (node_type[sizeof (DDI_NT_BLOCK) - 1] == '\0' ||
5671 		    node_type[sizeof (DDI_NT_BLOCK) - 1] == ':') &&
5672 		    strcmp(node_type, DDI_NT_FD) != 0) {
5673 
5674 			rv = i_ddi_set_devi_class(dip, ESC_DISK, flag);
5675 
5676 		} else if (strncmp(node_type, DDI_NT_NET,
5677 		    sizeof (DDI_NT_NET) - 1) == 0 &&
5678 		    (node_type[sizeof (DDI_NT_NET) - 1] == '\0' ||
5679 		    node_type[sizeof (DDI_NT_NET) - 1] == ':')) {
5680 
5681 			rv = i_ddi_set_devi_class(dip, ESC_NETWORK, flag);
5682 
5683 		} else if (strncmp(node_type, DDI_NT_PRINTER,
5684 		    sizeof (DDI_NT_PRINTER) - 1) == 0 &&
5685 		    (node_type[sizeof (DDI_NT_PRINTER) - 1] == '\0' ||
5686 		    node_type[sizeof (DDI_NT_PRINTER) - 1] == ':')) {
5687 
5688 			rv = i_ddi_set_devi_class(dip, ESC_PRINTER, flag);
5689 
5690 		} else if (strncmp(node_type, DDI_PSEUDO,
5691 		    sizeof (DDI_PSEUDO) -1) == 0 &&
5692 		    (strncmp(ESC_LOFI, ddi_node_name(dip),
5693 		    sizeof (ESC_LOFI) -1) == 0)) {
5694 			rv = i_ddi_set_devi_class(dip, ESC_LOFI, flag);
5695 		}
5696 	}
5697 
5698 	return (rv);
5699 }
5700 
5701 /*
5702  * Check compliance with PSARC 2003/375:
5703  *
5704  * The name must contain only characters a-z, A-Z, 0-9 or _ and it must not
5705  * exceed IFNAMSIZ (16) characters in length.
5706  */
5707 static boolean_t
5708 verify_name(char *name)
5709 {
5710 	size_t	len = strlen(name);
5711 	char	*cp;
5712 
5713 	if (len == 0 || len > IFNAMSIZ)
5714 		return (B_FALSE);
5715 
5716 	for (cp = name; *cp != '\0'; cp++) {
5717 		if (!isalnum(*cp) && *cp != '_')
5718 			return (B_FALSE);
5719 	}
5720 
5721 	return (B_TRUE);
5722 }
5723 
5724 /*
5725  * ddi_create_minor_common:	Create a  ddi_minor_data structure and
5726  *				attach it to the given devinfo node.
5727  */
5728 
5729 int
5730 ddi_create_minor_common(dev_info_t *dip, char *name, int spec_type,
5731     minor_t minor_num, char *node_type, int flag, ddi_minor_type mtype,
5732     const char *read_priv, const char *write_priv, mode_t priv_mode)
5733 {
5734 	struct ddi_minor_data *dmdp;
5735 	major_t major;
5736 
5737 	if (spec_type != S_IFCHR && spec_type != S_IFBLK)
5738 		return (DDI_FAILURE);
5739 
5740 	if (name == NULL)
5741 		return (DDI_FAILURE);
5742 
5743 	/*
5744 	 * Log a message if the minor number the driver is creating
5745 	 * is not expressible on the on-disk filesystem (currently
5746 	 * this is limited to 18 bits both by UFS). The device can
5747 	 * be opened via devfs, but not by device special files created
5748 	 * via mknod().
5749 	 */
5750 	if (minor_num > L_MAXMIN32) {
5751 		cmn_err(CE_WARN,
5752 		    "%s%d:%s minor 0x%x too big for 32-bit applications",
5753 		    ddi_driver_name(dip), ddi_get_instance(dip),
5754 		    name, minor_num);
5755 		return (DDI_FAILURE);
5756 	}
5757 
5758 	/* dip must be bound and attached */
5759 	major = ddi_driver_major(dip);
5760 	ASSERT(major != DDI_MAJOR_T_NONE);
5761 
5762 	/*
5763 	 * Default node_type to DDI_PSEUDO and issue notice in debug mode
5764 	 */
5765 	if (node_type == NULL) {
5766 		node_type = DDI_PSEUDO;
5767 		NDI_CONFIG_DEBUG((CE_NOTE, "!illegal node_type NULL for %s%d "
5768 		    " minor node %s; default to DDI_PSEUDO",
5769 		    ddi_driver_name(dip), ddi_get_instance(dip), name));
5770 	}
5771 
5772 	/*
5773 	 * If the driver is a network driver, ensure that the name falls within
5774 	 * the interface naming constraints specified by PSARC/2003/375.
5775 	 */
5776 	if (strcmp(node_type, DDI_NT_NET) == 0) {
5777 		if (!verify_name(name))
5778 			return (DDI_FAILURE);
5779 
5780 		if (mtype == DDM_MINOR) {
5781 			struct devnames *dnp = &devnamesp[major];
5782 
5783 			/* Mark driver as a network driver */
5784 			LOCK_DEV_OPS(&dnp->dn_lock);
5785 			dnp->dn_flags |= DN_NETWORK_DRIVER;
5786 
5787 			/*
5788 			 * If this minor node is created during the device
5789 			 * attachment, this is a physical network device.
5790 			 * Mark the driver as a physical network driver.
5791 			 */
5792 			if (DEVI_IS_ATTACHING(dip))
5793 				dnp->dn_flags |= DN_NETWORK_PHYSDRIVER;
5794 			UNLOCK_DEV_OPS(&dnp->dn_lock);
5795 		}
5796 	}
5797 
5798 	if (mtype == DDM_MINOR) {
5799 		if (derive_devi_class(dip,  node_type, KM_NOSLEEP) !=
5800 		    DDI_SUCCESS)
5801 			return (DDI_FAILURE);
5802 	}
5803 
5804 	/*
5805 	 * Take care of minor number information for the node.
5806 	 */
5807 
5808 	if ((dmdp = kmem_zalloc(sizeof (struct ddi_minor_data),
5809 	    KM_NOSLEEP)) == NULL) {
5810 		return (DDI_FAILURE);
5811 	}
5812 	if ((dmdp->ddm_name = i_ddi_strdup(name, KM_NOSLEEP)) == NULL) {
5813 		kmem_free(dmdp, sizeof (struct ddi_minor_data));
5814 		return (DDI_FAILURE);
5815 	}
5816 	dmdp->dip = dip;
5817 	dmdp->ddm_dev = makedevice(major, minor_num);
5818 	dmdp->ddm_spec_type = spec_type;
5819 	dmdp->ddm_node_type = node_type;
5820 	dmdp->type = mtype;
5821 	if (flag & CLONE_DEV) {
5822 		dmdp->type = DDM_ALIAS;
5823 		dmdp->ddm_dev = makedevice(ddi_driver_major(clone_dip), major);
5824 	}
5825 	if (flag & PRIVONLY_DEV) {
5826 		dmdp->ddm_flags |= DM_NO_FSPERM;
5827 	}
5828 	if (read_priv || write_priv) {
5829 		dmdp->ddm_node_priv =
5830 		    devpolicy_priv_by_name(read_priv, write_priv);
5831 	}
5832 	dmdp->ddm_priv_mode = priv_mode;
5833 
5834 	ddi_append_minor_node(dip, dmdp);
5835 
5836 	/*
5837 	 * only log ddi_create_minor_node() calls which occur
5838 	 * outside the scope of attach(9e)/detach(9e) reconfigurations
5839 	 */
5840 	if (!(DEVI_IS_ATTACHING(dip) || DEVI_IS_DETACHING(dip)) &&
5841 	    mtype != DDM_INTERNAL_PATH) {
5842 		(void) i_log_devfs_minor_create(dip, name);
5843 	}
5844 
5845 	/*
5846 	 * Check if any dacf rules match the creation of this minor node
5847 	 */
5848 	dacfc_match_create_minor(name, node_type, dip, dmdp, flag);
5849 	return (DDI_SUCCESS);
5850 }
5851 
5852 int
5853 ddi_create_minor_node(dev_info_t *dip, char *name, int spec_type,
5854     minor_t minor_num, char *node_type, int flag)
5855 {
5856 	return (ddi_create_minor_common(dip, name, spec_type, minor_num,
5857 	    node_type, flag, DDM_MINOR, NULL, NULL, 0));
5858 }
5859 
5860 int
5861 ddi_create_priv_minor_node(dev_info_t *dip, char *name, int spec_type,
5862     minor_t minor_num, char *node_type, int flag,
5863     const char *rdpriv, const char *wrpriv, mode_t priv_mode)
5864 {
5865 	return (ddi_create_minor_common(dip, name, spec_type, minor_num,
5866 	    node_type, flag, DDM_MINOR, rdpriv, wrpriv, priv_mode));
5867 }
5868 
5869 int
5870 ddi_create_default_minor_node(dev_info_t *dip, char *name, int spec_type,
5871     minor_t minor_num, char *node_type, int flag)
5872 {
5873 	return (ddi_create_minor_common(dip, name, spec_type, minor_num,
5874 	    node_type, flag, DDM_DEFAULT, NULL, NULL, 0));
5875 }
5876 
5877 /*
5878  * Internal (non-ddi) routine for drivers to export names known
5879  * to the kernel (especially ddi_pathname_to_dev_t and friends)
5880  * but not exported externally to /dev
5881  */
5882 int
5883 ddi_create_internal_pathname(dev_info_t *dip, char *name, int spec_type,
5884     minor_t minor_num)
5885 {
5886 	return (ddi_create_minor_common(dip, name, spec_type, minor_num,
5887 	    "internal", 0, DDM_INTERNAL_PATH, NULL, NULL, 0));
5888 }
5889 
5890 void
5891 ddi_remove_minor_node(dev_info_t *dip, char *name)
5892 {
5893 	int			circ;
5894 	struct ddi_minor_data	*dmdp, *dmdp1;
5895 	struct ddi_minor_data	**dmdp_prev;
5896 
5897 	ndi_devi_enter(dip, &circ);
5898 	dmdp_prev = &DEVI(dip)->devi_minor;
5899 	dmdp = DEVI(dip)->devi_minor;
5900 	while (dmdp != NULL) {
5901 		dmdp1 = dmdp->next;
5902 		if ((name == NULL || (dmdp->ddm_name != NULL &&
5903 		    strcmp(name, dmdp->ddm_name) == 0))) {
5904 			if (dmdp->ddm_name != NULL) {
5905 				if (dmdp->type != DDM_INTERNAL_PATH)
5906 					(void) i_log_devfs_minor_remove(dip,
5907 					    dmdp->ddm_name);
5908 				kmem_free(dmdp->ddm_name,
5909 				    strlen(dmdp->ddm_name) + 1);
5910 			}
5911 			/*
5912 			 * Release device privilege, if any.
5913 			 * Release dacf client data associated with this minor
5914 			 * node by storing NULL.
5915 			 */
5916 			if (dmdp->ddm_node_priv)
5917 				dpfree(dmdp->ddm_node_priv);
5918 			dacf_store_info((dacf_infohdl_t)dmdp, NULL);
5919 			kmem_free(dmdp, sizeof (struct ddi_minor_data));
5920 			*dmdp_prev = dmdp1;
5921 			/*
5922 			 * OK, we found it, so get out now -- if we drive on,
5923 			 * we will strcmp against garbage.  See 1139209.
5924 			 */
5925 			if (name != NULL)
5926 				break;
5927 		} else {
5928 			dmdp_prev = &dmdp->next;
5929 		}
5930 		dmdp = dmdp1;
5931 	}
5932 	ndi_devi_exit(dip, circ);
5933 }
5934 
5935 
5936 int
5937 ddi_in_panic()
5938 {
5939 	return (panicstr != NULL);
5940 }
5941 
5942 
5943 /*
5944  * Find first bit set in a mask (returned counting from 1 up)
5945  */
5946 
5947 int
5948 ddi_ffs(long mask)
5949 {
5950 	return (ffs(mask));
5951 }
5952 
5953 /*
5954  * Find last bit set. Take mask and clear
5955  * all but the most significant bit, and
5956  * then let ffs do the rest of the work.
5957  *
5958  * Algorithm courtesy of Steve Chessin.
5959  */
5960 
5961 int
5962 ddi_fls(long mask)
5963 {
5964 	while (mask) {
5965 		long nx;
5966 
5967 		if ((nx = (mask & (mask - 1))) == 0)
5968 			break;
5969 		mask = nx;
5970 	}
5971 	return (ffs(mask));
5972 }
5973 
5974 /*
5975  * The ddi_soft_state_* routines comprise generic storage management utilities
5976  * for driver soft state structures (in "the old days," this was done with
5977  * statically sized array - big systems and dynamic loading and unloading
5978  * make heap allocation more attractive).
5979  */
5980 
5981 /*
5982  * Allocate a set of pointers to 'n_items' objects of size 'size'
5983  * bytes.  Each pointer is initialized to nil.
5984  *
5985  * The 'size' and 'n_items' values are stashed in the opaque
5986  * handle returned to the caller.
5987  *
5988  * This implementation interprets 'set of pointers' to mean 'array
5989  * of pointers' but note that nothing in the interface definition
5990  * precludes an implementation that uses, for example, a linked list.
5991  * However there should be a small efficiency gain from using an array
5992  * at lookup time.
5993  *
5994  * NOTE	As an optimization, we make our growable array allocations in
5995  *	powers of two (bytes), since that's how much kmem_alloc (currently)
5996  *	gives us anyway.  It should save us some free/realloc's ..
5997  *
5998  *	As a further optimization, we make the growable array start out
5999  *	with MIN_N_ITEMS in it.
6000  */
6001 
6002 #define	MIN_N_ITEMS	8	/* 8 void *'s == 32 bytes */
6003 
6004 int
6005 ddi_soft_state_init(void **state_p, size_t size, size_t n_items)
6006 {
6007 	i_ddi_soft_state	*ss;
6008 
6009 	if (state_p == NULL || size == 0)
6010 		return (EINVAL);
6011 
6012 	ss = kmem_zalloc(sizeof (*ss), KM_SLEEP);
6013 	mutex_init(&ss->lock, NULL, MUTEX_DRIVER, NULL);
6014 	ss->size = size;
6015 
6016 	if (n_items < MIN_N_ITEMS)
6017 		ss->n_items = MIN_N_ITEMS;
6018 	else {
6019 		int bitlog;
6020 
6021 		if ((bitlog = ddi_fls(n_items)) == ddi_ffs(n_items))
6022 			bitlog--;
6023 		ss->n_items = 1 << bitlog;
6024 	}
6025 
6026 	ASSERT(ss->n_items >= n_items);
6027 
6028 	ss->array = kmem_zalloc(ss->n_items * sizeof (void *), KM_SLEEP);
6029 
6030 	*state_p = ss;
6031 	return (0);
6032 }
6033 
6034 /*
6035  * Allocate a state structure of size 'size' to be associated
6036  * with item 'item'.
6037  *
6038  * In this implementation, the array is extended to
6039  * allow the requested offset, if needed.
6040  */
6041 int
6042 ddi_soft_state_zalloc(void *state, int item)
6043 {
6044 	i_ddi_soft_state	*ss = (i_ddi_soft_state *)state;
6045 	void			**array;
6046 	void			*new_element;
6047 
6048 	if ((state == NULL) || (item < 0))
6049 		return (DDI_FAILURE);
6050 
6051 	mutex_enter(&ss->lock);
6052 	if (ss->size == 0) {
6053 		mutex_exit(&ss->lock);
6054 		cmn_err(CE_WARN, "ddi_soft_state_zalloc: bad handle: %s",
6055 		    mod_containing_pc(caller()));
6056 		return (DDI_FAILURE);
6057 	}
6058 
6059 	array = ss->array;	/* NULL if ss->n_items == 0 */
6060 	ASSERT(ss->n_items != 0 && array != NULL);
6061 
6062 	/*
6063 	 * refuse to tread on an existing element
6064 	 */
6065 	if (item < ss->n_items && array[item] != NULL) {
6066 		mutex_exit(&ss->lock);
6067 		return (DDI_FAILURE);
6068 	}
6069 
6070 	/*
6071 	 * Allocate a new element to plug in
6072 	 */
6073 	new_element = kmem_zalloc(ss->size, KM_SLEEP);
6074 
6075 	/*
6076 	 * Check if the array is big enough, if not, grow it.
6077 	 */
6078 	if (item >= ss->n_items) {
6079 		void			**new_array;
6080 		size_t			new_n_items;
6081 		struct i_ddi_soft_state	*dirty;
6082 
6083 		/*
6084 		 * Allocate a new array of the right length, copy
6085 		 * all the old pointers to the new array, then
6086 		 * if it exists at all, put the old array on the
6087 		 * dirty list.
6088 		 *
6089 		 * Note that we can't kmem_free() the old array.
6090 		 *
6091 		 * Why -- well the 'get' operation is 'mutex-free', so we
6092 		 * can't easily catch a suspended thread that is just about
6093 		 * to dereference the array we just grew out of.  So we
6094 		 * cons up a header and put it on a list of 'dirty'
6095 		 * pointer arrays.  (Dirty in the sense that there may
6096 		 * be suspended threads somewhere that are in the middle
6097 		 * of referencing them).  Fortunately, we -can- garbage
6098 		 * collect it all at ddi_soft_state_fini time.
6099 		 */
6100 		new_n_items = ss->n_items;
6101 		while (new_n_items < (1 + item))
6102 			new_n_items <<= 1;	/* double array size .. */
6103 
6104 		ASSERT(new_n_items >= (1 + item));	/* sanity check! */
6105 
6106 		new_array = kmem_zalloc(new_n_items * sizeof (void *),
6107 		    KM_SLEEP);
6108 		/*
6109 		 * Copy the pointers into the new array
6110 		 */
6111 		bcopy(array, new_array, ss->n_items * sizeof (void *));
6112 
6113 		/*
6114 		 * Save the old array on the dirty list
6115 		 */
6116 		dirty = kmem_zalloc(sizeof (*dirty), KM_SLEEP);
6117 		dirty->array = ss->array;
6118 		dirty->n_items = ss->n_items;
6119 		dirty->next = ss->next;
6120 		ss->next = dirty;
6121 
6122 		ss->array = (array = new_array);
6123 		ss->n_items = new_n_items;
6124 	}
6125 
6126 	ASSERT(array != NULL && item < ss->n_items && array[item] == NULL);
6127 
6128 	array[item] = new_element;
6129 
6130 	mutex_exit(&ss->lock);
6131 	return (DDI_SUCCESS);
6132 }
6133 
6134 /*
6135  * Fetch a pointer to the allocated soft state structure.
6136  *
6137  * This is designed to be cheap.
6138  *
6139  * There's an argument that there should be more checking for
6140  * nil pointers and out of bounds on the array.. but we do a lot
6141  * of that in the alloc/free routines.
6142  *
6143  * An array has the convenience that we don't need to lock read-access
6144  * to it c.f. a linked list.  However our "expanding array" strategy
6145  * means that we should hold a readers lock on the i_ddi_soft_state
6146  * structure.
6147  *
6148  * However, from a performance viewpoint, we need to do it without
6149  * any locks at all -- this also makes it a leaf routine.  The algorithm
6150  * is 'lock-free' because we only discard the pointer arrays at
6151  * ddi_soft_state_fini() time.
6152  */
6153 void *
6154 ddi_get_soft_state(void *state, int item)
6155 {
6156 	i_ddi_soft_state	*ss = (i_ddi_soft_state *)state;
6157 
6158 	ASSERT((ss != NULL) && (item >= 0));
6159 
6160 	if (item < ss->n_items && ss->array != NULL)
6161 		return (ss->array[item]);
6162 	return (NULL);
6163 }
6164 
6165 /*
6166  * Free the state structure corresponding to 'item.'   Freeing an
6167  * element that has either gone or was never allocated is not
6168  * considered an error.  Note that we free the state structure, but
6169  * we don't shrink our pointer array, or discard 'dirty' arrays,
6170  * since even a few pointers don't really waste too much memory.
6171  *
6172  * Passing an item number that is out of bounds, or a null pointer will
6173  * provoke an error message.
6174  */
6175 void
6176 ddi_soft_state_free(void *state, int item)
6177 {
6178 	i_ddi_soft_state	*ss = (i_ddi_soft_state *)state;
6179 	void			**array;
6180 	void			*element;
6181 	static char		msg[] = "ddi_soft_state_free:";
6182 
6183 	if (ss == NULL) {
6184 		cmn_err(CE_WARN, "%s null handle: %s",
6185 		    msg, mod_containing_pc(caller()));
6186 		return;
6187 	}
6188 
6189 	element = NULL;
6190 
6191 	mutex_enter(&ss->lock);
6192 
6193 	if ((array = ss->array) == NULL || ss->size == 0) {
6194 		cmn_err(CE_WARN, "%s bad handle: %s",
6195 		    msg, mod_containing_pc(caller()));
6196 	} else if (item < 0 || item >= ss->n_items) {
6197 		cmn_err(CE_WARN, "%s item %d not in range [0..%lu]: %s",
6198 		    msg, item, ss->n_items - 1, mod_containing_pc(caller()));
6199 	} else if (array[item] != NULL) {
6200 		element = array[item];
6201 		array[item] = NULL;
6202 	}
6203 
6204 	mutex_exit(&ss->lock);
6205 
6206 	if (element)
6207 		kmem_free(element, ss->size);
6208 }
6209 
6210 /*
6211  * Free the entire set of pointers, and any
6212  * soft state structures contained therein.
6213  *
6214  * Note that we don't grab the ss->lock mutex, even though
6215  * we're inspecting the various fields of the data structure.
6216  *
6217  * There is an implicit assumption that this routine will
6218  * never run concurrently with any of the above on this
6219  * particular state structure i.e. by the time the driver
6220  * calls this routine, there should be no other threads
6221  * running in the driver.
6222  */
6223 void
6224 ddi_soft_state_fini(void **state_p)
6225 {
6226 	i_ddi_soft_state	*ss, *dirty;
6227 	int			item;
6228 	static char		msg[] = "ddi_soft_state_fini:";
6229 
6230 	if (state_p == NULL ||
6231 	    (ss = (i_ddi_soft_state *)(*state_p)) == NULL) {
6232 		cmn_err(CE_WARN, "%s null handle: %s",
6233 		    msg, mod_containing_pc(caller()));
6234 		return;
6235 	}
6236 
6237 	if (ss->size == 0) {
6238 		cmn_err(CE_WARN, "%s bad handle: %s",
6239 		    msg, mod_containing_pc(caller()));
6240 		return;
6241 	}
6242 
6243 	if (ss->n_items > 0) {
6244 		for (item = 0; item < ss->n_items; item++)
6245 			ddi_soft_state_free(ss, item);
6246 		kmem_free(ss->array, ss->n_items * sizeof (void *));
6247 	}
6248 
6249 	/*
6250 	 * Now delete any dirty arrays from previous 'grow' operations
6251 	 */
6252 	for (dirty = ss->next; dirty; dirty = ss->next) {
6253 		ss->next = dirty->next;
6254 		kmem_free(dirty->array, dirty->n_items * sizeof (void *));
6255 		kmem_free(dirty, sizeof (*dirty));
6256 	}
6257 
6258 	mutex_destroy(&ss->lock);
6259 	kmem_free(ss, sizeof (*ss));
6260 
6261 	*state_p = NULL;
6262 }
6263 
6264 #define	SS_N_ITEMS_PER_HASH	16
6265 #define	SS_MIN_HASH_SZ		16
6266 #define	SS_MAX_HASH_SZ		4096
6267 
6268 int
6269 ddi_soft_state_bystr_init(ddi_soft_state_bystr **state_p, size_t size,
6270     int n_items)
6271 {
6272 	i_ddi_soft_state_bystr	*sss;
6273 	int			hash_sz;
6274 
6275 	ASSERT(state_p && size && n_items);
6276 	if ((state_p == NULL) || (size == 0) || (n_items == 0))
6277 		return (EINVAL);
6278 
6279 	/* current implementation is based on hash, convert n_items to hash */
6280 	hash_sz = n_items / SS_N_ITEMS_PER_HASH;
6281 	if (hash_sz < SS_MIN_HASH_SZ)
6282 		hash_sz = SS_MIN_HASH_SZ;
6283 	else if (hash_sz > SS_MAX_HASH_SZ)
6284 		hash_sz = SS_MAX_HASH_SZ;
6285 
6286 	/* allocate soft_state pool */
6287 	sss = kmem_zalloc(sizeof (*sss), KM_SLEEP);
6288 	sss->ss_size = size;
6289 	sss->ss_mod_hash = mod_hash_create_strhash("soft_state_bystr",
6290 	    hash_sz, mod_hash_null_valdtor);
6291 	*state_p = (ddi_soft_state_bystr *)sss;
6292 	return (0);
6293 }
6294 
6295 int
6296 ddi_soft_state_bystr_zalloc(ddi_soft_state_bystr *state, const char *str)
6297 {
6298 	i_ddi_soft_state_bystr	*sss = (i_ddi_soft_state_bystr *)state;
6299 	void			*sso;
6300 	char			*dup_str;
6301 
6302 	ASSERT(sss && str && sss->ss_mod_hash);
6303 	if ((sss == NULL) || (str == NULL) || (sss->ss_mod_hash == NULL))
6304 		return (DDI_FAILURE);
6305 	sso = kmem_zalloc(sss->ss_size, KM_SLEEP);
6306 	dup_str = i_ddi_strdup((char *)str, KM_SLEEP);
6307 	if (mod_hash_insert(sss->ss_mod_hash,
6308 	    (mod_hash_key_t)dup_str, (mod_hash_val_t)sso) == 0)
6309 		return (DDI_SUCCESS);
6310 
6311 	/*
6312 	 * The only error from an strhash insert is caused by a duplicate key.
6313 	 * We refuse to tread on an existing elements, so free and fail.
6314 	 */
6315 	kmem_free(dup_str, strlen(dup_str) + 1);
6316 	kmem_free(sso, sss->ss_size);
6317 	return (DDI_FAILURE);
6318 }
6319 
6320 void *
6321 ddi_soft_state_bystr_get(ddi_soft_state_bystr *state, const char *str)
6322 {
6323 	i_ddi_soft_state_bystr	*sss = (i_ddi_soft_state_bystr *)state;
6324 	void			*sso;
6325 
6326 	ASSERT(sss && str && sss->ss_mod_hash);
6327 	if ((sss == NULL) || (str == NULL) || (sss->ss_mod_hash == NULL))
6328 		return (NULL);
6329 
6330 	if (mod_hash_find(sss->ss_mod_hash,
6331 	    (mod_hash_key_t)str, (mod_hash_val_t *)&sso) == 0)
6332 		return (sso);
6333 	return (NULL);
6334 }
6335 
6336 void
6337 ddi_soft_state_bystr_free(ddi_soft_state_bystr *state, const char *str)
6338 {
6339 	i_ddi_soft_state_bystr	*sss = (i_ddi_soft_state_bystr *)state;
6340 	void			*sso;
6341 
6342 	ASSERT(sss && str && sss->ss_mod_hash);
6343 	if ((sss == NULL) || (str == NULL) || (sss->ss_mod_hash == NULL))
6344 		return;
6345 
6346 	(void) mod_hash_remove(sss->ss_mod_hash,
6347 	    (mod_hash_key_t)str, (mod_hash_val_t *)&sso);
6348 	kmem_free(sso, sss->ss_size);
6349 }
6350 
6351 void
6352 ddi_soft_state_bystr_fini(ddi_soft_state_bystr **state_p)
6353 {
6354 	i_ddi_soft_state_bystr	*sss;
6355 
6356 	ASSERT(state_p);
6357 	if (state_p == NULL)
6358 		return;
6359 
6360 	sss = (i_ddi_soft_state_bystr *)(*state_p);
6361 	if (sss == NULL)
6362 		return;
6363 
6364 	ASSERT(sss->ss_mod_hash);
6365 	if (sss->ss_mod_hash) {
6366 		mod_hash_destroy_strhash(sss->ss_mod_hash);
6367 		sss->ss_mod_hash = NULL;
6368 	}
6369 
6370 	kmem_free(sss, sizeof (*sss));
6371 	*state_p = NULL;
6372 }
6373 
6374 /*
6375  * The ddi_strid_* routines provide string-to-index management utilities.
6376  */
6377 /* allocate and initialize an strid set */
6378 int
6379 ddi_strid_init(ddi_strid **strid_p, int n_items)
6380 {
6381 	i_ddi_strid	*ss;
6382 	int		hash_sz;
6383 
6384 	if (strid_p == NULL)
6385 		return (DDI_FAILURE);
6386 
6387 	/* current implementation is based on hash, convert n_items to hash */
6388 	hash_sz = n_items / SS_N_ITEMS_PER_HASH;
6389 	if (hash_sz < SS_MIN_HASH_SZ)
6390 		hash_sz = SS_MIN_HASH_SZ;
6391 	else if (hash_sz > SS_MAX_HASH_SZ)
6392 		hash_sz = SS_MAX_HASH_SZ;
6393 
6394 	ss = kmem_alloc(sizeof (*ss), KM_SLEEP);
6395 	ss->strid_chunksz = n_items;
6396 	ss->strid_spacesz = n_items;
6397 	ss->strid_space = id_space_create("strid", 1, n_items);
6398 	ss->strid_bystr = mod_hash_create_strhash("strid_bystr", hash_sz,
6399 	    mod_hash_null_valdtor);
6400 	ss->strid_byid = mod_hash_create_idhash("strid_byid", hash_sz,
6401 	    mod_hash_null_valdtor);
6402 	*strid_p = (ddi_strid *)ss;
6403 	return (DDI_SUCCESS);
6404 }
6405 
6406 /* allocate an id mapping within the specified set for str, return id */
6407 static id_t
6408 i_ddi_strid_alloc(ddi_strid *strid, char *str)
6409 {
6410 	i_ddi_strid	*ss = (i_ddi_strid *)strid;
6411 	id_t		id;
6412 	char		*s;
6413 
6414 	ASSERT(ss && str);
6415 	if ((ss == NULL) || (str == NULL))
6416 		return (0);
6417 
6418 	/*
6419 	 * Allocate an id using VM_FIRSTFIT in order to keep allocated id
6420 	 * range as compressed as possible.  This is important to minimize
6421 	 * the amount of space used when the id is used as a ddi_soft_state
6422 	 * index by the caller.
6423 	 *
6424 	 * If the id list is exhausted, increase the size of the list
6425 	 * by the chuck size specified in ddi_strid_init and reattempt
6426 	 * the allocation
6427 	 */
6428 	if ((id = id_allocff_nosleep(ss->strid_space)) == (id_t)-1) {
6429 		id_space_extend(ss->strid_space, ss->strid_spacesz,
6430 		    ss->strid_spacesz + ss->strid_chunksz);
6431 		ss->strid_spacesz += ss->strid_chunksz;
6432 		if ((id = id_allocff_nosleep(ss->strid_space)) == (id_t)-1)
6433 			return (0);
6434 	}
6435 
6436 	/*
6437 	 * NOTE: since we create and destroy in unison we can save space by
6438 	 * using bystr key as the byid value.  This means destroy must occur
6439 	 * in (byid, bystr) order.
6440 	 */
6441 	s = i_ddi_strdup(str, KM_SLEEP);
6442 	if (mod_hash_insert(ss->strid_bystr, (mod_hash_key_t)s,
6443 	    (mod_hash_val_t)(intptr_t)id) != 0) {
6444 		ddi_strid_free(strid, id);
6445 		return (0);
6446 	}
6447 	if (mod_hash_insert(ss->strid_byid, (mod_hash_key_t)(intptr_t)id,
6448 	    (mod_hash_val_t)s) != 0) {
6449 		ddi_strid_free(strid, id);
6450 		return (0);
6451 	}
6452 
6453 	/* NOTE: s if freed on mod_hash_destroy by mod_hash_strval_dtor */
6454 	return (id);
6455 }
6456 
6457 /* allocate an id mapping within the specified set for str, return id */
6458 id_t
6459 ddi_strid_alloc(ddi_strid *strid, char *str)
6460 {
6461 	return (i_ddi_strid_alloc(strid, str));
6462 }
6463 
6464 /* return the id within the specified strid given the str */
6465 id_t
6466 ddi_strid_str2id(ddi_strid *strid, char *str)
6467 {
6468 	i_ddi_strid	*ss = (i_ddi_strid *)strid;
6469 	id_t		id = 0;
6470 	mod_hash_val_t	hv;
6471 
6472 	ASSERT(ss && str);
6473 	if (ss && str && (mod_hash_find(ss->strid_bystr,
6474 	    (mod_hash_key_t)str, &hv) == 0))
6475 		id = (int)(intptr_t)hv;
6476 	return (id);
6477 }
6478 
6479 /* return str within the specified strid given the id */
6480 char *
6481 ddi_strid_id2str(ddi_strid *strid, id_t id)
6482 {
6483 	i_ddi_strid	*ss = (i_ddi_strid *)strid;
6484 	char		*str = NULL;
6485 	mod_hash_val_t	hv;
6486 
6487 	ASSERT(ss && id > 0);
6488 	if (ss && (id > 0) && (mod_hash_find(ss->strid_byid,
6489 	    (mod_hash_key_t)(uintptr_t)id, &hv) == 0))
6490 		str = (char *)hv;
6491 	return (str);
6492 }
6493 
6494 /* free the id mapping within the specified strid */
6495 void
6496 ddi_strid_free(ddi_strid *strid, id_t id)
6497 {
6498 	i_ddi_strid	*ss = (i_ddi_strid *)strid;
6499 	char		*str;
6500 
6501 	ASSERT(ss && id > 0);
6502 	if ((ss == NULL) || (id <= 0))
6503 		return;
6504 
6505 	/* bystr key is byid value: destroy order must be (byid, bystr) */
6506 	str = ddi_strid_id2str(strid, id);
6507 	(void) mod_hash_destroy(ss->strid_byid, (mod_hash_key_t)(uintptr_t)id);
6508 	id_free(ss->strid_space, id);
6509 
6510 	if (str)
6511 		(void) mod_hash_destroy(ss->strid_bystr, (mod_hash_key_t)str);
6512 }
6513 
6514 /* destroy the strid set */
6515 void
6516 ddi_strid_fini(ddi_strid **strid_p)
6517 {
6518 	i_ddi_strid	*ss;
6519 
6520 	ASSERT(strid_p);
6521 	if (strid_p == NULL)
6522 		return;
6523 
6524 	ss = (i_ddi_strid *)(*strid_p);
6525 	if (ss == NULL)
6526 		return;
6527 
6528 	/* bystr key is byid value: destroy order must be (byid, bystr) */
6529 	if (ss->strid_byid)
6530 		mod_hash_destroy_hash(ss->strid_byid);
6531 	if (ss->strid_byid)
6532 		mod_hash_destroy_hash(ss->strid_bystr);
6533 	if (ss->strid_space)
6534 		id_space_destroy(ss->strid_space);
6535 	kmem_free(ss, sizeof (*ss));
6536 	*strid_p = NULL;
6537 }
6538 
6539 /*
6540  * This sets the devi_addr entry in the dev_info structure 'dip' to 'name'.
6541  * Storage is double buffered to prevent updates during devi_addr use -
6542  * double buffering is adaquate for reliable ddi_deviname() consumption.
6543  * The double buffer is not freed until dev_info structure destruction
6544  * (by i_ddi_free_node).
6545  */
6546 void
6547 ddi_set_name_addr(dev_info_t *dip, char *name)
6548 {
6549 	char	*buf = DEVI(dip)->devi_addr_buf;
6550 	char	*newaddr;
6551 
6552 	if (buf == NULL) {
6553 		buf = kmem_zalloc(2 * MAXNAMELEN, KM_SLEEP);
6554 		DEVI(dip)->devi_addr_buf = buf;
6555 	}
6556 
6557 	if (name) {
6558 		ASSERT(strlen(name) < MAXNAMELEN);
6559 		newaddr = (DEVI(dip)->devi_addr == buf) ?
6560 		    (buf + MAXNAMELEN) : buf;
6561 		(void) strlcpy(newaddr, name, MAXNAMELEN);
6562 	} else
6563 		newaddr = NULL;
6564 
6565 	DEVI(dip)->devi_addr = newaddr;
6566 }
6567 
6568 char *
6569 ddi_get_name_addr(dev_info_t *dip)
6570 {
6571 	return (DEVI(dip)->devi_addr);
6572 }
6573 
6574 void
6575 ddi_set_parent_data(dev_info_t *dip, void *pd)
6576 {
6577 	DEVI(dip)->devi_parent_data = pd;
6578 }
6579 
6580 void *
6581 ddi_get_parent_data(dev_info_t *dip)
6582 {
6583 	return (DEVI(dip)->devi_parent_data);
6584 }
6585 
6586 /*
6587  * ddi_name_to_major: returns the major number of a named module,
6588  * derived from the current driver alias binding.
6589  *
6590  * Caveat: drivers should avoid the use of this function, in particular
6591  * together with ddi_get_name/ddi_binding name, as per
6592  *	major = ddi_name_to_major(ddi_get_name(devi));
6593  * ddi_name_to_major() relies on the state of the device/alias binding,
6594  * which can and does change dynamically as aliases are administered
6595  * over time.  An attached device instance cannot rely on the major
6596  * number returned by ddi_name_to_major() to match its own major number.
6597  *
6598  * For driver use, ddi_driver_major() reliably returns the major number
6599  * for the module to which the device was bound at attach time over
6600  * the life of the instance.
6601  *	major = ddi_driver_major(dev_info_t *)
6602  */
6603 major_t
6604 ddi_name_to_major(char *name)
6605 {
6606 	return (mod_name_to_major(name));
6607 }
6608 
6609 /*
6610  * ddi_major_to_name: Returns the module name bound to a major number.
6611  */
6612 char *
6613 ddi_major_to_name(major_t major)
6614 {
6615 	return (mod_major_to_name(major));
6616 }
6617 
6618 /*
6619  * Return the name of the devinfo node pointed at by 'dip' in the buffer
6620  * pointed at by 'name.'  A devinfo node is named as a result of calling
6621  * ddi_initchild().
6622  *
6623  * Note: the driver must be held before calling this function!
6624  */
6625 char *
6626 ddi_deviname(dev_info_t *dip, char *name)
6627 {
6628 	char *addrname;
6629 	char none = '\0';
6630 
6631 	if (dip == ddi_root_node()) {
6632 		*name = '\0';
6633 		return (name);
6634 	}
6635 
6636 	if (i_ddi_node_state(dip) < DS_BOUND) {
6637 		addrname = &none;
6638 	} else {
6639 		/*
6640 		 * Use ddi_get_name_addr() without checking state so we get
6641 		 * a unit-address if we are called after ddi_set_name_addr()
6642 		 * by nexus DDI_CTL_INITCHILD code, but before completing
6643 		 * node promotion to DS_INITIALIZED.  We currently have
6644 		 * two situations where we are called in this state:
6645 		 *   o  For framework processing of a path-oriented alias.
6646 		 *   o  If a SCSA nexus driver calls ddi_devid_register()
6647 		 *	from it's tran_tgt_init(9E) implementation.
6648 		 */
6649 		addrname = ddi_get_name_addr(dip);
6650 		if (addrname == NULL)
6651 			addrname = &none;
6652 	}
6653 
6654 	if (*addrname == '\0') {
6655 		(void) sprintf(name, "/%s", ddi_node_name(dip));
6656 	} else {
6657 		(void) sprintf(name, "/%s@%s", ddi_node_name(dip), addrname);
6658 	}
6659 
6660 	return (name);
6661 }
6662 
6663 /*
6664  * Spits out the name of device node, typically name@addr, for a given node,
6665  * using the driver name, not the nodename.
6666  *
6667  * Used by match_parent. Not to be used elsewhere.
6668  */
6669 char *
6670 i_ddi_parname(dev_info_t *dip, char *name)
6671 {
6672 	char *addrname;
6673 
6674 	if (dip == ddi_root_node()) {
6675 		*name = '\0';
6676 		return (name);
6677 	}
6678 
6679 	ASSERT(i_ddi_node_state(dip) >= DS_INITIALIZED);
6680 
6681 	if (*(addrname = ddi_get_name_addr(dip)) == '\0')
6682 		(void) sprintf(name, "%s", ddi_binding_name(dip));
6683 	else
6684 		(void) sprintf(name, "%s@%s", ddi_binding_name(dip), addrname);
6685 	return (name);
6686 }
6687 
6688 static char *
6689 pathname_work(dev_info_t *dip, char *path)
6690 {
6691 	char *bp;
6692 
6693 	if (dip == ddi_root_node()) {
6694 		*path = '\0';
6695 		return (path);
6696 	}
6697 	(void) pathname_work(ddi_get_parent(dip), path);
6698 	bp = path + strlen(path);
6699 	(void) ddi_deviname(dip, bp);
6700 	return (path);
6701 }
6702 
6703 char *
6704 ddi_pathname(dev_info_t *dip, char *path)
6705 {
6706 	return (pathname_work(dip, path));
6707 }
6708 
6709 char *
6710 ddi_pathname_minor(struct ddi_minor_data *dmdp, char *path)
6711 {
6712 	if (dmdp->dip == NULL)
6713 		*path = '\0';
6714 	else {
6715 		(void) ddi_pathname(dmdp->dip, path);
6716 		if (dmdp->ddm_name) {
6717 			(void) strcat(path, ":");
6718 			(void) strcat(path, dmdp->ddm_name);
6719 		}
6720 	}
6721 	return (path);
6722 }
6723 
6724 static char *
6725 pathname_work_obp(dev_info_t *dip, char *path)
6726 {
6727 	char *bp;
6728 	char *obp_path;
6729 
6730 	/*
6731 	 * look up the "obp-path" property, return the path if it exists
6732 	 */
6733 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
6734 	    "obp-path", &obp_path) == DDI_PROP_SUCCESS) {
6735 		(void) strcpy(path, obp_path);
6736 		ddi_prop_free(obp_path);
6737 		return (path);
6738 	}
6739 
6740 	/*
6741 	 * stop at root, no obp path
6742 	 */
6743 	if (dip == ddi_root_node()) {
6744 		return (NULL);
6745 	}
6746 
6747 	obp_path = pathname_work_obp(ddi_get_parent(dip), path);
6748 	if (obp_path == NULL)
6749 		return (NULL);
6750 
6751 	/*
6752 	 * append our component to parent's obp path
6753 	 */
6754 	bp = path + strlen(path);
6755 	if (*(bp - 1) != '/')
6756 		(void) strcat(bp++, "/");
6757 	(void) ddi_deviname(dip, bp);
6758 	return (path);
6759 }
6760 
6761 /*
6762  * return the 'obp-path' based path for the given node, or NULL if the node
6763  * does not have a different obp path. NOTE: Unlike ddi_pathname, this
6764  * function can't be called from interrupt context (since we need to
6765  * lookup a string property).
6766  */
6767 char *
6768 ddi_pathname_obp(dev_info_t *dip, char *path)
6769 {
6770 	ASSERT(!servicing_interrupt());
6771 	if (dip == NULL || path == NULL)
6772 		return (NULL);
6773 
6774 	/* split work into a separate function to aid debugging */
6775 	return (pathname_work_obp(dip, path));
6776 }
6777 
6778 int
6779 ddi_pathname_obp_set(dev_info_t *dip, char *component)
6780 {
6781 	dev_info_t *pdip;
6782 	char *obp_path = NULL;
6783 	int rc = DDI_FAILURE;
6784 
6785 	if (dip == NULL)
6786 		return (DDI_FAILURE);
6787 
6788 	obp_path = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
6789 
6790 	pdip = ddi_get_parent(dip);
6791 
6792 	if (ddi_pathname_obp(pdip, obp_path) == NULL) {
6793 		(void) ddi_pathname(pdip, obp_path);
6794 	}
6795 
6796 	if (component) {
6797 		(void) strncat(obp_path, "/", MAXPATHLEN);
6798 		(void) strncat(obp_path, component, MAXPATHLEN);
6799 	}
6800 	rc = ndi_prop_update_string(DDI_DEV_T_NONE, dip, "obp-path",
6801 	    obp_path);
6802 
6803 	if (obp_path)
6804 		kmem_free(obp_path, MAXPATHLEN);
6805 
6806 	return (rc);
6807 }
6808 
6809 /*
6810  * Given a dev_t, return the pathname of the corresponding device in the
6811  * buffer pointed at by "path."  The buffer is assumed to be large enough
6812  * to hold the pathname of the device (MAXPATHLEN).
6813  *
6814  * The pathname of a device is the pathname of the devinfo node to which
6815  * the device "belongs," concatenated with the character ':' and the name
6816  * of the minor node corresponding to the dev_t.  If spec_type is 0 then
6817  * just the pathname of the devinfo node is returned without driving attach
6818  * of that node.  For a non-zero spec_type, an attach is performed and a
6819  * search of the minor list occurs.
6820  *
6821  * It is possible that the path associated with the dev_t is not
6822  * currently available in the devinfo tree.  In order to have a
6823  * dev_t, a device must have been discovered before, which means
6824  * that the path is always in the instance tree.  The one exception
6825  * to this is if the dev_t is associated with a pseudo driver, in
6826  * which case the device must exist on the pseudo branch of the
6827  * devinfo tree as a result of parsing .conf files.
6828  */
6829 int
6830 ddi_dev_pathname(dev_t devt, int spec_type, char *path)
6831 {
6832 	int		circ;
6833 	major_t		major = getmajor(devt);
6834 	int		instance;
6835 	dev_info_t	*dip;
6836 	char		*minorname;
6837 	char		*drvname;
6838 
6839 	if (major >= devcnt)
6840 		goto fail;
6841 	if (major == clone_major) {
6842 		/* clone has no minor nodes, manufacture the path here */
6843 		if ((drvname = ddi_major_to_name(getminor(devt))) == NULL)
6844 			goto fail;
6845 
6846 		(void) snprintf(path, MAXPATHLEN, "%s:%s", CLONE_PATH, drvname);
6847 		return (DDI_SUCCESS);
6848 	}
6849 
6850 	/* extract instance from devt (getinfo(9E) DDI_INFO_DEVT2INSTANCE). */
6851 	if ((instance = dev_to_instance(devt)) == -1)
6852 		goto fail;
6853 
6854 	/* reconstruct the path given the major/instance */
6855 	if (e_ddi_majorinstance_to_path(major, instance, path) != DDI_SUCCESS)
6856 		goto fail;
6857 
6858 	/* if spec_type given we must drive attach and search minor nodes */
6859 	if ((spec_type == S_IFCHR) || (spec_type == S_IFBLK)) {
6860 		/* attach the path so we can search minors */
6861 		if ((dip = e_ddi_hold_devi_by_path(path, 0)) == NULL)
6862 			goto fail;
6863 
6864 		/* Add minorname to path. */
6865 		ndi_devi_enter(dip, &circ);
6866 		minorname = i_ddi_devtspectype_to_minorname(dip,
6867 		    devt, spec_type);
6868 		if (minorname) {
6869 			(void) strcat(path, ":");
6870 			(void) strcat(path, minorname);
6871 		}
6872 		ndi_devi_exit(dip, circ);
6873 		ddi_release_devi(dip);
6874 		if (minorname == NULL)
6875 			goto fail;
6876 	}
6877 	ASSERT(strlen(path) < MAXPATHLEN);
6878 	return (DDI_SUCCESS);
6879 
6880 fail:	*path = 0;
6881 	return (DDI_FAILURE);
6882 }
6883 
6884 /*
6885  * Given a major number and an instance, return the path.
6886  * This interface does NOT drive attach.
6887  */
6888 int
6889 e_ddi_majorinstance_to_path(major_t major, int instance, char *path)
6890 {
6891 	struct devnames *dnp;
6892 	dev_info_t	*dip;
6893 
6894 	if ((major >= devcnt) || (instance == -1)) {
6895 		*path = 0;
6896 		return (DDI_FAILURE);
6897 	}
6898 
6899 	/* look for the major/instance in the instance tree */
6900 	if (e_ddi_instance_majorinstance_to_path(major, instance,
6901 	    path) == DDI_SUCCESS) {
6902 		ASSERT(strlen(path) < MAXPATHLEN);
6903 		return (DDI_SUCCESS);
6904 	}
6905 
6906 	/*
6907 	 * Not in instance tree, find the instance on the per driver list and
6908 	 * construct path to instance via ddi_pathname(). This is how paths
6909 	 * down the 'pseudo' branch are constructed.
6910 	 */
6911 	dnp = &(devnamesp[major]);
6912 	LOCK_DEV_OPS(&(dnp->dn_lock));
6913 	for (dip = dnp->dn_head; dip;
6914 	    dip = (dev_info_t *)DEVI(dip)->devi_next) {
6915 		/* Skip if instance does not match. */
6916 		if (DEVI(dip)->devi_instance != instance)
6917 			continue;
6918 
6919 		/*
6920 		 * An ndi_hold_devi() does not prevent DS_INITIALIZED->DS_BOUND
6921 		 * node demotion, so it is not an effective way of ensuring
6922 		 * that the ddi_pathname result has a unit-address.  Instead,
6923 		 * we reverify the node state after calling ddi_pathname().
6924 		 */
6925 		if (i_ddi_node_state(dip) >= DS_INITIALIZED) {
6926 			(void) ddi_pathname(dip, path);
6927 			if (i_ddi_node_state(dip) < DS_INITIALIZED)
6928 				continue;
6929 			UNLOCK_DEV_OPS(&(dnp->dn_lock));
6930 			ASSERT(strlen(path) < MAXPATHLEN);
6931 			return (DDI_SUCCESS);
6932 		}
6933 	}
6934 	UNLOCK_DEV_OPS(&(dnp->dn_lock));
6935 
6936 	/* can't reconstruct the path */
6937 	*path = 0;
6938 	return (DDI_FAILURE);
6939 }
6940 
6941 #define	GLD_DRIVER_PPA "SUNW,gld_v0_ppa"
6942 
6943 /*
6944  * Given the dip for a network interface return the ppa for that interface.
6945  *
6946  * In all cases except GLD v0 drivers, the ppa == instance.
6947  * In the case of GLD v0 drivers, the ppa is equal to the attach order.
6948  * So for these drivers when the attach routine calls gld_register(),
6949  * the GLD framework creates an integer property called "gld_driver_ppa"
6950  * that can be queried here.
6951  *
6952  * The only time this function is used is when a system is booting over nfs.
6953  * In this case the system has to resolve the pathname of the boot device
6954  * to it's ppa.
6955  */
6956 int
6957 i_ddi_devi_get_ppa(dev_info_t *dip)
6958 {
6959 	return (ddi_prop_get_int(DDI_DEV_T_ANY, dip,
6960 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
6961 	    GLD_DRIVER_PPA, ddi_get_instance(dip)));
6962 }
6963 
6964 /*
6965  * i_ddi_devi_set_ppa() should only be called from gld_register()
6966  * and only for GLD v0 drivers
6967  */
6968 void
6969 i_ddi_devi_set_ppa(dev_info_t *dip, int ppa)
6970 {
6971 	(void) e_ddi_prop_update_int(DDI_DEV_T_NONE, dip, GLD_DRIVER_PPA, ppa);
6972 }
6973 
6974 
6975 /*
6976  * Private DDI Console bell functions.
6977  */
6978 void
6979 ddi_ring_console_bell(clock_t duration)
6980 {
6981 	if (ddi_console_bell_func != NULL)
6982 		(*ddi_console_bell_func)(duration);
6983 }
6984 
6985 void
6986 ddi_set_console_bell(void (*bellfunc)(clock_t duration))
6987 {
6988 	ddi_console_bell_func = bellfunc;
6989 }
6990 
6991 int
6992 ddi_dma_alloc_handle(dev_info_t *dip, ddi_dma_attr_t *attr,
6993 	int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep)
6994 {
6995 	int (*funcp)() = ddi_dma_allochdl;
6996 	ddi_dma_attr_t dma_attr;
6997 	struct bus_ops *bop;
6998 
6999 	if (attr == (ddi_dma_attr_t *)0)
7000 		return (DDI_DMA_BADATTR);
7001 
7002 	dma_attr = *attr;
7003 
7004 	bop = DEVI(dip)->devi_ops->devo_bus_ops;
7005 	if (bop && bop->bus_dma_allochdl)
7006 		funcp = bop->bus_dma_allochdl;
7007 
7008 	return ((*funcp)(dip, dip, &dma_attr, waitfp, arg, handlep));
7009 }
7010 
7011 void
7012 ddi_dma_free_handle(ddi_dma_handle_t *handlep)
7013 {
7014 	ddi_dma_handle_t h = *handlep;
7015 	(void) ddi_dma_freehdl(HD, HD, h);
7016 }
7017 
7018 static uintptr_t dma_mem_list_id = 0;
7019 
7020 
7021 int
7022 ddi_dma_mem_alloc(ddi_dma_handle_t handle, size_t length,
7023 	ddi_device_acc_attr_t *accattrp, uint_t flags,
7024 	int (*waitfp)(caddr_t), caddr_t arg, caddr_t *kaddrp,
7025 	size_t *real_length, ddi_acc_handle_t *handlep)
7026 {
7027 	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle;
7028 	dev_info_t *dip = hp->dmai_rdip;
7029 	ddi_acc_hdl_t *ap;
7030 	ddi_dma_attr_t *attrp = &hp->dmai_attr;
7031 	uint_t sleepflag, xfermodes;
7032 	int (*fp)(caddr_t);
7033 	int rval;
7034 
7035 	if (waitfp == DDI_DMA_SLEEP)
7036 		fp = (int (*)())KM_SLEEP;
7037 	else if (waitfp == DDI_DMA_DONTWAIT)
7038 		fp = (int (*)())KM_NOSLEEP;
7039 	else
7040 		fp = waitfp;
7041 	*handlep = impl_acc_hdl_alloc(fp, arg);
7042 	if (*handlep == NULL)
7043 		return (DDI_FAILURE);
7044 
7045 	/* check if the cache attributes are supported */
7046 	if (i_ddi_check_cache_attr(flags) == B_FALSE)
7047 		return (DDI_FAILURE);
7048 
7049 	/*
7050 	 * Transfer the meaningful bits to xfermodes.
7051 	 * Double-check if the 3rd party driver correctly sets the bits.
7052 	 * If not, set DDI_DMA_STREAMING to keep compatibility.
7053 	 */
7054 	xfermodes = flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING);
7055 	if (xfermodes == 0) {
7056 		xfermodes = DDI_DMA_STREAMING;
7057 	}
7058 
7059 	/*
7060 	 * initialize the common elements of data access handle
7061 	 */
7062 	ap = impl_acc_hdl_get(*handlep);
7063 	ap->ah_vers = VERS_ACCHDL;
7064 	ap->ah_dip = dip;
7065 	ap->ah_offset = 0;
7066 	ap->ah_len = 0;
7067 	ap->ah_xfermodes = flags;
7068 	ap->ah_acc = *accattrp;
7069 
7070 	sleepflag = ((waitfp == DDI_DMA_SLEEP) ? 1 : 0);
7071 	if (xfermodes == DDI_DMA_CONSISTENT) {
7072 		rval = i_ddi_mem_alloc(dip, attrp, length, sleepflag,
7073 		    flags, accattrp, kaddrp, NULL, ap);
7074 		*real_length = length;
7075 	} else {
7076 		rval = i_ddi_mem_alloc(dip, attrp, length, sleepflag,
7077 		    flags, accattrp, kaddrp, real_length, ap);
7078 	}
7079 	if (rval == DDI_SUCCESS) {
7080 		ap->ah_len = (off_t)(*real_length);
7081 		ap->ah_addr = *kaddrp;
7082 	} else {
7083 		impl_acc_hdl_free(*handlep);
7084 		*handlep = (ddi_acc_handle_t)NULL;
7085 		if (waitfp != DDI_DMA_SLEEP && waitfp != DDI_DMA_DONTWAIT) {
7086 			ddi_set_callback(waitfp, arg, &dma_mem_list_id);
7087 		}
7088 		rval = DDI_FAILURE;
7089 	}
7090 	return (rval);
7091 }
7092 
7093 void
7094 ddi_dma_mem_free(ddi_acc_handle_t *handlep)
7095 {
7096 	ddi_acc_hdl_t *ap;
7097 
7098 	ap = impl_acc_hdl_get(*handlep);
7099 	ASSERT(ap);
7100 
7101 	i_ddi_mem_free((caddr_t)ap->ah_addr, ap);
7102 
7103 	/*
7104 	 * free the handle
7105 	 */
7106 	impl_acc_hdl_free(*handlep);
7107 	*handlep = (ddi_acc_handle_t)NULL;
7108 
7109 	if (dma_mem_list_id != 0) {
7110 		ddi_run_callback(&dma_mem_list_id);
7111 	}
7112 }
7113 
7114 int
7115 ddi_dma_buf_bind_handle(ddi_dma_handle_t handle, struct buf *bp,
7116 	uint_t flags, int (*waitfp)(caddr_t), caddr_t arg,
7117 	ddi_dma_cookie_t *cookiep, uint_t *ccountp)
7118 {
7119 	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle;
7120 	dev_info_t *dip, *rdip;
7121 	struct ddi_dma_req dmareq;
7122 	int (*funcp)();
7123 
7124 	dmareq.dmar_flags = flags;
7125 	dmareq.dmar_fp = waitfp;
7126 	dmareq.dmar_arg = arg;
7127 	dmareq.dmar_object.dmao_size = (uint_t)bp->b_bcount;
7128 
7129 	if (bp->b_flags & B_PAGEIO) {
7130 		dmareq.dmar_object.dmao_type = DMA_OTYP_PAGES;
7131 		dmareq.dmar_object.dmao_obj.pp_obj.pp_pp = bp->b_pages;
7132 		dmareq.dmar_object.dmao_obj.pp_obj.pp_offset =
7133 		    (uint_t)(((uintptr_t)bp->b_un.b_addr) & MMU_PAGEOFFSET);
7134 	} else {
7135 		dmareq.dmar_object.dmao_obj.virt_obj.v_addr = bp->b_un.b_addr;
7136 		if (bp->b_flags & B_SHADOW) {
7137 			dmareq.dmar_object.dmao_obj.virt_obj.v_priv =
7138 			    bp->b_shadow;
7139 			dmareq.dmar_object.dmao_type = DMA_OTYP_BUFVADDR;
7140 		} else {
7141 			dmareq.dmar_object.dmao_type =
7142 			    (bp->b_flags & (B_PHYS | B_REMAPPED)) ?
7143 			    DMA_OTYP_BUFVADDR : DMA_OTYP_VADDR;
7144 			dmareq.dmar_object.dmao_obj.virt_obj.v_priv = NULL;
7145 		}
7146 
7147 		/*
7148 		 * If the buffer has no proc pointer, or the proc
7149 		 * struct has the kernel address space, or the buffer has
7150 		 * been marked B_REMAPPED (meaning that it is now
7151 		 * mapped into the kernel's address space), then
7152 		 * the address space is kas (kernel address space).
7153 		 */
7154 		if ((bp->b_proc == NULL) || (bp->b_proc->p_as == &kas) ||
7155 		    (bp->b_flags & B_REMAPPED)) {
7156 			dmareq.dmar_object.dmao_obj.virt_obj.v_as = 0;
7157 		} else {
7158 			dmareq.dmar_object.dmao_obj.virt_obj.v_as =
7159 			    bp->b_proc->p_as;
7160 		}
7161 	}
7162 
7163 	dip = rdip = hp->dmai_rdip;
7164 	if (dip != ddi_root_node())
7165 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_bindhdl;
7166 	funcp = DEVI(rdip)->devi_bus_dma_bindfunc;
7167 	return ((*funcp)(dip, rdip, handle, &dmareq, cookiep, ccountp));
7168 }
7169 
7170 int
7171 ddi_dma_addr_bind_handle(ddi_dma_handle_t handle, struct as *as,
7172 	caddr_t addr, size_t len, uint_t flags, int (*waitfp)(caddr_t),
7173 	caddr_t arg, ddi_dma_cookie_t *cookiep, uint_t *ccountp)
7174 {
7175 	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle;
7176 	dev_info_t *dip, *rdip;
7177 	struct ddi_dma_req dmareq;
7178 	int (*funcp)();
7179 
7180 	if (len == (uint_t)0) {
7181 		return (DDI_DMA_NOMAPPING);
7182 	}
7183 	dmareq.dmar_flags = flags;
7184 	dmareq.dmar_fp = waitfp;
7185 	dmareq.dmar_arg = arg;
7186 	dmareq.dmar_object.dmao_size = len;
7187 	dmareq.dmar_object.dmao_type = DMA_OTYP_VADDR;
7188 	dmareq.dmar_object.dmao_obj.virt_obj.v_as = as;
7189 	dmareq.dmar_object.dmao_obj.virt_obj.v_addr = addr;
7190 	dmareq.dmar_object.dmao_obj.virt_obj.v_priv = NULL;
7191 
7192 	dip = rdip = hp->dmai_rdip;
7193 	if (dip != ddi_root_node())
7194 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_bindhdl;
7195 	funcp = DEVI(rdip)->devi_bus_dma_bindfunc;
7196 	return ((*funcp)(dip, rdip, handle, &dmareq, cookiep, ccountp));
7197 }
7198 
7199 void
7200 ddi_dma_nextcookie(ddi_dma_handle_t handle, ddi_dma_cookie_t *cookiep)
7201 {
7202 	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle;
7203 	ddi_dma_cookie_t *cp;
7204 
7205 	cp = hp->dmai_cookie;
7206 	ASSERT(cp);
7207 
7208 	cookiep->dmac_notused = cp->dmac_notused;
7209 	cookiep->dmac_type = cp->dmac_type;
7210 	cookiep->dmac_address = cp->dmac_address;
7211 	cookiep->dmac_size = cp->dmac_size;
7212 	hp->dmai_cookie++;
7213 }
7214 
7215 int
7216 ddi_dma_numwin(ddi_dma_handle_t handle, uint_t *nwinp)
7217 {
7218 	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle;
7219 	if ((hp->dmai_rflags & DDI_DMA_PARTIAL) == 0) {
7220 		return (DDI_FAILURE);
7221 	} else {
7222 		*nwinp = hp->dmai_nwin;
7223 		return (DDI_SUCCESS);
7224 	}
7225 }
7226 
7227 int
7228 ddi_dma_getwin(ddi_dma_handle_t h, uint_t win, off_t *offp,
7229 	size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp)
7230 {
7231 	int (*funcp)() = ddi_dma_win;
7232 	struct bus_ops *bop;
7233 
7234 	bop = DEVI(HD)->devi_ops->devo_bus_ops;
7235 	if (bop && bop->bus_dma_win)
7236 		funcp = bop->bus_dma_win;
7237 
7238 	return ((*funcp)(HD, HD, h, win, offp, lenp, cookiep, ccountp));
7239 }
7240 
7241 int
7242 ddi_dma_set_sbus64(ddi_dma_handle_t h, ulong_t burstsizes)
7243 {
7244 	return (ddi_dma_mctl(HD, HD, h, DDI_DMA_SET_SBUS64, 0,
7245 	    &burstsizes, 0, 0));
7246 }
7247 
7248 int
7249 i_ddi_dma_fault_check(ddi_dma_impl_t *hp)
7250 {
7251 	return (hp->dmai_fault);
7252 }
7253 
7254 int
7255 ddi_check_dma_handle(ddi_dma_handle_t handle)
7256 {
7257 	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle;
7258 	int (*check)(ddi_dma_impl_t *);
7259 
7260 	if ((check = hp->dmai_fault_check) == NULL)
7261 		check = i_ddi_dma_fault_check;
7262 
7263 	return (((*check)(hp) == DDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
7264 }
7265 
7266 void
7267 i_ddi_dma_set_fault(ddi_dma_handle_t handle)
7268 {
7269 	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle;
7270 	void (*notify)(ddi_dma_impl_t *);
7271 
7272 	if (!hp->dmai_fault) {
7273 		hp->dmai_fault = 1;
7274 		if ((notify = hp->dmai_fault_notify) != NULL)
7275 			(*notify)(hp);
7276 	}
7277 }
7278 
7279 void
7280 i_ddi_dma_clr_fault(ddi_dma_handle_t handle)
7281 {
7282 	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle;
7283 	void (*notify)(ddi_dma_impl_t *);
7284 
7285 	if (hp->dmai_fault) {
7286 		hp->dmai_fault = 0;
7287 		if ((notify = hp->dmai_fault_notify) != NULL)
7288 			(*notify)(hp);
7289 	}
7290 }
7291 
7292 /*
7293  * register mapping routines.
7294  */
7295 int
7296 ddi_regs_map_setup(dev_info_t *dip, uint_t rnumber, caddr_t *addrp,
7297 	offset_t offset, offset_t len, ddi_device_acc_attr_t *accattrp,
7298 	ddi_acc_handle_t *handle)
7299 {
7300 	ddi_map_req_t mr;
7301 	ddi_acc_hdl_t *hp;
7302 	int result;
7303 
7304 	/*
7305 	 * Allocate and initialize the common elements of data access handle.
7306 	 */
7307 	*handle = impl_acc_hdl_alloc(KM_SLEEP, NULL);
7308 	hp = impl_acc_hdl_get(*handle);
7309 	hp->ah_vers = VERS_ACCHDL;
7310 	hp->ah_dip = dip;
7311 	hp->ah_rnumber = rnumber;
7312 	hp->ah_offset = offset;
7313 	hp->ah_len = len;
7314 	hp->ah_acc = *accattrp;
7315 
7316 	/*
7317 	 * Set up the mapping request and call to parent.
7318 	 */
7319 	mr.map_op = DDI_MO_MAP_LOCKED;
7320 	mr.map_type = DDI_MT_RNUMBER;
7321 	mr.map_obj.rnumber = rnumber;
7322 	mr.map_prot = PROT_READ | PROT_WRITE;
7323 	mr.map_flags = DDI_MF_KERNEL_MAPPING;
7324 	mr.map_handlep = hp;
7325 	mr.map_vers = DDI_MAP_VERSION;
7326 	result = ddi_map(dip, &mr, offset, len, addrp);
7327 
7328 	/*
7329 	 * check for end result
7330 	 */
7331 	if (result != DDI_SUCCESS) {
7332 		impl_acc_hdl_free(*handle);
7333 		*handle = (ddi_acc_handle_t)NULL;
7334 	} else {
7335 		hp->ah_addr = *addrp;
7336 	}
7337 
7338 	return (result);
7339 }
7340 
7341 void
7342 ddi_regs_map_free(ddi_acc_handle_t *handlep)
7343 {
7344 	ddi_map_req_t mr;
7345 	ddi_acc_hdl_t *hp;
7346 
7347 	hp = impl_acc_hdl_get(*handlep);
7348 	ASSERT(hp);
7349 
7350 	mr.map_op = DDI_MO_UNMAP;
7351 	mr.map_type = DDI_MT_RNUMBER;
7352 	mr.map_obj.rnumber = hp->ah_rnumber;
7353 	mr.map_prot = PROT_READ | PROT_WRITE;
7354 	mr.map_flags = DDI_MF_KERNEL_MAPPING;
7355 	mr.map_handlep = hp;
7356 	mr.map_vers = DDI_MAP_VERSION;
7357 
7358 	/*
7359 	 * Call my parent to unmap my regs.
7360 	 */
7361 	(void) ddi_map(hp->ah_dip, &mr, hp->ah_offset,
7362 	    hp->ah_len, &hp->ah_addr);
7363 	/*
7364 	 * free the handle
7365 	 */
7366 	impl_acc_hdl_free(*handlep);
7367 	*handlep = (ddi_acc_handle_t)NULL;
7368 }
7369 
7370 int
7371 ddi_device_zero(ddi_acc_handle_t handle, caddr_t dev_addr, size_t bytecount,
7372 	ssize_t dev_advcnt, uint_t dev_datasz)
7373 {
7374 	uint8_t *b;
7375 	uint16_t *w;
7376 	uint32_t *l;
7377 	uint64_t *ll;
7378 
7379 	/* check for total byte count is multiple of data transfer size */
7380 	if (bytecount != ((bytecount / dev_datasz) * dev_datasz))
7381 		return (DDI_FAILURE);
7382 
7383 	switch (dev_datasz) {
7384 	case DDI_DATA_SZ01_ACC:
7385 		for (b = (uint8_t *)dev_addr;
7386 		    bytecount != 0; bytecount -= 1, b += dev_advcnt)
7387 			ddi_put8(handle, b, 0);
7388 		break;
7389 	case DDI_DATA_SZ02_ACC:
7390 		for (w = (uint16_t *)dev_addr;
7391 		    bytecount != 0; bytecount -= 2, w += dev_advcnt)
7392 			ddi_put16(handle, w, 0);
7393 		break;
7394 	case DDI_DATA_SZ04_ACC:
7395 		for (l = (uint32_t *)dev_addr;
7396 		    bytecount != 0; bytecount -= 4, l += dev_advcnt)
7397 			ddi_put32(handle, l, 0);
7398 		break;
7399 	case DDI_DATA_SZ08_ACC:
7400 		for (ll = (uint64_t *)dev_addr;
7401 		    bytecount != 0; bytecount -= 8, ll += dev_advcnt)
7402 			ddi_put64(handle, ll, 0x0ll);
7403 		break;
7404 	default:
7405 		return (DDI_FAILURE);
7406 	}
7407 	return (DDI_SUCCESS);
7408 }
7409 
7410 int
7411 ddi_device_copy(
7412 	ddi_acc_handle_t src_handle, caddr_t src_addr, ssize_t src_advcnt,
7413 	ddi_acc_handle_t dest_handle, caddr_t dest_addr, ssize_t dest_advcnt,
7414 	size_t bytecount, uint_t dev_datasz)
7415 {
7416 	uint8_t *b_src, *b_dst;
7417 	uint16_t *w_src, *w_dst;
7418 	uint32_t *l_src, *l_dst;
7419 	uint64_t *ll_src, *ll_dst;
7420 
7421 	/* check for total byte count is multiple of data transfer size */
7422 	if (bytecount != ((bytecount / dev_datasz) * dev_datasz))
7423 		return (DDI_FAILURE);
7424 
7425 	switch (dev_datasz) {
7426 	case DDI_DATA_SZ01_ACC:
7427 		b_src = (uint8_t *)src_addr;
7428 		b_dst = (uint8_t *)dest_addr;
7429 
7430 		for (; bytecount != 0; bytecount -= 1) {
7431 			ddi_put8(dest_handle, b_dst,
7432 			    ddi_get8(src_handle, b_src));
7433 			b_dst += dest_advcnt;
7434 			b_src += src_advcnt;
7435 		}
7436 		break;
7437 	case DDI_DATA_SZ02_ACC:
7438 		w_src = (uint16_t *)src_addr;
7439 		w_dst = (uint16_t *)dest_addr;
7440 
7441 		for (; bytecount != 0; bytecount -= 2) {
7442 			ddi_put16(dest_handle, w_dst,
7443 			    ddi_get16(src_handle, w_src));
7444 			w_dst += dest_advcnt;
7445 			w_src += src_advcnt;
7446 		}
7447 		break;
7448 	case DDI_DATA_SZ04_ACC:
7449 		l_src = (uint32_t *)src_addr;
7450 		l_dst = (uint32_t *)dest_addr;
7451 
7452 		for (; bytecount != 0; bytecount -= 4) {
7453 			ddi_put32(dest_handle, l_dst,
7454 			    ddi_get32(src_handle, l_src));
7455 			l_dst += dest_advcnt;
7456 			l_src += src_advcnt;
7457 		}
7458 		break;
7459 	case DDI_DATA_SZ08_ACC:
7460 		ll_src = (uint64_t *)src_addr;
7461 		ll_dst = (uint64_t *)dest_addr;
7462 
7463 		for (; bytecount != 0; bytecount -= 8) {
7464 			ddi_put64(dest_handle, ll_dst,
7465 			    ddi_get64(src_handle, ll_src));
7466 			ll_dst += dest_advcnt;
7467 			ll_src += src_advcnt;
7468 		}
7469 		break;
7470 	default:
7471 		return (DDI_FAILURE);
7472 	}
7473 	return (DDI_SUCCESS);
7474 }
7475 
7476 #define	swap16(value)  \
7477 	((((value) & 0xff) << 8) | ((value) >> 8))
7478 
7479 #define	swap32(value)	\
7480 	(((uint32_t)swap16((uint16_t)((value) & 0xffff)) << 16) | \
7481 	(uint32_t)swap16((uint16_t)((value) >> 16)))
7482 
7483 #define	swap64(value)	\
7484 	(((uint64_t)swap32((uint32_t)((value) & 0xffffffff)) \
7485 	    << 32) | \
7486 	(uint64_t)swap32((uint32_t)((value) >> 32)))
7487 
7488 uint16_t
7489 ddi_swap16(uint16_t value)
7490 {
7491 	return (swap16(value));
7492 }
7493 
7494 uint32_t
7495 ddi_swap32(uint32_t value)
7496 {
7497 	return (swap32(value));
7498 }
7499 
7500 uint64_t
7501 ddi_swap64(uint64_t value)
7502 {
7503 	return (swap64(value));
7504 }
7505 
7506 /*
7507  * Convert a binding name to a driver name.
7508  * A binding name is the name used to determine the driver for a
7509  * device - it may be either an alias for the driver or the name
7510  * of the driver itself.
7511  */
7512 char *
7513 i_binding_to_drv_name(char *bname)
7514 {
7515 	major_t major_no;
7516 
7517 	ASSERT(bname != NULL);
7518 
7519 	if ((major_no = ddi_name_to_major(bname)) == -1)
7520 		return (NULL);
7521 	return (ddi_major_to_name(major_no));
7522 }
7523 
7524 /*
7525  * Search for minor name that has specified dev_t and spec_type.
7526  * If spec_type is zero then any dev_t match works.  Since we
7527  * are returning a pointer to the minor name string, we require the
7528  * caller to do the locking.
7529  */
7530 char *
7531 i_ddi_devtspectype_to_minorname(dev_info_t *dip, dev_t dev, int spec_type)
7532 {
7533 	struct ddi_minor_data	*dmdp;
7534 
7535 	/*
7536 	 * The did layered driver currently intentionally returns a
7537 	 * devinfo ptr for an underlying sd instance based on a did
7538 	 * dev_t. In this case it is not an error.
7539 	 *
7540 	 * The did layered driver is associated with Sun Cluster.
7541 	 */
7542 	ASSERT((ddi_driver_major(dip) == getmajor(dev)) ||
7543 	    (strcmp(ddi_major_to_name(getmajor(dev)), "did") == 0));
7544 
7545 	ASSERT(DEVI_BUSY_OWNED(dip));
7546 	for (dmdp = DEVI(dip)->devi_minor; dmdp; dmdp = dmdp->next) {
7547 		if (((dmdp->type == DDM_MINOR) ||
7548 		    (dmdp->type == DDM_INTERNAL_PATH) ||
7549 		    (dmdp->type == DDM_DEFAULT)) &&
7550 		    (dmdp->ddm_dev == dev) &&
7551 		    ((((spec_type & (S_IFCHR|S_IFBLK))) == 0) ||
7552 		    (dmdp->ddm_spec_type == spec_type)))
7553 			return (dmdp->ddm_name);
7554 	}
7555 
7556 	return (NULL);
7557 }
7558 
7559 /*
7560  * Find the devt and spectype of the specified minor_name.
7561  * Return DDI_FAILURE if minor_name not found. Since we are
7562  * returning everything via arguments we can do the locking.
7563  */
7564 int
7565 i_ddi_minorname_to_devtspectype(dev_info_t *dip, char *minor_name,
7566 	dev_t *devtp, int *spectypep)
7567 {
7568 	int			circ;
7569 	struct ddi_minor_data	*dmdp;
7570 
7571 	/* deal with clone minor nodes */
7572 	if (dip == clone_dip) {
7573 		major_t	major;
7574 		/*
7575 		 * Make sure minor_name is a STREAMS driver.
7576 		 * We load the driver but don't attach to any instances.
7577 		 */
7578 
7579 		major = ddi_name_to_major(minor_name);
7580 		if (major == DDI_MAJOR_T_NONE)
7581 			return (DDI_FAILURE);
7582 
7583 		if (ddi_hold_driver(major) == NULL)
7584 			return (DDI_FAILURE);
7585 
7586 		if (STREAMSTAB(major) == NULL) {
7587 			ddi_rele_driver(major);
7588 			return (DDI_FAILURE);
7589 		}
7590 		ddi_rele_driver(major);
7591 
7592 		if (devtp)
7593 			*devtp = makedevice(clone_major, (minor_t)major);
7594 
7595 		if (spectypep)
7596 			*spectypep = S_IFCHR;
7597 
7598 		return (DDI_SUCCESS);
7599 	}
7600 
7601 	ndi_devi_enter(dip, &circ);
7602 	for (dmdp = DEVI(dip)->devi_minor; dmdp; dmdp = dmdp->next) {
7603 		if (((dmdp->type != DDM_MINOR) &&
7604 		    (dmdp->type != DDM_INTERNAL_PATH) &&
7605 		    (dmdp->type != DDM_DEFAULT)) ||
7606 		    strcmp(minor_name, dmdp->ddm_name))
7607 			continue;
7608 
7609 		if (devtp)
7610 			*devtp = dmdp->ddm_dev;
7611 
7612 		if (spectypep)
7613 			*spectypep = dmdp->ddm_spec_type;
7614 
7615 		ndi_devi_exit(dip, circ);
7616 		return (DDI_SUCCESS);
7617 	}
7618 	ndi_devi_exit(dip, circ);
7619 
7620 	return (DDI_FAILURE);
7621 }
7622 
7623 static kmutex_t devid_gen_mutex;
7624 static short	devid_gen_number;
7625 
7626 #ifdef DEBUG
7627 
7628 static int	devid_register_corrupt = 0;
7629 static int	devid_register_corrupt_major = 0;
7630 static int	devid_register_corrupt_hint = 0;
7631 static int	devid_register_corrupt_hint_major = 0;
7632 
7633 static int devid_lyr_debug = 0;
7634 
7635 #define	DDI_DEBUG_DEVID_DEVTS(msg, ndevs, devs)		\
7636 	if (devid_lyr_debug)					\
7637 		ddi_debug_devid_devts(msg, ndevs, devs)
7638 
7639 #else
7640 
7641 #define	DDI_DEBUG_DEVID_DEVTS(msg, ndevs, devs)
7642 
7643 #endif /* DEBUG */
7644 
7645 
7646 #ifdef	DEBUG
7647 
7648 static void
7649 ddi_debug_devid_devts(char *msg, int ndevs, dev_t *devs)
7650 {
7651 	int i;
7652 
7653 	cmn_err(CE_CONT, "%s:\n", msg);
7654 	for (i = 0; i < ndevs; i++) {
7655 		cmn_err(CE_CONT, "    0x%lx\n", devs[i]);
7656 	}
7657 }
7658 
7659 static void
7660 ddi_debug_devid_paths(char *msg, int npaths, char **paths)
7661 {
7662 	int i;
7663 
7664 	cmn_err(CE_CONT, "%s:\n", msg);
7665 	for (i = 0; i < npaths; i++) {
7666 		cmn_err(CE_CONT, "    %s\n", paths[i]);
7667 	}
7668 }
7669 
7670 static void
7671 ddi_debug_devid_devts_per_path(char *path, int ndevs, dev_t *devs)
7672 {
7673 	int i;
7674 
7675 	cmn_err(CE_CONT, "dev_ts per path %s\n", path);
7676 	for (i = 0; i < ndevs; i++) {
7677 		cmn_err(CE_CONT, "    0x%lx\n", devs[i]);
7678 	}
7679 }
7680 
7681 #endif	/* DEBUG */
7682 
7683 /*
7684  * Register device id into DDI framework.
7685  * Must be called when the driver is bound.
7686  */
7687 static int
7688 i_ddi_devid_register(dev_info_t *dip, ddi_devid_t devid)
7689 {
7690 	impl_devid_t	*i_devid = (impl_devid_t *)devid;
7691 	size_t		driver_len;
7692 	const char	*driver_name;
7693 	char		*devid_str;
7694 	major_t		major;
7695 
7696 	if ((dip == NULL) ||
7697 	    ((major = ddi_driver_major(dip)) == DDI_MAJOR_T_NONE))
7698 		return (DDI_FAILURE);
7699 
7700 	/* verify that the devid is valid */
7701 	if (ddi_devid_valid(devid) != DDI_SUCCESS)
7702 		return (DDI_FAILURE);
7703 
7704 	/* Updating driver name hint in devid */
7705 	driver_name = ddi_driver_name(dip);
7706 	driver_len = strlen(driver_name);
7707 	if (driver_len > DEVID_HINT_SIZE) {
7708 		/* Pick up last four characters of driver name */
7709 		driver_name += driver_len - DEVID_HINT_SIZE;
7710 		driver_len = DEVID_HINT_SIZE;
7711 	}
7712 	bzero(i_devid->did_driver, DEVID_HINT_SIZE);
7713 	bcopy(driver_name, i_devid->did_driver, driver_len);
7714 
7715 #ifdef DEBUG
7716 	/* Corrupt the devid for testing. */
7717 	if (devid_register_corrupt)
7718 		i_devid->did_id[0] += devid_register_corrupt;
7719 	if (devid_register_corrupt_major &&
7720 	    (major == devid_register_corrupt_major))
7721 		i_devid->did_id[0] += 1;
7722 	if (devid_register_corrupt_hint)
7723 		i_devid->did_driver[0] += devid_register_corrupt_hint;
7724 	if (devid_register_corrupt_hint_major &&
7725 	    (major == devid_register_corrupt_hint_major))
7726 		i_devid->did_driver[0] += 1;
7727 #endif /* DEBUG */
7728 
7729 	/* encode the devid as a string */
7730 	if ((devid_str = ddi_devid_str_encode(devid, NULL)) == NULL)
7731 		return (DDI_FAILURE);
7732 
7733 	/* add string as a string property */
7734 	if (ndi_prop_update_string(DDI_DEV_T_NONE, dip,
7735 	    DEVID_PROP_NAME, devid_str) != DDI_SUCCESS) {
7736 		cmn_err(CE_WARN, "%s%d: devid property update failed",
7737 		    ddi_driver_name(dip), ddi_get_instance(dip));
7738 		ddi_devid_str_free(devid_str);
7739 		return (DDI_FAILURE);
7740 	}
7741 
7742 	/* keep pointer to devid string for interrupt context fma code */
7743 	if (DEVI(dip)->devi_devid_str)
7744 		ddi_devid_str_free(DEVI(dip)->devi_devid_str);
7745 	DEVI(dip)->devi_devid_str = devid_str;
7746 	return (DDI_SUCCESS);
7747 }
7748 
7749 int
7750 ddi_devid_register(dev_info_t *dip, ddi_devid_t devid)
7751 {
7752 	int rval;
7753 
7754 	rval = i_ddi_devid_register(dip, devid);
7755 	if (rval == DDI_SUCCESS) {
7756 		/*
7757 		 * Register devid in devid-to-path cache
7758 		 */
7759 		if (e_devid_cache_register(dip, devid) == DDI_SUCCESS) {
7760 			mutex_enter(&DEVI(dip)->devi_lock);
7761 			DEVI(dip)->devi_flags |= DEVI_CACHED_DEVID;
7762 			mutex_exit(&DEVI(dip)->devi_lock);
7763 		} else if (ddi_get_name_addr(dip)) {
7764 			/*
7765 			 * We only expect cache_register DDI_FAILURE when we
7766 			 * can't form the full path because of NULL devi_addr.
7767 			 */
7768 			cmn_err(CE_WARN, "%s%d: failed to cache devid",
7769 			    ddi_driver_name(dip), ddi_get_instance(dip));
7770 		}
7771 	} else {
7772 		cmn_err(CE_WARN, "%s%d: failed to register devid",
7773 		    ddi_driver_name(dip), ddi_get_instance(dip));
7774 	}
7775 	return (rval);
7776 }
7777 
7778 /*
7779  * Remove (unregister) device id from DDI framework.
7780  * Must be called when device is detached.
7781  */
7782 static void
7783 i_ddi_devid_unregister(dev_info_t *dip)
7784 {
7785 	if (DEVI(dip)->devi_devid_str) {
7786 		ddi_devid_str_free(DEVI(dip)->devi_devid_str);
7787 		DEVI(dip)->devi_devid_str = NULL;
7788 	}
7789 
7790 	/* remove the devid property */
7791 	(void) ndi_prop_remove(DDI_DEV_T_NONE, dip, DEVID_PROP_NAME);
7792 }
7793 
7794 void
7795 ddi_devid_unregister(dev_info_t *dip)
7796 {
7797 	mutex_enter(&DEVI(dip)->devi_lock);
7798 	DEVI(dip)->devi_flags &= ~DEVI_CACHED_DEVID;
7799 	mutex_exit(&DEVI(dip)->devi_lock);
7800 	e_devid_cache_unregister(dip);
7801 	i_ddi_devid_unregister(dip);
7802 }
7803 
7804 /*
7805  * Allocate and initialize a device id.
7806  */
7807 int
7808 ddi_devid_init(
7809 	dev_info_t	*dip,
7810 	ushort_t	devid_type,
7811 	ushort_t	nbytes,
7812 	void		*id,
7813 	ddi_devid_t	*ret_devid)
7814 {
7815 	impl_devid_t	*i_devid;
7816 	int		sz = sizeof (*i_devid) + nbytes - sizeof (char);
7817 	int		driver_len;
7818 	const char	*driver_name;
7819 
7820 	switch (devid_type) {
7821 	case DEVID_SCSI3_WWN:
7822 		/*FALLTHRU*/
7823 	case DEVID_SCSI_SERIAL:
7824 		/*FALLTHRU*/
7825 	case DEVID_ATA_SERIAL:
7826 		/*FALLTHRU*/
7827 	case DEVID_ENCAP:
7828 		if (nbytes == 0)
7829 			return (DDI_FAILURE);
7830 		if (id == NULL)
7831 			return (DDI_FAILURE);
7832 		break;
7833 	case DEVID_FAB:
7834 		if (nbytes != 0)
7835 			return (DDI_FAILURE);
7836 		if (id != NULL)
7837 			return (DDI_FAILURE);
7838 		nbytes = sizeof (int) +
7839 		    sizeof (struct timeval32) + sizeof (short);
7840 		sz += nbytes;
7841 		break;
7842 	default:
7843 		return (DDI_FAILURE);
7844 	}
7845 
7846 	if ((i_devid = kmem_zalloc(sz, KM_SLEEP)) == NULL)
7847 		return (DDI_FAILURE);
7848 
7849 	i_devid->did_magic_hi = DEVID_MAGIC_MSB;
7850 	i_devid->did_magic_lo = DEVID_MAGIC_LSB;
7851 	i_devid->did_rev_hi = DEVID_REV_MSB;
7852 	i_devid->did_rev_lo = DEVID_REV_LSB;
7853 	DEVID_FORMTYPE(i_devid, devid_type);
7854 	DEVID_FORMLEN(i_devid, nbytes);
7855 
7856 	/* Fill in driver name hint */
7857 	driver_name = ddi_driver_name(dip);
7858 	driver_len = strlen(driver_name);
7859 	if (driver_len > DEVID_HINT_SIZE) {
7860 		/* Pick up last four characters of driver name */
7861 		driver_name += driver_len - DEVID_HINT_SIZE;
7862 		driver_len = DEVID_HINT_SIZE;
7863 	}
7864 
7865 	bcopy(driver_name, i_devid->did_driver, driver_len);
7866 
7867 	/* Fill in id field */
7868 	if (devid_type == DEVID_FAB) {
7869 		char		*cp;
7870 		uint32_t	hostid;
7871 		struct timeval32 timestamp32;
7872 		int		i;
7873 		int		*ip;
7874 		short		gen;
7875 
7876 		/* increase the generation number */
7877 		mutex_enter(&devid_gen_mutex);
7878 		gen = devid_gen_number++;
7879 		mutex_exit(&devid_gen_mutex);
7880 
7881 		cp = i_devid->did_id;
7882 
7883 		/* Fill in host id (big-endian byte ordering) */
7884 		hostid = zone_get_hostid(NULL);
7885 		*cp++ = hibyte(hiword(hostid));
7886 		*cp++ = lobyte(hiword(hostid));
7887 		*cp++ = hibyte(loword(hostid));
7888 		*cp++ = lobyte(loword(hostid));
7889 
7890 		/*
7891 		 * Fill in timestamp (big-endian byte ordering)
7892 		 *
7893 		 * (Note that the format may have to be changed
7894 		 * before 2038 comes around, though it's arguably
7895 		 * unique enough as it is..)
7896 		 */
7897 		uniqtime32(&timestamp32);
7898 		ip = (int *)&timestamp32;
7899 		for (i = 0;
7900 		    i < sizeof (timestamp32) / sizeof (int); i++, ip++) {
7901 			int	val;
7902 			val = *ip;
7903 			*cp++ = hibyte(hiword(val));
7904 			*cp++ = lobyte(hiword(val));
7905 			*cp++ = hibyte(loword(val));
7906 			*cp++ = lobyte(loword(val));
7907 		}
7908 
7909 		/* fill in the generation number */
7910 		*cp++ = hibyte(gen);
7911 		*cp++ = lobyte(gen);
7912 	} else
7913 		bcopy(id, i_devid->did_id, nbytes);
7914 
7915 	/* return device id */
7916 	*ret_devid = (ddi_devid_t)i_devid;
7917 	return (DDI_SUCCESS);
7918 }
7919 
7920 int
7921 ddi_devid_get(dev_info_t *dip, ddi_devid_t *ret_devid)
7922 {
7923 	return (i_ddi_devi_get_devid(DDI_DEV_T_ANY, dip, ret_devid));
7924 }
7925 
7926 int
7927 i_ddi_devi_get_devid(dev_t dev, dev_info_t *dip, ddi_devid_t *ret_devid)
7928 {
7929 	char		*devidstr;
7930 
7931 	ASSERT(dev != DDI_DEV_T_NONE);
7932 
7933 	/* look up the property, devt specific first */
7934 	if (ddi_prop_lookup_string(dev, dip, DDI_PROP_DONTPASS,
7935 	    DEVID_PROP_NAME, &devidstr) != DDI_PROP_SUCCESS) {
7936 		if ((dev == DDI_DEV_T_ANY) ||
7937 		    (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip,
7938 		    DDI_PROP_DONTPASS, DEVID_PROP_NAME, &devidstr) !=
7939 		    DDI_PROP_SUCCESS)) {
7940 			return (DDI_FAILURE);
7941 		}
7942 	}
7943 
7944 	/* convert to binary form */
7945 	if (ddi_devid_str_decode(devidstr, ret_devid, NULL) == -1) {
7946 		ddi_prop_free(devidstr);
7947 		return (DDI_FAILURE);
7948 	}
7949 	ddi_prop_free(devidstr);
7950 	return (DDI_SUCCESS);
7951 }
7952 
7953 /*
7954  * Return a copy of the device id for dev_t
7955  */
7956 int
7957 ddi_lyr_get_devid(dev_t dev, ddi_devid_t *ret_devid)
7958 {
7959 	dev_info_t	*dip;
7960 	int		rval;
7961 
7962 	/* get the dip */
7963 	if ((dip = e_ddi_hold_devi_by_dev(dev, 0)) == NULL)
7964 		return (DDI_FAILURE);
7965 
7966 	rval = i_ddi_devi_get_devid(dev, dip, ret_devid);
7967 
7968 	ddi_release_devi(dip);		/* e_ddi_hold_devi_by_dev() */
7969 	return (rval);
7970 }
7971 
7972 /*
7973  * Return a copy of the minor name for dev_t and spec_type
7974  */
7975 int
7976 ddi_lyr_get_minor_name(dev_t dev, int spec_type, char **minor_name)
7977 {
7978 	char		*buf;
7979 	int		circ;
7980 	dev_info_t	*dip;
7981 	char		*nm;
7982 	int		rval;
7983 
7984 	if ((dip = e_ddi_hold_devi_by_dev(dev, 0)) == NULL) {
7985 		*minor_name = NULL;
7986 		return (DDI_FAILURE);
7987 	}
7988 
7989 	/* Find the minor name and copy into max size buf */
7990 	buf = kmem_alloc(MAXNAMELEN, KM_SLEEP);
7991 	ndi_devi_enter(dip, &circ);
7992 	nm = i_ddi_devtspectype_to_minorname(dip, dev, spec_type);
7993 	if (nm)
7994 		(void) strcpy(buf, nm);
7995 	ndi_devi_exit(dip, circ);
7996 	ddi_release_devi(dip);	/* e_ddi_hold_devi_by_dev() */
7997 
7998 	if (nm) {
7999 		/* duplicate into min size buf for return result */
8000 		*minor_name = i_ddi_strdup(buf, KM_SLEEP);
8001 		rval = DDI_SUCCESS;
8002 	} else {
8003 		*minor_name = NULL;
8004 		rval = DDI_FAILURE;
8005 	}
8006 
8007 	/* free max size buf and return */
8008 	kmem_free(buf, MAXNAMELEN);
8009 	return (rval);
8010 }
8011 
8012 int
8013 ddi_lyr_devid_to_devlist(
8014 	ddi_devid_t	devid,
8015 	char		*minor_name,
8016 	int		*retndevs,
8017 	dev_t		**retdevs)
8018 {
8019 	ASSERT(ddi_devid_valid(devid) == DDI_SUCCESS);
8020 
8021 	if (e_devid_cache_to_devt_list(devid, minor_name,
8022 	    retndevs, retdevs) == DDI_SUCCESS) {
8023 		ASSERT(*retndevs > 0);
8024 		DDI_DEBUG_DEVID_DEVTS("ddi_lyr_devid_to_devlist",
8025 		    *retndevs, *retdevs);
8026 		return (DDI_SUCCESS);
8027 	}
8028 
8029 	if (e_ddi_devid_discovery(devid) == DDI_FAILURE) {
8030 		return (DDI_FAILURE);
8031 	}
8032 
8033 	if (e_devid_cache_to_devt_list(devid, minor_name,
8034 	    retndevs, retdevs) == DDI_SUCCESS) {
8035 		ASSERT(*retndevs > 0);
8036 		DDI_DEBUG_DEVID_DEVTS("ddi_lyr_devid_to_devlist",
8037 		    *retndevs, *retdevs);
8038 		return (DDI_SUCCESS);
8039 	}
8040 
8041 	return (DDI_FAILURE);
8042 }
8043 
8044 void
8045 ddi_lyr_free_devlist(dev_t *devlist, int ndevs)
8046 {
8047 	kmem_free(devlist, sizeof (dev_t) * ndevs);
8048 }
8049 
8050 /*
8051  * Note: This will need to be fixed if we ever allow processes to
8052  * have more than one data model per exec.
8053  */
8054 model_t
8055 ddi_mmap_get_model(void)
8056 {
8057 	return (get_udatamodel());
8058 }
8059 
8060 model_t
8061 ddi_model_convert_from(model_t model)
8062 {
8063 	return ((model & DDI_MODEL_MASK) & ~DDI_MODEL_NATIVE);
8064 }
8065 
8066 /*
8067  * ddi interfaces managing storage and retrieval of eventcookies.
8068  */
8069 
8070 /*
8071  * Invoke bus nexus driver's implementation of the
8072  * (*bus_remove_eventcall)() interface to remove a registered
8073  * callback handler for "event".
8074  */
8075 int
8076 ddi_remove_event_handler(ddi_callback_id_t id)
8077 {
8078 	ndi_event_callbacks_t *cb = (ndi_event_callbacks_t *)id;
8079 	dev_info_t *ddip;
8080 
8081 	ASSERT(cb);
8082 	if (!cb) {
8083 		return (DDI_FAILURE);
8084 	}
8085 
8086 	ddip = NDI_EVENT_DDIP(cb->ndi_evtcb_cookie);
8087 	return (ndi_busop_remove_eventcall(ddip, id));
8088 }
8089 
8090 /*
8091  * Invoke bus nexus driver's implementation of the
8092  * (*bus_add_eventcall)() interface to register a callback handler
8093  * for "event".
8094  */
8095 int
8096 ddi_add_event_handler(dev_info_t *dip, ddi_eventcookie_t event,
8097     void (*handler)(dev_info_t *, ddi_eventcookie_t, void *, void *),
8098     void *arg, ddi_callback_id_t *id)
8099 {
8100 	return (ndi_busop_add_eventcall(dip, dip, event, handler, arg, id));
8101 }
8102 
8103 
8104 /*
8105  * Return a handle for event "name" by calling up the device tree
8106  * hierarchy via  (*bus_get_eventcookie)() interface until claimed
8107  * by a bus nexus or top of dev_info tree is reached.
8108  */
8109 int
8110 ddi_get_eventcookie(dev_info_t *dip, char *name,
8111     ddi_eventcookie_t *event_cookiep)
8112 {
8113 	return (ndi_busop_get_eventcookie(dip, dip,
8114 	    name, event_cookiep));
8115 }
8116 
8117 /*
8118  * This procedure is provided as the general callback function when
8119  * umem_lockmemory calls as_add_callback for long term memory locking.
8120  * When as_unmap, as_setprot, or as_free encounter segments which have
8121  * locked memory, this callback will be invoked.
8122  */
8123 void
8124 umem_lock_undo(struct as *as, void *arg, uint_t event)
8125 {
8126 	_NOTE(ARGUNUSED(as, event))
8127 	struct ddi_umem_cookie *cp = (struct ddi_umem_cookie *)arg;
8128 
8129 	/*
8130 	 * Call the cleanup function.  Decrement the cookie reference
8131 	 * count, if it goes to zero, return the memory for the cookie.
8132 	 * The i_ddi_umem_unlock for this cookie may or may not have been
8133 	 * called already.  It is the responsibility of the caller of
8134 	 * umem_lockmemory to handle the case of the cleanup routine
8135 	 * being called after a ddi_umem_unlock for the cookie
8136 	 * was called.
8137 	 */
8138 
8139 	(*cp->callbacks.cbo_umem_lock_cleanup)((ddi_umem_cookie_t)cp);
8140 
8141 	/* remove the cookie if reference goes to zero */
8142 	if (atomic_add_long_nv((ulong_t *)(&(cp->cook_refcnt)), -1) == 0) {
8143 		kmem_free(cp, sizeof (struct ddi_umem_cookie));
8144 	}
8145 }
8146 
8147 /*
8148  * The following two Consolidation Private routines provide generic
8149  * interfaces to increase/decrease the amount of device-locked memory.
8150  *
8151  * To keep project_rele and project_hold consistent, i_ddi_decr_locked_memory()
8152  * must be called every time i_ddi_incr_locked_memory() is called.
8153  */
8154 int
8155 /* ARGSUSED */
8156 i_ddi_incr_locked_memory(proc_t *procp, rctl_qty_t inc)
8157 {
8158 	ASSERT(procp != NULL);
8159 	mutex_enter(&procp->p_lock);
8160 	if (rctl_incr_locked_mem(procp, NULL, inc, 1)) {
8161 		mutex_exit(&procp->p_lock);
8162 		return (ENOMEM);
8163 	}
8164 	mutex_exit(&procp->p_lock);
8165 	return (0);
8166 }
8167 
8168 /*
8169  * To keep project_rele and project_hold consistent, i_ddi_incr_locked_memory()
8170  * must be called every time i_ddi_decr_locked_memory() is called.
8171  */
8172 /* ARGSUSED */
8173 void
8174 i_ddi_decr_locked_memory(proc_t *procp, rctl_qty_t dec)
8175 {
8176 	ASSERT(procp != NULL);
8177 	mutex_enter(&procp->p_lock);
8178 	rctl_decr_locked_mem(procp, NULL, dec, 1);
8179 	mutex_exit(&procp->p_lock);
8180 }
8181 
8182 /*
8183  * The cookie->upd_max_lock_rctl flag is used to determine if we should
8184  * charge device locked memory to the max-locked-memory rctl.  Tracking
8185  * device locked memory causes the rctl locks to get hot under high-speed
8186  * I/O such as RDSv3 over IB.  If there is no max-locked-memory rctl limit,
8187  * we bypass charging the locked memory to the rctl altogether.  The cookie's
8188  * flag tells us if the rctl value should be updated when unlocking the memory,
8189  * in case the rctl gets changed after the memory was locked.  Any device
8190  * locked memory in that rare case will not be counted toward the rctl limit.
8191  *
8192  * When tracking the locked memory, the kproject_t parameter is always NULL
8193  * in the code paths:
8194  *	i_ddi_incr_locked_memory -> rctl_incr_locked_mem
8195  *	i_ddi_decr_locked_memory -> rctl_decr_locked_mem
8196  * Thus, we always use the tk_proj member to check the projp setting.
8197  */
8198 static void
8199 init_lockedmem_rctl_flag(struct ddi_umem_cookie *cookie)
8200 {
8201 	proc_t		*p;
8202 	kproject_t	*projp;
8203 	zone_t		*zonep;
8204 
8205 	ASSERT(cookie);
8206 	p = cookie->procp;
8207 	ASSERT(p);
8208 
8209 	zonep = p->p_zone;
8210 	projp = p->p_task->tk_proj;
8211 
8212 	ASSERT(zonep);
8213 	ASSERT(projp);
8214 
8215 	if (zonep->zone_locked_mem_ctl == UINT64_MAX &&
8216 	    projp->kpj_data.kpd_locked_mem_ctl == UINT64_MAX)
8217 		cookie->upd_max_lock_rctl = 0;
8218 	else
8219 		cookie->upd_max_lock_rctl = 1;
8220 }
8221 
8222 /*
8223  * This routine checks if the max-locked-memory resource ctl is
8224  * exceeded, if not increments it, grabs a hold on the project.
8225  * Returns 0 if successful otherwise returns error code
8226  */
8227 static int
8228 umem_incr_devlockmem(struct ddi_umem_cookie *cookie)
8229 {
8230 	proc_t		*procp;
8231 	int		ret;
8232 
8233 	ASSERT(cookie);
8234 	if (cookie->upd_max_lock_rctl == 0)
8235 		return (0);
8236 
8237 	procp = cookie->procp;
8238 	ASSERT(procp);
8239 
8240 	if ((ret = i_ddi_incr_locked_memory(procp,
8241 	    cookie->size)) != 0) {
8242 		return (ret);
8243 	}
8244 	return (0);
8245 }
8246 
8247 /*
8248  * Decrements the max-locked-memory resource ctl and releases
8249  * the hold on the project that was acquired during umem_incr_devlockmem
8250  */
8251 static void
8252 umem_decr_devlockmem(struct ddi_umem_cookie *cookie)
8253 {
8254 	proc_t		*proc;
8255 
8256 	if (cookie->upd_max_lock_rctl == 0)
8257 		return;
8258 
8259 	proc = (proc_t *)cookie->procp;
8260 	if (!proc)
8261 		return;
8262 
8263 	i_ddi_decr_locked_memory(proc, cookie->size);
8264 }
8265 
8266 /*
8267  * A consolidation private function which is essentially equivalent to
8268  * ddi_umem_lock but with the addition of arguments ops_vector and procp.
8269  * A call to as_add_callback is done if DDI_UMEMLOCK_LONGTERM is set, and
8270  * the ops_vector is valid.
8271  *
8272  * Lock the virtual address range in the current process and create a
8273  * ddi_umem_cookie (of type UMEM_LOCKED). This can be used to pass to
8274  * ddi_umem_iosetup to create a buf or do devmap_umem_setup/remap to export
8275  * to user space.
8276  *
8277  * Note: The resource control accounting currently uses a full charge model
8278  * in other words attempts to lock the same/overlapping areas of memory
8279  * will deduct the full size of the buffer from the projects running
8280  * counter for the device locked memory.
8281  *
8282  * addr, size should be PAGESIZE aligned
8283  *
8284  * flags - DDI_UMEMLOCK_READ, DDI_UMEMLOCK_WRITE or both
8285  *	identifies whether the locked memory will be read or written or both
8286  *      DDI_UMEMLOCK_LONGTERM  must be set when the locking will
8287  * be maintained for an indefinitely long period (essentially permanent),
8288  * rather than for what would be required for a typical I/O completion.
8289  * When DDI_UMEMLOCK_LONGTERM is set, umem_lockmemory will return EFAULT
8290  * if the memory pertains to a regular file which is mapped MAP_SHARED.
8291  * This is to prevent a deadlock if a file truncation is attempted after
8292  * after the locking is done.
8293  *
8294  * Returns 0 on success
8295  *	EINVAL - for invalid parameters
8296  *	EPERM, ENOMEM and other error codes returned by as_pagelock
8297  *	ENOMEM - is returned if the current request to lock memory exceeds
8298  *		*.max-locked-memory resource control value.
8299  *      EFAULT - memory pertains to a regular file mapped shared and
8300  *		and DDI_UMEMLOCK_LONGTERM flag is set
8301  *	EAGAIN - could not start the ddi_umem_unlock list processing thread
8302  */
8303 int
8304 umem_lockmemory(caddr_t addr, size_t len, int flags, ddi_umem_cookie_t *cookie,
8305 		struct umem_callback_ops *ops_vector,
8306 		proc_t *procp)
8307 {
8308 	int	error;
8309 	struct ddi_umem_cookie *p;
8310 	void	(*driver_callback)() = NULL;
8311 	struct as *as;
8312 	struct seg		*seg;
8313 	vnode_t			*vp;
8314 
8315 	/* Allow device drivers to not have to reference "curproc" */
8316 	if (procp == NULL)
8317 		procp = curproc;
8318 	as = procp->p_as;
8319 	*cookie = NULL;		/* in case of any error return */
8320 
8321 	/* These are the only three valid flags */
8322 	if ((flags & ~(DDI_UMEMLOCK_READ | DDI_UMEMLOCK_WRITE |
8323 	    DDI_UMEMLOCK_LONGTERM)) != 0)
8324 		return (EINVAL);
8325 
8326 	/* At least one (can be both) of the two access flags must be set */
8327 	if ((flags & (DDI_UMEMLOCK_READ | DDI_UMEMLOCK_WRITE)) == 0)
8328 		return (EINVAL);
8329 
8330 	/* addr and len must be page-aligned */
8331 	if (((uintptr_t)addr & PAGEOFFSET) != 0)
8332 		return (EINVAL);
8333 
8334 	if ((len & PAGEOFFSET) != 0)
8335 		return (EINVAL);
8336 
8337 	/*
8338 	 * For longterm locking a driver callback must be specified; if
8339 	 * not longterm then a callback is optional.
8340 	 */
8341 	if (ops_vector != NULL) {
8342 		if (ops_vector->cbo_umem_callback_version !=
8343 		    UMEM_CALLBACK_VERSION)
8344 			return (EINVAL);
8345 		else
8346 			driver_callback = ops_vector->cbo_umem_lock_cleanup;
8347 	}
8348 	if ((driver_callback == NULL) && (flags & DDI_UMEMLOCK_LONGTERM))
8349 		return (EINVAL);
8350 
8351 	/*
8352 	 * Call i_ddi_umem_unlock_thread_start if necessary.  It will
8353 	 * be called on first ddi_umem_lock or umem_lockmemory call.
8354 	 */
8355 	if (ddi_umem_unlock_thread == NULL)
8356 		i_ddi_umem_unlock_thread_start();
8357 
8358 	/* Allocate memory for the cookie */
8359 	p = kmem_zalloc(sizeof (struct ddi_umem_cookie), KM_SLEEP);
8360 
8361 	/* Convert the flags to seg_rw type */
8362 	if (flags & DDI_UMEMLOCK_WRITE) {
8363 		p->s_flags = S_WRITE;
8364 	} else {
8365 		p->s_flags = S_READ;
8366 	}
8367 
8368 	/* Store procp in cookie for later iosetup/unlock */
8369 	p->procp = (void *)procp;
8370 
8371 	/*
8372 	 * Store the struct as pointer in cookie for later use by
8373 	 * ddi_umem_unlock.  The proc->p_as will be stale if ddi_umem_unlock
8374 	 * is called after relvm is called.
8375 	 */
8376 	p->asp = as;
8377 
8378 	/*
8379 	 * The size field is needed for lockmem accounting.
8380 	 */
8381 	p->size = len;
8382 	init_lockedmem_rctl_flag(p);
8383 
8384 	if (umem_incr_devlockmem(p) != 0) {
8385 		/*
8386 		 * The requested memory cannot be locked
8387 		 */
8388 		kmem_free(p, sizeof (struct ddi_umem_cookie));
8389 		*cookie = (ddi_umem_cookie_t)NULL;
8390 		return (ENOMEM);
8391 	}
8392 
8393 	/* Lock the pages corresponding to addr, len in memory */
8394 	error = as_pagelock(as, &(p->pparray), addr, len, p->s_flags);
8395 	if (error != 0) {
8396 		umem_decr_devlockmem(p);
8397 		kmem_free(p, sizeof (struct ddi_umem_cookie));
8398 		*cookie = (ddi_umem_cookie_t)NULL;
8399 		return (error);
8400 	}
8401 
8402 	/*
8403 	 * For longterm locking the addr must pertain to a seg_vn segment or
8404 	 * or a seg_spt segment.
8405 	 * If the segment pertains to a regular file, it cannot be
8406 	 * mapped MAP_SHARED.
8407 	 * This is to prevent a deadlock if a file truncation is attempted
8408 	 * after the locking is done.
8409 	 * Doing this after as_pagelock guarantees persistence of the as; if
8410 	 * an unacceptable segment is found, the cleanup includes calling
8411 	 * as_pageunlock before returning EFAULT.
8412 	 *
8413 	 * segdev is allowed here as it is already locked.  This allows
8414 	 * for memory exported by drivers through mmap() (which is already
8415 	 * locked) to be allowed for LONGTERM.
8416 	 */
8417 	if (flags & DDI_UMEMLOCK_LONGTERM) {
8418 		extern  struct seg_ops segspt_shmops;
8419 		extern	struct seg_ops segdev_ops;
8420 		AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
8421 		for (seg = as_segat(as, addr); ; seg = AS_SEGNEXT(as, seg)) {
8422 			if (seg == NULL || seg->s_base > addr + len)
8423 				break;
8424 			if (seg->s_ops == &segdev_ops)
8425 				continue;
8426 			if (((seg->s_ops != &segvn_ops) &&
8427 			    (seg->s_ops != &segspt_shmops)) ||
8428 			    ((SEGOP_GETVP(seg, addr, &vp) == 0 &&
8429 			    vp != NULL && vp->v_type == VREG) &&
8430 			    (SEGOP_GETTYPE(seg, addr) & MAP_SHARED))) {
8431 				as_pageunlock(as, p->pparray,
8432 				    addr, len, p->s_flags);
8433 				AS_LOCK_EXIT(as, &as->a_lock);
8434 				umem_decr_devlockmem(p);
8435 				kmem_free(p, sizeof (struct ddi_umem_cookie));
8436 				*cookie = (ddi_umem_cookie_t)NULL;
8437 				return (EFAULT);
8438 			}
8439 		}
8440 		AS_LOCK_EXIT(as, &as->a_lock);
8441 	}
8442 
8443 
8444 	/* Initialize the fields in the ddi_umem_cookie */
8445 	p->cvaddr = addr;
8446 	p->type = UMEM_LOCKED;
8447 	if (driver_callback != NULL) {
8448 		/* i_ddi_umem_unlock and umem_lock_undo may need the cookie */
8449 		p->cook_refcnt = 2;
8450 		p->callbacks = *ops_vector;
8451 	} else {
8452 		/* only i_ddi_umme_unlock needs the cookie */
8453 		p->cook_refcnt = 1;
8454 	}
8455 
8456 	*cookie = (ddi_umem_cookie_t)p;
8457 
8458 	/*
8459 	 * If a driver callback was specified, add an entry to the
8460 	 * as struct callback list. The as_pagelock above guarantees
8461 	 * the persistence of as.
8462 	 */
8463 	if (driver_callback) {
8464 		error = as_add_callback(as, umem_lock_undo, p, AS_ALL_EVENT,
8465 		    addr, len, KM_SLEEP);
8466 		if (error != 0) {
8467 			as_pageunlock(as, p->pparray,
8468 			    addr, len, p->s_flags);
8469 			umem_decr_devlockmem(p);
8470 			kmem_free(p, sizeof (struct ddi_umem_cookie));
8471 			*cookie = (ddi_umem_cookie_t)NULL;
8472 		}
8473 	}
8474 	return (error);
8475 }
8476 
8477 /*
8478  * Unlock the pages locked by ddi_umem_lock or umem_lockmemory and free
8479  * the cookie.  Called from i_ddi_umem_unlock_thread.
8480  */
8481 
8482 static void
8483 i_ddi_umem_unlock(struct ddi_umem_cookie *p)
8484 {
8485 	uint_t	rc;
8486 
8487 	/*
8488 	 * There is no way to determine whether a callback to
8489 	 * umem_lock_undo was registered via as_add_callback.
8490 	 * (i.e. umem_lockmemory was called with DDI_MEMLOCK_LONGTERM and
8491 	 * a valid callback function structure.)  as_delete_callback
8492 	 * is called to delete a possible registered callback.  If the
8493 	 * return from as_delete_callbacks is AS_CALLBACK_DELETED, it
8494 	 * indicates that there was a callback registered, and that is was
8495 	 * successfully deleted.  Thus, the cookie reference count
8496 	 * will never be decremented by umem_lock_undo.  Just return the
8497 	 * memory for the cookie, since both users of the cookie are done.
8498 	 * A return of AS_CALLBACK_NOTFOUND indicates a callback was
8499 	 * never registered.  A return of AS_CALLBACK_DELETE_DEFERRED
8500 	 * indicates that callback processing is taking place and, and
8501 	 * umem_lock_undo is, or will be, executing, and thus decrementing
8502 	 * the cookie reference count when it is complete.
8503 	 *
8504 	 * This needs to be done before as_pageunlock so that the
8505 	 * persistence of as is guaranteed because of the locked pages.
8506 	 *
8507 	 */
8508 	rc = as_delete_callback(p->asp, p);
8509 
8510 
8511 	/*
8512 	 * The proc->p_as will be stale if i_ddi_umem_unlock is called
8513 	 * after relvm is called so use p->asp.
8514 	 */
8515 	as_pageunlock(p->asp, p->pparray, p->cvaddr, p->size, p->s_flags);
8516 
8517 	/*
8518 	 * Now that we have unlocked the memory decrement the
8519 	 * *.max-locked-memory rctl
8520 	 */
8521 	umem_decr_devlockmem(p);
8522 
8523 	if (rc == AS_CALLBACK_DELETED) {
8524 		/* umem_lock_undo will not happen, return the cookie memory */
8525 		ASSERT(p->cook_refcnt == 2);
8526 		kmem_free(p, sizeof (struct ddi_umem_cookie));
8527 	} else {
8528 		/*
8529 		 * umem_undo_lock may happen if as_delete_callback returned
8530 		 * AS_CALLBACK_DELETE_DEFERRED.  In that case, decrement the
8531 		 * reference count, atomically, and return the cookie
8532 		 * memory if the reference count goes to zero.  The only
8533 		 * other value for rc is AS_CALLBACK_NOTFOUND.  In that
8534 		 * case, just return the cookie memory.
8535 		 */
8536 		if ((rc != AS_CALLBACK_DELETE_DEFERRED) ||
8537 		    (atomic_add_long_nv((ulong_t *)(&(p->cook_refcnt)), -1)
8538 		    == 0)) {
8539 			kmem_free(p, sizeof (struct ddi_umem_cookie));
8540 		}
8541 	}
8542 }
8543 
8544 /*
8545  * i_ddi_umem_unlock_thread - deferred ddi_umem_unlock list handler.
8546  *
8547  * Call i_ddi_umem_unlock for entries in the ddi_umem_unlock list
8548  * until it is empty.  Then, wait for more to be added.  This thread is awoken
8549  * via calls to ddi_umem_unlock.
8550  */
8551 
8552 static void
8553 i_ddi_umem_unlock_thread(void)
8554 {
8555 	struct ddi_umem_cookie	*ret_cookie;
8556 	callb_cpr_t	cprinfo;
8557 
8558 	/* process the ddi_umem_unlock list */
8559 	CALLB_CPR_INIT(&cprinfo, &ddi_umem_unlock_mutex,
8560 	    callb_generic_cpr, "unlock_thread");
8561 	for (;;) {
8562 		mutex_enter(&ddi_umem_unlock_mutex);
8563 		if (ddi_umem_unlock_head != NULL) {	/* list not empty */
8564 			ret_cookie = ddi_umem_unlock_head;
8565 			/* take if off the list */
8566 			if ((ddi_umem_unlock_head =
8567 			    ddi_umem_unlock_head->unl_forw) == NULL) {
8568 				ddi_umem_unlock_tail = NULL;
8569 			}
8570 			mutex_exit(&ddi_umem_unlock_mutex);
8571 			/* unlock the pages in this cookie */
8572 			(void) i_ddi_umem_unlock(ret_cookie);
8573 		} else {   /* list is empty, wait for next ddi_umem_unlock */
8574 			CALLB_CPR_SAFE_BEGIN(&cprinfo);
8575 			cv_wait(&ddi_umem_unlock_cv, &ddi_umem_unlock_mutex);
8576 			CALLB_CPR_SAFE_END(&cprinfo, &ddi_umem_unlock_mutex);
8577 			mutex_exit(&ddi_umem_unlock_mutex);
8578 		}
8579 	}
8580 	/* ddi_umem_unlock_thread does not exit */
8581 	/* NOTREACHED */
8582 }
8583 
8584 /*
8585  * Start the thread that will process the ddi_umem_unlock list if it is
8586  * not already started (i_ddi_umem_unlock_thread).
8587  */
8588 static void
8589 i_ddi_umem_unlock_thread_start(void)
8590 {
8591 	mutex_enter(&ddi_umem_unlock_mutex);
8592 	if (ddi_umem_unlock_thread == NULL) {
8593 		ddi_umem_unlock_thread = thread_create(NULL, 0,
8594 		    i_ddi_umem_unlock_thread, NULL, 0, &p0,
8595 		    TS_RUN, minclsyspri);
8596 	}
8597 	mutex_exit(&ddi_umem_unlock_mutex);
8598 }
8599 
8600 /*
8601  * Lock the virtual address range in the current process and create a
8602  * ddi_umem_cookie (of type UMEM_LOCKED). This can be used to pass to
8603  * ddi_umem_iosetup to create a buf or do devmap_umem_setup/remap to export
8604  * to user space.
8605  *
8606  * Note: The resource control accounting currently uses a full charge model
8607  * in other words attempts to lock the same/overlapping areas of memory
8608  * will deduct the full size of the buffer from the projects running
8609  * counter for the device locked memory. This applies to umem_lockmemory too.
8610  *
8611  * addr, size should be PAGESIZE aligned
8612  * flags - DDI_UMEMLOCK_READ, DDI_UMEMLOCK_WRITE or both
8613  *	identifies whether the locked memory will be read or written or both
8614  *
8615  * Returns 0 on success
8616  *	EINVAL - for invalid parameters
8617  *	EPERM, ENOMEM and other error codes returned by as_pagelock
8618  *	ENOMEM - is returned if the current request to lock memory exceeds
8619  *		*.max-locked-memory resource control value.
8620  *	EAGAIN - could not start the ddi_umem_unlock list processing thread
8621  */
8622 int
8623 ddi_umem_lock(caddr_t addr, size_t len, int flags, ddi_umem_cookie_t *cookie)
8624 {
8625 	int	error;
8626 	struct ddi_umem_cookie *p;
8627 
8628 	*cookie = NULL;		/* in case of any error return */
8629 
8630 	/* These are the only two valid flags */
8631 	if ((flags & ~(DDI_UMEMLOCK_READ | DDI_UMEMLOCK_WRITE)) != 0) {
8632 		return (EINVAL);
8633 	}
8634 
8635 	/* At least one of the two flags (or both) must be set */
8636 	if ((flags & (DDI_UMEMLOCK_READ | DDI_UMEMLOCK_WRITE)) == 0) {
8637 		return (EINVAL);
8638 	}
8639 
8640 	/* addr and len must be page-aligned */
8641 	if (((uintptr_t)addr & PAGEOFFSET) != 0) {
8642 		return (EINVAL);
8643 	}
8644 
8645 	if ((len & PAGEOFFSET) != 0) {
8646 		return (EINVAL);
8647 	}
8648 
8649 	/*
8650 	 * Call i_ddi_umem_unlock_thread_start if necessary.  It will
8651 	 * be called on first ddi_umem_lock or umem_lockmemory call.
8652 	 */
8653 	if (ddi_umem_unlock_thread == NULL)
8654 		i_ddi_umem_unlock_thread_start();
8655 
8656 	/* Allocate memory for the cookie */
8657 	p = kmem_zalloc(sizeof (struct ddi_umem_cookie), KM_SLEEP);
8658 
8659 	/* Convert the flags to seg_rw type */
8660 	if (flags & DDI_UMEMLOCK_WRITE) {
8661 		p->s_flags = S_WRITE;
8662 	} else {
8663 		p->s_flags = S_READ;
8664 	}
8665 
8666 	/* Store curproc in cookie for later iosetup/unlock */
8667 	p->procp = (void *)curproc;
8668 
8669 	/*
8670 	 * Store the struct as pointer in cookie for later use by
8671 	 * ddi_umem_unlock.  The proc->p_as will be stale if ddi_umem_unlock
8672 	 * is called after relvm is called.
8673 	 */
8674 	p->asp = curproc->p_as;
8675 	/*
8676 	 * The size field is needed for lockmem accounting.
8677 	 */
8678 	p->size = len;
8679 	init_lockedmem_rctl_flag(p);
8680 
8681 	if (umem_incr_devlockmem(p) != 0) {
8682 		/*
8683 		 * The requested memory cannot be locked
8684 		 */
8685 		kmem_free(p, sizeof (struct ddi_umem_cookie));
8686 		*cookie = (ddi_umem_cookie_t)NULL;
8687 		return (ENOMEM);
8688 	}
8689 
8690 	/* Lock the pages corresponding to addr, len in memory */
8691 	error = as_pagelock(((proc_t *)p->procp)->p_as, &(p->pparray),
8692 	    addr, len, p->s_flags);
8693 	if (error != 0) {
8694 		umem_decr_devlockmem(p);
8695 		kmem_free(p, sizeof (struct ddi_umem_cookie));
8696 		*cookie = (ddi_umem_cookie_t)NULL;
8697 		return (error);
8698 	}
8699 
8700 	/* Initialize the fields in the ddi_umem_cookie */
8701 	p->cvaddr = addr;
8702 	p->type = UMEM_LOCKED;
8703 	p->cook_refcnt = 1;
8704 
8705 	*cookie = (ddi_umem_cookie_t)p;
8706 	return (error);
8707 }
8708 
8709 /*
8710  * Add the cookie to the ddi_umem_unlock list.  Pages will be
8711  * unlocked by i_ddi_umem_unlock_thread.
8712  */
8713 
8714 void
8715 ddi_umem_unlock(ddi_umem_cookie_t cookie)
8716 {
8717 	struct ddi_umem_cookie	*p = (struct ddi_umem_cookie *)cookie;
8718 
8719 	ASSERT(p->type == UMEM_LOCKED);
8720 	ASSERT(CPU_ON_INTR(CPU) == 0); /* cannot be high level */
8721 	ASSERT(ddi_umem_unlock_thread != NULL);
8722 
8723 	p->unl_forw = (struct ddi_umem_cookie *)NULL;	/* end of list */
8724 	/*
8725 	 * Queue the unlock request and notify i_ddi_umem_unlock thread
8726 	 * if it's called in the interrupt context. Otherwise, unlock pages
8727 	 * immediately.
8728 	 */
8729 	if (servicing_interrupt()) {
8730 		/* queue the unlock request and notify the thread */
8731 		mutex_enter(&ddi_umem_unlock_mutex);
8732 		if (ddi_umem_unlock_head == NULL) {
8733 			ddi_umem_unlock_head = ddi_umem_unlock_tail = p;
8734 			cv_broadcast(&ddi_umem_unlock_cv);
8735 		} else {
8736 			ddi_umem_unlock_tail->unl_forw = p;
8737 			ddi_umem_unlock_tail = p;
8738 		}
8739 		mutex_exit(&ddi_umem_unlock_mutex);
8740 	} else {
8741 		/* unlock the pages right away */
8742 		(void) i_ddi_umem_unlock(p);
8743 	}
8744 }
8745 
8746 /*
8747  * Create a buf structure from a ddi_umem_cookie
8748  * cookie - is a ddi_umem_cookie for from ddi_umem_lock and ddi_umem_alloc
8749  *		(only UMEM_LOCKED & KMEM_NON_PAGEABLE types supported)
8750  * off, len - identifies the portion of the memory represented by the cookie
8751  *		that the buf points to.
8752  *	NOTE: off, len need to follow the alignment/size restrictions of the
8753  *		device (dev) that this buf will be passed to. Some devices
8754  *		will accept unrestricted alignment/size, whereas others (such as
8755  *		st) require some block-size alignment/size. It is the caller's
8756  *		responsibility to ensure that the alignment/size restrictions
8757  *		are met (we cannot assert as we do not know the restrictions)
8758  *
8759  * direction - is one of B_READ or B_WRITE and needs to be compatible with
8760  *		the flags used in ddi_umem_lock
8761  *
8762  * The following three arguments are used to initialize fields in the
8763  * buf structure and are uninterpreted by this routine.
8764  *
8765  * dev
8766  * blkno
8767  * iodone
8768  *
8769  * sleepflag - is one of DDI_UMEM_SLEEP or DDI_UMEM_NOSLEEP
8770  *
8771  * Returns a buf structure pointer on success (to be freed by freerbuf)
8772  *	NULL on any parameter error or memory alloc failure
8773  *
8774  */
8775 struct buf *
8776 ddi_umem_iosetup(ddi_umem_cookie_t cookie, off_t off, size_t len,
8777 	int direction, dev_t dev, daddr_t blkno,
8778 	int (*iodone)(struct buf *), int sleepflag)
8779 {
8780 	struct ddi_umem_cookie *p = (struct ddi_umem_cookie *)cookie;
8781 	struct buf *bp;
8782 
8783 	/*
8784 	 * check for valid cookie offset, len
8785 	 */
8786 	if ((off + len) > p->size) {
8787 		return (NULL);
8788 	}
8789 
8790 	if (len > p->size) {
8791 		return (NULL);
8792 	}
8793 
8794 	/* direction has to be one of B_READ or B_WRITE */
8795 	if ((direction != B_READ) && (direction != B_WRITE)) {
8796 		return (NULL);
8797 	}
8798 
8799 	/* These are the only two valid sleepflags */
8800 	if ((sleepflag != DDI_UMEM_SLEEP) && (sleepflag != DDI_UMEM_NOSLEEP)) {
8801 		return (NULL);
8802 	}
8803 
8804 	/*
8805 	 * Only cookies of type UMEM_LOCKED and KMEM_NON_PAGEABLE are supported
8806 	 */
8807 	if ((p->type != UMEM_LOCKED) && (p->type != KMEM_NON_PAGEABLE)) {
8808 		return (NULL);
8809 	}
8810 
8811 	/* If type is KMEM_NON_PAGEABLE procp is NULL */
8812 	ASSERT((p->type == KMEM_NON_PAGEABLE) ?
8813 	    (p->procp == NULL) : (p->procp != NULL));
8814 
8815 	bp = kmem_alloc(sizeof (struct buf), sleepflag);
8816 	if (bp == NULL) {
8817 		return (NULL);
8818 	}
8819 	bioinit(bp);
8820 
8821 	bp->b_flags = B_BUSY | B_PHYS | direction;
8822 	bp->b_edev = dev;
8823 	bp->b_lblkno = blkno;
8824 	bp->b_iodone = iodone;
8825 	bp->b_bcount = len;
8826 	bp->b_proc = (proc_t *)p->procp;
8827 	ASSERT(((uintptr_t)(p->cvaddr) & PAGEOFFSET) == 0);
8828 	bp->b_un.b_addr = (caddr_t)((uintptr_t)(p->cvaddr) + off);
8829 	if (p->pparray != NULL) {
8830 		bp->b_flags |= B_SHADOW;
8831 		ASSERT(((uintptr_t)(p->cvaddr) & PAGEOFFSET) == 0);
8832 		bp->b_shadow = p->pparray + btop(off);
8833 	}
8834 	return (bp);
8835 }
8836 
8837 /*
8838  * Fault-handling and related routines
8839  */
8840 
8841 ddi_devstate_t
8842 ddi_get_devstate(dev_info_t *dip)
8843 {
8844 	if (DEVI_IS_DEVICE_OFFLINE(dip))
8845 		return (DDI_DEVSTATE_OFFLINE);
8846 	else if (DEVI_IS_DEVICE_DOWN(dip) || DEVI_IS_BUS_DOWN(dip))
8847 		return (DDI_DEVSTATE_DOWN);
8848 	else if (DEVI_IS_BUS_QUIESCED(dip))
8849 		return (DDI_DEVSTATE_QUIESCED);
8850 	else if (DEVI_IS_DEVICE_DEGRADED(dip))
8851 		return (DDI_DEVSTATE_DEGRADED);
8852 	else
8853 		return (DDI_DEVSTATE_UP);
8854 }
8855 
8856 void
8857 ddi_dev_report_fault(dev_info_t *dip, ddi_fault_impact_t impact,
8858 	ddi_fault_location_t location, const char *message)
8859 {
8860 	struct ddi_fault_event_data fd;
8861 	ddi_eventcookie_t ec;
8862 
8863 	/*
8864 	 * Assemble all the information into a fault-event-data structure
8865 	 */
8866 	fd.f_dip = dip;
8867 	fd.f_impact = impact;
8868 	fd.f_location = location;
8869 	fd.f_message = message;
8870 	fd.f_oldstate = ddi_get_devstate(dip);
8871 
8872 	/*
8873 	 * Get eventcookie from defining parent.
8874 	 */
8875 	if (ddi_get_eventcookie(dip, DDI_DEVI_FAULT_EVENT, &ec) !=
8876 	    DDI_SUCCESS)
8877 		return;
8878 
8879 	(void) ndi_post_event(dip, dip, ec, &fd);
8880 }
8881 
8882 char *
8883 i_ddi_devi_class(dev_info_t *dip)
8884 {
8885 	return (DEVI(dip)->devi_device_class);
8886 }
8887 
8888 int
8889 i_ddi_set_devi_class(dev_info_t *dip, char *devi_class, int flag)
8890 {
8891 	struct dev_info *devi = DEVI(dip);
8892 
8893 	mutex_enter(&devi->devi_lock);
8894 
8895 	if (devi->devi_device_class)
8896 		kmem_free(devi->devi_device_class,
8897 		    strlen(devi->devi_device_class) + 1);
8898 
8899 	if ((devi->devi_device_class = i_ddi_strdup(devi_class, flag))
8900 	    != NULL) {
8901 		mutex_exit(&devi->devi_lock);
8902 		return (DDI_SUCCESS);
8903 	}
8904 
8905 	mutex_exit(&devi->devi_lock);
8906 
8907 	return (DDI_FAILURE);
8908 }
8909 
8910 
8911 /*
8912  * Task Queues DDI interfaces.
8913  */
8914 
8915 /* ARGSUSED */
8916 ddi_taskq_t *
8917 ddi_taskq_create(dev_info_t *dip, const char *name, int nthreads,
8918     pri_t pri, uint_t cflags)
8919 {
8920 	char full_name[TASKQ_NAMELEN];
8921 	const char *tq_name;
8922 	int nodeid = 0;
8923 
8924 	if (dip == NULL)
8925 		tq_name = name;
8926 	else {
8927 		nodeid = ddi_get_instance(dip);
8928 
8929 		if (name == NULL)
8930 			name = "tq";
8931 
8932 		(void) snprintf(full_name, sizeof (full_name), "%s_%s",
8933 		    ddi_driver_name(dip), name);
8934 
8935 		tq_name = full_name;
8936 	}
8937 
8938 	return ((ddi_taskq_t *)taskq_create_instance(tq_name, nodeid, nthreads,
8939 	    pri == TASKQ_DEFAULTPRI ? minclsyspri : pri,
8940 	    nthreads, INT_MAX, TASKQ_PREPOPULATE));
8941 }
8942 
8943 void
8944 ddi_taskq_destroy(ddi_taskq_t *tq)
8945 {
8946 	taskq_destroy((taskq_t *)tq);
8947 }
8948 
8949 int
8950 ddi_taskq_dispatch(ddi_taskq_t *tq, void (* func)(void *),
8951     void *arg, uint_t dflags)
8952 {
8953 	taskqid_t id = taskq_dispatch((taskq_t *)tq, func, arg,
8954 	    dflags == DDI_SLEEP ? TQ_SLEEP : TQ_NOSLEEP);
8955 
8956 	return (id != 0 ? DDI_SUCCESS : DDI_FAILURE);
8957 }
8958 
8959 void
8960 ddi_taskq_wait(ddi_taskq_t *tq)
8961 {
8962 	taskq_wait((taskq_t *)tq);
8963 }
8964 
8965 void
8966 ddi_taskq_suspend(ddi_taskq_t *tq)
8967 {
8968 	taskq_suspend((taskq_t *)tq);
8969 }
8970 
8971 boolean_t
8972 ddi_taskq_suspended(ddi_taskq_t *tq)
8973 {
8974 	return (taskq_suspended((taskq_t *)tq));
8975 }
8976 
8977 void
8978 ddi_taskq_resume(ddi_taskq_t *tq)
8979 {
8980 	taskq_resume((taskq_t *)tq);
8981 }
8982 
8983 int
8984 ddi_parse(
8985 	const char	*ifname,
8986 	char		*alnum,
8987 	uint_t		*nump)
8988 {
8989 	const char	*p;
8990 	int		l;
8991 	ulong_t		num;
8992 	boolean_t	nonum = B_TRUE;
8993 	char		c;
8994 
8995 	l = strlen(ifname);
8996 	for (p = ifname + l; p != ifname; l--) {
8997 		c = *--p;
8998 		if (!isdigit(c)) {
8999 			(void) strlcpy(alnum, ifname, l + 1);
9000 			if (ddi_strtoul(p + 1, NULL, 10, &num) != 0)
9001 				return (DDI_FAILURE);
9002 			break;
9003 		}
9004 		nonum = B_FALSE;
9005 	}
9006 	if (l == 0 || nonum)
9007 		return (DDI_FAILURE);
9008 
9009 	*nump = num;
9010 	return (DDI_SUCCESS);
9011 }
9012 
9013 /*
9014  * Default initialization function for drivers that don't need to quiesce.
9015  */
9016 /* ARGSUSED */
9017 int
9018 ddi_quiesce_not_needed(dev_info_t *dip)
9019 {
9020 	return (DDI_SUCCESS);
9021 }
9022 
9023 /*
9024  * Initialization function for drivers that should implement quiesce()
9025  * but haven't yet.
9026  */
9027 /* ARGSUSED */
9028 int
9029 ddi_quiesce_not_supported(dev_info_t *dip)
9030 {
9031 	return (DDI_FAILURE);
9032 }
9033 
9034 char *
9035 ddi_strdup(const char *str, int flag)
9036 {
9037 	int	n;
9038 	char	*ptr;
9039 
9040 	ASSERT(str != NULL);
9041 	ASSERT((flag == KM_SLEEP) || (flag == KM_NOSLEEP));
9042 
9043 	n = strlen(str);
9044 	if ((ptr = kmem_alloc(n + 1, flag)) == NULL)
9045 		return (NULL);
9046 	bcopy(str, ptr, n + 1);
9047 	return (ptr);
9048 }
9049 
9050 char *
9051 strdup(const char *str)
9052 {
9053 	return (ddi_strdup(str, KM_SLEEP));
9054 }
9055 
9056 void
9057 strfree(char *str)
9058 {
9059 	ASSERT(str != NULL);
9060 	kmem_free(str, strlen(str) + 1);
9061 }
9062 
9063 /*
9064  * Generic DDI callback interfaces.
9065  */
9066 
9067 int
9068 ddi_cb_register(dev_info_t *dip, ddi_cb_flags_t flags, ddi_cb_func_t cbfunc,
9069     void *arg1, void *arg2, ddi_cb_handle_t *ret_hdlp)
9070 {
9071 	ddi_cb_t	*cbp;
9072 
9073 	ASSERT(dip != NULL);
9074 	ASSERT(DDI_CB_FLAG_VALID(flags));
9075 	ASSERT(cbfunc != NULL);
9076 	ASSERT(ret_hdlp != NULL);
9077 
9078 	/* Sanity check the context */
9079 	ASSERT(!servicing_interrupt());
9080 	if (servicing_interrupt())
9081 		return (DDI_FAILURE);
9082 
9083 	/* Validate parameters */
9084 	if ((dip == NULL) || !DDI_CB_FLAG_VALID(flags) ||
9085 	    (cbfunc == NULL) || (ret_hdlp == NULL))
9086 		return (DDI_EINVAL);
9087 
9088 	/* Check for previous registration */
9089 	if (DEVI(dip)->devi_cb_p != NULL)
9090 		return (DDI_EALREADY);
9091 
9092 	/* Allocate and initialize callback */
9093 	cbp = kmem_zalloc(sizeof (ddi_cb_t), KM_SLEEP);
9094 	cbp->cb_dip = dip;
9095 	cbp->cb_func = cbfunc;
9096 	cbp->cb_arg1 = arg1;
9097 	cbp->cb_arg2 = arg2;
9098 	cbp->cb_flags = flags;
9099 	DEVI(dip)->devi_cb_p = cbp;
9100 
9101 	/* If adding an IRM callback, notify IRM */
9102 	if (flags & DDI_CB_FLAG_INTR)
9103 		i_ddi_irm_set_cb(dip, B_TRUE);
9104 
9105 	*ret_hdlp = (ddi_cb_handle_t)&(DEVI(dip)->devi_cb_p);
9106 	return (DDI_SUCCESS);
9107 }
9108 
9109 int
9110 ddi_cb_unregister(ddi_cb_handle_t hdl)
9111 {
9112 	ddi_cb_t	*cbp;
9113 	dev_info_t	*dip;
9114 
9115 	ASSERT(hdl != NULL);
9116 
9117 	/* Sanity check the context */
9118 	ASSERT(!servicing_interrupt());
9119 	if (servicing_interrupt())
9120 		return (DDI_FAILURE);
9121 
9122 	/* Validate parameters */
9123 	if ((hdl == NULL) || ((cbp = *(ddi_cb_t **)hdl) == NULL) ||
9124 	    ((dip = cbp->cb_dip) == NULL))
9125 		return (DDI_EINVAL);
9126 
9127 	/* If removing an IRM callback, notify IRM */
9128 	if (cbp->cb_flags & DDI_CB_FLAG_INTR)
9129 		i_ddi_irm_set_cb(dip, B_FALSE);
9130 
9131 	/* Destroy the callback */
9132 	kmem_free(cbp, sizeof (ddi_cb_t));
9133 	DEVI(dip)->devi_cb_p = NULL;
9134 
9135 	return (DDI_SUCCESS);
9136 }
9137 
9138 /*
9139  * Platform independent DR routines
9140  */
9141 
9142 static int
9143 ndi2errno(int n)
9144 {
9145 	int err = 0;
9146 
9147 	switch (n) {
9148 		case NDI_NOMEM:
9149 			err = ENOMEM;
9150 			break;
9151 		case NDI_BUSY:
9152 			err = EBUSY;
9153 			break;
9154 		case NDI_FAULT:
9155 			err = EFAULT;
9156 			break;
9157 		case NDI_FAILURE:
9158 			err = EIO;
9159 			break;
9160 		case NDI_SUCCESS:
9161 			break;
9162 		case NDI_BADHANDLE:
9163 		default:
9164 			err = EINVAL;
9165 			break;
9166 	}
9167 	return (err);
9168 }
9169 
9170 /*
9171  * Prom tree node list
9172  */
9173 struct ptnode {
9174 	pnode_t		nodeid;
9175 	struct ptnode	*next;
9176 };
9177 
9178 /*
9179  * Prom tree walk arg
9180  */
9181 struct pta {
9182 	dev_info_t	*pdip;
9183 	devi_branch_t	*bp;
9184 	uint_t		flags;
9185 	dev_info_t	*fdip;
9186 	struct ptnode	*head;
9187 };
9188 
9189 static void
9190 visit_node(pnode_t nodeid, struct pta *ap)
9191 {
9192 	struct ptnode	**nextp;
9193 	int		(*select)(pnode_t, void *, uint_t);
9194 
9195 	ASSERT(nodeid != OBP_NONODE && nodeid != OBP_BADNODE);
9196 
9197 	select = ap->bp->create.prom_branch_select;
9198 
9199 	ASSERT(select);
9200 
9201 	if (select(nodeid, ap->bp->arg, 0) == DDI_SUCCESS) {
9202 
9203 		for (nextp = &ap->head; *nextp; nextp = &(*nextp)->next)
9204 			;
9205 
9206 		*nextp = kmem_zalloc(sizeof (struct ptnode), KM_SLEEP);
9207 
9208 		(*nextp)->nodeid = nodeid;
9209 	}
9210 
9211 	if ((ap->flags & DEVI_BRANCH_CHILD) == DEVI_BRANCH_CHILD)
9212 		return;
9213 
9214 	nodeid = prom_childnode(nodeid);
9215 	while (nodeid != OBP_NONODE && nodeid != OBP_BADNODE) {
9216 		visit_node(nodeid, ap);
9217 		nodeid = prom_nextnode(nodeid);
9218 	}
9219 }
9220 
9221 /*
9222  * NOTE: The caller of this function must check for device contracts
9223  * or LDI callbacks against this dip before setting the dip offline.
9224  */
9225 static int
9226 set_infant_dip_offline(dev_info_t *dip, void *arg)
9227 {
9228 	char	*path = (char *)arg;
9229 
9230 	ASSERT(dip);
9231 	ASSERT(arg);
9232 
9233 	if (i_ddi_node_state(dip) >= DS_ATTACHED) {
9234 		(void) ddi_pathname(dip, path);
9235 		cmn_err(CE_WARN, "Attempt to set offline flag on attached "
9236 		    "node: %s", path);
9237 		return (DDI_FAILURE);
9238 	}
9239 
9240 	mutex_enter(&(DEVI(dip)->devi_lock));
9241 	if (!DEVI_IS_DEVICE_OFFLINE(dip))
9242 		DEVI_SET_DEVICE_OFFLINE(dip);
9243 	mutex_exit(&(DEVI(dip)->devi_lock));
9244 
9245 	return (DDI_SUCCESS);
9246 }
9247 
9248 typedef struct result {
9249 	char	*path;
9250 	int	result;
9251 } result_t;
9252 
9253 static int
9254 dip_set_offline(dev_info_t *dip, void *arg)
9255 {
9256 	int end;
9257 	result_t *resp = (result_t *)arg;
9258 
9259 	ASSERT(dip);
9260 	ASSERT(resp);
9261 
9262 	/*
9263 	 * We stop the walk if e_ddi_offline_notify() returns
9264 	 * failure, because this implies that one or more consumers
9265 	 * (either LDI or contract based) has blocked the offline.
9266 	 * So there is no point in conitnuing the walk
9267 	 */
9268 	if (e_ddi_offline_notify(dip) == DDI_FAILURE) {
9269 		resp->result = DDI_FAILURE;
9270 		return (DDI_WALK_TERMINATE);
9271 	}
9272 
9273 	/*
9274 	 * If set_infant_dip_offline() returns failure, it implies
9275 	 * that we failed to set a particular dip offline. This
9276 	 * does not imply that the offline as a whole should fail.
9277 	 * We want to do the best we can, so we continue the walk.
9278 	 */
9279 	if (set_infant_dip_offline(dip, resp->path) == DDI_SUCCESS)
9280 		end = DDI_SUCCESS;
9281 	else
9282 		end = DDI_FAILURE;
9283 
9284 	e_ddi_offline_finalize(dip, end);
9285 
9286 	return (DDI_WALK_CONTINUE);
9287 }
9288 
9289 /*
9290  * The call to e_ddi_offline_notify() exists for the
9291  * unlikely error case that a branch we are trying to
9292  * create already exists and has device contracts or LDI
9293  * event callbacks against it.
9294  *
9295  * We allow create to succeed for such branches only if
9296  * no constraints block the offline.
9297  */
9298 static int
9299 branch_set_offline(dev_info_t *dip, char *path)
9300 {
9301 	int		circ;
9302 	int		end;
9303 	result_t	res;
9304 
9305 
9306 	if (e_ddi_offline_notify(dip) == DDI_FAILURE) {
9307 		return (DDI_FAILURE);
9308 	}
9309 
9310 	if (set_infant_dip_offline(dip, path) == DDI_SUCCESS)
9311 		end = DDI_SUCCESS;
9312 	else
9313 		end = DDI_FAILURE;
9314 
9315 	e_ddi_offline_finalize(dip, end);
9316 
9317 	if (end == DDI_FAILURE)
9318 		return (DDI_FAILURE);
9319 
9320 	res.result = DDI_SUCCESS;
9321 	res.path = path;
9322 
9323 	ndi_devi_enter(dip, &circ);
9324 	ddi_walk_devs(ddi_get_child(dip), dip_set_offline, &res);
9325 	ndi_devi_exit(dip, circ);
9326 
9327 	return (res.result);
9328 }
9329 
9330 /*ARGSUSED*/
9331 static int
9332 create_prom_branch(void *arg, int has_changed)
9333 {
9334 	int		circ;
9335 	int		exists, rv;
9336 	pnode_t		nodeid;
9337 	struct ptnode	*tnp;
9338 	dev_info_t	*dip;
9339 	struct pta	*ap = arg;
9340 	devi_branch_t	*bp;
9341 	char		*path;
9342 
9343 	ASSERT(ap);
9344 	ASSERT(ap->fdip == NULL);
9345 	ASSERT(ap->pdip && ndi_dev_is_prom_node(ap->pdip));
9346 
9347 	bp = ap->bp;
9348 
9349 	nodeid = ddi_get_nodeid(ap->pdip);
9350 	if (nodeid == OBP_NONODE || nodeid == OBP_BADNODE) {
9351 		cmn_err(CE_WARN, "create_prom_branch: invalid "
9352 		    "nodeid: 0x%x", nodeid);
9353 		return (EINVAL);
9354 	}
9355 
9356 	ap->head = NULL;
9357 
9358 	nodeid = prom_childnode(nodeid);
9359 	while (nodeid != OBP_NONODE && nodeid != OBP_BADNODE) {
9360 		visit_node(nodeid, ap);
9361 		nodeid = prom_nextnode(nodeid);
9362 	}
9363 
9364 	if (ap->head == NULL)
9365 		return (ENODEV);
9366 
9367 	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
9368 	rv = 0;
9369 	while ((tnp = ap->head) != NULL) {
9370 		ap->head = tnp->next;
9371 
9372 		ndi_devi_enter(ap->pdip, &circ);
9373 
9374 		/*
9375 		 * Check if the branch already exists.
9376 		 */
9377 		exists = 0;
9378 		dip = e_ddi_nodeid_to_dip(tnp->nodeid);
9379 		if (dip != NULL) {
9380 			exists = 1;
9381 
9382 			/* Parent is held busy, so release hold */
9383 			ndi_rele_devi(dip);
9384 #ifdef	DEBUG
9385 			cmn_err(CE_WARN, "create_prom_branch: dip(%p) exists"
9386 			    " for nodeid 0x%x", (void *)dip, tnp->nodeid);
9387 #endif
9388 		} else {
9389 			dip = i_ddi_create_branch(ap->pdip, tnp->nodeid);
9390 		}
9391 
9392 		kmem_free(tnp, sizeof (struct ptnode));
9393 
9394 		/*
9395 		 * Hold the branch if it is not already held
9396 		 */
9397 		if (dip && !exists) {
9398 			e_ddi_branch_hold(dip);
9399 		}
9400 
9401 		ASSERT(dip == NULL || e_ddi_branch_held(dip));
9402 
9403 		/*
9404 		 * Set all dips in the newly created branch offline so that
9405 		 * only a "configure" operation can attach
9406 		 * the branch
9407 		 */
9408 		if (dip == NULL || branch_set_offline(dip, path)
9409 		    == DDI_FAILURE) {
9410 			ndi_devi_exit(ap->pdip, circ);
9411 			rv = EIO;
9412 			continue;
9413 		}
9414 
9415 		ASSERT(ddi_get_parent(dip) == ap->pdip);
9416 
9417 		ndi_devi_exit(ap->pdip, circ);
9418 
9419 		if (ap->flags & DEVI_BRANCH_CONFIGURE) {
9420 			int error = e_ddi_branch_configure(dip, &ap->fdip, 0);
9421 			if (error && rv == 0)
9422 				rv = error;
9423 		}
9424 
9425 		/*
9426 		 * Invoke devi_branch_callback() (if it exists) only for
9427 		 * newly created branches
9428 		 */
9429 		if (bp->devi_branch_callback && !exists)
9430 			bp->devi_branch_callback(dip, bp->arg, 0);
9431 	}
9432 
9433 	kmem_free(path, MAXPATHLEN);
9434 
9435 	return (rv);
9436 }
9437 
9438 static int
9439 sid_node_create(dev_info_t *pdip, devi_branch_t *bp, dev_info_t **rdipp)
9440 {
9441 	int			rv, circ, len;
9442 	int			i, flags, ret;
9443 	dev_info_t		*dip;
9444 	char			*nbuf;
9445 	char			*path;
9446 	static const char	*noname = "<none>";
9447 
9448 	ASSERT(pdip);
9449 	ASSERT(DEVI_BUSY_OWNED(pdip));
9450 
9451 	flags = 0;
9452 
9453 	/*
9454 	 * Creating the root of a branch ?
9455 	 */
9456 	if (rdipp) {
9457 		*rdipp = NULL;
9458 		flags = DEVI_BRANCH_ROOT;
9459 	}
9460 
9461 	ndi_devi_alloc_sleep(pdip, (char *)noname, DEVI_SID_NODEID, &dip);
9462 	rv = bp->create.sid_branch_create(dip, bp->arg, flags);
9463 
9464 	nbuf = kmem_alloc(OBP_MAXDRVNAME, KM_SLEEP);
9465 
9466 	if (rv == DDI_WALK_ERROR) {
9467 		cmn_err(CE_WARN, "e_ddi_branch_create: Error setting"
9468 		    " properties on devinfo node %p",  (void *)dip);
9469 		goto fail;
9470 	}
9471 
9472 	len = OBP_MAXDRVNAME;
9473 	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip,
9474 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "name", nbuf, &len)
9475 	    != DDI_PROP_SUCCESS) {
9476 		cmn_err(CE_WARN, "e_ddi_branch_create: devinfo node %p has"
9477 		    "no name property", (void *)dip);
9478 		goto fail;
9479 	}
9480 
9481 	ASSERT(i_ddi_node_state(dip) == DS_PROTO);
9482 	if (ndi_devi_set_nodename(dip, nbuf, 0) != NDI_SUCCESS) {
9483 		cmn_err(CE_WARN, "e_ddi_branch_create: cannot set name (%s)"
9484 		    " for devinfo node %p", nbuf, (void *)dip);
9485 		goto fail;
9486 	}
9487 
9488 	kmem_free(nbuf, OBP_MAXDRVNAME);
9489 
9490 	/*
9491 	 * Ignore bind failures just like boot does
9492 	 */
9493 	(void) ndi_devi_bind_driver(dip, 0);
9494 
9495 	switch (rv) {
9496 	case DDI_WALK_CONTINUE:
9497 	case DDI_WALK_PRUNESIB:
9498 		ndi_devi_enter(dip, &circ);
9499 
9500 		i = DDI_WALK_CONTINUE;
9501 		for (; i == DDI_WALK_CONTINUE; ) {
9502 			i = sid_node_create(dip, bp, NULL);
9503 		}
9504 
9505 		ASSERT(i == DDI_WALK_ERROR || i == DDI_WALK_PRUNESIB);
9506 		if (i == DDI_WALK_ERROR)
9507 			rv = i;
9508 		/*
9509 		 * If PRUNESIB stop creating siblings
9510 		 * of dip's child. Subsequent walk behavior
9511 		 * is determined by rv returned by dip.
9512 		 */
9513 
9514 		ndi_devi_exit(dip, circ);
9515 		break;
9516 	case DDI_WALK_TERMINATE:
9517 		/*
9518 		 * Don't create children and ask our parent
9519 		 * to not create siblings either.
9520 		 */
9521 		rv = DDI_WALK_PRUNESIB;
9522 		break;
9523 	case DDI_WALK_PRUNECHILD:
9524 		/*
9525 		 * Don't create children, but ask parent to continue
9526 		 * with siblings.
9527 		 */
9528 		rv = DDI_WALK_CONTINUE;
9529 		break;
9530 	default:
9531 		ASSERT(0);
9532 		break;
9533 	}
9534 
9535 	if (rdipp)
9536 		*rdipp = dip;
9537 
9538 	/*
9539 	 * Set device offline - only the "configure" op should cause an attach.
9540 	 * Note that it is safe to set the dip offline without checking
9541 	 * for either device contract or layered driver (LDI) based constraints
9542 	 * since there cannot be any contracts or LDI opens of this device.
9543 	 * This is because this node is a newly created dip with the parent busy
9544 	 * held, so no other thread can come in and attach this dip. A dip that
9545 	 * has never been attached cannot have contracts since by definition
9546 	 * a device contract (an agreement between a process and a device minor
9547 	 * node) can only be created against a device that has minor nodes
9548 	 * i.e is attached. Similarly an LDI open will only succeed if the
9549 	 * dip is attached. We assert below that the dip is not attached.
9550 	 */
9551 	ASSERT(i_ddi_node_state(dip) < DS_ATTACHED);
9552 	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
9553 	ret = set_infant_dip_offline(dip, path);
9554 	ASSERT(ret == DDI_SUCCESS);
9555 	kmem_free(path, MAXPATHLEN);
9556 
9557 	return (rv);
9558 fail:
9559 	(void) ndi_devi_free(dip);
9560 	kmem_free(nbuf, OBP_MAXDRVNAME);
9561 	return (DDI_WALK_ERROR);
9562 }
9563 
9564 static int
9565 create_sid_branch(
9566 	dev_info_t	*pdip,
9567 	devi_branch_t	*bp,
9568 	dev_info_t	**dipp,
9569 	uint_t		flags)
9570 {
9571 	int		rv = 0, state = DDI_WALK_CONTINUE;
9572 	dev_info_t	*rdip;
9573 
9574 	while (state == DDI_WALK_CONTINUE) {
9575 		int	circ;
9576 
9577 		ndi_devi_enter(pdip, &circ);
9578 
9579 		state = sid_node_create(pdip, bp, &rdip);
9580 		if (rdip == NULL) {
9581 			ndi_devi_exit(pdip, circ);
9582 			ASSERT(state == DDI_WALK_ERROR);
9583 			break;
9584 		}
9585 
9586 		e_ddi_branch_hold(rdip);
9587 
9588 		ndi_devi_exit(pdip, circ);
9589 
9590 		if (flags & DEVI_BRANCH_CONFIGURE) {
9591 			int error = e_ddi_branch_configure(rdip, dipp, 0);
9592 			if (error && rv == 0)
9593 				rv = error;
9594 		}
9595 
9596 		/*
9597 		 * devi_branch_callback() is optional
9598 		 */
9599 		if (bp->devi_branch_callback)
9600 			bp->devi_branch_callback(rdip, bp->arg, 0);
9601 	}
9602 
9603 	ASSERT(state == DDI_WALK_ERROR || state == DDI_WALK_PRUNESIB);
9604 
9605 	return (state == DDI_WALK_ERROR ? EIO : rv);
9606 }
9607 
9608 int
9609 e_ddi_branch_create(
9610 	dev_info_t	*pdip,
9611 	devi_branch_t	*bp,
9612 	dev_info_t	**dipp,
9613 	uint_t		flags)
9614 {
9615 	int prom_devi, sid_devi, error;
9616 
9617 	if (pdip == NULL || bp == NULL || bp->type == 0)
9618 		return (EINVAL);
9619 
9620 	prom_devi = (bp->type == DEVI_BRANCH_PROM) ? 1 : 0;
9621 	sid_devi = (bp->type == DEVI_BRANCH_SID) ? 1 : 0;
9622 
9623 	if (prom_devi && bp->create.prom_branch_select == NULL)
9624 		return (EINVAL);
9625 	else if (sid_devi && bp->create.sid_branch_create == NULL)
9626 		return (EINVAL);
9627 	else if (!prom_devi && !sid_devi)
9628 		return (EINVAL);
9629 
9630 	if (flags & DEVI_BRANCH_EVENT)
9631 		return (EINVAL);
9632 
9633 	if (prom_devi) {
9634 		struct pta pta = {0};
9635 
9636 		pta.pdip = pdip;
9637 		pta.bp = bp;
9638 		pta.flags = flags;
9639 
9640 		error = prom_tree_access(create_prom_branch, &pta, NULL);
9641 
9642 		if (dipp)
9643 			*dipp = pta.fdip;
9644 		else if (pta.fdip)
9645 			ndi_rele_devi(pta.fdip);
9646 	} else {
9647 		error = create_sid_branch(pdip, bp, dipp, flags);
9648 	}
9649 
9650 	return (error);
9651 }
9652 
9653 int
9654 e_ddi_branch_configure(dev_info_t *rdip, dev_info_t **dipp, uint_t flags)
9655 {
9656 	int		rv;
9657 	char		*devnm;
9658 	dev_info_t	*pdip;
9659 
9660 	if (dipp)
9661 		*dipp = NULL;
9662 
9663 	if (rdip == NULL || flags != 0 || (flags & DEVI_BRANCH_EVENT))
9664 		return (EINVAL);
9665 
9666 	pdip = ddi_get_parent(rdip);
9667 
9668 	ndi_hold_devi(pdip);
9669 
9670 	if (!e_ddi_branch_held(rdip)) {
9671 		ndi_rele_devi(pdip);
9672 		cmn_err(CE_WARN, "e_ddi_branch_configure: "
9673 		    "dip(%p) not held", (void *)rdip);
9674 		return (EINVAL);
9675 	}
9676 
9677 	if (i_ddi_node_state(rdip) < DS_INITIALIZED) {
9678 		/*
9679 		 * First attempt to bind a driver. If we fail, return
9680 		 * success (On some platforms, dips for some device
9681 		 * types (CPUs) may not have a driver)
9682 		 */
9683 		if (ndi_devi_bind_driver(rdip, 0) != NDI_SUCCESS) {
9684 			ndi_rele_devi(pdip);
9685 			return (0);
9686 		}
9687 
9688 		if (ddi_initchild(pdip, rdip) != DDI_SUCCESS) {
9689 			rv = NDI_FAILURE;
9690 			goto out;
9691 		}
9692 	}
9693 
9694 	ASSERT(i_ddi_node_state(rdip) >= DS_INITIALIZED);
9695 
9696 	devnm = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
9697 
9698 	(void) ddi_deviname(rdip, devnm);
9699 
9700 	if ((rv = ndi_devi_config_one(pdip, devnm+1, &rdip,
9701 	    NDI_DEVI_ONLINE | NDI_CONFIG)) == NDI_SUCCESS) {
9702 		/* release hold from ndi_devi_config_one() */
9703 		ndi_rele_devi(rdip);
9704 	}
9705 
9706 	kmem_free(devnm, MAXNAMELEN + 1);
9707 out:
9708 	if (rv != NDI_SUCCESS && dipp && rdip) {
9709 		ndi_hold_devi(rdip);
9710 		*dipp = rdip;
9711 	}
9712 	ndi_rele_devi(pdip);
9713 	return (ndi2errno(rv));
9714 }
9715 
9716 void
9717 e_ddi_branch_hold(dev_info_t *rdip)
9718 {
9719 	if (e_ddi_branch_held(rdip)) {
9720 		cmn_err(CE_WARN, "e_ddi_branch_hold: branch already held");
9721 		return;
9722 	}
9723 
9724 	mutex_enter(&DEVI(rdip)->devi_lock);
9725 	if ((DEVI(rdip)->devi_flags & DEVI_BRANCH_HELD) == 0) {
9726 		DEVI(rdip)->devi_flags |= DEVI_BRANCH_HELD;
9727 		DEVI(rdip)->devi_ref++;
9728 	}
9729 	ASSERT(DEVI(rdip)->devi_ref > 0);
9730 	mutex_exit(&DEVI(rdip)->devi_lock);
9731 }
9732 
9733 int
9734 e_ddi_branch_held(dev_info_t *rdip)
9735 {
9736 	int rv = 0;
9737 
9738 	mutex_enter(&DEVI(rdip)->devi_lock);
9739 	if ((DEVI(rdip)->devi_flags & DEVI_BRANCH_HELD) &&
9740 	    DEVI(rdip)->devi_ref > 0) {
9741 		rv = 1;
9742 	}
9743 	mutex_exit(&DEVI(rdip)->devi_lock);
9744 
9745 	return (rv);
9746 }
9747 
9748 void
9749 e_ddi_branch_rele(dev_info_t *rdip)
9750 {
9751 	mutex_enter(&DEVI(rdip)->devi_lock);
9752 	DEVI(rdip)->devi_flags &= ~DEVI_BRANCH_HELD;
9753 	DEVI(rdip)->devi_ref--;
9754 	mutex_exit(&DEVI(rdip)->devi_lock);
9755 }
9756 
9757 int
9758 e_ddi_branch_unconfigure(
9759 	dev_info_t *rdip,
9760 	dev_info_t **dipp,
9761 	uint_t flags)
9762 {
9763 	int	circ, rv;
9764 	int	destroy;
9765 	char	*devnm;
9766 	uint_t	nflags;
9767 	dev_info_t *pdip;
9768 
9769 	if (dipp)
9770 		*dipp = NULL;
9771 
9772 	if (rdip == NULL)
9773 		return (EINVAL);
9774 
9775 	pdip = ddi_get_parent(rdip);
9776 
9777 	ASSERT(pdip);
9778 
9779 	/*
9780 	 * Check if caller holds pdip busy - can cause deadlocks during
9781 	 * devfs_clean()
9782 	 */
9783 	if (DEVI_BUSY_OWNED(pdip)) {
9784 		cmn_err(CE_WARN, "e_ddi_branch_unconfigure: failed: parent"
9785 		    " devinfo node(%p) is busy held", (void *)pdip);
9786 		return (EINVAL);
9787 	}
9788 
9789 	destroy = (flags & DEVI_BRANCH_DESTROY) ? 1 : 0;
9790 
9791 	devnm = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
9792 
9793 	ndi_devi_enter(pdip, &circ);
9794 	(void) ddi_deviname(rdip, devnm);
9795 	ndi_devi_exit(pdip, circ);
9796 
9797 	/*
9798 	 * ddi_deviname() returns a component name with / prepended.
9799 	 */
9800 	(void) devfs_clean(pdip, devnm + 1, DV_CLEAN_FORCE);
9801 
9802 	ndi_devi_enter(pdip, &circ);
9803 
9804 	/*
9805 	 * Recreate device name as it may have changed state (init/uninit)
9806 	 * when parent busy lock was dropped for devfs_clean()
9807 	 */
9808 	(void) ddi_deviname(rdip, devnm);
9809 
9810 	if (!e_ddi_branch_held(rdip)) {
9811 		kmem_free(devnm, MAXNAMELEN + 1);
9812 		ndi_devi_exit(pdip, circ);
9813 		cmn_err(CE_WARN, "e_ddi_%s_branch: dip(%p) not held",
9814 		    destroy ? "destroy" : "unconfigure", (void *)rdip);
9815 		return (EINVAL);
9816 	}
9817 
9818 	/*
9819 	 * Release hold on the branch. This is ok since we are holding the
9820 	 * parent busy. If rdip is not removed, we must do a hold on the
9821 	 * branch before returning.
9822 	 */
9823 	e_ddi_branch_rele(rdip);
9824 
9825 	nflags = NDI_DEVI_OFFLINE;
9826 	if (destroy || (flags & DEVI_BRANCH_DESTROY)) {
9827 		nflags |= NDI_DEVI_REMOVE;
9828 		destroy = 1;
9829 	} else {
9830 		nflags |= NDI_UNCONFIG;		/* uninit but don't remove */
9831 	}
9832 
9833 	if (flags & DEVI_BRANCH_EVENT)
9834 		nflags |= NDI_POST_EVENT;
9835 
9836 	if (i_ddi_devi_attached(pdip) &&
9837 	    (i_ddi_node_state(rdip) >= DS_INITIALIZED)) {
9838 		rv = ndi_devi_unconfig_one(pdip, devnm+1, dipp, nflags);
9839 	} else {
9840 		rv = e_ddi_devi_unconfig(rdip, dipp, nflags);
9841 		if (rv == NDI_SUCCESS) {
9842 			ASSERT(!destroy || ddi_get_child(rdip) == NULL);
9843 			rv = ndi_devi_offline(rdip, nflags);
9844 		}
9845 	}
9846 
9847 	if (!destroy || rv != NDI_SUCCESS) {
9848 		/* The dip still exists, so do a hold */
9849 		e_ddi_branch_hold(rdip);
9850 	}
9851 out:
9852 	kmem_free(devnm, MAXNAMELEN + 1);
9853 	ndi_devi_exit(pdip, circ);
9854 	return (ndi2errno(rv));
9855 }
9856 
9857 int
9858 e_ddi_branch_destroy(dev_info_t *rdip, dev_info_t **dipp, uint_t flag)
9859 {
9860 	return (e_ddi_branch_unconfigure(rdip, dipp,
9861 	    flag|DEVI_BRANCH_DESTROY));
9862 }
9863 
9864 /*
9865  * Number of chains for hash table
9866  */
9867 #define	NUMCHAINS	17
9868 
9869 /*
9870  * Devinfo busy arg
9871  */
9872 struct devi_busy {
9873 	int dv_total;
9874 	int s_total;
9875 	mod_hash_t *dv_hash;
9876 	mod_hash_t *s_hash;
9877 	int (*callback)(dev_info_t *, void *, uint_t);
9878 	void *arg;
9879 };
9880 
9881 static int
9882 visit_dip(dev_info_t *dip, void *arg)
9883 {
9884 	uintptr_t sbusy, dvbusy, ref;
9885 	struct devi_busy *bsp = arg;
9886 
9887 	ASSERT(bsp->callback);
9888 
9889 	/*
9890 	 * A dip cannot be busy if its reference count is 0
9891 	 */
9892 	if ((ref = e_ddi_devi_holdcnt(dip)) == 0) {
9893 		return (bsp->callback(dip, bsp->arg, 0));
9894 	}
9895 
9896 	if (mod_hash_find(bsp->dv_hash, dip, (mod_hash_val_t *)&dvbusy))
9897 		dvbusy = 0;
9898 
9899 	/*
9900 	 * To catch device opens currently maintained on specfs common snodes.
9901 	 */
9902 	if (mod_hash_find(bsp->s_hash, dip, (mod_hash_val_t *)&sbusy))
9903 		sbusy = 0;
9904 
9905 #ifdef	DEBUG
9906 	if (ref < sbusy || ref < dvbusy) {
9907 		cmn_err(CE_WARN, "dip(%p): sopen = %lu, dvopen = %lu "
9908 		    "dip ref = %lu\n", (void *)dip, sbusy, dvbusy, ref);
9909 	}
9910 #endif
9911 
9912 	dvbusy = (sbusy > dvbusy) ? sbusy : dvbusy;
9913 
9914 	return (bsp->callback(dip, bsp->arg, dvbusy));
9915 }
9916 
9917 static int
9918 visit_snode(struct snode *sp, void *arg)
9919 {
9920 	uintptr_t sbusy;
9921 	dev_info_t *dip;
9922 	int count;
9923 	struct devi_busy *bsp = arg;
9924 
9925 	ASSERT(sp);
9926 
9927 	/*
9928 	 * The stable lock is held. This prevents
9929 	 * the snode and its associated dip from
9930 	 * going away.
9931 	 */
9932 	dip = NULL;
9933 	count = spec_devi_open_count(sp, &dip);
9934 
9935 	if (count <= 0)
9936 		return (DDI_WALK_CONTINUE);
9937 
9938 	ASSERT(dip);
9939 
9940 	if (mod_hash_remove(bsp->s_hash, dip, (mod_hash_val_t *)&sbusy))
9941 		sbusy = count;
9942 	else
9943 		sbusy += count;
9944 
9945 	if (mod_hash_insert(bsp->s_hash, dip, (mod_hash_val_t)sbusy)) {
9946 		cmn_err(CE_WARN, "%s: s_hash insert failed: dip=0x%p, "
9947 		    "sbusy = %lu", "e_ddi_branch_referenced",
9948 		    (void *)dip, sbusy);
9949 	}
9950 
9951 	bsp->s_total += count;
9952 
9953 	return (DDI_WALK_CONTINUE);
9954 }
9955 
9956 static void
9957 visit_dvnode(struct dv_node *dv, void *arg)
9958 {
9959 	uintptr_t dvbusy;
9960 	uint_t count;
9961 	struct vnode *vp;
9962 	struct devi_busy *bsp = arg;
9963 
9964 	ASSERT(dv && dv->dv_devi);
9965 
9966 	vp = DVTOV(dv);
9967 
9968 	mutex_enter(&vp->v_lock);
9969 	count = vp->v_count;
9970 	mutex_exit(&vp->v_lock);
9971 
9972 	if (!count)
9973 		return;
9974 
9975 	if (mod_hash_remove(bsp->dv_hash, dv->dv_devi,
9976 	    (mod_hash_val_t *)&dvbusy))
9977 		dvbusy = count;
9978 	else
9979 		dvbusy += count;
9980 
9981 	if (mod_hash_insert(bsp->dv_hash, dv->dv_devi,
9982 	    (mod_hash_val_t)dvbusy)) {
9983 		cmn_err(CE_WARN, "%s: dv_hash insert failed: dip=0x%p, "
9984 		    "dvbusy=%lu", "e_ddi_branch_referenced",
9985 		    (void *)dv->dv_devi, dvbusy);
9986 	}
9987 
9988 	bsp->dv_total += count;
9989 }
9990 
9991 /*
9992  * Returns reference count on success or -1 on failure.
9993  */
9994 int
9995 e_ddi_branch_referenced(
9996 	dev_info_t *rdip,
9997 	int (*callback)(dev_info_t *dip, void *arg, uint_t ref),
9998 	void *arg)
9999 {
10000 	int circ;
10001 	char *path;
10002 	dev_info_t *pdip;
10003 	struct devi_busy bsa = {0};
10004 
10005 	ASSERT(rdip);
10006 
10007 	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
10008 
10009 	ndi_hold_devi(rdip);
10010 
10011 	pdip = ddi_get_parent(rdip);
10012 
10013 	ASSERT(pdip);
10014 
10015 	/*
10016 	 * Check if caller holds pdip busy - can cause deadlocks during
10017 	 * devfs_walk()
10018 	 */
10019 	if (!e_ddi_branch_held(rdip) || DEVI_BUSY_OWNED(pdip)) {
10020 		cmn_err(CE_WARN, "e_ddi_branch_referenced: failed: "
10021 		    "devinfo branch(%p) not held or parent busy held",
10022 		    (void *)rdip);
10023 		ndi_rele_devi(rdip);
10024 		kmem_free(path, MAXPATHLEN);
10025 		return (-1);
10026 	}
10027 
10028 	ndi_devi_enter(pdip, &circ);
10029 	(void) ddi_pathname(rdip, path);
10030 	ndi_devi_exit(pdip, circ);
10031 
10032 	bsa.dv_hash = mod_hash_create_ptrhash("dv_node busy hash", NUMCHAINS,
10033 	    mod_hash_null_valdtor, sizeof (struct dev_info));
10034 
10035 	bsa.s_hash = mod_hash_create_ptrhash("snode busy hash", NUMCHAINS,
10036 	    mod_hash_null_valdtor, sizeof (struct snode));
10037 
10038 	if (devfs_walk(path, visit_dvnode, &bsa)) {
10039 		cmn_err(CE_WARN, "e_ddi_branch_referenced: "
10040 		    "devfs walk failed for: %s", path);
10041 		kmem_free(path, MAXPATHLEN);
10042 		bsa.s_total = bsa.dv_total = -1;
10043 		goto out;
10044 	}
10045 
10046 	kmem_free(path, MAXPATHLEN);
10047 
10048 	/*
10049 	 * Walk the snode table to detect device opens, which are currently
10050 	 * maintained on specfs common snodes.
10051 	 */
10052 	spec_snode_walk(visit_snode, &bsa);
10053 
10054 	if (callback == NULL)
10055 		goto out;
10056 
10057 	bsa.callback = callback;
10058 	bsa.arg = arg;
10059 
10060 	if (visit_dip(rdip, &bsa) == DDI_WALK_CONTINUE) {
10061 		ndi_devi_enter(rdip, &circ);
10062 		ddi_walk_devs(ddi_get_child(rdip), visit_dip, &bsa);
10063 		ndi_devi_exit(rdip, circ);
10064 	}
10065 
10066 out:
10067 	ndi_rele_devi(rdip);
10068 	mod_hash_destroy_ptrhash(bsa.s_hash);
10069 	mod_hash_destroy_ptrhash(bsa.dv_hash);
10070 	return (bsa.s_total > bsa.dv_total ? bsa.s_total : bsa.dv_total);
10071 }
10072