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