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