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