1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
25 */
26
27#include <sys/note.h>
28#include <sys/types.h>
29#include <sys/param.h>
30#include <sys/systm.h>
31#include <sys/buf.h>
32#include <sys/uio.h>
33#include <sys/cred.h>
34#include <sys/poll.h>
35#include <sys/mman.h>
36#include <sys/kmem.h>
37#include <sys/model.h>
38#include <sys/file.h>
39#include <sys/proc.h>
40#include <sys/open.h>
41#include <sys/user.h>
42#include <sys/t_lock.h>
43#include <sys/vm.h>
44#include <sys/stat.h>
45#include <vm/hat.h>
46#include <vm/seg.h>
47#include <vm/seg_vn.h>
48#include <vm/seg_dev.h>
49#include <vm/as.h>
50#include <sys/cmn_err.h>
51#include <sys/cpuvar.h>
52#include <sys/debug.h>
53#include <sys/autoconf.h>
54#include <sys/sunddi.h>
55#include <sys/esunddi.h>
56#include <sys/sunndi.h>
57#include <sys/kstat.h>
58#include <sys/conf.h>
59#include <sys/ddi_impldefs.h>	/* include implementation structure defs */
60#include <sys/ndi_impldefs.h>	/* include prototypes */
61#include <sys/ddi_periodic.h>
62#include <sys/hwconf.h>
63#include <sys/pathname.h>
64#include <sys/modctl.h>
65#include <sys/epm.h>
66#include <sys/devctl.h>
67#include <sys/callb.h>
68#include <sys/cladm.h>
69#include <sys/sysevent.h>
70#include <sys/dacf_impl.h>
71#include <sys/ddidevmap.h>
72#include <sys/bootconf.h>
73#include <sys/disp.h>
74#include <sys/atomic.h>
75#include <sys/promif.h>
76#include <sys/instance.h>
77#include <sys/sysevent/eventdefs.h>
78#include <sys/task.h>
79#include <sys/project.h>
80#include <sys/taskq.h>
81#include <sys/devpolicy.h>
82#include <sys/ctype.h>
83#include <net/if.h>
84#include <sys/rctl.h>
85#include <sys/zone.h>
86#include <sys/clock_impl.h>
87#include <sys/ddi.h>
88#include <sys/modhash.h>
89#include <sys/sunldi_impl.h>
90#include <sys/fs/dv_node.h>
91#include <sys/fs/snode.h>
92
93extern	pri_t	minclsyspri;
94
95extern	rctl_hndl_t rc_project_locked_mem;
96extern	rctl_hndl_t rc_zone_locked_mem;
97
98#ifdef DEBUG
99static int sunddi_debug = 0;
100#endif /* DEBUG */
101
102/* ddi_umem_unlock miscellaneous */
103
104static	void	i_ddi_umem_unlock_thread_start(void);
105
106static	kmutex_t	ddi_umem_unlock_mutex; /* unlock list mutex */
107static	kcondvar_t	ddi_umem_unlock_cv; /* unlock list block/unblock */
108static	kthread_t	*ddi_umem_unlock_thread;
109/*
110 * The ddi_umem_unlock FIFO list.  NULL head pointer indicates empty list.
111 */
112static	struct	ddi_umem_cookie *ddi_umem_unlock_head = NULL;
113static	struct	ddi_umem_cookie *ddi_umem_unlock_tail = NULL;
114
115/*
116 * DDI(Sun) Function and flag definitions:
117 */
118
119#if defined(__x86)
120/*
121 * Used to indicate which entries were chosen from a range.
122 */
123char	*chosen_reg = "chosen-reg";
124#endif
125
126/*
127 * Function used to ring system console bell
128 */
129void (*ddi_console_bell_func)(clock_t duration);
130
131/*
132 * Creating register mappings and handling interrupts:
133 */
134
135/*
136 * Generic ddi_map: Call parent to fulfill request...
137 */
138
139int
140ddi_map(dev_info_t *dp, ddi_map_req_t *mp, off_t offset,
141    off_t len, caddr_t *addrp)
142{
143	dev_info_t *pdip;
144
145	ASSERT(dp);
146	pdip = (dev_info_t *)DEVI(dp)->devi_parent;
147	return ((DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)(pdip,
148	    dp, mp, offset, len, addrp));
149}
150
151/*
152 * ddi_apply_range: (Called by nexi only.)
153 * Apply ranges in parent node dp, to child regspec rp...
154 */
155
156int
157ddi_apply_range(dev_info_t *dp, dev_info_t *rdip, struct regspec *rp)
158{
159	return (i_ddi_apply_range(dp, rdip, rp));
160}
161
162int
163ddi_map_regs(dev_info_t *dip, uint_t rnumber, caddr_t *kaddrp, off_t offset,
164    off_t len)
165{
166	ddi_map_req_t mr;
167#if defined(__x86)
168	struct {
169		int	bus;
170		int	addr;
171		int	size;
172	} reg, *reglist;
173	uint_t	length;
174	int	rc;
175
176	/*
177	 * get the 'registers' or the 'reg' property.
178	 * We look up the reg property as an array of
179	 * int's.
180	 */
181	rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
182	    DDI_PROP_DONTPASS, "registers", (int **)&reglist, &length);
183	if (rc != DDI_PROP_SUCCESS)
184		rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
185		    DDI_PROP_DONTPASS, "reg", (int **)&reglist, &length);
186	if (rc == DDI_PROP_SUCCESS) {
187		/*
188		 * point to the required entry.
189		 */
190		reg = reglist[rnumber];
191		reg.addr += offset;
192		if (len != 0)
193			reg.size = len;
194		/*
195		 * make a new property containing ONLY the required tuple.
196		 */
197		if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
198		    chosen_reg, (int *)&reg, (sizeof (reg)/sizeof (int)))
199		    != DDI_PROP_SUCCESS) {
200			cmn_err(CE_WARN, "%s%d: cannot create '%s' "
201			    "property", DEVI(dip)->devi_name,
202			    DEVI(dip)->devi_instance, chosen_reg);
203		}
204		/*
205		 * free the memory allocated by
206		 * ddi_prop_lookup_int_array ().
207		 */
208		ddi_prop_free((void *)reglist);
209	}
210#endif
211	mr.map_op = DDI_MO_MAP_LOCKED;
212	mr.map_type = DDI_MT_RNUMBER;
213	mr.map_obj.rnumber = rnumber;
214	mr.map_prot = PROT_READ | PROT_WRITE;
215	mr.map_flags = DDI_MF_KERNEL_MAPPING;
216	mr.map_handlep = NULL;
217	mr.map_vers = DDI_MAP_VERSION;
218
219	/*
220	 * Call my parent to map in my regs.
221	 */
222
223	return (ddi_map(dip, &mr, offset, len, kaddrp));
224}
225
226void
227ddi_unmap_regs(dev_info_t *dip, uint_t rnumber, caddr_t *kaddrp, off_t offset,
228    off_t len)
229{
230	ddi_map_req_t mr;
231
232	mr.map_op = DDI_MO_UNMAP;
233	mr.map_type = DDI_MT_RNUMBER;
234	mr.map_flags = DDI_MF_KERNEL_MAPPING;
235	mr.map_prot = PROT_READ | PROT_WRITE;	/* who cares? */
236	mr.map_obj.rnumber = rnumber;
237	mr.map_handlep = NULL;
238	mr.map_vers = DDI_MAP_VERSION;
239
240	/*
241	 * Call my parent to unmap my regs.
242	 */
243
244	(void) ddi_map(dip, &mr, offset, len, kaddrp);
245	*kaddrp = (caddr_t)0;
246#if defined(__x86)
247	(void) ddi_prop_remove(DDI_DEV_T_NONE, dip, chosen_reg);
248#endif
249}
250
251int
252ddi_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
253	off_t offset, off_t len, caddr_t *vaddrp)
254{
255	return (i_ddi_bus_map(dip, rdip, mp, offset, len, vaddrp));
256}
257
258/*
259 * nullbusmap:	The/DDI default bus_map entry point for nexi
260 *		not conforming to the reg/range paradigm (i.e. scsi, etc.)
261 *		with no HAT/MMU layer to be programmed at this level.
262 *
263 *		If the call is to map by rnumber, return an error,
264 *		otherwise pass anything else up the tree to my parent.
265 */
266int
267nullbusmap(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
268	off_t offset, off_t len, caddr_t *vaddrp)
269{
270	_NOTE(ARGUNUSED(rdip))
271	if (mp->map_type == DDI_MT_RNUMBER)
272		return (DDI_ME_UNSUPPORTED);
273
274	return (ddi_map(dip, mp, offset, len, vaddrp));
275}
276
277/*
278 * ddi_rnumber_to_regspec: Not for use by leaf drivers.
279 *			   Only for use by nexi using the reg/range paradigm.
280 */
281struct regspec *
282ddi_rnumber_to_regspec(dev_info_t *dip, int rnumber)
283{
284	return (i_ddi_rnumber_to_regspec(dip, rnumber));
285}
286
287
288/*
289 * Note that we allow the dip to be nil because we may be called
290 * prior even to the instantiation of the devinfo tree itself - all
291 * regular leaf and nexus drivers should always use a non-nil dip!
292 *
293 * We treat peek in a somewhat cavalier fashion .. assuming that we'll
294 * simply get a synchronous fault as soon as we touch a missing address.
295 *
296 * Poke is rather more carefully handled because we might poke to a write
297 * buffer, "succeed", then only find some time later that we got an
298 * asynchronous fault that indicated that the address we were writing to
299 * was not really backed by hardware.
300 */
301
302static int
303i_ddi_peekpoke(dev_info_t *devi, ddi_ctl_enum_t cmd, size_t size,
304    void *addr, void *value_p)
305{
306	union {
307		uint64_t	u64;
308		uint32_t	u32;
309		uint16_t	u16;
310		uint8_t		u8;
311	} peekpoke_value;
312
313	peekpoke_ctlops_t peekpoke_args;
314	uint64_t dummy_result;
315	int rval;
316
317	/* Note: size is assumed to be correct;  it is not checked. */
318	peekpoke_args.size = size;
319	peekpoke_args.dev_addr = (uintptr_t)addr;
320	peekpoke_args.handle = NULL;
321	peekpoke_args.repcount = 1;
322	peekpoke_args.flags = 0;
323
324	if (cmd == DDI_CTLOPS_POKE) {
325		switch (size) {
326		case sizeof (uint8_t):
327			peekpoke_value.u8 = *(uint8_t *)value_p;
328			break;
329		case sizeof (uint16_t):
330			peekpoke_value.u16 = *(uint16_t *)value_p;
331			break;
332		case sizeof (uint32_t):
333			peekpoke_value.u32 = *(uint32_t *)value_p;
334			break;
335		case sizeof (uint64_t):
336			peekpoke_value.u64 = *(uint64_t *)value_p;
337			break;
338		}
339	}
340
341	peekpoke_args.host_addr = (uintptr_t)&peekpoke_value.u64;
342
343	if (devi != NULL)
344		rval = ddi_ctlops(devi, devi, cmd, &peekpoke_args,
345		    &dummy_result);
346	else
347		rval = peekpoke_mem(cmd, &peekpoke_args);
348
349	/*
350	 * A NULL value_p is permitted by ddi_peek(9F); discard the result.
351	 */
352	if ((cmd == DDI_CTLOPS_PEEK) & (value_p != NULL)) {
353		switch (size) {
354		case sizeof (uint8_t):
355			*(uint8_t *)value_p = peekpoke_value.u8;
356			break;
357		case sizeof (uint16_t):
358			*(uint16_t *)value_p = peekpoke_value.u16;
359			break;
360		case sizeof (uint32_t):
361			*(uint32_t *)value_p = peekpoke_value.u32;
362			break;
363		case sizeof (uint64_t):
364			*(uint64_t *)value_p = peekpoke_value.u64;
365			break;
366		}
367	}
368
369	return (rval);
370}
371
372/*
373 * Keep ddi_peek() and ddi_poke() in case 3rd parties are calling this.
374 * they shouldn't be, but the 9f manpage kind of pseudo exposes it.
375 */
376int
377ddi_peek(dev_info_t *devi, size_t size, void *addr, void *value_p)
378{
379	switch (size) {
380	case sizeof (uint8_t):
381	case sizeof (uint16_t):
382	case sizeof (uint32_t):
383	case sizeof (uint64_t):
384		break;
385	default:
386		return (DDI_FAILURE);
387	}
388
389	return (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, size, addr, value_p));
390}
391
392int
393ddi_poke(dev_info_t *devi, size_t size, void *addr, void *value_p)
394{
395	switch (size) {
396	case sizeof (uint8_t):
397	case sizeof (uint16_t):
398	case sizeof (uint32_t):
399	case sizeof (uint64_t):
400		break;
401	default:
402		return (DDI_FAILURE);
403	}
404
405	return (i_ddi_peekpoke(devi, DDI_CTLOPS_POKE, size, addr, value_p));
406}
407
408int
409ddi_peek8(dev_info_t *dip, int8_t *addr, int8_t *val_p)
410{
411	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
412	    val_p));
413}
414
415int
416ddi_peek16(dev_info_t *dip, int16_t *addr, int16_t *val_p)
417{
418	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
419	    val_p));
420}
421
422int
423ddi_peek32(dev_info_t *dip, int32_t *addr, int32_t *val_p)
424{
425	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
426	    val_p));
427}
428
429int
430ddi_peek64(dev_info_t *dip, int64_t *addr, int64_t *val_p)
431{
432	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
433	    val_p));
434}
435
436
437/*
438 * We need to separate the old interfaces from the new ones and leave them
439 * in here for a while. Previous versions of the OS defined the new interfaces
440 * to the old interfaces. This way we can fix things up so that we can
441 * eventually remove these interfaces.
442 * e.g. A 3rd party module/driver using ddi_peek8 and built against S10
443 * or earlier will actually have a reference to ddi_peekc in the binary.
444 */
445#ifdef _ILP32
446int
447ddi_peekc(dev_info_t *dip, int8_t *addr, int8_t *val_p)
448{
449	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
450	    val_p));
451}
452
453int
454ddi_peeks(dev_info_t *dip, int16_t *addr, int16_t *val_p)
455{
456	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
457	    val_p));
458}
459
460int
461ddi_peekl(dev_info_t *dip, int32_t *addr, int32_t *val_p)
462{
463	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
464	    val_p));
465}
466
467int
468ddi_peekd(dev_info_t *dip, int64_t *addr, int64_t *val_p)
469{
470	return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr,
471	    val_p));
472}
473#endif /* _ILP32 */
474
475int
476ddi_poke8(dev_info_t *dip, int8_t *addr, int8_t val)
477{
478	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
479}
480
481int
482ddi_poke16(dev_info_t *dip, int16_t *addr, int16_t val)
483{
484	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
485}
486
487int
488ddi_poke32(dev_info_t *dip, int32_t *addr, int32_t val)
489{
490	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
491}
492
493int
494ddi_poke64(dev_info_t *dip, int64_t *addr, int64_t val)
495{
496	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
497}
498
499/*
500 * We need to separate the old interfaces from the new ones and leave them
501 * in here for a while. Previous versions of the OS defined the new interfaces
502 * to the old interfaces. This way we can fix things up so that we can
503 * eventually remove these interfaces.
504 * e.g. A 3rd party module/driver using ddi_poke8 and built against S10
505 * or earlier will actually have a reference to ddi_pokec in the binary.
506 */
507#ifdef _ILP32
508int
509ddi_pokec(dev_info_t *dip, int8_t *addr, int8_t val)
510{
511	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
512}
513
514int
515ddi_pokes(dev_info_t *dip, int16_t *addr, int16_t val)
516{
517	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
518}
519
520int
521ddi_pokel(dev_info_t *dip, int32_t *addr, int32_t val)
522{
523	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
524}
525
526int
527ddi_poked(dev_info_t *dip, int64_t *addr, int64_t val)
528{
529	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
530}
531#endif /* _ILP32 */
532
533/*
534 * ddi_peekpokeio() is used primarily by the mem drivers for moving
535 * data to and from uio structures via peek and poke.  Note that we
536 * use "internal" routines ddi_peek and ddi_poke to make this go
537 * slightly faster, avoiding the call overhead ..
538 */
539int
540ddi_peekpokeio(dev_info_t *devi, struct uio *uio, enum uio_rw rw,
541    caddr_t addr, size_t len, uint_t xfersize)
542{
543	int64_t	ibuffer;
544	int8_t w8;
545	size_t sz;
546	int o;
547
548	if (xfersize > sizeof (long))
549		xfersize = sizeof (long);
550
551	while (len != 0) {
552		if ((len | (uintptr_t)addr) & 1) {
553			sz = sizeof (int8_t);
554			if (rw == UIO_WRITE) {
555				if ((o = uwritec(uio)) == -1)
556					return (DDI_FAILURE);
557				if (ddi_poke8(devi, (int8_t *)addr,
558				    (int8_t)o) != DDI_SUCCESS)
559					return (DDI_FAILURE);
560			} else {
561				if (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, sz,
562				    (int8_t *)addr, &w8) != DDI_SUCCESS)
563					return (DDI_FAILURE);
564				if (ureadc(w8, uio))
565					return (DDI_FAILURE);
566			}
567		} else {
568			switch (xfersize) {
569			case sizeof (int64_t):
570				if (((len | (uintptr_t)addr) &
571				    (sizeof (int64_t) - 1)) == 0) {
572					sz = xfersize;
573					break;
574				}
575				/*FALLTHROUGH*/
576			case sizeof (int32_t):
577				if (((len | (uintptr_t)addr) &
578				    (sizeof (int32_t) - 1)) == 0) {
579					sz = xfersize;
580					break;
581				}
582				/*FALLTHROUGH*/
583			default:
584				/*
585				 * This still assumes that we might have an
586				 * I/O bus out there that permits 16-bit
587				 * transfers (and that it would be upset by
588				 * 32-bit transfers from such locations).
589				 */
590				sz = sizeof (int16_t);
591				break;
592			}
593
594			if (rw == UIO_READ) {
595				if (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, sz,
596				    addr, &ibuffer) != DDI_SUCCESS)
597					return (DDI_FAILURE);
598			}
599
600			if (uiomove(&ibuffer, sz, rw, uio))
601				return (DDI_FAILURE);
602
603			if (rw == UIO_WRITE) {
604				if (i_ddi_peekpoke(devi, DDI_CTLOPS_POKE, sz,
605				    addr, &ibuffer) != DDI_SUCCESS)
606					return (DDI_FAILURE);
607			}
608		}
609		addr += sz;
610		len -= sz;
611	}
612	return (DDI_SUCCESS);
613}
614
615/*
616 * These routines are used by drivers that do layered ioctls
617 * On sparc, they're implemented in assembler to avoid spilling
618 * register windows in the common (copyin) case ..
619 */
620#if !defined(__sparc)
621int
622ddi_copyin(const void *buf, void *kernbuf, size_t size, int flags)
623{
624	if (flags & FKIOCTL)
625		return (kcopy(buf, kernbuf, size) ? -1 : 0);
626	return (copyin(buf, kernbuf, size));
627}
628
629int
630ddi_copyout(const void *buf, void *kernbuf, size_t size, int flags)
631{
632	if (flags & FKIOCTL)
633		return (kcopy(buf, kernbuf, size) ? -1 : 0);
634	return (copyout(buf, kernbuf, size));
635}
636#endif	/* !__sparc */
637
638/*
639 * Conversions in nexus pagesize units.  We don't duplicate the
640 * 'nil dip' semantics of peek/poke because btopr/btop/ptob are DDI/DKI
641 * routines anyway.
642 */
643unsigned long
644ddi_btop(dev_info_t *dip, unsigned long bytes)
645{
646	unsigned long pages;
647
648	(void) ddi_ctlops(dip, dip, DDI_CTLOPS_BTOP, &bytes, &pages);
649	return (pages);
650}
651
652unsigned long
653ddi_btopr(dev_info_t *dip, unsigned long bytes)
654{
655	unsigned long pages;
656
657	(void) ddi_ctlops(dip, dip, DDI_CTLOPS_BTOPR, &bytes, &pages);
658	return (pages);
659}
660
661unsigned long
662ddi_ptob(dev_info_t *dip, unsigned long pages)
663{
664	unsigned long bytes;
665
666	(void) ddi_ctlops(dip, dip, DDI_CTLOPS_PTOB, &pages, &bytes);
667	return (bytes);
668}
669
670unsigned int
671ddi_enter_critical(void)
672{
673	return ((uint_t)spl7());
674}
675
676void
677ddi_exit_critical(unsigned int spl)
678{
679	splx((int)spl);
680}
681
682/*
683 * Nexus ctlops punter
684 */
685
686#if !defined(__sparc)
687/*
688 * Request bus_ctl parent to handle a bus_ctl request
689 *
690 * (The sparc version is in sparc_ddi.s)
691 */
692int
693ddi_ctlops(dev_info_t *d, dev_info_t *r, ddi_ctl_enum_t op, void *a, void *v)
694{
695	int (*fp)();
696
697	if (!d || !r)
698		return (DDI_FAILURE);
699
700	if ((d = (dev_info_t *)DEVI(d)->devi_bus_ctl) == NULL)
701		return (DDI_FAILURE);
702
703	fp = DEVI(d)->devi_ops->devo_bus_ops->bus_ctl;
704	return ((*fp)(d, r, op, a, v));
705}
706
707#endif
708
709/*
710 * DMA/DVMA setup
711 */
712
713#if !defined(__sparc)
714/*
715 * Request bus_dma_ctl parent to fiddle with a dma request.
716 *
717 * (The sparc version is in sparc_subr.s)
718 */
719int
720ddi_dma_mctl(dev_info_t *dip, dev_info_t *rdip,
721    ddi_dma_handle_t handle, enum ddi_dma_ctlops request,
722    off_t *offp, size_t *lenp, caddr_t *objp, uint_t flags)
723{
724	int (*fp)();
725
726	if (dip != ddi_root_node())
727		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_ctl;
728	fp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_ctl;
729	return ((*fp) (dip, rdip, handle, request, offp, lenp, objp, flags));
730}
731#endif
732
733/*
734 * For all DMA control functions, call the DMA control
735 * routine and return status.
736 *
737 * Just plain assume that the parent is to be called.
738 * If a nexus driver or a thread outside the framework
739 * of a nexus driver or a leaf driver calls these functions,
740 * it is up to them to deal with the fact that the parent's
741 * bus_dma_ctl function will be the first one called.
742 */
743
744#define	HD	((ddi_dma_impl_t *)h)->dmai_rdip
745
746/*
747 * This routine is left in place to satisfy link dependencies
748 * for any 3rd party nexus drivers that rely on it.  It is never
749 * called, though.
750 */
751/*ARGSUSED*/
752int
753ddi_dma_map(dev_info_t *dip, dev_info_t *rdip,
754    struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep)
755{
756	return (DDI_FAILURE);
757}
758
759#if !defined(__sparc)
760
761/*
762 * The SPARC versions of these routines are done in assembler to
763 * save register windows, so they're in sparc_subr.s.
764 */
765
766int
767ddi_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr,
768    int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep)
769{
770	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_attr_t *,
771	    int (*)(caddr_t), caddr_t, ddi_dma_handle_t *);
772
773	if (dip != ddi_root_node())
774		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl;
775
776	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_allochdl;
777	return ((*funcp)(dip, rdip, attr, waitfp, arg, handlep));
778}
779
780int
781ddi_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handlep)
782{
783	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t);
784
785	if (dip != ddi_root_node())
786		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl;
787
788	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_freehdl;
789	return ((*funcp)(dip, rdip, handlep));
790}
791
792int
793ddi_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
794    ddi_dma_handle_t handle, struct ddi_dma_req *dmareq,
795    ddi_dma_cookie_t *cp, uint_t *ccountp)
796{
797	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t,
798	    struct ddi_dma_req *, ddi_dma_cookie_t *, uint_t *);
799
800	if (dip != ddi_root_node())
801		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_bindhdl;
802
803	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_bindhdl;
804	return ((*funcp)(dip, rdip, handle, dmareq, cp, ccountp));
805}
806
807int
808ddi_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
809    ddi_dma_handle_t handle)
810{
811	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t);
812
813	if (dip != ddi_root_node())
814		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl;
815
816	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_unbindhdl;
817	return ((*funcp)(dip, rdip, handle));
818}
819
820
821int
822ddi_dma_flush(dev_info_t *dip, dev_info_t *rdip,
823    ddi_dma_handle_t handle, off_t off, size_t len,
824    uint_t cache_flags)
825{
826	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t,
827	    off_t, size_t, uint_t);
828
829	if (dip != ddi_root_node())
830		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush;
831
832	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_flush;
833	return ((*funcp)(dip, rdip, handle, off, len, cache_flags));
834}
835
836int
837ddi_dma_win(dev_info_t *dip, dev_info_t *rdip,
838    ddi_dma_handle_t handle, uint_t win, off_t *offp,
839    size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp)
840{
841	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t,
842	    uint_t, off_t *, size_t *, ddi_dma_cookie_t *, uint_t *);
843
844	if (dip != ddi_root_node())
845		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_win;
846
847	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_win;
848	return ((*funcp)(dip, rdip, handle, win, offp, lenp,
849	    cookiep, ccountp));
850}
851
852int
853ddi_dma_sync(ddi_dma_handle_t h, off_t o, size_t l, uint_t whom)
854{
855	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)h;
856	dev_info_t *dip, *rdip;
857	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t, off_t,
858	    size_t, uint_t);
859
860	/*
861	 * the DMA nexus driver will set DMP_NOSYNC if the
862	 * platform does not require any sync operation. For
863	 * example if the memory is uncached or consistent
864	 * and without any I/O write buffers involved.
865	 */
866	if ((hp->dmai_rflags & DMP_NOSYNC) == DMP_NOSYNC)
867		return (DDI_SUCCESS);
868
869	dip = rdip = hp->dmai_rdip;
870	if (dip != ddi_root_node())
871		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush;
872	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_flush;
873	return ((*funcp)(dip, rdip, h, o, l, whom));
874}
875
876int
877ddi_dma_unbind_handle(ddi_dma_handle_t h)
878{
879	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)h;
880	dev_info_t *dip, *rdip;
881	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t);
882
883	dip = rdip = hp->dmai_rdip;
884	if (dip != ddi_root_node())
885		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl;
886	funcp = DEVI(rdip)->devi_bus_dma_unbindfunc;
887	return ((*funcp)(dip, rdip, h));
888}
889
890#endif	/* !__sparc */
891
892/*
893 * DMA burst sizes, and transfer minimums
894 */
895
896int
897ddi_dma_burstsizes(ddi_dma_handle_t handle)
898{
899	ddi_dma_impl_t *dimp = (ddi_dma_impl_t *)handle;
900
901	if (!dimp)
902		return (0);
903	else
904		return (dimp->dmai_burstsizes);
905}
906
907/*
908 * Given two DMA attribute structures, apply the attributes
909 * of one to the other, following the rules of attributes
910 * and the wishes of the caller.
911 *
912 * The rules of DMA attribute structures are that you cannot
913 * make things *less* restrictive as you apply one set
914 * of attributes to another.
915 *
916 */
917void
918ddi_dma_attr_merge(ddi_dma_attr_t *attr, ddi_dma_attr_t *mod)
919{
920	attr->dma_attr_addr_lo =
921	    MAX(attr->dma_attr_addr_lo, mod->dma_attr_addr_lo);
922	attr->dma_attr_addr_hi =
923	    MIN(attr->dma_attr_addr_hi, mod->dma_attr_addr_hi);
924	attr->dma_attr_count_max =
925	    MIN(attr->dma_attr_count_max, mod->dma_attr_count_max);
926	attr->dma_attr_align =
927	    MAX(attr->dma_attr_align,  mod->dma_attr_align);
928	attr->dma_attr_burstsizes =
929	    (uint_t)(attr->dma_attr_burstsizes & mod->dma_attr_burstsizes);
930	attr->dma_attr_minxfer =
931	    maxbit(attr->dma_attr_minxfer, mod->dma_attr_minxfer);
932	attr->dma_attr_maxxfer =
933	    MIN(attr->dma_attr_maxxfer, mod->dma_attr_maxxfer);
934	attr->dma_attr_seg = MIN(attr->dma_attr_seg, mod->dma_attr_seg);
935	attr->dma_attr_sgllen = MIN((uint_t)attr->dma_attr_sgllen,
936	    (uint_t)mod->dma_attr_sgllen);
937	attr->dma_attr_granular =
938	    MAX(attr->dma_attr_granular, mod->dma_attr_granular);
939}
940
941/*
942 * mmap/segmap interface:
943 */
944
945/*
946 * ddi_segmap:		setup the default segment driver. Calls the drivers
947 *			XXmmap routine to validate the range to be mapped.
948 *			Return ENXIO of the range is not valid.  Create
949 *			a seg_dev segment that contains all of the
950 *			necessary information and will reference the
951 *			default segment driver routines. It returns zero
952 *			on success or non-zero on failure.
953 */
954int
955ddi_segmap(dev_t dev, off_t offset, struct as *asp, caddr_t *addrp, off_t len,
956    uint_t prot, uint_t maxprot, uint_t flags, cred_t *credp)
957{
958	extern int spec_segmap(dev_t, off_t, struct as *, caddr_t *,
959	    off_t, uint_t, uint_t, uint_t, struct cred *);
960
961	return (spec_segmap(dev, offset, asp, addrp, len,
962	    prot, maxprot, flags, credp));
963}
964
965/*
966 * ddi_map_fault:	Resolve mappings at fault time.  Used by segment
967 *			drivers. Allows each successive parent to resolve
968 *			address translations and add its mappings to the
969 *			mapping list supplied in the page structure. It
970 *			returns zero on success	or non-zero on failure.
971 */
972
973int
974ddi_map_fault(dev_info_t *dip, struct hat *hat, struct seg *seg,
975    caddr_t addr, struct devpage *dp, pfn_t pfn, uint_t prot, uint_t lock)
976{
977	return (i_ddi_map_fault(dip, dip, hat, seg, addr, dp, pfn, prot, lock));
978}
979
980/*
981 * ddi_device_mapping_check:	Called from ddi_segmap_setup.
982 *	Invokes platform specific DDI to determine whether attributes specified
983 *	in attr(9s) are	valid for the region of memory that will be made
984 *	available for direct access to user process via the mmap(2) system call.
985 */
986int
987ddi_device_mapping_check(dev_t dev, ddi_device_acc_attr_t *accattrp,
988    uint_t rnumber, uint_t *hat_flags)
989{
990	ddi_acc_handle_t handle;
991	ddi_map_req_t mr;
992	ddi_acc_hdl_t *hp;
993	int result;
994	dev_info_t *dip;
995
996	/*
997	 * we use e_ddi_hold_devi_by_dev to search for the devi.  We
998	 * release it immediately since it should already be held by
999	 * a devfs vnode.
1000	 */
1001	if ((dip =
1002	    e_ddi_hold_devi_by_dev(dev, E_DDI_HOLD_DEVI_NOATTACH)) == NULL)
1003		return (-1);
1004	ddi_release_devi(dip);		/* for e_ddi_hold_devi_by_dev() */
1005
1006	/*
1007	 * Allocate and initialize the common elements of data
1008	 * access handle.
1009	 */
1010	handle = impl_acc_hdl_alloc(KM_SLEEP, NULL);
1011	if (handle == NULL)
1012		return (-1);
1013
1014	hp = impl_acc_hdl_get(handle);
1015	hp->ah_vers = VERS_ACCHDL;
1016	hp->ah_dip = dip;
1017	hp->ah_rnumber = rnumber;
1018	hp->ah_offset = 0;
1019	hp->ah_len = 0;
1020	hp->ah_acc = *accattrp;
1021
1022	/*
1023	 * Set up the mapping request and call to parent.
1024	 */
1025	mr.map_op = DDI_MO_MAP_HANDLE;
1026	mr.map_type = DDI_MT_RNUMBER;
1027	mr.map_obj.rnumber = rnumber;
1028	mr.map_prot = PROT_READ | PROT_WRITE;
1029	mr.map_flags = DDI_MF_KERNEL_MAPPING;
1030	mr.map_handlep = hp;
1031	mr.map_vers = DDI_MAP_VERSION;
1032	result = ddi_map(dip, &mr, 0, 0, NULL);
1033
1034	/*
1035	 * Region must be mappable, pick up flags from the framework.
1036	 */
1037	*hat_flags = hp->ah_hat_flags;
1038
1039	impl_acc_hdl_free(handle);
1040
1041	/*
1042	 * check for end result.
1043	 */
1044	if (result != DDI_SUCCESS)
1045		return (-1);
1046	return (0);
1047}
1048
1049
1050/*
1051 * Property functions:	 See also, ddipropdefs.h.
1052 *
1053 * These functions are the framework for the property functions,
1054 * i.e. they support software defined properties.  All implementation
1055 * specific property handling (i.e.: self-identifying devices and
1056 * PROM defined properties are handled in the implementation specific
1057 * functions (defined in ddi_implfuncs.h).
1058 */
1059
1060/*
1061 * nopropop:	Shouldn't be called, right?
1062 */
1063int
1064nopropop(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
1065    char *name, caddr_t valuep, int *lengthp)
1066{
1067	_NOTE(ARGUNUSED(dev, dip, prop_op, mod_flags, name, valuep, lengthp))
1068	return (DDI_PROP_NOT_FOUND);
1069}
1070
1071#ifdef	DDI_PROP_DEBUG
1072int ddi_prop_debug_flag = 0;
1073
1074int
1075ddi_prop_debug(int enable)
1076{
1077	int prev = ddi_prop_debug_flag;
1078
1079	if ((enable != 0) || (prev != 0))
1080		printf("ddi_prop_debug: debugging %s\n",
1081		    enable ? "enabled" : "disabled");
1082	ddi_prop_debug_flag = enable;
1083	return (prev);
1084}
1085
1086#endif	/* DDI_PROP_DEBUG */
1087
1088/*
1089 * Search a property list for a match, if found return pointer
1090 * to matching prop struct, else return NULL.
1091 */
1092
1093ddi_prop_t *
1094i_ddi_prop_search(dev_t dev, char *name, uint_t flags, ddi_prop_t **list_head)
1095{
1096	ddi_prop_t	*propp;
1097
1098	/*
1099	 * find the property in child's devinfo:
1100	 * Search order defined by this search function is first matching
1101	 * property with input dev == DDI_DEV_T_ANY matching any dev or
1102	 * dev == propp->prop_dev, name == propp->name, and the correct
1103	 * data type as specified in the flags.  If a DDI_DEV_T_NONE dev
1104	 * value made it this far then it implies a DDI_DEV_T_ANY search.
1105	 */
1106	if (dev == DDI_DEV_T_NONE)
1107		dev = DDI_DEV_T_ANY;
1108
1109	for (propp = *list_head; propp != NULL; propp = propp->prop_next)  {
1110
1111		if (!DDI_STRSAME(propp->prop_name, name))
1112			continue;
1113
1114		if ((dev != DDI_DEV_T_ANY) && (propp->prop_dev != dev))
1115			continue;
1116
1117		if (((propp->prop_flags & flags) & DDI_PROP_TYPE_MASK) == 0)
1118			continue;
1119
1120		return (propp);
1121	}
1122
1123	return ((ddi_prop_t *)0);
1124}
1125
1126/*
1127 * Search for property within devnames structures
1128 */
1129ddi_prop_t *
1130i_ddi_search_global_prop(dev_t dev, char *name, uint_t flags)
1131{
1132	major_t		major;
1133	struct devnames	*dnp;
1134	ddi_prop_t	*propp;
1135
1136	/*
1137	 * Valid dev_t value is needed to index into the
1138	 * correct devnames entry, therefore a dev_t
1139	 * value of DDI_DEV_T_ANY is not appropriate.
1140	 */
1141	ASSERT(dev != DDI_DEV_T_ANY);
1142	if (dev == DDI_DEV_T_ANY) {
1143		return ((ddi_prop_t *)0);
1144	}
1145
1146	major = getmajor(dev);
1147	dnp = &(devnamesp[major]);
1148
1149	if (dnp->dn_global_prop_ptr == NULL)
1150		return ((ddi_prop_t *)0);
1151
1152	LOCK_DEV_OPS(&dnp->dn_lock);
1153
1154	for (propp = dnp->dn_global_prop_ptr->prop_list;
1155	    propp != NULL;
1156	    propp = (ddi_prop_t *)propp->prop_next) {
1157
1158		if (!DDI_STRSAME(propp->prop_name, name))
1159			continue;
1160
1161		if ((!(flags & DDI_PROP_ROOTNEX_GLOBAL)) &&
1162		    (!(flags & LDI_DEV_T_ANY)) && (propp->prop_dev != dev))
1163			continue;
1164
1165		if (((propp->prop_flags & flags) & DDI_PROP_TYPE_MASK) == 0)
1166			continue;
1167
1168		/* Property found, return it */
1169		UNLOCK_DEV_OPS(&dnp->dn_lock);
1170		return (propp);
1171	}
1172
1173	UNLOCK_DEV_OPS(&dnp->dn_lock);
1174	return ((ddi_prop_t *)0);
1175}
1176
1177static char prop_no_mem_msg[] = "can't allocate memory for ddi property <%s>";
1178
1179/*
1180 * ddi_prop_search_global:
1181 *	Search the global property list within devnames
1182 *	for the named property.  Return the encoded value.
1183 */
1184static int
1185i_ddi_prop_search_global(dev_t dev, uint_t flags, char *name,
1186    void *valuep, uint_t *lengthp)
1187{
1188	ddi_prop_t	*propp;
1189	caddr_t		buffer;
1190
1191	propp =  i_ddi_search_global_prop(dev, name, flags);
1192
1193	/* Property NOT found, bail */
1194	if (propp == (ddi_prop_t *)0)
1195		return (DDI_PROP_NOT_FOUND);
1196
1197	if (propp->prop_flags & DDI_PROP_UNDEF_IT)
1198		return (DDI_PROP_UNDEFINED);
1199
1200	if ((buffer = kmem_alloc(propp->prop_len,
1201	    (flags & DDI_PROP_CANSLEEP) ? KM_SLEEP : KM_NOSLEEP)) == NULL) {
1202		cmn_err(CE_CONT, prop_no_mem_msg, name);
1203		return (DDI_PROP_NO_MEMORY);
1204	}
1205
1206	/*
1207	 * Return the encoded data
1208	 */
1209	*(caddr_t *)valuep = buffer;
1210	*lengthp = propp->prop_len;
1211	bcopy(propp->prop_val, buffer, propp->prop_len);
1212
1213	return (DDI_PROP_SUCCESS);
1214}
1215
1216/*
1217 * ddi_prop_search_common:	Lookup and return the encoded value
1218 */
1219int
1220ddi_prop_search_common(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1221    uint_t flags, char *name, void *valuep, uint_t *lengthp)
1222{
1223	ddi_prop_t	*propp;
1224	int		i;
1225	caddr_t		buffer;
1226	caddr_t		prealloc = NULL;
1227	int		plength = 0;
1228	dev_info_t	*pdip;
1229	int		(*bop)();
1230
1231	/*CONSTANTCONDITION*/
1232	while (1)  {
1233
1234		mutex_enter(&(DEVI(dip)->devi_lock));
1235
1236
1237		/*
1238		 * find the property in child's devinfo:
1239		 * Search order is:
1240		 *	1. driver defined properties
1241		 *	2. system defined properties
1242		 *	3. driver global properties
1243		 *	4. boot defined properties
1244		 */
1245
1246		propp = i_ddi_prop_search(dev, name, flags,
1247		    &(DEVI(dip)->devi_drv_prop_ptr));
1248		if (propp == NULL)  {
1249			propp = i_ddi_prop_search(dev, name, flags,
1250			    &(DEVI(dip)->devi_sys_prop_ptr));
1251		}
1252		if ((propp == NULL) && DEVI(dip)->devi_global_prop_list) {
1253			propp = i_ddi_prop_search(dev, name, flags,
1254			    &DEVI(dip)->devi_global_prop_list->prop_list);
1255		}
1256
1257		if (propp == NULL)  {
1258			propp = i_ddi_prop_search(dev, name, flags,
1259			    &(DEVI(dip)->devi_hw_prop_ptr));
1260		}
1261
1262		/*
1263		 * Software property found?
1264		 */
1265		if (propp != (ddi_prop_t *)0)	{
1266
1267			/*
1268			 * If explicit undefine, return now.
1269			 */
1270			if (propp->prop_flags & DDI_PROP_UNDEF_IT) {
1271				mutex_exit(&(DEVI(dip)->devi_lock));
1272				if (prealloc)
1273					kmem_free(prealloc, plength);
1274				return (DDI_PROP_UNDEFINED);
1275			}
1276
1277			/*
1278			 * If we only want to know if it exists, return now
1279			 */
1280			if (prop_op == PROP_EXISTS) {
1281				mutex_exit(&(DEVI(dip)->devi_lock));
1282				ASSERT(prealloc == NULL);
1283				return (DDI_PROP_SUCCESS);
1284			}
1285
1286			/*
1287			 * If length only request or prop length == 0,
1288			 * service request and return now.
1289			 */
1290			if ((prop_op == PROP_LEN) ||(propp->prop_len == 0)) {
1291				*lengthp = propp->prop_len;
1292
1293				/*
1294				 * if prop_op is PROP_LEN_AND_VAL_ALLOC
1295				 * that means prop_len is 0, so set valuep
1296				 * also to NULL
1297				 */
1298				if (prop_op == PROP_LEN_AND_VAL_ALLOC)
1299					*(caddr_t *)valuep = NULL;
1300
1301				mutex_exit(&(DEVI(dip)->devi_lock));
1302				if (prealloc)
1303					kmem_free(prealloc, plength);
1304				return (DDI_PROP_SUCCESS);
1305			}
1306
1307			/*
1308			 * If LEN_AND_VAL_ALLOC and the request can sleep,
1309			 * drop the mutex, allocate the buffer, and go
1310			 * through the loop again.  If we already allocated
1311			 * the buffer, and the size of the property changed,
1312			 * keep trying...
1313			 */
1314			if ((prop_op == PROP_LEN_AND_VAL_ALLOC) &&
1315			    (flags & DDI_PROP_CANSLEEP))  {
1316				if (prealloc && (propp->prop_len != plength)) {
1317					kmem_free(prealloc, plength);
1318					prealloc = NULL;
1319				}
1320				if (prealloc == NULL)  {
1321					plength = propp->prop_len;
1322					mutex_exit(&(DEVI(dip)->devi_lock));
1323					prealloc = kmem_alloc(plength,
1324					    KM_SLEEP);
1325					continue;
1326				}
1327			}
1328
1329			/*
1330			 * Allocate buffer, if required.  Either way,
1331			 * set `buffer' variable.
1332			 */
1333			i = *lengthp;			/* Get callers length */
1334			*lengthp = propp->prop_len;	/* Set callers length */
1335
1336			switch (prop_op) {
1337
1338			case PROP_LEN_AND_VAL_ALLOC:
1339
1340				if (prealloc == NULL) {
1341					buffer = kmem_alloc(propp->prop_len,
1342					    KM_NOSLEEP);
1343				} else {
1344					buffer = prealloc;
1345				}
1346
1347				if (buffer == NULL)  {
1348					mutex_exit(&(DEVI(dip)->devi_lock));
1349					cmn_err(CE_CONT, prop_no_mem_msg, name);
1350					return (DDI_PROP_NO_MEMORY);
1351				}
1352				/* Set callers buf ptr */
1353				*(caddr_t *)valuep = buffer;
1354				break;
1355
1356			case PROP_LEN_AND_VAL_BUF:
1357
1358				if (propp->prop_len > (i)) {
1359					mutex_exit(&(DEVI(dip)->devi_lock));
1360					return (DDI_PROP_BUF_TOO_SMALL);
1361				}
1362
1363				buffer = valuep;  /* Get callers buf ptr */
1364				break;
1365
1366			default:
1367				break;
1368			}
1369
1370			/*
1371			 * Do the copy.
1372			 */
1373			bcopy(propp->prop_val, buffer, propp->prop_len);
1374			mutex_exit(&(DEVI(dip)->devi_lock));
1375			return (DDI_PROP_SUCCESS);
1376		}
1377
1378		mutex_exit(&(DEVI(dip)->devi_lock));
1379		if (prealloc)
1380			kmem_free(prealloc, plength);
1381		prealloc = NULL;
1382
1383		/*
1384		 * Prop not found, call parent bus_ops to deal with possible
1385		 * h/w layer (possible PROM defined props, etc.) and to
1386		 * possibly ascend the hierarchy, if allowed by flags.
1387		 */
1388		pdip = (dev_info_t *)DEVI(dip)->devi_parent;
1389
1390		/*
1391		 * One last call for the root driver PROM props?
1392		 */
1393		if (dip == ddi_root_node())  {
1394			return (ddi_bus_prop_op(dev, dip, dip, prop_op,
1395			    flags, name, valuep, (int *)lengthp));
1396		}
1397
1398		/*
1399		 * We may have been called to check for properties
1400		 * within a single devinfo node that has no parent -
1401		 * see make_prop()
1402		 */
1403		if (pdip == NULL) {
1404			ASSERT((flags &
1405			    (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM)) ==
1406			    (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM));
1407			return (DDI_PROP_NOT_FOUND);
1408		}
1409
1410		/*
1411		 * Instead of recursing, we do iterative calls up the tree.
1412		 * As a bit of optimization, skip the bus_op level if the
1413		 * node is a s/w node and if the parent's bus_prop_op function
1414		 * is `ddi_bus_prop_op', because we know that in this case,
1415		 * this function does nothing.
1416		 *
1417		 * 4225415: If the parent isn't attached, or the child
1418		 * hasn't been named by the parent yet, use the default
1419		 * ddi_bus_prop_op as a proxy for the parent.  This
1420		 * allows property lookups in any child/parent state to
1421		 * include 'prom' and inherited properties, even when
1422		 * there are no drivers attached to the child or parent.
1423		 */
1424
1425		bop = ddi_bus_prop_op;
1426		if (i_ddi_devi_attached(pdip) &&
1427		    (i_ddi_node_state(dip) >= DS_INITIALIZED))
1428			bop = DEVI(pdip)->devi_ops->devo_bus_ops->bus_prop_op;
1429
1430		i = DDI_PROP_NOT_FOUND;
1431
1432		if ((bop != ddi_bus_prop_op) || ndi_dev_is_prom_node(dip)) {
1433			i = (*bop)(dev, pdip, dip, prop_op,
1434			    flags | DDI_PROP_DONTPASS,
1435			    name, valuep, lengthp);
1436		}
1437
1438		if ((flags & DDI_PROP_DONTPASS) ||
1439		    (i != DDI_PROP_NOT_FOUND))
1440			return (i);
1441
1442		dip = pdip;
1443	}
1444	/*NOTREACHED*/
1445}
1446
1447
1448/*
1449 * ddi_prop_op: The basic property operator for drivers.
1450 *
1451 * In ddi_prop_op, the type of valuep is interpreted based on prop_op:
1452 *
1453 *	prop_op			valuep
1454 *	------			------
1455 *
1456 *	PROP_LEN		<unused>
1457 *
1458 *	PROP_LEN_AND_VAL_BUF	Pointer to callers buffer
1459 *
1460 *	PROP_LEN_AND_VAL_ALLOC	Address of callers pointer (will be set to
1461 *				address of allocated buffer, if successful)
1462 */
1463int
1464ddi_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
1465    char *name, caddr_t valuep, int *lengthp)
1466{
1467	int	i;
1468
1469	ASSERT((mod_flags & DDI_PROP_TYPE_MASK) == 0);
1470
1471	/*
1472	 * If this was originally an LDI prop lookup then we bail here.
1473	 * The reason is that the LDI property lookup interfaces first call
1474	 * a drivers prop_op() entry point to allow it to override
1475	 * properties.  But if we've made it here, then the driver hasn't
1476	 * overriden any properties.  We don't want to continue with the
1477	 * property search here because we don't have any type inforamtion.
1478	 * When we return failure, the LDI interfaces will then proceed to
1479	 * call the typed property interfaces to look up the property.
1480	 */
1481	if (mod_flags & DDI_PROP_DYNAMIC)
1482		return (DDI_PROP_NOT_FOUND);
1483
1484	/*
1485	 * check for pre-typed property consumer asking for typed property:
1486	 * see e_ddi_getprop_int64.
1487	 */
1488	if (mod_flags & DDI_PROP_CONSUMER_TYPED)
1489		mod_flags |= DDI_PROP_TYPE_INT64;
1490	mod_flags |= DDI_PROP_TYPE_ANY;
1491
1492	i = ddi_prop_search_common(dev, dip, prop_op,
1493	    mod_flags, name, valuep, (uint_t *)lengthp);
1494	if (i == DDI_PROP_FOUND_1275)
1495		return (DDI_PROP_SUCCESS);
1496	return (i);
1497}
1498
1499/*
1500 * ddi_prop_op_nblocks_blksize: The basic property operator for drivers that
1501 * maintain size in number of blksize blocks.  Provides a dynamic property
1502 * implementation for size oriented properties based on nblocks64 and blksize
1503 * values passed in by the driver.  Fallback to ddi_prop_op if the nblocks64
1504 * is too large.  This interface should not be used with a nblocks64 that
1505 * represents the driver's idea of how to represent unknown, if nblocks is
1506 * unknown use ddi_prop_op.
1507 */
1508int
1509ddi_prop_op_nblocks_blksize(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1510    int mod_flags, char *name, caddr_t valuep, int *lengthp,
1511    uint64_t nblocks64, uint_t blksize)
1512{
1513	uint64_t size64;
1514	int	blkshift;
1515
1516	/* convert block size to shift value */
1517	ASSERT(BIT_ONLYONESET(blksize));
1518	blkshift = highbit(blksize) - 1;
1519
1520	/*
1521	 * There is no point in supporting nblocks64 values that don't have
1522	 * an accurate uint64_t byte count representation.
1523	 */
1524	if (nblocks64 >= (UINT64_MAX >> blkshift))
1525		return (ddi_prop_op(dev, dip, prop_op, mod_flags,
1526		    name, valuep, lengthp));
1527
1528	size64 = nblocks64 << blkshift;
1529	return (ddi_prop_op_size_blksize(dev, dip, prop_op, mod_flags,
1530	    name, valuep, lengthp, size64, blksize));
1531}
1532
1533/*
1534 * ddi_prop_op_nblocks: ddi_prop_op_nblocks_blksize with DEV_BSIZE blksize.
1535 */
1536int
1537ddi_prop_op_nblocks(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1538    int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t nblocks64)
1539{
1540	return (ddi_prop_op_nblocks_blksize(dev, dip, prop_op,
1541	    mod_flags, name, valuep, lengthp, nblocks64, DEV_BSIZE));
1542}
1543
1544/*
1545 * ddi_prop_op_size_blksize: The basic property operator for block drivers that
1546 * maintain size in bytes. Provides a of dynamic property implementation for
1547 * size oriented properties based on size64 value and blksize passed in by the
1548 * driver.  Fallback to ddi_prop_op if the size64 is too large. This interface
1549 * should not be used with a size64 that represents the driver's idea of how
1550 * to represent unknown, if size is unknown use ddi_prop_op.
1551 *
1552 * NOTE: the legacy "nblocks"/"size" properties are treated as 32-bit unsigned
1553 * integers. While the most likely interface to request them ([bc]devi_size)
1554 * is declared int (signed) there is no enforcement of this, which means we
1555 * can't enforce limitations here without risking regression.
1556 */
1557int
1558ddi_prop_op_size_blksize(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1559    int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t size64,
1560    uint_t blksize)
1561{
1562	uint64_t nblocks64;
1563	int	callers_length;
1564	caddr_t	buffer;
1565	int	blkshift;
1566
1567	/*
1568	 * This is a kludge to support capture of size(9P) pure dynamic
1569	 * properties in snapshots for non-cmlb code (without exposing
1570	 * i_ddi_prop_dyn changes). When everyone uses cmlb, this code
1571	 * should be removed.
1572	 */
1573	if (i_ddi_prop_dyn_driver_get(dip) == NULL) {
1574		static i_ddi_prop_dyn_t prop_dyn_size[] = {
1575		    {"Size",		DDI_PROP_TYPE_INT64,	S_IFCHR},
1576		    {"Nblocks",		DDI_PROP_TYPE_INT64,	S_IFBLK},
1577		    {NULL}
1578		};
1579		i_ddi_prop_dyn_driver_set(dip, prop_dyn_size);
1580	}
1581
1582	/* convert block size to shift value */
1583	ASSERT(BIT_ONLYONESET(blksize));
1584	blkshift = highbit(blksize) - 1;
1585
1586	/* compute DEV_BSIZE nblocks value */
1587	nblocks64 = size64 >> blkshift;
1588
1589	/* get callers length, establish length of our dynamic properties */
1590	callers_length = *lengthp;
1591
1592	if (strcmp(name, "Nblocks") == 0)
1593		*lengthp = sizeof (uint64_t);
1594	else if (strcmp(name, "Size") == 0)
1595		*lengthp = sizeof (uint64_t);
1596	else if ((strcmp(name, "nblocks") == 0) && (nblocks64 < UINT_MAX))
1597		*lengthp = sizeof (uint32_t);
1598	else if ((strcmp(name, "size") == 0) && (size64 < UINT_MAX))
1599		*lengthp = sizeof (uint32_t);
1600	else if ((strcmp(name, "blksize") == 0) && (blksize < UINT_MAX))
1601		*lengthp = sizeof (uint32_t);
1602	else {
1603		/* fallback to ddi_prop_op */
1604		return (ddi_prop_op(dev, dip, prop_op, mod_flags,
1605		    name, valuep, lengthp));
1606	}
1607
1608	/* service request for the length of the property */
1609	if (prop_op == PROP_LEN)
1610		return (DDI_PROP_SUCCESS);
1611
1612	switch (prop_op) {
1613	case PROP_LEN_AND_VAL_ALLOC:
1614		if ((buffer = kmem_alloc(*lengthp,
1615		    (mod_flags & DDI_PROP_CANSLEEP) ?
1616		    KM_SLEEP : KM_NOSLEEP)) == NULL)
1617			return (DDI_PROP_NO_MEMORY);
1618
1619		*(caddr_t *)valuep = buffer;	/* set callers buf ptr */
1620		break;
1621
1622	case PROP_LEN_AND_VAL_BUF:
1623		/* the length of the property and the request must match */
1624		if (callers_length != *lengthp)
1625			return (DDI_PROP_INVAL_ARG);
1626
1627		buffer = valuep;		/* get callers buf ptr */
1628		break;
1629
1630	default:
1631		return (DDI_PROP_INVAL_ARG);
1632	}
1633
1634	/* transfer the value into the buffer */
1635	if (strcmp(name, "Nblocks") == 0)
1636		*((uint64_t *)buffer) = nblocks64;
1637	else if (strcmp(name, "Size") == 0)
1638		*((uint64_t *)buffer) = size64;
1639	else if (strcmp(name, "nblocks") == 0)
1640		*((uint32_t *)buffer) = (uint32_t)nblocks64;
1641	else if (strcmp(name, "size") == 0)
1642		*((uint32_t *)buffer) = (uint32_t)size64;
1643	else if (strcmp(name, "blksize") == 0)
1644		*((uint32_t *)buffer) = (uint32_t)blksize;
1645	return (DDI_PROP_SUCCESS);
1646}
1647
1648/*
1649 * ddi_prop_op_size: ddi_prop_op_size_blksize with DEV_BSIZE block size.
1650 */
1651int
1652ddi_prop_op_size(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1653    int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t size64)
1654{
1655	return (ddi_prop_op_size_blksize(dev, dip, prop_op,
1656	    mod_flags, name, valuep, lengthp, size64, DEV_BSIZE));
1657}
1658
1659/*
1660 * Variable length props...
1661 */
1662
1663/*
1664 * ddi_getlongprop:	Get variable length property len+val into a buffer
1665 *		allocated by property provider via kmem_alloc. Requester
1666 *		is responsible for freeing returned property via kmem_free.
1667 *
1668 *	Arguments:
1669 *
1670 *	dev_t:	Input:	dev_t of property.
1671 *	dip:	Input:	dev_info_t pointer of child.
1672 *	flags:	Input:	Possible flag modifiers are:
1673 *		DDI_PROP_DONTPASS:	Don't pass to parent if prop not found.
1674 *		DDI_PROP_CANSLEEP:	Memory allocation may sleep.
1675 *	name:	Input:	name of property.
1676 *	valuep:	Output:	Addr of callers buffer pointer.
1677 *	lengthp:Output:	*lengthp will contain prop length on exit.
1678 *
1679 *	Possible Returns:
1680 *
1681 *		DDI_PROP_SUCCESS:	Prop found and returned.
1682 *		DDI_PROP_NOT_FOUND:	Prop not found
1683 *		DDI_PROP_UNDEFINED:	Prop explicitly undefined.
1684 *		DDI_PROP_NO_MEMORY:	Prop found, but unable to alloc mem.
1685 */
1686
1687int
1688ddi_getlongprop(dev_t dev, dev_info_t *dip, int flags,
1689    char *name, caddr_t valuep, int *lengthp)
1690{
1691	return (ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_ALLOC,
1692	    flags, name, valuep, lengthp));
1693}
1694
1695/*
1696 *
1697 * ddi_getlongprop_buf:		Get long prop into pre-allocated callers
1698 *				buffer. (no memory allocation by provider).
1699 *
1700 *	dev_t:	Input:	dev_t of property.
1701 *	dip:	Input:	dev_info_t pointer of child.
1702 *	flags:	Input:	DDI_PROP_DONTPASS or NULL
1703 *	name:	Input:	name of property
1704 *	valuep:	Input:	ptr to callers buffer.
1705 *	lengthp:I/O:	ptr to length of callers buffer on entry,
1706 *			actual length of property on exit.
1707 *
1708 *	Possible returns:
1709 *
1710 *		DDI_PROP_SUCCESS	Prop found and returned
1711 *		DDI_PROP_NOT_FOUND	Prop not found
1712 *		DDI_PROP_UNDEFINED	Prop explicitly undefined.
1713 *		DDI_PROP_BUF_TOO_SMALL	Prop found, callers buf too small,
1714 *					no value returned, but actual prop
1715 *					length returned in *lengthp
1716 *
1717 */
1718
1719int
1720ddi_getlongprop_buf(dev_t dev, dev_info_t *dip, int flags,
1721    char *name, caddr_t valuep, int *lengthp)
1722{
1723	return (ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_BUF,
1724	    flags, name, valuep, lengthp));
1725}
1726
1727/*
1728 * Integer/boolean sized props.
1729 *
1730 * Call is value only... returns found boolean or int sized prop value or
1731 * defvalue if prop not found or is wrong length or is explicitly undefined.
1732 * Only flag is DDI_PROP_DONTPASS...
1733 *
1734 * By convention, this interface returns boolean (0) sized properties
1735 * as value (int)1.
1736 *
1737 * This never returns an error, if property not found or specifically
1738 * undefined, the input `defvalue' is returned.
1739 */
1740
1741int
1742ddi_getprop(dev_t dev, dev_info_t *dip, int flags, char *name, int defvalue)
1743{
1744	int	propvalue = defvalue;
1745	int	proplength = sizeof (int);
1746	int	error;
1747
1748	error = ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_BUF,
1749	    flags, name, (caddr_t)&propvalue, &proplength);
1750
1751	if ((error == DDI_PROP_SUCCESS) && (proplength == 0))
1752		propvalue = 1;
1753
1754	return (propvalue);
1755}
1756
1757/*
1758 * Get prop length interface: flags are 0 or DDI_PROP_DONTPASS
1759 * if returns DDI_PROP_SUCCESS, length returned in *lengthp.
1760 */
1761
1762int
1763ddi_getproplen(dev_t dev, dev_info_t *dip, int flags, char *name, int *lengthp)
1764{
1765	return (ddi_prop_op(dev, dip, PROP_LEN, flags, name, NULL, lengthp));
1766}
1767
1768/*
1769 * Allocate a struct prop_driver_data, along with 'size' bytes
1770 * for decoded property data.  This structure is freed by
1771 * calling ddi_prop_free(9F).
1772 */
1773static void *
1774ddi_prop_decode_alloc(size_t size, void (*prop_free)(struct prop_driver_data *))
1775{
1776	struct prop_driver_data *pdd;
1777
1778	/*
1779	 * Allocate a structure with enough memory to store the decoded data.
1780	 */
1781	pdd = kmem_zalloc(sizeof (struct prop_driver_data) + size, KM_SLEEP);
1782	pdd->pdd_size = (sizeof (struct prop_driver_data) + size);
1783	pdd->pdd_prop_free = prop_free;
1784
1785	/*
1786	 * Return a pointer to the location to put the decoded data.
1787	 */
1788	return ((void *)((caddr_t)pdd + sizeof (struct prop_driver_data)));
1789}
1790
1791/*
1792 * Allocated the memory needed to store the encoded data in the property
1793 * handle.
1794 */
1795static int
1796ddi_prop_encode_alloc(prop_handle_t *ph, size_t size)
1797{
1798	/*
1799	 * If size is zero, then set data to NULL and size to 0.  This
1800	 * is a boolean property.
1801	 */
1802	if (size == 0) {
1803		ph->ph_size = 0;
1804		ph->ph_data = NULL;
1805		ph->ph_cur_pos = NULL;
1806		ph->ph_save_pos = NULL;
1807	} else {
1808		if (ph->ph_flags == DDI_PROP_DONTSLEEP) {
1809			ph->ph_data = kmem_zalloc(size, KM_NOSLEEP);
1810			if (ph->ph_data == NULL)
1811				return (DDI_PROP_NO_MEMORY);
1812		} else
1813			ph->ph_data = kmem_zalloc(size, KM_SLEEP);
1814		ph->ph_size = size;
1815		ph->ph_cur_pos = ph->ph_data;
1816		ph->ph_save_pos = ph->ph_data;
1817	}
1818	return (DDI_PROP_SUCCESS);
1819}
1820
1821/*
1822 * Free the space allocated by the lookup routines.  Each lookup routine
1823 * returns a pointer to the decoded data to the driver.  The driver then
1824 * passes this pointer back to us.  This data actually lives in a struct
1825 * prop_driver_data.  We use negative indexing to find the beginning of
1826 * the structure and then free the entire structure using the size and
1827 * the free routine stored in the structure.
1828 */
1829void
1830ddi_prop_free(void *datap)
1831{
1832	struct prop_driver_data *pdd;
1833
1834	/*
1835	 * Get the structure
1836	 */
1837	pdd = (struct prop_driver_data *)
1838	    ((caddr_t)datap - sizeof (struct prop_driver_data));
1839	/*
1840	 * Call the free routine to free it
1841	 */
1842	(*pdd->pdd_prop_free)(pdd);
1843}
1844
1845/*
1846 * Free the data associated with an array of ints,
1847 * allocated with ddi_prop_decode_alloc().
1848 */
1849static void
1850ddi_prop_free_ints(struct prop_driver_data *pdd)
1851{
1852	kmem_free(pdd, pdd->pdd_size);
1853}
1854
1855/*
1856 * Free a single string property or a single string contained within
1857 * the argv style return value of an array of strings.
1858 */
1859static void
1860ddi_prop_free_string(struct prop_driver_data *pdd)
1861{
1862	kmem_free(pdd, pdd->pdd_size);
1863
1864}
1865
1866/*
1867 * Free an array of strings.
1868 */
1869static void
1870ddi_prop_free_strings(struct prop_driver_data *pdd)
1871{
1872	kmem_free(pdd, pdd->pdd_size);
1873}
1874
1875/*
1876 * Free the data associated with an array of bytes.
1877 */
1878static void
1879ddi_prop_free_bytes(struct prop_driver_data *pdd)
1880{
1881	kmem_free(pdd, pdd->pdd_size);
1882}
1883
1884/*
1885 * Reset the current location pointer in the property handle to the
1886 * beginning of the data.
1887 */
1888void
1889ddi_prop_reset_pos(prop_handle_t *ph)
1890{
1891	ph->ph_cur_pos = ph->ph_data;
1892	ph->ph_save_pos = ph->ph_data;
1893}
1894
1895/*
1896 * Restore the current location pointer in the property handle to the
1897 * saved position.
1898 */
1899void
1900ddi_prop_save_pos(prop_handle_t *ph)
1901{
1902	ph->ph_save_pos = ph->ph_cur_pos;
1903}
1904
1905/*
1906 * Save the location that the current location pointer is pointing to..
1907 */
1908void
1909ddi_prop_restore_pos(prop_handle_t *ph)
1910{
1911	ph->ph_cur_pos = ph->ph_save_pos;
1912}
1913
1914/*
1915 * Property encode/decode functions
1916 */
1917
1918/*
1919 * Decode a single integer property
1920 */
1921static int
1922ddi_prop_fm_decode_int(prop_handle_t *ph, void *data, uint_t *nelements)
1923{
1924	int	i;
1925	int	tmp;
1926
1927	/*
1928	 * If there is nothing to decode return an error
1929	 */
1930	if (ph->ph_size == 0)
1931		return (DDI_PROP_END_OF_DATA);
1932
1933	/*
1934	 * Decode the property as a single integer and return it
1935	 * in data if we were able to decode it.
1936	 */
1937	i = DDI_PROP_INT(ph, DDI_PROP_CMD_DECODE, &tmp);
1938	if (i < DDI_PROP_RESULT_OK) {
1939		switch (i) {
1940		case DDI_PROP_RESULT_EOF:
1941			return (DDI_PROP_END_OF_DATA);
1942
1943		case DDI_PROP_RESULT_ERROR:
1944			return (DDI_PROP_CANNOT_DECODE);
1945		}
1946	}
1947
1948	*(int *)data = tmp;
1949	*nelements = 1;
1950	return (DDI_PROP_SUCCESS);
1951}
1952
1953/*
1954 * Decode a single 64 bit integer property
1955 */
1956static int
1957ddi_prop_fm_decode_int64(prop_handle_t *ph, void *data, uint_t *nelements)
1958{
1959	int	i;
1960	int64_t	tmp;
1961
1962	/*
1963	 * If there is nothing to decode return an error
1964	 */
1965	if (ph->ph_size == 0)
1966		return (DDI_PROP_END_OF_DATA);
1967
1968	/*
1969	 * Decode the property as a single integer and return it
1970	 * in data if we were able to decode it.
1971	 */
1972	i = DDI_PROP_INT64(ph, DDI_PROP_CMD_DECODE, &tmp);
1973	if (i < DDI_PROP_RESULT_OK) {
1974		switch (i) {
1975		case DDI_PROP_RESULT_EOF:
1976			return (DDI_PROP_END_OF_DATA);
1977
1978		case DDI_PROP_RESULT_ERROR:
1979			return (DDI_PROP_CANNOT_DECODE);
1980		}
1981	}
1982
1983	*(int64_t *)data = tmp;
1984	*nelements = 1;
1985	return (DDI_PROP_SUCCESS);
1986}
1987
1988/*
1989 * Decode an array of integers property
1990 */
1991static int
1992ddi_prop_fm_decode_ints(prop_handle_t *ph, void *data, uint_t *nelements)
1993{
1994	int	i;
1995	int	cnt = 0;
1996	int	*tmp;
1997	int	*intp;
1998	int	n;
1999
2000	/*
2001	 * Figure out how many array elements there are by going through the
2002	 * data without decoding it first and counting.
2003	 */
2004	for (;;) {
2005		i = DDI_PROP_INT(ph, DDI_PROP_CMD_SKIP, NULL);
2006		if (i < 0)
2007			break;
2008		cnt++;
2009	}
2010
2011	/*
2012	 * If there are no elements return an error
2013	 */
2014	if (cnt == 0)
2015		return (DDI_PROP_END_OF_DATA);
2016
2017	/*
2018	 * If we cannot skip through the data, we cannot decode it
2019	 */
2020	if (i == DDI_PROP_RESULT_ERROR)
2021		return (DDI_PROP_CANNOT_DECODE);
2022
2023	/*
2024	 * Reset the data pointer to the beginning of the encoded data
2025	 */
2026	ddi_prop_reset_pos(ph);
2027
2028	/*
2029	 * Allocated memory to store the decoded value in.
2030	 */
2031	intp = ddi_prop_decode_alloc((cnt * sizeof (int)),
2032	    ddi_prop_free_ints);
2033
2034	/*
2035	 * Decode each element and place it in the space we just allocated
2036	 */
2037	tmp = intp;
2038	for (n = 0; n < cnt; n++, tmp++) {
2039		i = DDI_PROP_INT(ph, DDI_PROP_CMD_DECODE, tmp);
2040		if (i < DDI_PROP_RESULT_OK) {
2041			/*
2042			 * Free the space we just allocated
2043			 * and return an error.
2044			 */
2045			ddi_prop_free(intp);
2046			switch (i) {
2047			case DDI_PROP_RESULT_EOF:
2048				return (DDI_PROP_END_OF_DATA);
2049
2050			case DDI_PROP_RESULT_ERROR:
2051				return (DDI_PROP_CANNOT_DECODE);
2052			}
2053		}
2054	}
2055
2056	*nelements = cnt;
2057	*(int **)data = intp;
2058
2059	return (DDI_PROP_SUCCESS);
2060}
2061
2062/*
2063 * Decode a 64 bit integer array property
2064 */
2065static int
2066ddi_prop_fm_decode_int64_array(prop_handle_t *ph, void *data, uint_t *nelements)
2067{
2068	int	i;
2069	int	n;
2070	int	cnt = 0;
2071	int64_t	*tmp;
2072	int64_t	*intp;
2073
2074	/*
2075	 * Count the number of array elements by going
2076	 * through the data without decoding it.
2077	 */
2078	for (;;) {
2079		i = DDI_PROP_INT64(ph, DDI_PROP_CMD_SKIP, NULL);
2080		if (i < 0)
2081			break;
2082		cnt++;
2083	}
2084
2085	/*
2086	 * If there are no elements return an error
2087	 */
2088	if (cnt == 0)
2089		return (DDI_PROP_END_OF_DATA);
2090
2091	/*
2092	 * If we cannot skip through the data, we cannot decode it
2093	 */
2094	if (i == DDI_PROP_RESULT_ERROR)
2095		return (DDI_PROP_CANNOT_DECODE);
2096
2097	/*
2098	 * Reset the data pointer to the beginning of the encoded data
2099	 */
2100	ddi_prop_reset_pos(ph);
2101
2102	/*
2103	 * Allocate memory to store the decoded value.
2104	 */
2105	intp = ddi_prop_decode_alloc((cnt * sizeof (int64_t)),
2106	    ddi_prop_free_ints);
2107
2108	/*
2109	 * Decode each element and place it in the space allocated
2110	 */
2111	tmp = intp;
2112	for (n = 0; n < cnt; n++, tmp++) {
2113		i = DDI_PROP_INT64(ph, DDI_PROP_CMD_DECODE, tmp);
2114		if (i < DDI_PROP_RESULT_OK) {
2115			/*
2116			 * Free the space we just allocated
2117			 * and return an error.
2118			 */
2119			ddi_prop_free(intp);
2120			switch (i) {
2121			case DDI_PROP_RESULT_EOF:
2122				return (DDI_PROP_END_OF_DATA);
2123
2124			case DDI_PROP_RESULT_ERROR:
2125				return (DDI_PROP_CANNOT_DECODE);
2126			}
2127		}
2128	}
2129
2130	*nelements = cnt;
2131	*(int64_t **)data = intp;
2132
2133	return (DDI_PROP_SUCCESS);
2134}
2135
2136/*
2137 * Encode an array of integers property (Can be one element)
2138 */
2139int
2140ddi_prop_fm_encode_ints(prop_handle_t *ph, void *data, uint_t nelements)
2141{
2142	int	i;
2143	int	*tmp;
2144	int	cnt;
2145	int	size;
2146
2147	/*
2148	 * If there is no data, we cannot do anything
2149	 */
2150	if (nelements == 0)
2151		return (DDI_PROP_CANNOT_ENCODE);
2152
2153	/*
2154	 * Get the size of an encoded int.
2155	 */
2156	size = DDI_PROP_INT(ph, DDI_PROP_CMD_GET_ESIZE, NULL);
2157
2158	if (size < DDI_PROP_RESULT_OK) {
2159		switch (size) {
2160		case DDI_PROP_RESULT_EOF:
2161			return (DDI_PROP_END_OF_DATA);
2162
2163		case DDI_PROP_RESULT_ERROR:
2164			return (DDI_PROP_CANNOT_ENCODE);
2165		}
2166	}
2167
2168	/*
2169	 * Allocate space in the handle to store the encoded int.
2170	 */
2171	if (ddi_prop_encode_alloc(ph, size * nelements) !=
2172	    DDI_PROP_SUCCESS)
2173		return (DDI_PROP_NO_MEMORY);
2174
2175	/*
2176	 * Encode the array of ints.
2177	 */
2178	tmp = (int *)data;
2179	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
2180		i = DDI_PROP_INT(ph, DDI_PROP_CMD_ENCODE, tmp);
2181		if (i < DDI_PROP_RESULT_OK) {
2182			switch (i) {
2183			case DDI_PROP_RESULT_EOF:
2184				return (DDI_PROP_END_OF_DATA);
2185
2186			case DDI_PROP_RESULT_ERROR:
2187				return (DDI_PROP_CANNOT_ENCODE);
2188			}
2189		}
2190	}
2191
2192	return (DDI_PROP_SUCCESS);
2193}
2194
2195
2196/*
2197 * Encode a 64 bit integer array property
2198 */
2199int
2200ddi_prop_fm_encode_int64(prop_handle_t *ph, void *data, uint_t nelements)
2201{
2202	int i;
2203	int cnt;
2204	int size;
2205	int64_t *tmp;
2206
2207	/*
2208	 * If there is no data, we cannot do anything
2209	 */
2210	if (nelements == 0)
2211		return (DDI_PROP_CANNOT_ENCODE);
2212
2213	/*
2214	 * Get the size of an encoded 64 bit int.
2215	 */
2216	size = DDI_PROP_INT64(ph, DDI_PROP_CMD_GET_ESIZE, NULL);
2217
2218	if (size < DDI_PROP_RESULT_OK) {
2219		switch (size) {
2220		case DDI_PROP_RESULT_EOF:
2221			return (DDI_PROP_END_OF_DATA);
2222
2223		case DDI_PROP_RESULT_ERROR:
2224			return (DDI_PROP_CANNOT_ENCODE);
2225		}
2226	}
2227
2228	/*
2229	 * Allocate space in the handle to store the encoded int.
2230	 */
2231	if (ddi_prop_encode_alloc(ph, size * nelements) !=
2232	    DDI_PROP_SUCCESS)
2233		return (DDI_PROP_NO_MEMORY);
2234
2235	/*
2236	 * Encode the array of ints.
2237	 */
2238	tmp = (int64_t *)data;
2239	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
2240		i = DDI_PROP_INT64(ph, DDI_PROP_CMD_ENCODE, tmp);
2241		if (i < DDI_PROP_RESULT_OK) {
2242			switch (i) {
2243			case DDI_PROP_RESULT_EOF:
2244				return (DDI_PROP_END_OF_DATA);
2245
2246			case DDI_PROP_RESULT_ERROR:
2247				return (DDI_PROP_CANNOT_ENCODE);
2248			}
2249		}
2250	}
2251
2252	return (DDI_PROP_SUCCESS);
2253}
2254
2255/*
2256 * Decode a single string property
2257 */
2258static int
2259ddi_prop_fm_decode_string(prop_handle_t *ph, void *data, uint_t *nelements)
2260{
2261	char		*tmp;
2262	char		*str;
2263	int		i;
2264	int		size;
2265
2266	/*
2267	 * If there is nothing to decode return an error
2268	 */
2269	if (ph->ph_size == 0)
2270		return (DDI_PROP_END_OF_DATA);
2271
2272	/*
2273	 * Get the decoded size of the encoded string.
2274	 */
2275	size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL);
2276	if (size < DDI_PROP_RESULT_OK) {
2277		switch (size) {
2278		case DDI_PROP_RESULT_EOF:
2279			return (DDI_PROP_END_OF_DATA);
2280
2281		case DDI_PROP_RESULT_ERROR:
2282			return (DDI_PROP_CANNOT_DECODE);
2283		}
2284	}
2285
2286	/*
2287	 * Allocated memory to store the decoded value in.
2288	 */
2289	str = ddi_prop_decode_alloc((size_t)size, ddi_prop_free_string);
2290
2291	ddi_prop_reset_pos(ph);
2292
2293	/*
2294	 * Decode the str and place it in the space we just allocated
2295	 */
2296	tmp = str;
2297	i = DDI_PROP_STR(ph, DDI_PROP_CMD_DECODE, tmp);
2298	if (i < DDI_PROP_RESULT_OK) {
2299		/*
2300		 * Free the space we just allocated
2301		 * and return an error.
2302		 */
2303		ddi_prop_free(str);
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	*(char **)data = str;
2314	*nelements = 1;
2315
2316	return (DDI_PROP_SUCCESS);
2317}
2318
2319/*
2320 * Decode an array of strings.
2321 */
2322int
2323ddi_prop_fm_decode_strings(prop_handle_t *ph, void *data, uint_t *nelements)
2324{
2325	int		cnt = 0;
2326	char		**strs;
2327	char		**tmp;
2328	char		*ptr;
2329	int		i;
2330	int		n;
2331	int		size;
2332	size_t		nbytes;
2333
2334	/*
2335	 * Figure out how many array elements there are by going through the
2336	 * data without decoding it first and counting.
2337	 */
2338	for (;;) {
2339		i = DDI_PROP_STR(ph, DDI_PROP_CMD_SKIP, NULL);
2340		if (i < 0)
2341			break;
2342		cnt++;
2343	}
2344
2345	/*
2346	 * If there are no elements return an error
2347	 */
2348	if (cnt == 0)
2349		return (DDI_PROP_END_OF_DATA);
2350
2351	/*
2352	 * If we cannot skip through the data, we cannot decode it
2353	 */
2354	if (i == DDI_PROP_RESULT_ERROR)
2355		return (DDI_PROP_CANNOT_DECODE);
2356
2357	/*
2358	 * Reset the data pointer to the beginning of the encoded data
2359	 */
2360	ddi_prop_reset_pos(ph);
2361
2362	/*
2363	 * Figure out how much memory we need for the sum total
2364	 */
2365	nbytes = (cnt + 1) * sizeof (char *);
2366
2367	for (n = 0; n < cnt; n++) {
2368		/*
2369		 * Get the decoded size of the current encoded string.
2370		 */
2371		size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL);
2372		if (size < DDI_PROP_RESULT_OK) {
2373			switch (size) {
2374			case DDI_PROP_RESULT_EOF:
2375				return (DDI_PROP_END_OF_DATA);
2376
2377			case DDI_PROP_RESULT_ERROR:
2378				return (DDI_PROP_CANNOT_DECODE);
2379			}
2380		}
2381
2382		nbytes += size;
2383	}
2384
2385	/*
2386	 * Allocate memory in which to store the decoded strings.
2387	 */
2388	strs = ddi_prop_decode_alloc(nbytes, ddi_prop_free_strings);
2389
2390	/*
2391	 * Set up pointers for each string by figuring out yet
2392	 * again how long each string is.
2393	 */
2394	ddi_prop_reset_pos(ph);
2395	ptr = (caddr_t)strs + ((cnt + 1) * sizeof (char *));
2396	for (tmp = strs, n = 0; n < cnt; n++, tmp++) {
2397		/*
2398		 * Get the decoded size of the current encoded string.
2399		 */
2400		size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL);
2401		if (size < DDI_PROP_RESULT_OK) {
2402			ddi_prop_free(strs);
2403			switch (size) {
2404			case DDI_PROP_RESULT_EOF:
2405				return (DDI_PROP_END_OF_DATA);
2406
2407			case DDI_PROP_RESULT_ERROR:
2408				return (DDI_PROP_CANNOT_DECODE);
2409			}
2410		}
2411
2412		*tmp = ptr;
2413		ptr += size;
2414	}
2415
2416	/*
2417	 * String array is terminated by a NULL
2418	 */
2419	*tmp = NULL;
2420
2421	/*
2422	 * Finally, we can decode each string
2423	 */
2424	ddi_prop_reset_pos(ph);
2425	for (tmp = strs, n = 0; n < cnt; n++, tmp++) {
2426		i = DDI_PROP_STR(ph, DDI_PROP_CMD_DECODE, *tmp);
2427		if (i < DDI_PROP_RESULT_OK) {
2428			/*
2429			 * Free the space we just allocated
2430			 * and return an error
2431			 */
2432			ddi_prop_free(strs);
2433			switch (i) {
2434			case DDI_PROP_RESULT_EOF:
2435				return (DDI_PROP_END_OF_DATA);
2436
2437			case DDI_PROP_RESULT_ERROR:
2438				return (DDI_PROP_CANNOT_DECODE);
2439			}
2440		}
2441	}
2442
2443	*(char ***)data = strs;
2444	*nelements = cnt;
2445
2446	return (DDI_PROP_SUCCESS);
2447}
2448
2449/*
2450 * Encode a string.
2451 */
2452int
2453ddi_prop_fm_encode_string(prop_handle_t *ph, void *data, uint_t nelements)
2454{
2455	char		**tmp;
2456	int		size;
2457	int		i;
2458
2459	/*
2460	 * If there is no data, we cannot do anything
2461	 */
2462	if (nelements == 0)
2463		return (DDI_PROP_CANNOT_ENCODE);
2464
2465	/*
2466	 * Get the size of the encoded string.
2467	 */
2468	tmp = (char **)data;
2469	size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_ESIZE, *tmp);
2470	if (size < DDI_PROP_RESULT_OK) {
2471		switch (size) {
2472		case DDI_PROP_RESULT_EOF:
2473			return (DDI_PROP_END_OF_DATA);
2474
2475		case DDI_PROP_RESULT_ERROR:
2476			return (DDI_PROP_CANNOT_ENCODE);
2477		}
2478	}
2479
2480	/*
2481	 * Allocate space in the handle to store the encoded string.
2482	 */
2483	if (ddi_prop_encode_alloc(ph, size) != DDI_PROP_SUCCESS)
2484		return (DDI_PROP_NO_MEMORY);
2485
2486	ddi_prop_reset_pos(ph);
2487
2488	/*
2489	 * Encode the string.
2490	 */
2491	tmp = (char **)data;
2492	i = DDI_PROP_STR(ph, DDI_PROP_CMD_ENCODE, *tmp);
2493	if (i < DDI_PROP_RESULT_OK) {
2494		switch (i) {
2495		case DDI_PROP_RESULT_EOF:
2496			return (DDI_PROP_END_OF_DATA);
2497
2498		case DDI_PROP_RESULT_ERROR:
2499			return (DDI_PROP_CANNOT_ENCODE);
2500		}
2501	}
2502
2503	return (DDI_PROP_SUCCESS);
2504}
2505
2506
2507/*
2508 * Encode an array of strings.
2509 */
2510int
2511ddi_prop_fm_encode_strings(prop_handle_t *ph, void *data, uint_t nelements)
2512{
2513	int		cnt = 0;
2514	char		**tmp;
2515	int		size;
2516	uint_t		total_size;
2517	int		i;
2518
2519	/*
2520	 * If there is no data, we cannot do anything
2521	 */
2522	if (nelements == 0)
2523		return (DDI_PROP_CANNOT_ENCODE);
2524
2525	/*
2526	 * Get the total size required to encode all the strings.
2527	 */
2528	total_size = 0;
2529	tmp = (char **)data;
2530	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
2531		size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_ESIZE, *tmp);
2532		if (size < DDI_PROP_RESULT_OK) {
2533			switch (size) {
2534			case DDI_PROP_RESULT_EOF:
2535				return (DDI_PROP_END_OF_DATA);
2536
2537			case DDI_PROP_RESULT_ERROR:
2538				return (DDI_PROP_CANNOT_ENCODE);
2539			}
2540		}
2541		total_size += (uint_t)size;
2542	}
2543
2544	/*
2545	 * Allocate space in the handle to store the encoded strings.
2546	 */
2547	if (ddi_prop_encode_alloc(ph, total_size) != DDI_PROP_SUCCESS)
2548		return (DDI_PROP_NO_MEMORY);
2549
2550	ddi_prop_reset_pos(ph);
2551
2552	/*
2553	 * Encode the array of strings.
2554	 */
2555	tmp = (char **)data;
2556	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
2557		i = DDI_PROP_STR(ph, DDI_PROP_CMD_ENCODE, *tmp);
2558		if (i < DDI_PROP_RESULT_OK) {
2559			switch (i) {
2560			case DDI_PROP_RESULT_EOF:
2561				return (DDI_PROP_END_OF_DATA);
2562
2563			case DDI_PROP_RESULT_ERROR:
2564				return (DDI_PROP_CANNOT_ENCODE);
2565			}
2566		}
2567	}
2568
2569	return (DDI_PROP_SUCCESS);
2570}
2571
2572
2573/*
2574 * Decode an array of bytes.
2575 */
2576static int
2577ddi_prop_fm_decode_bytes(prop_handle_t *ph, void *data, uint_t *nelements)
2578{
2579	uchar_t		*tmp;
2580	int		nbytes;
2581	int		i;
2582
2583	/*
2584	 * If there are no elements return an error
2585	 */
2586	if (ph->ph_size == 0)
2587		return (DDI_PROP_END_OF_DATA);
2588
2589	/*
2590	 * Get the size of the encoded array of bytes.
2591	 */
2592	nbytes = DDI_PROP_BYTES(ph, DDI_PROP_CMD_GET_DSIZE,
2593	    data, ph->ph_size);
2594	if (nbytes < DDI_PROP_RESULT_OK) {
2595		switch (nbytes) {
2596		case DDI_PROP_RESULT_EOF:
2597			return (DDI_PROP_END_OF_DATA);
2598
2599		case DDI_PROP_RESULT_ERROR:
2600			return (DDI_PROP_CANNOT_DECODE);
2601		}
2602	}
2603
2604	/*
2605	 * Allocated memory to store the decoded value in.
2606	 */
2607	tmp = ddi_prop_decode_alloc(nbytes, ddi_prop_free_bytes);
2608
2609	/*
2610	 * Decode each element and place it in the space we just allocated
2611	 */
2612	i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_DECODE, tmp, nbytes);
2613	if (i < DDI_PROP_RESULT_OK) {
2614		/*
2615		 * Free the space we just allocated
2616		 * and return an error
2617		 */
2618		ddi_prop_free(tmp);
2619		switch (i) {
2620		case DDI_PROP_RESULT_EOF:
2621			return (DDI_PROP_END_OF_DATA);
2622
2623		case DDI_PROP_RESULT_ERROR:
2624			return (DDI_PROP_CANNOT_DECODE);
2625		}
2626	}
2627
2628	*(uchar_t **)data = tmp;
2629	*nelements = nbytes;
2630
2631	return (DDI_PROP_SUCCESS);
2632}
2633
2634/*
2635 * Encode an array of bytes.
2636 */
2637int
2638ddi_prop_fm_encode_bytes(prop_handle_t *ph, void *data, uint_t nelements)
2639{
2640	int		size;
2641	int		i;
2642
2643	/*
2644	 * If there are no elements, then this is a boolean property,
2645	 * so just create a property handle with no data and return.
2646	 */
2647	if (nelements == 0) {
2648		(void) ddi_prop_encode_alloc(ph, 0);
2649		return (DDI_PROP_SUCCESS);
2650	}
2651
2652	/*
2653	 * Get the size of the encoded array of bytes.
2654	 */
2655	size = DDI_PROP_BYTES(ph, DDI_PROP_CMD_GET_ESIZE, (uchar_t *)data,
2656	    nelements);
2657	if (size < DDI_PROP_RESULT_OK) {
2658		switch (size) {
2659		case DDI_PROP_RESULT_EOF:
2660			return (DDI_PROP_END_OF_DATA);
2661
2662		case DDI_PROP_RESULT_ERROR:
2663			return (DDI_PROP_CANNOT_DECODE);
2664		}
2665	}
2666
2667	/*
2668	 * Allocate space in the handle to store the encoded bytes.
2669	 */
2670	if (ddi_prop_encode_alloc(ph, (uint_t)size) != DDI_PROP_SUCCESS)
2671		return (DDI_PROP_NO_MEMORY);
2672
2673	/*
2674	 * Encode the array of bytes.
2675	 */
2676	i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_ENCODE, (uchar_t *)data,
2677	    nelements);
2678	if (i < DDI_PROP_RESULT_OK) {
2679		switch (i) {
2680		case DDI_PROP_RESULT_EOF:
2681			return (DDI_PROP_END_OF_DATA);
2682
2683		case DDI_PROP_RESULT_ERROR:
2684			return (DDI_PROP_CANNOT_ENCODE);
2685		}
2686	}
2687
2688	return (DDI_PROP_SUCCESS);
2689}
2690
2691/*
2692 * OBP 1275 integer, string and byte operators.
2693 *
2694 * DDI_PROP_CMD_DECODE:
2695 *
2696 *	DDI_PROP_RESULT_ERROR:		cannot decode the data
2697 *	DDI_PROP_RESULT_EOF:		end of data
2698 *	DDI_PROP_OK:			data was decoded
2699 *
2700 * DDI_PROP_CMD_ENCODE:
2701 *
2702 *	DDI_PROP_RESULT_ERROR:		cannot encode the data
2703 *	DDI_PROP_RESULT_EOF:		end of data
2704 *	DDI_PROP_OK:			data was encoded
2705 *
2706 * DDI_PROP_CMD_SKIP:
2707 *
2708 *	DDI_PROP_RESULT_ERROR:		cannot skip the data
2709 *	DDI_PROP_RESULT_EOF:		end of data
2710 *	DDI_PROP_OK:			data was skipped
2711 *
2712 * DDI_PROP_CMD_GET_ESIZE:
2713 *
2714 *	DDI_PROP_RESULT_ERROR:		cannot get encoded size
2715 *	DDI_PROP_RESULT_EOF:		end of data
2716 *	> 0:				the encoded size
2717 *
2718 * DDI_PROP_CMD_GET_DSIZE:
2719 *
2720 *	DDI_PROP_RESULT_ERROR:		cannot get decoded size
2721 *	DDI_PROP_RESULT_EOF:		end of data
2722 *	> 0:				the decoded size
2723 */
2724
2725/*
2726 * OBP 1275 integer operator
2727 *
2728 * OBP properties are a byte stream of data, so integers may not be
2729 * properly aligned.  Therefore we need to copy them one byte at a time.
2730 */
2731int
2732ddi_prop_1275_int(prop_handle_t *ph, uint_t cmd, int *data)
2733{
2734	int	i;
2735
2736	switch (cmd) {
2737	case DDI_PROP_CMD_DECODE:
2738		/*
2739		 * Check that there is encoded data
2740		 */
2741		if (ph->ph_cur_pos == NULL || ph->ph_size == 0)
2742			return (DDI_PROP_RESULT_ERROR);
2743		if (ph->ph_flags & PH_FROM_PROM) {
2744			i = MIN(ph->ph_size, PROP_1275_INT_SIZE);
2745			if ((int *)ph->ph_cur_pos > ((int *)ph->ph_data +
2746			    ph->ph_size - i))
2747				return (DDI_PROP_RESULT_ERROR);
2748		} else {
2749			if (ph->ph_size < sizeof (int) ||
2750			    ((int *)ph->ph_cur_pos > ((int *)ph->ph_data +
2751			    ph->ph_size - sizeof (int))))
2752				return (DDI_PROP_RESULT_ERROR);
2753		}
2754
2755		/*
2756		 * Copy the integer, using the implementation-specific
2757		 * copy function if the property is coming from the PROM.
2758		 */
2759		if (ph->ph_flags & PH_FROM_PROM) {
2760			*data = impl_ddi_prop_int_from_prom(
2761			    (uchar_t *)ph->ph_cur_pos,
2762			    (ph->ph_size < PROP_1275_INT_SIZE) ?
2763			    ph->ph_size : PROP_1275_INT_SIZE);
2764		} else {
2765			bcopy(ph->ph_cur_pos, data, sizeof (int));
2766		}
2767
2768		/*
2769		 * Move the current location to the start of the next
2770		 * bit of undecoded data.
2771		 */
2772		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
2773		    PROP_1275_INT_SIZE;
2774		return (DDI_PROP_RESULT_OK);
2775
2776	case DDI_PROP_CMD_ENCODE:
2777		/*
2778		 * Check that there is room to encoded the data
2779		 */
2780		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
2781		    ph->ph_size < PROP_1275_INT_SIZE ||
2782		    ((int *)ph->ph_cur_pos > ((int *)ph->ph_data +
2783		    ph->ph_size - sizeof (int))))
2784			return (DDI_PROP_RESULT_ERROR);
2785
2786		/*
2787		 * Encode the integer into the byte stream one byte at a
2788		 * time.
2789		 */
2790		bcopy(data, ph->ph_cur_pos, sizeof (int));
2791
2792		/*
2793		 * Move the current location to the start of the next bit of
2794		 * space where we can store encoded data.
2795		 */
2796		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE;
2797		return (DDI_PROP_RESULT_OK);
2798
2799	case DDI_PROP_CMD_SKIP:
2800		/*
2801		 * Check that there is encoded data
2802		 */
2803		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
2804		    ph->ph_size < PROP_1275_INT_SIZE)
2805			return (DDI_PROP_RESULT_ERROR);
2806
2807
2808		if ((caddr_t)ph->ph_cur_pos ==
2809		    (caddr_t)ph->ph_data + ph->ph_size) {
2810			return (DDI_PROP_RESULT_EOF);
2811		} else if ((caddr_t)ph->ph_cur_pos >
2812		    (caddr_t)ph->ph_data + ph->ph_size) {
2813			return (DDI_PROP_RESULT_EOF);
2814		}
2815
2816		/*
2817		 * Move the current location to the start of the next bit of
2818		 * undecoded data.
2819		 */
2820		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE;
2821		return (DDI_PROP_RESULT_OK);
2822
2823	case DDI_PROP_CMD_GET_ESIZE:
2824		/*
2825		 * Return the size of an encoded integer on OBP
2826		 */
2827		return (PROP_1275_INT_SIZE);
2828
2829	case DDI_PROP_CMD_GET_DSIZE:
2830		/*
2831		 * Return the size of a decoded integer on the system.
2832		 */
2833		return (sizeof (int));
2834
2835	default:
2836#ifdef DEBUG
2837		panic("ddi_prop_1275_int: %x impossible", cmd);
2838		/*NOTREACHED*/
2839#else
2840		return (DDI_PROP_RESULT_ERROR);
2841#endif	/* DEBUG */
2842	}
2843}
2844
2845/*
2846 * 64 bit integer operator.
2847 *
2848 * This is an extension, defined by Sun, to the 1275 integer
2849 * operator.  This routine handles the encoding/decoding of
2850 * 64 bit integer properties.
2851 */
2852int
2853ddi_prop_int64_op(prop_handle_t *ph, uint_t cmd, int64_t *data)
2854{
2855
2856	switch (cmd) {
2857	case DDI_PROP_CMD_DECODE:
2858		/*
2859		 * Check that there is encoded data
2860		 */
2861		if (ph->ph_cur_pos == NULL || ph->ph_size == 0)
2862			return (DDI_PROP_RESULT_ERROR);
2863		if (ph->ph_flags & PH_FROM_PROM) {
2864			return (DDI_PROP_RESULT_ERROR);
2865		} else {
2866			if (ph->ph_size < sizeof (int64_t) ||
2867			    ((int64_t *)ph->ph_cur_pos >
2868			    ((int64_t *)ph->ph_data +
2869			    ph->ph_size - sizeof (int64_t))))
2870				return (DDI_PROP_RESULT_ERROR);
2871		}
2872		/*
2873		 * Copy the integer, using the implementation-specific
2874		 * copy function if the property is coming from the PROM.
2875		 */
2876		if (ph->ph_flags & PH_FROM_PROM) {
2877			return (DDI_PROP_RESULT_ERROR);
2878		} else {
2879			bcopy(ph->ph_cur_pos, data, sizeof (int64_t));
2880		}
2881
2882		/*
2883		 * Move the current location to the start of the next
2884		 * bit of undecoded data.
2885		 */
2886		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
2887		    sizeof (int64_t);
2888			return (DDI_PROP_RESULT_OK);
2889
2890	case DDI_PROP_CMD_ENCODE:
2891		/*
2892		 * Check that there is room to encoded the data
2893		 */
2894		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
2895		    ph->ph_size < sizeof (int64_t) ||
2896		    ((int64_t *)ph->ph_cur_pos > ((int64_t *)ph->ph_data +
2897		    ph->ph_size - sizeof (int64_t))))
2898			return (DDI_PROP_RESULT_ERROR);
2899
2900		/*
2901		 * Encode the integer into the byte stream one byte at a
2902		 * time.
2903		 */
2904		bcopy(data, ph->ph_cur_pos, sizeof (int64_t));
2905
2906		/*
2907		 * Move the current location to the start of the next bit of
2908		 * space where we can store encoded data.
2909		 */
2910		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
2911		    sizeof (int64_t);
2912		return (DDI_PROP_RESULT_OK);
2913
2914	case DDI_PROP_CMD_SKIP:
2915		/*
2916		 * Check that there is encoded data
2917		 */
2918		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
2919		    ph->ph_size < sizeof (int64_t))
2920			return (DDI_PROP_RESULT_ERROR);
2921
2922		if ((caddr_t)ph->ph_cur_pos ==
2923		    (caddr_t)ph->ph_data + ph->ph_size) {
2924			return (DDI_PROP_RESULT_EOF);
2925		} else if ((caddr_t)ph->ph_cur_pos >
2926		    (caddr_t)ph->ph_data + ph->ph_size) {
2927			return (DDI_PROP_RESULT_EOF);
2928		}
2929
2930		/*
2931		 * Move the current location to the start of
2932		 * the next bit of undecoded data.
2933		 */
2934		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
2935		    sizeof (int64_t);
2936			return (DDI_PROP_RESULT_OK);
2937
2938	case DDI_PROP_CMD_GET_ESIZE:
2939		/*
2940		 * Return the size of an encoded integer on OBP
2941		 */
2942		return (sizeof (int64_t));
2943
2944	case DDI_PROP_CMD_GET_DSIZE:
2945		/*
2946		 * Return the size of a decoded integer on the system.
2947		 */
2948		return (sizeof (int64_t));
2949
2950	default:
2951#ifdef DEBUG
2952		panic("ddi_prop_int64_op: %x impossible", cmd);
2953		/*NOTREACHED*/
2954#else
2955		return (DDI_PROP_RESULT_ERROR);
2956#endif  /* DEBUG */
2957	}
2958}
2959
2960/*
2961 * OBP 1275 string operator.
2962 *
2963 * OBP strings are NULL terminated.
2964 */
2965int
2966ddi_prop_1275_string(prop_handle_t *ph, uint_t cmd, char *data)
2967{
2968	int	n;
2969	char	*p;
2970	char	*end;
2971
2972	switch (cmd) {
2973	case DDI_PROP_CMD_DECODE:
2974		/*
2975		 * Check that there is encoded data
2976		 */
2977		if (ph->ph_cur_pos == NULL || ph->ph_size == 0) {
2978			return (DDI_PROP_RESULT_ERROR);
2979		}
2980
2981		/*
2982		 * Match DDI_PROP_CMD_GET_DSIZE logic for when to stop and
2983		 * how to NULL terminate result.
2984		 */
2985		p = (char *)ph->ph_cur_pos;
2986		end = (char *)ph->ph_data + ph->ph_size;
2987		if (p >= end)
2988			return (DDI_PROP_RESULT_EOF);
2989
2990		while (p < end) {
2991			*data++ = *p;
2992			if (*p++ == 0) {	/* NULL from OBP */
2993				ph->ph_cur_pos = p;
2994				return (DDI_PROP_RESULT_OK);
2995			}
2996		}
2997
2998		/*
2999		 * If OBP did not NULL terminate string, which happens
3000		 * (at least) for 'true'/'false' boolean values, account for
3001		 * the space and store null termination on decode.
3002		 */
3003		ph->ph_cur_pos = p;
3004		*data = 0;
3005		return (DDI_PROP_RESULT_OK);
3006
3007	case DDI_PROP_CMD_ENCODE:
3008		/*
3009		 * Check that there is room to encoded the data
3010		 */
3011		if (ph->ph_cur_pos == NULL || ph->ph_size == 0) {
3012			return (DDI_PROP_RESULT_ERROR);
3013		}
3014
3015		n = strlen(data) + 1;
3016		if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
3017		    ph->ph_size - n)) {
3018			return (DDI_PROP_RESULT_ERROR);
3019		}
3020
3021		/*
3022		 * Copy the NULL terminated string
3023		 */
3024		bcopy(data, ph->ph_cur_pos, n);
3025
3026		/*
3027		 * Move the current location to the start of the next bit of
3028		 * space where we can store encoded data.
3029		 */
3030		ph->ph_cur_pos = (char *)ph->ph_cur_pos + n;
3031		return (DDI_PROP_RESULT_OK);
3032
3033	case DDI_PROP_CMD_SKIP:
3034		/*
3035		 * Check that there is encoded data
3036		 */
3037		if (ph->ph_cur_pos == NULL || ph->ph_size == 0) {
3038			return (DDI_PROP_RESULT_ERROR);
3039		}
3040
3041		/*
3042		 * Return the string length plus one for the NULL
3043		 * We know the size of the property, we need to
3044		 * ensure that the string is properly formatted,
3045		 * since we may be looking up random OBP data.
3046		 */
3047		p = (char *)ph->ph_cur_pos;
3048		end = (char *)ph->ph_data + ph->ph_size;
3049		if (p >= end)
3050			return (DDI_PROP_RESULT_EOF);
3051
3052		while (p < end) {
3053			if (*p++ == 0) {	/* NULL from OBP */
3054				ph->ph_cur_pos = p;
3055				return (DDI_PROP_RESULT_OK);
3056			}
3057		}
3058
3059		/*
3060		 * Accommodate the fact that OBP does not always NULL
3061		 * terminate strings.
3062		 */
3063		ph->ph_cur_pos = p;
3064		return (DDI_PROP_RESULT_OK);
3065
3066	case DDI_PROP_CMD_GET_ESIZE:
3067		/*
3068		 * Return the size of the encoded string on OBP.
3069		 */
3070		return (strlen(data) + 1);
3071
3072	case DDI_PROP_CMD_GET_DSIZE:
3073		/*
3074		 * Return the string length plus one for the NULL.
3075		 * We know the size of the property, we need to
3076		 * ensure that the string is properly formatted,
3077		 * since we may be looking up random OBP data.
3078		 */
3079		p = (char *)ph->ph_cur_pos;
3080		end = (char *)ph->ph_data + ph->ph_size;
3081		if (p >= end)
3082			return (DDI_PROP_RESULT_EOF);
3083
3084		for (n = 0; p < end; n++) {
3085			if (*p++ == 0) {	/* NULL from OBP */
3086				ph->ph_cur_pos = p;
3087				return (n + 1);
3088			}
3089		}
3090
3091		/*
3092		 * If OBP did not NULL terminate string, which happens for
3093		 * 'true'/'false' boolean values, account for the space
3094		 * to store null termination here.
3095		 */
3096		ph->ph_cur_pos = p;
3097		return (n + 1);
3098
3099	default:
3100#ifdef DEBUG
3101		panic("ddi_prop_1275_string: %x impossible", cmd);
3102		/*NOTREACHED*/
3103#else
3104		return (DDI_PROP_RESULT_ERROR);
3105#endif	/* DEBUG */
3106	}
3107}
3108
3109/*
3110 * OBP 1275 byte operator
3111 *
3112 * Caller must specify the number of bytes to get.  OBP encodes bytes
3113 * as a byte so there is a 1-to-1 translation.
3114 */
3115int
3116ddi_prop_1275_bytes(prop_handle_t *ph, uint_t cmd, uchar_t *data,
3117	uint_t nelements)
3118{
3119	switch (cmd) {
3120	case DDI_PROP_CMD_DECODE:
3121		/*
3122		 * Check that there is encoded data
3123		 */
3124		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
3125		    ph->ph_size < nelements ||
3126		    ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
3127		    ph->ph_size - nelements)))
3128			return (DDI_PROP_RESULT_ERROR);
3129
3130		/*
3131		 * Copy out the bytes
3132		 */
3133		bcopy(ph->ph_cur_pos, data, nelements);
3134
3135		/*
3136		 * Move the current location
3137		 */
3138		ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements;
3139		return (DDI_PROP_RESULT_OK);
3140
3141	case DDI_PROP_CMD_ENCODE:
3142		/*
3143		 * Check that there is room to encode the data
3144		 */
3145		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
3146		    ph->ph_size < nelements ||
3147		    ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
3148		    ph->ph_size - nelements)))
3149			return (DDI_PROP_RESULT_ERROR);
3150
3151		/*
3152		 * Copy in the bytes
3153		 */
3154		bcopy(data, ph->ph_cur_pos, nelements);
3155
3156		/*
3157		 * Move the current location to the start of the next bit of
3158		 * space where we can store encoded data.
3159		 */
3160		ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements;
3161		return (DDI_PROP_RESULT_OK);
3162
3163	case DDI_PROP_CMD_SKIP:
3164		/*
3165		 * Check that there is encoded data
3166		 */
3167		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
3168		    ph->ph_size < nelements)
3169			return (DDI_PROP_RESULT_ERROR);
3170
3171		if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
3172		    ph->ph_size - nelements))
3173			return (DDI_PROP_RESULT_EOF);
3174
3175		/*
3176		 * Move the current location
3177		 */
3178		ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements;
3179		return (DDI_PROP_RESULT_OK);
3180
3181	case DDI_PROP_CMD_GET_ESIZE:
3182		/*
3183		 * The size in bytes of the encoded size is the
3184		 * same as the decoded size provided by the caller.
3185		 */
3186		return (nelements);
3187
3188	case DDI_PROP_CMD_GET_DSIZE:
3189		/*
3190		 * Just return the number of bytes specified by the caller.
3191		 */
3192		return (nelements);
3193
3194	default:
3195#ifdef DEBUG
3196		panic("ddi_prop_1275_bytes: %x impossible", cmd);
3197		/*NOTREACHED*/
3198#else
3199		return (DDI_PROP_RESULT_ERROR);
3200#endif	/* DEBUG */
3201	}
3202}
3203
3204/*
3205 * Used for properties that come from the OBP, hardware configuration files,
3206 * or that are created by calls to ddi_prop_update(9F).
3207 */
3208static struct prop_handle_ops prop_1275_ops = {
3209	ddi_prop_1275_int,
3210	ddi_prop_1275_string,
3211	ddi_prop_1275_bytes,
3212	ddi_prop_int64_op
3213};
3214
3215
3216/*
3217 * Interface to create/modify a managed property on child's behalf...
3218 * Flags interpreted are:
3219 *	DDI_PROP_CANSLEEP:	Allow memory allocation to sleep.
3220 *	DDI_PROP_SYSTEM_DEF:	Manipulate system list rather than driver list.
3221 *
3222 * Use same dev_t when modifying or undefining a property.
3223 * Search for properties with DDI_DEV_T_ANY to match first named
3224 * property on the list.
3225 *
3226 * Properties are stored LIFO and subsequently will match the first
3227 * `matching' instance.
3228 */
3229
3230/*
3231 * ddi_prop_add:	Add a software defined property
3232 */
3233
3234/*
3235 * define to get a new ddi_prop_t.
3236 * km_flags are KM_SLEEP or KM_NOSLEEP.
3237 */
3238
3239#define	DDI_NEW_PROP_T(km_flags)	\
3240	(kmem_zalloc(sizeof (ddi_prop_t), km_flags))
3241
3242static int
3243ddi_prop_add(dev_t dev, dev_info_t *dip, int flags,
3244    char *name, caddr_t value, int length)
3245{
3246	ddi_prop_t	*new_propp, *propp;
3247	ddi_prop_t	**list_head = &(DEVI(dip)->devi_drv_prop_ptr);
3248	int		km_flags = KM_NOSLEEP;
3249	int		name_buf_len;
3250
3251	/*
3252	 * If dev_t is DDI_DEV_T_ANY or name's length is zero return error.
3253	 */
3254
3255	if (dev == DDI_DEV_T_ANY || name == (char *)0 || strlen(name) == 0)
3256		return (DDI_PROP_INVAL_ARG);
3257
3258	if (flags & DDI_PROP_CANSLEEP)
3259		km_flags = KM_SLEEP;
3260
3261	if (flags & DDI_PROP_SYSTEM_DEF)
3262		list_head = &(DEVI(dip)->devi_sys_prop_ptr);
3263	else if (flags & DDI_PROP_HW_DEF)
3264		list_head = &(DEVI(dip)->devi_hw_prop_ptr);
3265
3266	if ((new_propp = DDI_NEW_PROP_T(km_flags)) == NULL)  {
3267		cmn_err(CE_CONT, prop_no_mem_msg, name);
3268		return (DDI_PROP_NO_MEMORY);
3269	}
3270
3271	/*
3272	 * If dev is major number 0, then we need to do a ddi_name_to_major
3273	 * to get the real major number for the device.  This needs to be
3274	 * done because some drivers need to call ddi_prop_create in their
3275	 * attach routines but they don't have a dev.  By creating the dev
3276	 * ourself if the major number is 0, drivers will not have to know what
3277	 * their major number.	They can just create a dev with major number
3278	 * 0 and pass it in.  For device 0, we will be doing a little extra
3279	 * work by recreating the same dev that we already have, but its the
3280	 * price you pay :-).
3281	 *
3282	 * This fixes bug #1098060.
3283	 */
3284	if (getmajor(dev) == DDI_MAJOR_T_UNKNOWN) {
3285		new_propp->prop_dev =
3286		    makedevice(ddi_name_to_major(DEVI(dip)->devi_binding_name),
3287		    getminor(dev));
3288	} else
3289		new_propp->prop_dev = dev;
3290
3291	/*
3292	 * Allocate space for property name and copy it in...
3293	 */
3294
3295	name_buf_len = strlen(name) + 1;
3296	new_propp->prop_name = kmem_alloc(name_buf_len, km_flags);
3297	if (new_propp->prop_name == 0)	{
3298		kmem_free(new_propp, sizeof (ddi_prop_t));
3299		cmn_err(CE_CONT, prop_no_mem_msg, name);
3300		return (DDI_PROP_NO_MEMORY);
3301	}
3302	bcopy(name, new_propp->prop_name, name_buf_len);
3303
3304	/*
3305	 * Set the property type
3306	 */
3307	new_propp->prop_flags = flags & DDI_PROP_TYPE_MASK;
3308
3309	/*
3310	 * Set length and value ONLY if not an explicit property undefine:
3311	 * NOTE: value and length are zero for explicit undefines.
3312	 */
3313
3314	if (flags & DDI_PROP_UNDEF_IT) {
3315		new_propp->prop_flags |= DDI_PROP_UNDEF_IT;
3316	} else {
3317		if ((new_propp->prop_len = length) != 0) {
3318			new_propp->prop_val = kmem_alloc(length, km_flags);
3319			if (new_propp->prop_val == 0)  {
3320				kmem_free(new_propp->prop_name, name_buf_len);
3321				kmem_free(new_propp, sizeof (ddi_prop_t));
3322				cmn_err(CE_CONT, prop_no_mem_msg, name);
3323				return (DDI_PROP_NO_MEMORY);
3324			}
3325			bcopy(value, new_propp->prop_val, length);
3326		}
3327	}
3328
3329	/*
3330	 * Link property into beginning of list. (Properties are LIFO order.)
3331	 */
3332
3333	mutex_enter(&(DEVI(dip)->devi_lock));
3334	propp = *list_head;
3335	new_propp->prop_next = propp;
3336	*list_head = new_propp;
3337	mutex_exit(&(DEVI(dip)->devi_lock));
3338	return (DDI_PROP_SUCCESS);
3339}
3340
3341
3342/*
3343 * ddi_prop_change:	Modify a software managed property value
3344 *
3345 *			Set new length and value if found.
3346 *			returns DDI_PROP_INVAL_ARG if dev is DDI_DEV_T_ANY or
3347 *			input name is the NULL string.
3348 *			returns DDI_PROP_NO_MEMORY if unable to allocate memory
3349 *
3350 *			Note: an undef can be modified to be a define,
3351 *			(you can't go the other way.)
3352 */
3353
3354static int
3355ddi_prop_change(dev_t dev, dev_info_t *dip, int flags,
3356    char *name, caddr_t value, int length)
3357{
3358	ddi_prop_t	*propp;
3359	ddi_prop_t	**ppropp;
3360	caddr_t		p = NULL;
3361
3362	if ((dev == DDI_DEV_T_ANY) || (name == NULL) || (strlen(name) == 0))
3363		return (DDI_PROP_INVAL_ARG);
3364
3365	/*
3366	 * Preallocate buffer, even if we don't need it...
3367	 */
3368	if (length != 0)  {
3369		p = kmem_alloc(length, (flags & DDI_PROP_CANSLEEP) ?
3370		    KM_SLEEP : KM_NOSLEEP);
3371		if (p == NULL)	{
3372			cmn_err(CE_CONT, prop_no_mem_msg, name);
3373			return (DDI_PROP_NO_MEMORY);
3374		}
3375	}
3376
3377	/*
3378	 * If the dev_t value contains DDI_MAJOR_T_UNKNOWN for the major
3379	 * number, a real dev_t value should be created based upon the dip's
3380	 * binding driver.  See ddi_prop_add...
3381	 */
3382	if (getmajor(dev) == DDI_MAJOR_T_UNKNOWN)
3383		dev = makedevice(
3384		    ddi_name_to_major(DEVI(dip)->devi_binding_name),
3385		    getminor(dev));
3386
3387	/*
3388	 * Check to see if the property exists.  If so we modify it.
3389	 * Else we create it by calling ddi_prop_add().
3390	 */
3391	mutex_enter(&(DEVI(dip)->devi_lock));
3392	ppropp = &DEVI(dip)->devi_drv_prop_ptr;
3393	if (flags & DDI_PROP_SYSTEM_DEF)
3394		ppropp = &DEVI(dip)->devi_sys_prop_ptr;
3395	else if (flags & DDI_PROP_HW_DEF)
3396		ppropp = &DEVI(dip)->devi_hw_prop_ptr;
3397
3398	if ((propp = i_ddi_prop_search(dev, name, flags, ppropp)) != NULL) {
3399		/*
3400		 * Need to reallocate buffer?  If so, do it
3401		 * carefully (reuse same space if new prop
3402		 * is same size and non-NULL sized).
3403		 */
3404		if (length != 0)
3405			bcopy(value, p, length);
3406
3407		if (propp->prop_len != 0)
3408			kmem_free(propp->prop_val, propp->prop_len);
3409
3410		propp->prop_len = length;
3411		propp->prop_val = p;
3412		propp->prop_flags &= ~DDI_PROP_UNDEF_IT;
3413		mutex_exit(&(DEVI(dip)->devi_lock));
3414		return (DDI_PROP_SUCCESS);
3415	}
3416
3417	mutex_exit(&(DEVI(dip)->devi_lock));
3418	if (length != 0)
3419		kmem_free(p, length);
3420
3421	return (ddi_prop_add(dev, dip, flags, name, value, length));
3422}
3423
3424/*
3425 * Common update routine used to update and encode a property.	Creates
3426 * a property handle, calls the property encode routine, figures out if
3427 * the property already exists and updates if it does.	Otherwise it
3428 * creates if it does not exist.
3429 */
3430int
3431ddi_prop_update_common(dev_t match_dev, dev_info_t *dip, int flags,
3432    char *name, void *data, uint_t nelements,
3433    int (*prop_create)(prop_handle_t *, void *data, uint_t nelements))
3434{
3435	prop_handle_t	ph;
3436	int		rval;
3437	uint_t		ourflags;
3438
3439	/*
3440	 * If dev_t is DDI_DEV_T_ANY or name's length is zero,
3441	 * return error.
3442	 */
3443	if (match_dev == DDI_DEV_T_ANY || name == NULL || strlen(name) == 0)
3444		return (DDI_PROP_INVAL_ARG);
3445
3446	/*
3447	 * Create the handle
3448	 */
3449	ph.ph_data = NULL;
3450	ph.ph_cur_pos = NULL;
3451	ph.ph_save_pos = NULL;
3452	ph.ph_size = 0;
3453	ph.ph_ops = &prop_1275_ops;
3454
3455	/*
3456	 * ourflags:
3457	 * For compatibility with the old interfaces.  The old interfaces
3458	 * didn't sleep by default and slept when the flag was set.  These
3459	 * interfaces to the opposite.	So the old interfaces now set the
3460	 * DDI_PROP_DONTSLEEP flag by default which tells us not to sleep.
3461	 *
3462	 * ph.ph_flags:
3463	 * Blocked data or unblocked data allocation
3464	 * for ph.ph_data in ddi_prop_encode_alloc()
3465	 */
3466	if (flags & DDI_PROP_DONTSLEEP) {
3467		ourflags = flags;
3468		ph.ph_flags = DDI_PROP_DONTSLEEP;
3469	} else {
3470		ourflags = flags | DDI_PROP_CANSLEEP;
3471		ph.ph_flags = DDI_PROP_CANSLEEP;
3472	}
3473
3474	/*
3475	 * Encode the data and store it in the property handle by
3476	 * calling the prop_encode routine.
3477	 */
3478	if ((rval = (*prop_create)(&ph, data, nelements)) !=
3479	    DDI_PROP_SUCCESS) {
3480		if (rval == DDI_PROP_NO_MEMORY)
3481			cmn_err(CE_CONT, prop_no_mem_msg, name);
3482		if (ph.ph_size != 0)
3483			kmem_free(ph.ph_data, ph.ph_size);
3484		return (rval);
3485	}
3486
3487	/*
3488	 * The old interfaces use a stacking approach to creating
3489	 * properties.	If we are being called from the old interfaces,
3490	 * the DDI_PROP_STACK_CREATE flag will be set, so we just do a
3491	 * create without checking.
3492	 */
3493	if (flags & DDI_PROP_STACK_CREATE) {
3494		rval = ddi_prop_add(match_dev, dip,
3495		    ourflags, name, ph.ph_data, ph.ph_size);
3496	} else {
3497		rval = ddi_prop_change(match_dev, dip,
3498		    ourflags, name, ph.ph_data, ph.ph_size);
3499	}
3500
3501	/*
3502	 * Free the encoded data allocated in the prop_encode routine.
3503	 */
3504	if (ph.ph_size != 0)
3505		kmem_free(ph.ph_data, ph.ph_size);
3506
3507	return (rval);
3508}
3509
3510
3511/*
3512 * ddi_prop_create:	Define a managed property:
3513 *			See above for details.
3514 */
3515
3516int
3517ddi_prop_create(dev_t dev, dev_info_t *dip, int flag,
3518    char *name, caddr_t value, int length)
3519{
3520	if (!(flag & DDI_PROP_CANSLEEP)) {
3521		flag |= DDI_PROP_DONTSLEEP;
3522#ifdef DDI_PROP_DEBUG
3523		if (length != 0)
3524			cmn_err(CE_NOTE, "!ddi_prop_create: interface obsolete,"
3525			    "use ddi_prop_update (prop = %s, node = %s%d)",
3526			    name, ddi_driver_name(dip), ddi_get_instance(dip));
3527#endif /* DDI_PROP_DEBUG */
3528	}
3529	flag &= ~DDI_PROP_SYSTEM_DEF;
3530	flag |= DDI_PROP_STACK_CREATE | DDI_PROP_TYPE_ANY;
3531	return (ddi_prop_update_common(dev, dip, flag, name,
3532	    value, length, ddi_prop_fm_encode_bytes));
3533}
3534
3535int
3536e_ddi_prop_create(dev_t dev, dev_info_t *dip, int flag,
3537    char *name, caddr_t value, int length)
3538{
3539	if (!(flag & DDI_PROP_CANSLEEP))
3540		flag |= DDI_PROP_DONTSLEEP;
3541	flag |= DDI_PROP_SYSTEM_DEF | DDI_PROP_STACK_CREATE | DDI_PROP_TYPE_ANY;
3542	return (ddi_prop_update_common(dev, dip, flag,
3543	    name, value, length, ddi_prop_fm_encode_bytes));
3544}
3545
3546int
3547ddi_prop_modify(dev_t dev, dev_info_t *dip, int flag,
3548    char *name, caddr_t value, int length)
3549{
3550	ASSERT((flag & DDI_PROP_TYPE_MASK) == 0);
3551
3552	/*
3553	 * If dev_t is DDI_DEV_T_ANY or name's length is zero,
3554	 * return error.
3555	 */
3556	if (dev == DDI_DEV_T_ANY || name == NULL || strlen(name) == 0)
3557		return (DDI_PROP_INVAL_ARG);
3558
3559	if (!(flag & DDI_PROP_CANSLEEP))
3560		flag |= DDI_PROP_DONTSLEEP;
3561	flag &= ~DDI_PROP_SYSTEM_DEF;
3562	if (ddi_prop_exists(dev, dip, (flag | DDI_PROP_NOTPROM), name) == 0)
3563		return (DDI_PROP_NOT_FOUND);
3564
3565	return (ddi_prop_update_common(dev, dip,
3566	    (flag | DDI_PROP_TYPE_BYTE), name,
3567	    value, length, ddi_prop_fm_encode_bytes));
3568}
3569
3570int
3571e_ddi_prop_modify(dev_t dev, dev_info_t *dip, int flag,
3572    char *name, caddr_t value, int length)
3573{
3574	ASSERT((flag & DDI_PROP_TYPE_MASK) == 0);
3575
3576	/*
3577	 * If dev_t is DDI_DEV_T_ANY or name's length is zero,
3578	 * return error.
3579	 */
3580	if (dev == DDI_DEV_T_ANY || name == NULL || strlen(name) == 0)
3581		return (DDI_PROP_INVAL_ARG);
3582
3583	if (ddi_prop_exists(dev, dip, (flag | DDI_PROP_SYSTEM_DEF), name) == 0)
3584		return (DDI_PROP_NOT_FOUND);
3585
3586	if (!(flag & DDI_PROP_CANSLEEP))
3587		flag |= DDI_PROP_DONTSLEEP;
3588	return (ddi_prop_update_common(dev, dip,
3589	    (flag | DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_BYTE),
3590	    name, value, length, ddi_prop_fm_encode_bytes));
3591}
3592
3593
3594/*
3595 * Common lookup routine used to lookup and decode a property.
3596 * Creates a property handle, searches for the raw encoded data,
3597 * fills in the handle, and calls the property decode functions
3598 * passed in.
3599 *
3600 * This routine is not static because ddi_bus_prop_op() which lives in
3601 * ddi_impl.c calls it.  No driver should be calling this routine.
3602 */
3603int
3604ddi_prop_lookup_common(dev_t match_dev, dev_info_t *dip,
3605    uint_t flags, char *name, void *data, uint_t *nelements,
3606    int (*prop_decoder)(prop_handle_t *, void *data, uint_t *nelements))
3607{
3608	int		rval;
3609	uint_t		ourflags;
3610	prop_handle_t	ph;
3611
3612	if ((match_dev == DDI_DEV_T_NONE) ||
3613	    (name == NULL) || (strlen(name) == 0))
3614		return (DDI_PROP_INVAL_ARG);
3615
3616	ourflags = (flags & DDI_PROP_DONTSLEEP) ? flags :
3617	    flags | DDI_PROP_CANSLEEP;
3618
3619	/*
3620	 * Get the encoded data
3621	 */
3622	bzero(&ph, sizeof (prop_handle_t));
3623
3624	if ((flags & DDI_UNBND_DLPI2) || (flags & DDI_PROP_ROOTNEX_GLOBAL)) {
3625		/*
3626		 * For rootnex and unbound dlpi style-2 devices, index into
3627		 * the devnames' array and search the global
3628		 * property list.
3629		 */
3630		ourflags &= ~DDI_UNBND_DLPI2;
3631		rval = i_ddi_prop_search_global(match_dev,
3632		    ourflags, name, &ph.ph_data, &ph.ph_size);
3633	} else {
3634		rval = ddi_prop_search_common(match_dev, dip,
3635		    PROP_LEN_AND_VAL_ALLOC, ourflags, name,
3636		    &ph.ph_data, &ph.ph_size);
3637
3638	}
3639
3640	if (rval != DDI_PROP_SUCCESS && rval != DDI_PROP_FOUND_1275) {
3641		ASSERT(ph.ph_data == NULL);
3642		ASSERT(ph.ph_size == 0);
3643		return (rval);
3644	}
3645
3646	/*
3647	 * If the encoded data came from a OBP or software
3648	 * use the 1275 OBP decode/encode routines.
3649	 */
3650	ph.ph_cur_pos = ph.ph_data;
3651	ph.ph_save_pos = ph.ph_data;
3652	ph.ph_ops = &prop_1275_ops;
3653	ph.ph_flags = (rval == DDI_PROP_FOUND_1275) ? PH_FROM_PROM : 0;
3654
3655	rval = (*prop_decoder)(&ph, data, nelements);
3656
3657	/*
3658	 * Free the encoded data
3659	 */
3660	if (ph.ph_size != 0)
3661		kmem_free(ph.ph_data, ph.ph_size);
3662
3663	return (rval);
3664}
3665
3666/*
3667 * Lookup and return an array of composite properties.  The driver must
3668 * provide the decode routine.
3669 */
3670int
3671ddi_prop_lookup(dev_t match_dev, dev_info_t *dip,
3672    uint_t flags, char *name, void *data, uint_t *nelements,
3673    int (*prop_decoder)(prop_handle_t *, void *data, uint_t *nelements))
3674{
3675	return (ddi_prop_lookup_common(match_dev, dip,
3676	    (flags | DDI_PROP_TYPE_COMPOSITE), name,
3677	    data, nelements, prop_decoder));
3678}
3679
3680/*
3681 * Return 1 if a property exists (no type checking done).
3682 * Return 0 if it does not exist.
3683 */
3684int
3685ddi_prop_exists(dev_t match_dev, dev_info_t *dip, uint_t flags, char *name)
3686{
3687	int	i;
3688	uint_t	x = 0;
3689
3690	i = ddi_prop_search_common(match_dev, dip, PROP_EXISTS,
3691	    flags | DDI_PROP_TYPE_MASK, name, NULL, &x);
3692	return (i == DDI_PROP_SUCCESS || i == DDI_PROP_FOUND_1275);
3693}
3694
3695
3696/*
3697 * Update an array of composite properties.  The driver must
3698 * provide the encode routine.
3699 */
3700int
3701ddi_prop_update(dev_t match_dev, dev_info_t *dip,
3702    char *name, void *data, uint_t nelements,
3703    int (*prop_create)(prop_handle_t *, void *data, uint_t nelements))
3704{
3705	return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_COMPOSITE,
3706	    name, data, nelements, prop_create));
3707}
3708
3709/*
3710 * Get a single integer or boolean property and return it.
3711 * If the property does not exists, or cannot be decoded,
3712 * then return the defvalue passed in.
3713 *
3714 * This routine always succeeds.
3715 */
3716int
3717ddi_prop_get_int(dev_t match_dev, dev_info_t *dip, uint_t flags,
3718    char *name, int defvalue)
3719{
3720	int	data;
3721	uint_t	nelements;
3722	int	rval;
3723
3724	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3725	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
3726#ifdef DEBUG
3727		if (dip != NULL) {
3728			cmn_err(CE_WARN, "ddi_prop_get_int: invalid flag"
3729			    " 0x%x (prop = %s, node = %s%d)", flags,
3730			    name, ddi_driver_name(dip), ddi_get_instance(dip));
3731		}
3732#endif /* DEBUG */
3733		flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3734		    LDI_DEV_T_ANY | DDI_UNBND_DLPI2;
3735	}
3736
3737	if ((rval = ddi_prop_lookup_common(match_dev, dip,
3738	    (flags | DDI_PROP_TYPE_INT), name, &data, &nelements,
3739	    ddi_prop_fm_decode_int)) != DDI_PROP_SUCCESS) {
3740		if (rval == DDI_PROP_END_OF_DATA)
3741			data = 1;
3742		else
3743			data = defvalue;
3744	}
3745	return (data);
3746}
3747
3748/*
3749 * Get a single 64 bit integer or boolean property and return it.
3750 * If the property does not exists, or cannot be decoded,
3751 * then return the defvalue passed in.
3752 *
3753 * This routine always succeeds.
3754 */
3755int64_t
3756ddi_prop_get_int64(dev_t match_dev, dev_info_t *dip, uint_t flags,
3757    char *name, int64_t defvalue)
3758{
3759	int64_t	data;
3760	uint_t	nelements;
3761	int	rval;
3762
3763	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3764	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
3765#ifdef DEBUG
3766		if (dip != NULL) {
3767			cmn_err(CE_WARN, "ddi_prop_get_int64: invalid flag"
3768			    " 0x%x (prop = %s, node = %s%d)", flags,
3769			    name, ddi_driver_name(dip), ddi_get_instance(dip));
3770		}
3771#endif /* DEBUG */
3772		return (DDI_PROP_INVAL_ARG);
3773	}
3774
3775	if ((rval = ddi_prop_lookup_common(match_dev, dip,
3776	    (flags | DDI_PROP_TYPE_INT64 | DDI_PROP_NOTPROM),
3777	    name, &data, &nelements, ddi_prop_fm_decode_int64))
3778	    != DDI_PROP_SUCCESS) {
3779		if (rval == DDI_PROP_END_OF_DATA)
3780			data = 1;
3781		else
3782			data = defvalue;
3783	}
3784	return (data);
3785}
3786
3787/*
3788 * Get an array of integer property
3789 */
3790int
3791ddi_prop_lookup_int_array(dev_t match_dev, dev_info_t *dip, uint_t flags,
3792    char *name, int **data, uint_t *nelements)
3793{
3794	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3795	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
3796#ifdef DEBUG
3797		if (dip != NULL) {
3798			cmn_err(CE_WARN, "ddi_prop_lookup_int_array: "
3799			    "invalid flag 0x%x (prop = %s, node = %s%d)",
3800			    flags, name, ddi_driver_name(dip),
3801			    ddi_get_instance(dip));
3802		}
3803#endif /* DEBUG */
3804		flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3805		    LDI_DEV_T_ANY | DDI_UNBND_DLPI2;
3806	}
3807
3808	return (ddi_prop_lookup_common(match_dev, dip,
3809	    (flags | DDI_PROP_TYPE_INT), name, data,
3810	    nelements, ddi_prop_fm_decode_ints));
3811}
3812
3813/*
3814 * Get an array of 64 bit integer properties
3815 */
3816int
3817ddi_prop_lookup_int64_array(dev_t match_dev, dev_info_t *dip, uint_t flags,
3818    char *name, int64_t **data, uint_t *nelements)
3819{
3820	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3821	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
3822#ifdef DEBUG
3823		if (dip != NULL) {
3824			cmn_err(CE_WARN, "ddi_prop_lookup_int64_array: "
3825			    "invalid flag 0x%x (prop = %s, node = %s%d)",
3826			    flags, name, ddi_driver_name(dip),
3827			    ddi_get_instance(dip));
3828		}
3829#endif /* DEBUG */
3830		return (DDI_PROP_INVAL_ARG);
3831	}
3832
3833	return (ddi_prop_lookup_common(match_dev, dip,
3834	    (flags | DDI_PROP_TYPE_INT64 | DDI_PROP_NOTPROM),
3835	    name, data, nelements, ddi_prop_fm_decode_int64_array));
3836}
3837
3838/*
3839 * Update a single integer property.  If the property exists on the drivers
3840 * property list it updates, else it creates it.
3841 */
3842int
3843ddi_prop_update_int(dev_t match_dev, dev_info_t *dip,
3844    char *name, int data)
3845{
3846	return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_INT,
3847	    name, &data, 1, ddi_prop_fm_encode_ints));
3848}
3849
3850/*
3851 * Update a single 64 bit integer property.
3852 * Update the driver property list if it exists, else create it.
3853 */
3854int
3855ddi_prop_update_int64(dev_t match_dev, dev_info_t *dip,
3856    char *name, int64_t data)
3857{
3858	return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_INT64,
3859	    name, &data, 1, ddi_prop_fm_encode_int64));
3860}
3861
3862int
3863e_ddi_prop_update_int(dev_t match_dev, dev_info_t *dip,
3864    char *name, int data)
3865{
3866	return (ddi_prop_update_common(match_dev, dip,
3867	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_INT,
3868	    name, &data, 1, ddi_prop_fm_encode_ints));
3869}
3870
3871int
3872e_ddi_prop_update_int64(dev_t match_dev, dev_info_t *dip,
3873    char *name, int64_t data)
3874{
3875	return (ddi_prop_update_common(match_dev, dip,
3876	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_INT64,
3877	    name, &data, 1, ddi_prop_fm_encode_int64));
3878}
3879
3880/*
3881 * Update an array of integer property.  If the property exists on the drivers
3882 * property list it updates, else it creates it.
3883 */
3884int
3885ddi_prop_update_int_array(dev_t match_dev, dev_info_t *dip,
3886    char *name, int *data, uint_t nelements)
3887{
3888	return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_INT,
3889	    name, data, nelements, ddi_prop_fm_encode_ints));
3890}
3891
3892/*
3893 * Update an array of 64 bit integer properties.
3894 * Update the driver property list if it exists, else create it.
3895 */
3896int
3897ddi_prop_update_int64_array(dev_t match_dev, dev_info_t *dip,
3898    char *name, int64_t *data, uint_t nelements)
3899{
3900	return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_INT64,
3901	    name, data, nelements, ddi_prop_fm_encode_int64));
3902}
3903
3904int
3905e_ddi_prop_update_int64_array(dev_t match_dev, dev_info_t *dip,
3906    char *name, int64_t *data, uint_t nelements)
3907{
3908	return (ddi_prop_update_common(match_dev, dip,
3909	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_INT64,
3910	    name, data, nelements, ddi_prop_fm_encode_int64));
3911}
3912
3913int
3914e_ddi_prop_update_int_array(dev_t match_dev, dev_info_t *dip,
3915    char *name, int *data, uint_t nelements)
3916{
3917	return (ddi_prop_update_common(match_dev, dip,
3918	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_INT,
3919	    name, data, nelements, ddi_prop_fm_encode_ints));
3920}
3921
3922/*
3923 * Get a single string property.
3924 */
3925int
3926ddi_prop_lookup_string(dev_t match_dev, dev_info_t *dip, uint_t flags,
3927    char *name, char **data)
3928{
3929	uint_t x;
3930
3931	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3932	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
3933#ifdef DEBUG
3934		if (dip != NULL) {
3935			cmn_err(CE_WARN, "%s: invalid flag 0x%x "
3936			    "(prop = %s, node = %s%d); invalid bits ignored",
3937			    "ddi_prop_lookup_string", flags, name,
3938			    ddi_driver_name(dip), ddi_get_instance(dip));
3939		}
3940#endif /* DEBUG */
3941		flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3942		    LDI_DEV_T_ANY | DDI_UNBND_DLPI2;
3943	}
3944
3945	return (ddi_prop_lookup_common(match_dev, dip,
3946	    (flags | DDI_PROP_TYPE_STRING), name, data,
3947	    &x, ddi_prop_fm_decode_string));
3948}
3949
3950/*
3951 * Get an array of strings property.
3952 */
3953int
3954ddi_prop_lookup_string_array(dev_t match_dev, dev_info_t *dip, uint_t flags,
3955    char *name, char ***data, uint_t *nelements)
3956{
3957	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3958	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
3959#ifdef DEBUG
3960		if (dip != NULL) {
3961			cmn_err(CE_WARN, "ddi_prop_lookup_string_array: "
3962			    "invalid flag 0x%x (prop = %s, node = %s%d)",
3963			    flags, name, ddi_driver_name(dip),
3964			    ddi_get_instance(dip));
3965		}
3966#endif /* DEBUG */
3967		flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3968		    LDI_DEV_T_ANY | DDI_UNBND_DLPI2;
3969	}
3970
3971	return (ddi_prop_lookup_common(match_dev, dip,
3972	    (flags | DDI_PROP_TYPE_STRING), name, data,
3973	    nelements, ddi_prop_fm_decode_strings));
3974}
3975
3976/*
3977 * Update a single string property.
3978 */
3979int
3980ddi_prop_update_string(dev_t match_dev, dev_info_t *dip,
3981    char *name, char *data)
3982{
3983	return (ddi_prop_update_common(match_dev, dip,
3984	    DDI_PROP_TYPE_STRING, name, &data, 1,
3985	    ddi_prop_fm_encode_string));
3986}
3987
3988int
3989e_ddi_prop_update_string(dev_t match_dev, dev_info_t *dip,
3990    char *name, char *data)
3991{
3992	return (ddi_prop_update_common(match_dev, dip,
3993	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_STRING,
3994	    name, &data, 1, ddi_prop_fm_encode_string));
3995}
3996
3997
3998/*
3999 * Update an array of strings property.
4000 */
4001int
4002ddi_prop_update_string_array(dev_t match_dev, dev_info_t *dip,
4003    char *name, char **data, uint_t nelements)
4004{
4005	return (ddi_prop_update_common(match_dev, dip,
4006	    DDI_PROP_TYPE_STRING, name, data, nelements,
4007	    ddi_prop_fm_encode_strings));
4008}
4009
4010int
4011e_ddi_prop_update_string_array(dev_t match_dev, dev_info_t *dip,
4012    char *name, char **data, uint_t nelements)
4013{
4014	return (ddi_prop_update_common(match_dev, dip,
4015	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_STRING,
4016	    name, data, nelements,
4017	    ddi_prop_fm_encode_strings));
4018}
4019
4020
4021/*
4022 * Get an array of bytes property.
4023 */
4024int
4025ddi_prop_lookup_byte_array(dev_t match_dev, dev_info_t *dip, uint_t flags,
4026    char *name, uchar_t **data, uint_t *nelements)
4027{
4028	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
4029	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
4030#ifdef DEBUG
4031		if (dip != NULL) {
4032			cmn_err(CE_WARN, "ddi_prop_lookup_byte_array: "
4033			    " invalid flag 0x%x (prop = %s, node = %s%d)",
4034			    flags, name, ddi_driver_name(dip),
4035			    ddi_get_instance(dip));
4036		}
4037#endif /* DEBUG */
4038		flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
4039		    LDI_DEV_T_ANY | DDI_UNBND_DLPI2;
4040	}
4041
4042	return (ddi_prop_lookup_common(match_dev, dip,
4043	    (flags | DDI_PROP_TYPE_BYTE), name, data,
4044	    nelements, ddi_prop_fm_decode_bytes));
4045}
4046
4047/*
4048 * Update an array of bytes property.
4049 */
4050int
4051ddi_prop_update_byte_array(dev_t match_dev, dev_info_t *dip,
4052    char *name, uchar_t *data, uint_t nelements)
4053{
4054	if (nelements == 0)
4055		return (DDI_PROP_INVAL_ARG);
4056
4057	return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_BYTE,
4058	    name, data, nelements, ddi_prop_fm_encode_bytes));
4059}
4060
4061
4062int
4063e_ddi_prop_update_byte_array(dev_t match_dev, dev_info_t *dip,
4064    char *name, uchar_t *data, uint_t nelements)
4065{
4066	if (nelements == 0)
4067		return (DDI_PROP_INVAL_ARG);
4068
4069	return (ddi_prop_update_common(match_dev, dip,
4070	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_BYTE,
4071	    name, data, nelements, ddi_prop_fm_encode_bytes));
4072}
4073
4074
4075/*
4076 * ddi_prop_remove_common:	Undefine a managed property:
4077 *			Input dev_t must match dev_t when defined.
4078 *			Returns DDI_PROP_NOT_FOUND, possibly.
4079 *			DDI_PROP_INVAL_ARG is also possible if dev is
4080 *			DDI_DEV_T_ANY or incoming name is the NULL string.
4081 */
4082int
4083ddi_prop_remove_common(dev_t dev, dev_info_t *dip, char *name, int flag)
4084{
4085	ddi_prop_t	**list_head = &(DEVI(dip)->devi_drv_prop_ptr);
4086	ddi_prop_t	*propp;
4087	ddi_prop_t	*lastpropp = NULL;
4088
4089	if ((dev == DDI_DEV_T_ANY) || (name == (char *)0) ||
4090	    (strlen(name) == 0)) {
4091		return (DDI_PROP_INVAL_ARG);
4092	}
4093
4094	if (flag & DDI_PROP_SYSTEM_DEF)
4095		list_head = &(DEVI(dip)->devi_sys_prop_ptr);
4096	else if (flag & DDI_PROP_HW_DEF)
4097		list_head = &(DEVI(dip)->devi_hw_prop_ptr);
4098
4099	mutex_enter(&(DEVI(dip)->devi_lock));
4100
4101	for (propp = *list_head; propp != NULL; propp = propp->prop_next)  {
4102		if (DDI_STRSAME(propp->prop_name, name) &&
4103		    (dev == propp->prop_dev)) {
4104			/*
4105			 * Unlink this propp allowing for it to
4106			 * be first in the list:
4107			 */
4108
4109			if (lastpropp == NULL)
4110				*list_head = propp->prop_next;
4111			else
4112				lastpropp->prop_next = propp->prop_next;
4113
4114			mutex_exit(&(DEVI(dip)->devi_lock));
4115
4116			/*
4117			 * Free memory and return...
4118			 */
4119			kmem_free(propp->prop_name,
4120			    strlen(propp->prop_name) + 1);
4121			if (propp->prop_len != 0)
4122				kmem_free(propp->prop_val, propp->prop_len);
4123			kmem_free(propp, sizeof (ddi_prop_t));
4124			return (DDI_PROP_SUCCESS);
4125		}
4126		lastpropp = propp;
4127	}
4128	mutex_exit(&(DEVI(dip)->devi_lock));
4129	return (DDI_PROP_NOT_FOUND);
4130}
4131
4132int
4133ddi_prop_remove(dev_t dev, dev_info_t *dip, char *name)
4134{
4135	return (ddi_prop_remove_common(dev, dip, name, 0));
4136}
4137
4138int
4139e_ddi_prop_remove(dev_t dev, dev_info_t *dip, char *name)
4140{
4141	return (ddi_prop_remove_common(dev, dip, name, DDI_PROP_SYSTEM_DEF));
4142}
4143
4144/*
4145 * e_ddi_prop_list_delete: remove a list of properties
4146 *	Note that the caller needs to provide the required protection
4147 *	(eg. devi_lock if these properties are still attached to a devi)
4148 */
4149void
4150e_ddi_prop_list_delete(ddi_prop_t *props)
4151{
4152	i_ddi_prop_list_delete(props);
4153}
4154
4155/*
4156 * ddi_prop_remove_all_common:
4157 *	Used before unloading a driver to remove
4158 *	all properties. (undefines all dev_t's props.)
4159 *	Also removes `explicitly undefined' props.
4160 *	No errors possible.
4161 */
4162void
4163ddi_prop_remove_all_common(dev_info_t *dip, int flag)
4164{
4165	ddi_prop_t	**list_head;
4166
4167	mutex_enter(&(DEVI(dip)->devi_lock));
4168	if (flag & DDI_PROP_SYSTEM_DEF) {
4169		list_head = &(DEVI(dip)->devi_sys_prop_ptr);
4170	} else if (flag & DDI_PROP_HW_DEF) {
4171		list_head = &(DEVI(dip)->devi_hw_prop_ptr);
4172	} else {
4173		list_head = &(DEVI(dip)->devi_drv_prop_ptr);
4174	}
4175	i_ddi_prop_list_delete(*list_head);
4176	*list_head = NULL;
4177	mutex_exit(&(DEVI(dip)->devi_lock));
4178}
4179
4180
4181/*
4182 * ddi_prop_remove_all:		Remove all driver prop definitions.
4183 */
4184
4185void
4186ddi_prop_remove_all(dev_info_t *dip)
4187{
4188	i_ddi_prop_dyn_driver_set(dip, NULL);
4189	ddi_prop_remove_all_common(dip, 0);
4190}
4191
4192/*
4193 * e_ddi_prop_remove_all:	Remove all system prop definitions.
4194 */
4195
4196void
4197e_ddi_prop_remove_all(dev_info_t *dip)
4198{
4199	ddi_prop_remove_all_common(dip, (int)DDI_PROP_SYSTEM_DEF);
4200}
4201
4202
4203/*
4204 * ddi_prop_undefine:	Explicitly undefine a property.  Property
4205 *			searches which match this property return
4206 *			the error code DDI_PROP_UNDEFINED.
4207 *
4208 *			Use ddi_prop_remove to negate effect of
4209 *			ddi_prop_undefine
4210 *
4211 *			See above for error returns.
4212 */
4213
4214int
4215ddi_prop_undefine(dev_t dev, dev_info_t *dip, int flag, char *name)
4216{
4217	if (!(flag & DDI_PROP_CANSLEEP))
4218		flag |= DDI_PROP_DONTSLEEP;
4219	flag |= DDI_PROP_STACK_CREATE | DDI_PROP_UNDEF_IT | DDI_PROP_TYPE_ANY;
4220	return (ddi_prop_update_common(dev, dip, flag,
4221	    name, NULL, 0, ddi_prop_fm_encode_bytes));
4222}
4223
4224int
4225e_ddi_prop_undefine(dev_t dev, dev_info_t *dip, int flag, char *name)
4226{
4227	if (!(flag & DDI_PROP_CANSLEEP))
4228		flag |= DDI_PROP_DONTSLEEP;
4229	flag |= DDI_PROP_SYSTEM_DEF | DDI_PROP_STACK_CREATE |
4230	    DDI_PROP_UNDEF_IT | DDI_PROP_TYPE_ANY;
4231	return (ddi_prop_update_common(dev, dip, flag,
4232	    name, NULL, 0, ddi_prop_fm_encode_bytes));
4233}
4234
4235/*
4236 * Support for gathering dynamic properties in devinfo snapshot.
4237 */
4238void
4239i_ddi_prop_dyn_driver_set(dev_info_t *dip, i_ddi_prop_dyn_t *dp)
4240{
4241	DEVI(dip)->devi_prop_dyn_driver = dp;
4242}
4243
4244i_ddi_prop_dyn_t *
4245i_ddi_prop_dyn_driver_get(dev_info_t *dip)
4246{
4247	return (DEVI(dip)->devi_prop_dyn_driver);
4248}
4249
4250void
4251i_ddi_prop_dyn_parent_set(dev_info_t *dip, i_ddi_prop_dyn_t *dp)
4252{
4253	DEVI(dip)->devi_prop_dyn_parent = dp;
4254}
4255
4256i_ddi_prop_dyn_t *
4257i_ddi_prop_dyn_parent_get(dev_info_t *dip)
4258{
4259	return (DEVI(dip)->devi_prop_dyn_parent);
4260}
4261
4262void
4263i_ddi_prop_dyn_cache_invalidate(dev_info_t *dip, i_ddi_prop_dyn_t *dp)
4264{
4265	/* for now we invalidate the entire cached snapshot */
4266	if (dip && dp)
4267		i_ddi_di_cache_invalidate();
4268}
4269
4270/* ARGSUSED */
4271void
4272ddi_prop_cache_invalidate(dev_t dev, dev_info_t *dip, char *name, int flags)
4273{
4274	/* for now we invalidate the entire cached snapshot */
4275	i_ddi_di_cache_invalidate();
4276}
4277
4278
4279/*
4280 * Code to search hardware layer (PROM), if it exists, on behalf of child.
4281 *
4282 * if input dip != child_dip, then call is on behalf of child
4283 * to search PROM, do it via ddi_prop_search_common() and ascend only
4284 * if allowed.
4285 *
4286 * if input dip == ch_dip (child_dip), call is on behalf of root driver,
4287 * to search for PROM defined props only.
4288 *
4289 * Note that the PROM search is done only if the requested dev
4290 * is either DDI_DEV_T_ANY or DDI_DEV_T_NONE. PROM properties
4291 * have no associated dev, thus are automatically associated with
4292 * DDI_DEV_T_NONE.
4293 *
4294 * Modifying flag DDI_PROP_NOTPROM inhibits the search in the h/w layer.
4295 *
4296 * Returns DDI_PROP_FOUND_1275 if found to indicate to framework
4297 * that the property resides in the prom.
4298 */
4299int
4300impl_ddi_bus_prop_op(dev_t dev, dev_info_t *dip, dev_info_t *ch_dip,
4301    ddi_prop_op_t prop_op, int mod_flags,
4302    char *name, caddr_t valuep, int *lengthp)
4303{
4304	int	len;
4305	caddr_t buffer;
4306
4307	/*
4308	 * If requested dev is DDI_DEV_T_NONE or DDI_DEV_T_ANY, then
4309	 * look in caller's PROM if it's a self identifying device...
4310	 *
4311	 * Note that this is very similar to ddi_prop_op, but we
4312	 * search the PROM instead of the s/w defined properties,
4313	 * and we are called on by the parent driver to do this for
4314	 * the child.
4315	 */
4316
4317	if (((dev == DDI_DEV_T_NONE) || (dev == DDI_DEV_T_ANY)) &&
4318	    ndi_dev_is_prom_node(ch_dip) &&
4319	    ((mod_flags & DDI_PROP_NOTPROM) == 0)) {
4320		len = prom_getproplen((pnode_t)DEVI(ch_dip)->devi_nodeid, name);
4321		if (len == -1) {
4322			return (DDI_PROP_NOT_FOUND);
4323		}
4324
4325		/*
4326		 * If exists only request, we're done
4327		 */
4328		if (prop_op == PROP_EXISTS) {
4329			return (DDI_PROP_FOUND_1275);
4330		}
4331
4332		/*
4333		 * If length only request or prop length == 0, get out
4334		 */
4335		if ((prop_op == PROP_LEN) || (len == 0)) {
4336			*lengthp = len;
4337			return (DDI_PROP_FOUND_1275);
4338		}
4339
4340		/*
4341		 * Allocate buffer if required... (either way `buffer'
4342		 * is receiving address).
4343		 */
4344
4345		switch (prop_op) {
4346
4347		case PROP_LEN_AND_VAL_ALLOC:
4348
4349			buffer = kmem_alloc((size_t)len,
4350			    mod_flags & DDI_PROP_CANSLEEP ?
4351			    KM_SLEEP : KM_NOSLEEP);
4352			if (buffer == NULL) {
4353				return (DDI_PROP_NO_MEMORY);
4354			}
4355			*(caddr_t *)valuep = buffer;
4356			break;
4357
4358		case PROP_LEN_AND_VAL_BUF:
4359
4360			if (len > (*lengthp)) {
4361				*lengthp = len;
4362				return (DDI_PROP_BUF_TOO_SMALL);
4363			}
4364
4365			buffer = valuep;
4366			break;
4367
4368		default:
4369			break;
4370		}
4371
4372		/*
4373		 * Call the PROM function to do the copy.
4374		 */
4375		(void) prom_getprop((pnode_t)DEVI(ch_dip)->devi_nodeid,
4376		    name, buffer);
4377
4378		*lengthp = len; /* return the actual length to the caller */
4379		(void) impl_fix_props(dip, ch_dip, name, len, buffer);
4380		return (DDI_PROP_FOUND_1275);
4381	}
4382
4383	return (DDI_PROP_NOT_FOUND);
4384}
4385
4386/*
4387 * The ddi_bus_prop_op default bus nexus prop op function.
4388 *
4389 * Code to search hardware layer (PROM), if it exists,
4390 * on behalf of child, then, if appropriate, ascend and check
4391 * my own software defined properties...
4392 */
4393int
4394ddi_bus_prop_op(dev_t dev, dev_info_t *dip, dev_info_t *ch_dip,
4395    ddi_prop_op_t prop_op, int mod_flags,
4396    char *name, caddr_t valuep, int *lengthp)
4397{
4398	int	error;
4399
4400	error = impl_ddi_bus_prop_op(dev, dip, ch_dip, prop_op, mod_flags,
4401	    name, valuep, lengthp);
4402
4403	if (error == DDI_PROP_SUCCESS || error == DDI_PROP_FOUND_1275 ||
4404	    error == DDI_PROP_BUF_TOO_SMALL)
4405		return (error);
4406
4407	if (error == DDI_PROP_NO_MEMORY) {
4408		cmn_err(CE_CONT, prop_no_mem_msg, name);
4409		return (DDI_PROP_NO_MEMORY);
4410	}
4411
4412	/*
4413	 * Check the 'options' node as a last resort
4414	 */
4415	if ((mod_flags & DDI_PROP_DONTPASS) != 0)
4416		return (DDI_PROP_NOT_FOUND);
4417
4418	if (ch_dip == ddi_root_node())	{
4419		/*
4420		 * As a last resort, when we've reached
4421		 * the top and still haven't found the
4422		 * property, see if the desired property
4423		 * is attached to the options node.
4424		 *
4425		 * The options dip is attached right after boot.
4426		 */
4427		ASSERT(options_dip != NULL);
4428		/*
4429		 * Force the "don't pass" flag to *just* see
4430		 * what the options node has to offer.
4431		 */
4432		return (ddi_prop_search_common(dev, options_dip, prop_op,
4433		    mod_flags|DDI_PROP_DONTPASS, name, valuep,
4434		    (uint_t *)lengthp));
4435	}
4436
4437	/*
4438	 * Otherwise, continue search with parent's s/w defined properties...
4439	 * NOTE: Using `dip' in following call increments the level.
4440	 */
4441
4442	return (ddi_prop_search_common(dev, dip, prop_op, mod_flags,
4443	    name, valuep, (uint_t *)lengthp));
4444}
4445
4446/*
4447 * External property functions used by other parts of the kernel...
4448 */
4449
4450/*
4451 * e_ddi_getlongprop: See comments for ddi_get_longprop.
4452 */
4453
4454int
4455e_ddi_getlongprop(dev_t dev, vtype_t type, char *name, int flags,
4456    caddr_t valuep, int *lengthp)
4457{
4458	_NOTE(ARGUNUSED(type))
4459	dev_info_t *devi;
4460	ddi_prop_op_t prop_op = PROP_LEN_AND_VAL_ALLOC;
4461	int error;
4462
4463	if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL)
4464		return (DDI_PROP_NOT_FOUND);
4465
4466	error = cdev_prop_op(dev, devi, prop_op, flags, name, valuep, lengthp);
4467	ddi_release_devi(devi);
4468	return (error);
4469}
4470
4471/*
4472 * e_ddi_getlongprop_buf:	See comments for ddi_getlongprop_buf.
4473 */
4474
4475int
4476e_ddi_getlongprop_buf(dev_t dev, vtype_t type, char *name, int flags,
4477    caddr_t valuep, int *lengthp)
4478{
4479	_NOTE(ARGUNUSED(type))
4480	dev_info_t *devi;
4481	ddi_prop_op_t prop_op = PROP_LEN_AND_VAL_BUF;
4482	int error;
4483
4484	if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL)
4485		return (DDI_PROP_NOT_FOUND);
4486
4487	error = cdev_prop_op(dev, devi, prop_op, flags, name, valuep, lengthp);
4488	ddi_release_devi(devi);
4489	return (error);
4490}
4491
4492/*
4493 * e_ddi_getprop:	See comments for ddi_getprop.
4494 */
4495int
4496e_ddi_getprop(dev_t dev, vtype_t type, char *name, int flags, int defvalue)
4497{
4498	_NOTE(ARGUNUSED(type))
4499	dev_info_t *devi;
4500	ddi_prop_op_t prop_op = PROP_LEN_AND_VAL_BUF;
4501	int	propvalue = defvalue;
4502	int	proplength = sizeof (int);
4503	int	error;
4504
4505	if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL)
4506		return (defvalue);
4507
4508	error = cdev_prop_op(dev, devi, prop_op,
4509	    flags, name, (caddr_t)&propvalue, &proplength);
4510	ddi_release_devi(devi);
4511
4512	if ((error == DDI_PROP_SUCCESS) && (proplength == 0))
4513		propvalue = 1;
4514
4515	return (propvalue);
4516}
4517
4518/*
4519 * e_ddi_getprop_int64:
4520 *
4521 * This is a typed interfaces, but predates typed properties. With the
4522 * introduction of typed properties the framework tries to ensure
4523 * consistent use of typed interfaces. This is why TYPE_INT64 is not
4524 * part of TYPE_ANY.  E_ddi_getprop_int64 is a special case where a
4525 * typed interface invokes legacy (non-typed) interfaces:
4526 * cdev_prop_op(), prop_op(9E), ddi_prop_op(9F)).  In this case the
4527 * fact that TYPE_INT64 is not part of TYPE_ANY matters.  To support
4528 * this type of lookup as a single operation we invoke the legacy
4529 * non-typed interfaces with the special CONSUMER_TYPED bit set. The
4530 * framework ddi_prop_op(9F) implementation is expected to check for
4531 * CONSUMER_TYPED and, if set, expand type bits beyond TYPE_ANY
4532 * (currently TYPE_INT64).
4533 */
4534int64_t
4535e_ddi_getprop_int64(dev_t dev, vtype_t type, char *name,
4536    int flags, int64_t defvalue)
4537{
4538	_NOTE(ARGUNUSED(type))
4539	dev_info_t	*devi;
4540	ddi_prop_op_t	prop_op = PROP_LEN_AND_VAL_BUF;
4541	int64_t		propvalue = defvalue;
4542	int		proplength = sizeof (propvalue);
4543	int		error;
4544
4545	if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL)
4546		return (defvalue);
4547
4548	error = cdev_prop_op(dev, devi, prop_op, flags |
4549	    DDI_PROP_CONSUMER_TYPED, name, (caddr_t)&propvalue, &proplength);
4550	ddi_release_devi(devi);
4551
4552	if ((error == DDI_PROP_SUCCESS) && (proplength == 0))
4553		propvalue = 1;
4554
4555	return (propvalue);
4556}
4557
4558/*
4559 * e_ddi_getproplen:	See comments for ddi_getproplen.
4560 */
4561int
4562e_ddi_getproplen(dev_t dev, vtype_t type, char *name, int flags, int *lengthp)
4563{
4564	_NOTE(ARGUNUSED(type))
4565	dev_info_t *devi;
4566	ddi_prop_op_t prop_op = PROP_LEN;
4567	int error;
4568
4569	if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL)
4570		return (DDI_PROP_NOT_FOUND);
4571
4572	error = cdev_prop_op(dev, devi, prop_op, flags, name, NULL, lengthp);
4573	ddi_release_devi(devi);
4574	return (error);
4575}
4576
4577/*
4578 * Routines to get at elements of the dev_info structure
4579 */
4580
4581/*
4582 * ddi_binding_name: Return the driver binding name of the devinfo node
4583 *		This is the name the OS used to bind the node to a driver.
4584 */
4585char *
4586ddi_binding_name(dev_info_t *dip)
4587{
4588	return (DEVI(dip)->devi_binding_name);
4589}
4590
4591/*
4592 * ddi_driver_major: Return the major number of the driver that
4593 *	the supplied devinfo is bound to.  If not yet bound,
4594 *	DDI_MAJOR_T_NONE.
4595 *
4596 * When used by the driver bound to 'devi', this
4597 * function will reliably return the driver major number.
4598 * Other ways of determining the driver major number, such as
4599 *	major = ddi_name_to_major(ddi_get_name(devi));
4600 *	major = ddi_name_to_major(ddi_binding_name(devi));
4601 * can return a different result as the driver/alias binding
4602 * can change dynamically, and thus should be avoided.
4603 */
4604major_t
4605ddi_driver_major(dev_info_t *devi)
4606{
4607	return (DEVI(devi)->devi_major);
4608}
4609
4610/*
4611 * ddi_driver_name: Return the normalized driver name. this is the
4612 *		actual driver name
4613 */
4614const char *
4615ddi_driver_name(dev_info_t *devi)
4616{
4617	major_t major;
4618
4619	if ((major = ddi_driver_major(devi)) != DDI_MAJOR_T_NONE)
4620		return (ddi_major_to_name(major));
4621
4622	return (ddi_node_name(devi));
4623}
4624
4625/*
4626 * i_ddi_set_binding_name:	Set binding name.
4627 *
4628 *	Set the binding name to the given name.
4629 *	This routine is for use by the ddi implementation, not by drivers.
4630 */
4631void
4632i_ddi_set_binding_name(dev_info_t *dip, char *name)
4633{
4634	DEVI(dip)->devi_binding_name = name;
4635
4636}
4637
4638/*
4639 * ddi_get_name: A synonym of ddi_binding_name() ... returns a name
4640 * the implementation has used to bind the node to a driver.
4641 */
4642char *
4643ddi_get_name(dev_info_t *dip)
4644{
4645	return (DEVI(dip)->devi_binding_name);
4646}
4647
4648/*
4649 * ddi_node_name: Return the name property of the devinfo node
4650 *		This may differ from ddi_binding_name if the node name
4651 *		does not define a binding to a driver (i.e. generic names).
4652 */
4653char *
4654ddi_node_name(dev_info_t *dip)
4655{
4656	return (DEVI(dip)->devi_node_name);
4657}
4658
4659
4660/*
4661 * ddi_get_nodeid:	Get nodeid stored in dev_info structure.
4662 */
4663int
4664ddi_get_nodeid(dev_info_t *dip)
4665{
4666	return (DEVI(dip)->devi_nodeid);
4667}
4668
4669int
4670ddi_get_instance(dev_info_t *dip)
4671{
4672	return (DEVI(dip)->devi_instance);
4673}
4674
4675struct dev_ops *
4676ddi_get_driver(dev_info_t *dip)
4677{
4678	return (DEVI(dip)->devi_ops);
4679}
4680
4681void
4682ddi_set_driver(dev_info_t *dip, struct dev_ops *devo)
4683{
4684	DEVI(dip)->devi_ops = devo;
4685}
4686
4687/*
4688 * ddi_set_driver_private/ddi_get_driver_private:
4689 * Get/set device driver private data in devinfo.
4690 */
4691void
4692ddi_set_driver_private(dev_info_t *dip, void *data)
4693{
4694	DEVI(dip)->devi_driver_data = data;
4695}
4696
4697void *
4698ddi_get_driver_private(dev_info_t *dip)
4699{
4700	return (DEVI(dip)->devi_driver_data);
4701}
4702
4703/*
4704 * ddi_get_parent, ddi_get_child, ddi_get_next_sibling
4705 */
4706
4707dev_info_t *
4708ddi_get_parent(dev_info_t *dip)
4709{
4710	return ((dev_info_t *)DEVI(dip)->devi_parent);
4711}
4712
4713dev_info_t *
4714ddi_get_child(dev_info_t *dip)
4715{
4716	return ((dev_info_t *)DEVI(dip)->devi_child);
4717}
4718
4719dev_info_t *
4720ddi_get_next_sibling(dev_info_t *dip)
4721{
4722	return ((dev_info_t *)DEVI(dip)->devi_sibling);
4723}
4724
4725dev_info_t *
4726ddi_get_next(dev_info_t *dip)
4727{
4728	return ((dev_info_t *)DEVI(dip)->devi_next);
4729}
4730
4731void
4732ddi_set_next(dev_info_t *dip, dev_info_t *nextdip)
4733{
4734	DEVI(dip)->devi_next = DEVI(nextdip);
4735}
4736
4737/*
4738 * ddi_root_node:		Return root node of devinfo tree
4739 */
4740
4741dev_info_t *
4742ddi_root_node(void)
4743{
4744	extern dev_info_t *top_devinfo;
4745
4746	return (top_devinfo);
4747}
4748
4749/*
4750 * Miscellaneous functions:
4751 */
4752
4753/*
4754 * Implementation specific hooks
4755 */
4756
4757void
4758ddi_report_dev(dev_info_t *d)
4759{
4760	char *b;
4761
4762	(void) ddi_ctlops(d, d, DDI_CTLOPS_REPORTDEV, (void *)0, (void *)0);
4763
4764	/*
4765	 * If this devinfo node has cb_ops, it's implicitly accessible from
4766	 * userland, so we print its full name together with the instance
4767	 * number 'abbreviation' that the driver may use internally.
4768	 */
4769	if (DEVI(d)->devi_ops->devo_cb_ops != (struct cb_ops *)0 &&
4770	    (b = kmem_zalloc(MAXPATHLEN, KM_NOSLEEP))) {
4771		cmn_err(CE_CONT, "?%s%d is %s\n",
4772		    ddi_driver_name(d), ddi_get_instance(d),
4773		    ddi_pathname(d, b));
4774		kmem_free(b, MAXPATHLEN);
4775	}
4776}
4777
4778/*
4779 * ddi_ctlops() is described in the assembler not to buy a new register
4780 * window when it's called and can reduce cost in climbing the device tree
4781 * without using the tail call optimization.
4782 */
4783int
4784ddi_dev_regsize(dev_info_t *dev, uint_t rnumber, off_t *result)
4785{
4786	int ret;
4787
4788	ret = ddi_ctlops(dev, dev, DDI_CTLOPS_REGSIZE,
4789	    (void *)&rnumber, (void *)result);
4790
4791	return (ret == DDI_SUCCESS ? DDI_SUCCESS : DDI_FAILURE);
4792}
4793
4794int
4795ddi_dev_nregs(dev_info_t *dev, int *result)
4796{
4797	return (ddi_ctlops(dev, dev, DDI_CTLOPS_NREGS, 0, (void *)result));
4798}
4799
4800int
4801ddi_dev_is_sid(dev_info_t *d)
4802{
4803	return (ddi_ctlops(d, d, DDI_CTLOPS_SIDDEV, (void *)0, (void *)0));
4804}
4805
4806int
4807ddi_slaveonly(dev_info_t *d)
4808{
4809	return (ddi_ctlops(d, d, DDI_CTLOPS_SLAVEONLY, (void *)0, (void *)0));
4810}
4811
4812int
4813ddi_dev_affinity(dev_info_t *a, dev_info_t *b)
4814{
4815	return (ddi_ctlops(a, a, DDI_CTLOPS_AFFINITY, (void *)b, (void *)0));
4816}
4817
4818int
4819ddi_streams_driver(dev_info_t *dip)
4820{
4821	if (i_ddi_devi_attached(dip) &&
4822	    (DEVI(dip)->devi_ops->devo_cb_ops != NULL) &&
4823	    (DEVI(dip)->devi_ops->devo_cb_ops->cb_str != NULL))
4824		return (DDI_SUCCESS);
4825	return (DDI_FAILURE);
4826}
4827
4828/*
4829 * callback free list
4830 */
4831
4832static int ncallbacks;
4833static int nc_low = 170;
4834static int nc_med = 512;
4835static int nc_high = 2048;
4836static struct ddi_callback *callbackq;
4837static struct ddi_callback *callbackqfree;
4838
4839/*
4840 * set/run callback lists
4841 */
4842struct	cbstats	{
4843	kstat_named_t	cb_asked;
4844	kstat_named_t	cb_new;
4845	kstat_named_t	cb_run;
4846	kstat_named_t	cb_delete;
4847	kstat_named_t	cb_maxreq;
4848	kstat_named_t	cb_maxlist;
4849	kstat_named_t	cb_alloc;
4850	kstat_named_t	cb_runouts;
4851	kstat_named_t	cb_L2;
4852	kstat_named_t	cb_grow;
4853} cbstats = {
4854	{"asked",	KSTAT_DATA_UINT32},
4855	{"new",		KSTAT_DATA_UINT32},
4856	{"run",		KSTAT_DATA_UINT32},
4857	{"delete",	KSTAT_DATA_UINT32},
4858	{"maxreq",	KSTAT_DATA_UINT32},
4859	{"maxlist",	KSTAT_DATA_UINT32},
4860	{"alloc",	KSTAT_DATA_UINT32},
4861	{"runouts",	KSTAT_DATA_UINT32},
4862	{"L2",		KSTAT_DATA_UINT32},
4863	{"grow",	KSTAT_DATA_UINT32},
4864};
4865
4866#define	nc_asked	cb_asked.value.ui32
4867#define	nc_new		cb_new.value.ui32
4868#define	nc_run		cb_run.value.ui32
4869#define	nc_delete	cb_delete.value.ui32
4870#define	nc_maxreq	cb_maxreq.value.ui32
4871#define	nc_maxlist	cb_maxlist.value.ui32
4872#define	nc_alloc	cb_alloc.value.ui32
4873#define	nc_runouts	cb_runouts.value.ui32
4874#define	nc_L2		cb_L2.value.ui32
4875#define	nc_grow		cb_grow.value.ui32
4876
4877static kmutex_t ddi_callback_mutex;
4878
4879/*
4880 * callbacks are handled using a L1/L2 cache. The L1 cache
4881 * comes out of kmem_cache_alloc and can expand/shrink dynamically. If
4882 * we can't get callbacks from the L1 cache [because pageout is doing
4883 * I/O at the time freemem is 0], we allocate callbacks out of the
4884 * L2 cache. The L2 cache is static and depends on the memory size.
4885 * [We might also count the number of devices at probe time and
4886 * allocate one structure per device and adjust for deferred attach]
4887 */
4888void
4889impl_ddi_callback_init(void)
4890{
4891	int	i;
4892	uint_t	physmegs;
4893	kstat_t	*ksp;
4894
4895	physmegs = physmem >> (20 - PAGESHIFT);
4896	if (physmegs < 48) {
4897		ncallbacks = nc_low;
4898	} else if (physmegs < 128) {
4899		ncallbacks = nc_med;
4900	} else {
4901		ncallbacks = nc_high;
4902	}
4903
4904	/*
4905	 * init free list
4906	 */
4907	callbackq = kmem_zalloc(
4908	    ncallbacks * sizeof (struct ddi_callback), KM_SLEEP);
4909	for (i = 0; i < ncallbacks-1; i++)
4910		callbackq[i].c_nfree = &callbackq[i+1];
4911	callbackqfree = callbackq;
4912
4913	/* init kstats */
4914	if (ksp = kstat_create("unix", 0, "cbstats", "misc", KSTAT_TYPE_NAMED,
4915	    sizeof (cbstats) / sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL)) {
4916		ksp->ks_data = (void *) &cbstats;
4917		kstat_install(ksp);
4918	}
4919
4920}
4921
4922static void
4923callback_insert(int (*funcp)(caddr_t), caddr_t arg, uintptr_t *listid,
4924	int count)
4925{
4926	struct ddi_callback *list, *marker, *new;
4927	size_t size = sizeof (struct ddi_callback);
4928
4929	list = marker = (struct ddi_callback *)*listid;
4930	while (list != NULL) {
4931		if (list->c_call == funcp && list->c_arg == arg) {
4932			list->c_count += count;
4933			return;
4934		}
4935		marker = list;
4936		list = list->c_nlist;
4937	}
4938	new = kmem_alloc(size, KM_NOSLEEP);
4939	if (new == NULL) {
4940		new = callbackqfree;
4941		if (new == NULL) {
4942			new = kmem_alloc_tryhard(sizeof (struct ddi_callback),
4943			    &size, KM_NOSLEEP | KM_PANIC);
4944			cbstats.nc_grow++;
4945		} else {
4946			callbackqfree = new->c_nfree;
4947			cbstats.nc_L2++;
4948		}
4949	}
4950	if (marker != NULL) {
4951		marker->c_nlist = new;
4952	} else {
4953		*listid = (uintptr_t)new;
4954	}
4955	new->c_size = size;
4956	new->c_nlist = NULL;
4957	new->c_call = funcp;
4958	new->c_arg = arg;
4959	new->c_count = count;
4960	cbstats.nc_new++;
4961	cbstats.nc_alloc++;
4962	if (cbstats.nc_alloc > cbstats.nc_maxlist)
4963		cbstats.nc_maxlist = cbstats.nc_alloc;
4964}
4965
4966void
4967ddi_set_callback(int (*funcp)(caddr_t), caddr_t arg, uintptr_t *listid)
4968{
4969	mutex_enter(&ddi_callback_mutex);
4970	cbstats.nc_asked++;
4971	if ((cbstats.nc_asked - cbstats.nc_run) > cbstats.nc_maxreq)
4972		cbstats.nc_maxreq = (cbstats.nc_asked - cbstats.nc_run);
4973	(void) callback_insert(funcp, arg, listid, 1);
4974	mutex_exit(&ddi_callback_mutex);
4975}
4976
4977static void
4978real_callback_run(void *Queue)
4979{
4980	int (*funcp)(caddr_t);
4981	caddr_t arg;
4982	int count, rval;
4983	uintptr_t *listid;
4984	struct ddi_callback *list, *marker;
4985	int check_pending = 1;
4986	int pending = 0;
4987
4988	do {
4989		mutex_enter(&ddi_callback_mutex);
4990		listid = Queue;
4991		list = (struct ddi_callback *)*listid;
4992		if (list == NULL) {
4993			mutex_exit(&ddi_callback_mutex);
4994			return;
4995		}
4996		if (check_pending) {
4997			marker = list;
4998			while (marker != NULL) {
4999				pending += marker->c_count;
5000				marker = marker->c_nlist;
5001			}
5002			check_pending = 0;
5003		}
5004		ASSERT(pending > 0);
5005		ASSERT(list->c_count > 0);
5006		funcp = list->c_call;
5007		arg = list->c_arg;
5008		count = list->c_count;
5009		*(uintptr_t *)Queue = (uintptr_t)list->c_nlist;
5010		if (list >= &callbackq[0] &&
5011		    list <= &callbackq[ncallbacks-1]) {
5012			list->c_nfree = callbackqfree;
5013			callbackqfree = list;
5014		} else
5015			kmem_free(list, list->c_size);
5016
5017		cbstats.nc_delete++;
5018		cbstats.nc_alloc--;
5019		mutex_exit(&ddi_callback_mutex);
5020
5021		do {
5022			if ((rval = (*funcp)(arg)) == 0) {
5023				pending -= count;
5024				mutex_enter(&ddi_callback_mutex);
5025				(void) callback_insert(funcp, arg, listid,
5026				    count);
5027				cbstats.nc_runouts++;
5028			} else {
5029				pending--;
5030				mutex_enter(&ddi_callback_mutex);
5031				cbstats.nc_run++;
5032			}
5033			mutex_exit(&ddi_callback_mutex);
5034		} while (rval != 0 && (--count > 0));
5035	} while (pending > 0);
5036}
5037
5038void
5039ddi_run_callback(uintptr_t *listid)
5040{
5041	softcall(real_callback_run, listid);
5042}
5043
5044/*
5045 * ddi_periodic_t
5046 * ddi_periodic_add(void (*func)(void *), void *arg, hrtime_t interval,
5047 *     int level)
5048 *
5049 * INTERFACE LEVEL
5050 *      Solaris DDI specific (Solaris DDI)
5051 *
5052 * PARAMETERS
5053 *      func: the callback function
5054 *
5055 *            The callback function will be invoked. The function is invoked
5056 *            in kernel context if the argument level passed is the zero.
5057 *            Otherwise it's invoked in interrupt context at the specified
5058 *            level.
5059 *
5060 *       arg: the argument passed to the callback function
5061 *
5062 *  interval: interval time
5063 *
5064 *    level : callback interrupt level
5065 *
5066 *            If the value is the zero, the callback function is invoked
5067 *            in kernel context. If the value is more than the zero, but
5068 *            less than or equal to ten, the callback function is invoked in
5069 *            interrupt context at the specified interrupt level, which may
5070 *            be used for real time applications.
5071 *
5072 *            This value must be in range of 0-10, which can be a numeric
5073 *            number or a pre-defined macro (DDI_IPL_0, ... , DDI_IPL_10).
5074 *
5075 * DESCRIPTION
5076 *      ddi_periodic_add(9F) schedules the specified function to be
5077 *      periodically invoked in the interval time.
5078 *
5079 *      As well as timeout(9F), the exact time interval over which the function
5080 *      takes effect cannot be guaranteed, but the value given is a close
5081 *      approximation.
5082 *
5083 *      Drivers waiting on behalf of processes with real-time constraints must
5084 *      pass non-zero value with the level argument to ddi_periodic_add(9F).
5085 *
5086 * RETURN VALUES
5087 *      ddi_periodic_add(9F) returns a non-zero opaque value (ddi_periodic_t),
5088 *      which must be used for ddi_periodic_delete(9F) to specify the request.
5089 *
5090 * CONTEXT
5091 *      ddi_periodic_add(9F) can be called in user or kernel context, but
5092 *      it cannot be called in interrupt context, which is different from
5093 *      timeout(9F).
5094 */
5095ddi_periodic_t
5096ddi_periodic_add(void (*func)(void *), void *arg, hrtime_t interval, int level)
5097{
5098	/*
5099	 * Sanity check of the argument level.
5100	 */
5101	if (level < DDI_IPL_0 || level > DDI_IPL_10)
5102		cmn_err(CE_PANIC,
5103		    "ddi_periodic_add: invalid interrupt level (%d).", level);
5104
5105	/*
5106	 * Sanity check of the context. ddi_periodic_add() cannot be
5107	 * called in either interrupt context or high interrupt context.
5108	 */
5109	if (servicing_interrupt())
5110		cmn_err(CE_PANIC,
5111		    "ddi_periodic_add: called in (high) interrupt context.");
5112
5113	return ((ddi_periodic_t)i_timeout(func, arg, interval, level));
5114}
5115
5116/*
5117 * void
5118 * ddi_periodic_delete(ddi_periodic_t req)
5119 *
5120 * INTERFACE LEVEL
5121 *     Solaris DDI specific (Solaris DDI)
5122 *
5123 * PARAMETERS
5124 *     req: ddi_periodic_t opaque value ddi_periodic_add(9F) returned
5125 *     previously.
5126 *
5127 * DESCRIPTION
5128 *     ddi_periodic_delete(9F) cancels the ddi_periodic_add(9F) request
5129 *     previously requested.
5130 *
5131 *     ddi_periodic_delete(9F) will not return until the pending request
5132 *     is canceled or executed.
5133 *
5134 *     As well as untimeout(9F), calling ddi_periodic_delete(9F) for a
5135 *     timeout which is either running on another CPU, or has already
5136 *     completed causes no problems. However, unlike untimeout(9F), there is
5137 *     no restrictions on the lock which might be held across the call to
5138 *     ddi_periodic_delete(9F).
5139 *
5140 *     Drivers should be structured with the understanding that the arrival of
5141 *     both an interrupt and a timeout for that interrupt can occasionally
5142 *     occur, in either order.
5143 *
5144 * CONTEXT
5145 *     ddi_periodic_delete(9F) can be called in user or kernel context, but
5146 *     it cannot be called in interrupt context, which is different from
5147 *     untimeout(9F).
5148 */
5149void
5150ddi_periodic_delete(ddi_periodic_t req)
5151{
5152	/*
5153	 * Sanity check of the context. ddi_periodic_delete() cannot be
5154	 * called in either interrupt context or high interrupt context.
5155	 */
5156	if (servicing_interrupt())
5157		cmn_err(CE_PANIC,
5158		    "ddi_periodic_delete: called in (high) interrupt context.");
5159
5160	i_untimeout((timeout_t)req);
5161}
5162
5163dev_info_t *
5164nodevinfo(dev_t dev, int otyp)
5165{
5166	_NOTE(ARGUNUSED(dev, otyp))
5167	return ((dev_info_t *)0);
5168}
5169
5170/*
5171 * A driver should support its own getinfo(9E) entry point. This function
5172 * is provided as a convenience for ON drivers that don't expect their
5173 * getinfo(9E) entry point to be called. A driver that uses this must not
5174 * call ddi_create_minor_node.
5175 */
5176int
5177ddi_no_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
5178{
5179	_NOTE(ARGUNUSED(dip, infocmd, arg, result))
5180	return (DDI_FAILURE);
5181}
5182
5183/*
5184 * A driver should support its own getinfo(9E) entry point. This function
5185 * is provided as a convenience for ON drivers that where the minor number
5186 * is the instance. Drivers that do not have 1:1 mapping must implement
5187 * their own getinfo(9E) function.
5188 */
5189int
5190ddi_getinfo_1to1(dev_info_t *dip, ddi_info_cmd_t infocmd,
5191    void *arg, void **result)
5192{
5193	_NOTE(ARGUNUSED(dip))
5194	int	instance;
5195
5196	if (infocmd != DDI_INFO_DEVT2INSTANCE)
5197		return (DDI_FAILURE);
5198
5199	instance = getminor((dev_t)(uintptr_t)arg);
5200	*result = (void *)(uintptr_t)instance;
5201	return (DDI_SUCCESS);
5202}
5203
5204int
5205ddifail(dev_info_t *devi, ddi_attach_cmd_t cmd)
5206{
5207	_NOTE(ARGUNUSED(devi, cmd))
5208	return (DDI_FAILURE);
5209}
5210
5211int
5212ddi_no_dma_map(dev_info_t *dip, dev_info_t *rdip,
5213    struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep)
5214{
5215	_NOTE(ARGUNUSED(dip, rdip, dmareqp, handlep))
5216	return (DDI_DMA_NOMAPPING);
5217}
5218
5219int
5220ddi_no_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr,
5221    int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep)
5222{
5223	_NOTE(ARGUNUSED(dip, rdip, attr, waitfp, arg, handlep))
5224	return (DDI_DMA_BADATTR);
5225}
5226
5227int
5228ddi_no_dma_freehdl(dev_info_t *dip, dev_info_t *rdip,
5229    ddi_dma_handle_t handle)
5230{
5231	_NOTE(ARGUNUSED(dip, rdip, handle))
5232	return (DDI_FAILURE);
5233}
5234
5235int
5236ddi_no_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
5237    ddi_dma_handle_t handle, struct ddi_dma_req *dmareq,
5238    ddi_dma_cookie_t *cp, uint_t *ccountp)
5239{
5240	_NOTE(ARGUNUSED(dip, rdip, handle, dmareq, cp, ccountp))
5241	return (DDI_DMA_NOMAPPING);
5242}
5243
5244int
5245ddi_no_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
5246    ddi_dma_handle_t handle)
5247{
5248	_NOTE(ARGUNUSED(dip, rdip, handle))
5249	return (DDI_FAILURE);
5250}
5251
5252int
5253ddi_no_dma_flush(dev_info_t *dip, dev_info_t *rdip,
5254    ddi_dma_handle_t handle, off_t off, size_t len,
5255    uint_t cache_flags)
5256{
5257	_NOTE(ARGUNUSED(dip, rdip, handle, off, len, cache_flags))
5258	return (DDI_FAILURE);
5259}
5260
5261int
5262ddi_no_dma_win(dev_info_t *dip, dev_info_t *rdip,
5263    ddi_dma_handle_t handle, uint_t win, off_t *offp,
5264    size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp)
5265{
5266	_NOTE(ARGUNUSED(dip, rdip, handle, win, offp, lenp, cookiep, ccountp))
5267	return (DDI_FAILURE);
5268}
5269
5270int
5271ddi_no_dma_mctl(dev_info_t *dip, dev_info_t *rdip,
5272    ddi_dma_handle_t handle, enum ddi_dma_ctlops request,
5273    off_t *offp, size_t *lenp, caddr_t *objp, uint_t flags)
5274{
5275	_NOTE(ARGUNUSED(dip, rdip, handle, request, offp, lenp, objp, flags))
5276	return (DDI_FAILURE);
5277}
5278
5279void
5280ddivoid(void)
5281{}
5282
5283int
5284nochpoll(dev_t dev, short events, int anyyet, short *reventsp,
5285    struct pollhead **pollhdrp)
5286{
5287	_NOTE(ARGUNUSED(dev, events, anyyet, reventsp, pollhdrp))
5288	return (ENXIO);
5289}
5290
5291cred_t *
5292ddi_get_cred(void)
5293{
5294	return (CRED());
5295}
5296
5297clock_t
5298ddi_get_lbolt(void)
5299{
5300	return ((clock_t)lbolt_hybrid());
5301}
5302
5303int64_t
5304ddi_get_lbolt64(void)
5305{
5306	return (lbolt_hybrid());
5307}
5308
5309time_t
5310ddi_get_time(void)
5311{
5312	time_t	now;
5313
5314	if ((now = gethrestime_sec()) == 0) {
5315		timestruc_t ts;
5316		mutex_enter(&tod_lock);
5317		ts = tod_get();
5318		mutex_exit(&tod_lock);
5319		return (ts.tv_sec);
5320	} else {
5321		return (now);
5322	}
5323}
5324
5325pid_t
5326ddi_get_pid(void)
5327{
5328	return (ttoproc(curthread)->p_pid);
5329}
5330
5331kt_did_t
5332ddi_get_kt_did(void)
5333{
5334	return (curthread->t_did);
5335}
5336
5337/*
5338 * This function returns B_TRUE if the caller can reasonably expect that a call
5339 * to cv_wait_sig(9F), cv_timedwait_sig(9F), or qwait_sig(9F) could be awakened
5340 * by user-level signal.  If it returns B_FALSE, then the caller should use
5341 * other means to make certain that the wait will not hang "forever."
5342 *
5343 * It does not check the signal mask, nor for reception of any particular
5344 * signal.
5345 *
5346 * Currently, a thread can receive a signal if it's not a kernel thread and it
5347 * is not in the middle of exit(2) tear-down.  Threads that are in that
5348 * tear-down effectively convert cv_wait_sig to cv_wait, cv_timedwait_sig to
5349 * cv_timedwait, and qwait_sig to qwait.
5350 */
5351boolean_t
5352ddi_can_receive_sig(void)
5353{
5354	proc_t *pp;
5355
5356	if (curthread->t_proc_flag & TP_LWPEXIT)
5357		return (B_FALSE);
5358	if ((pp = ttoproc(curthread)) == NULL)
5359		return (B_FALSE);
5360	return (pp->p_as != &kas);
5361}
5362
5363/*
5364 * Swap bytes in 16-bit [half-]words
5365 */
5366void
5367swab(void *src, void *dst, size_t nbytes)
5368{
5369	uchar_t *pf = (uchar_t *)src;
5370	uchar_t *pt = (uchar_t *)dst;
5371	uchar_t tmp;
5372	int nshorts;
5373
5374	nshorts = nbytes >> 1;
5375
5376	while (--nshorts >= 0) {
5377		tmp = *pf++;
5378		*pt++ = *pf++;
5379		*pt++ = tmp;
5380	}
5381}
5382
5383static void
5384ddi_append_minor_node(dev_info_t *ddip, struct ddi_minor_data *dmdp)
5385{
5386	int			circ;
5387	struct ddi_minor_data	*dp;
5388
5389	ndi_devi_enter(ddip, &circ);
5390	if ((dp = DEVI(ddip)->devi_minor) == (struct ddi_minor_data *)NULL) {
5391		DEVI(ddip)->devi_minor = dmdp;
5392	} else {
5393		while (dp->next != (struct ddi_minor_data *)NULL)
5394			dp = dp->next;
5395		dp->next = dmdp;
5396	}
5397	ndi_devi_exit(ddip, circ);
5398}
5399
5400/*
5401 * Part of the obsolete SunCluster DDI Hooks.
5402 * Keep for binary compatibility
5403 */
5404minor_t
5405ddi_getiminor(dev_t dev)
5406{
5407	return (getminor(dev));
5408}
5409
5410static int
5411i_log_devfs_minor_create(dev_info_t *dip, char *minor_name)
5412{
5413	int se_flag;
5414	int kmem_flag;
5415	int se_err;
5416	char *pathname, *class_name;
5417	sysevent_t *ev = NULL;
5418	sysevent_id_t eid;
5419	sysevent_value_t se_val;
5420	sysevent_attr_list_t *ev_attr_list = NULL;
5421
5422	/* determine interrupt context */
5423	se_flag = (servicing_interrupt()) ? SE_NOSLEEP : SE_SLEEP;
5424	kmem_flag = (se_flag == SE_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
5425
5426	i_ddi_di_cache_invalidate();
5427
5428#ifdef DEBUG
5429	if ((se_flag == SE_NOSLEEP) && sunddi_debug) {
5430		cmn_err(CE_CONT, "ddi_create_minor_node: called from "
5431		    "interrupt level by driver %s",
5432		    ddi_driver_name(dip));
5433	}
5434#endif /* DEBUG */
5435
5436	ev = sysevent_alloc(EC_DEVFS, ESC_DEVFS_MINOR_CREATE, EP_DDI, se_flag);
5437	if (ev == NULL) {
5438		goto fail;
5439	}
5440
5441	pathname = kmem_alloc(MAXPATHLEN, kmem_flag);
5442	if (pathname == NULL) {
5443		sysevent_free(ev);
5444		goto fail;
5445	}
5446
5447	(void) ddi_pathname(dip, pathname);
5448	ASSERT(strlen(pathname));
5449	se_val.value_type = SE_DATA_TYPE_STRING;
5450	se_val.value.sv_string = pathname;
5451	if (sysevent_add_attr(&ev_attr_list, DEVFS_PATHNAME,
5452	    &se_val, se_flag) != 0) {
5453		kmem_free(pathname, MAXPATHLEN);
5454		sysevent_free(ev);
5455		goto fail;
5456	}
5457	kmem_free(pathname, MAXPATHLEN);
5458
5459	/* add the device class attribute */
5460	if ((class_name = i_ddi_devi_class(dip)) != NULL) {
5461		se_val.value_type = SE_DATA_TYPE_STRING;
5462		se_val.value.sv_string = class_name;
5463		if (sysevent_add_attr(&ev_attr_list,
5464		    DEVFS_DEVI_CLASS, &se_val, SE_SLEEP) != 0) {
5465			sysevent_free_attr(ev_attr_list);
5466			goto fail;
5467		}
5468	}
5469
5470	/*
5471	 * allow for NULL minor names
5472	 */
5473	if (minor_name != NULL) {
5474		se_val.value.sv_string = minor_name;
5475		if (sysevent_add_attr(&ev_attr_list, DEVFS_MINOR_NAME,
5476		    &se_val, se_flag) != 0) {
5477			sysevent_free_attr(ev_attr_list);
5478			sysevent_free(ev);
5479			goto fail;
5480		}
5481	}
5482
5483	if (sysevent_attach_attributes(ev, ev_attr_list) != 0) {
5484		sysevent_free_attr(ev_attr_list);
5485		sysevent_free(ev);
5486		goto fail;
5487	}
5488
5489	if ((se_err = log_sysevent(ev, se_flag, &eid)) != 0) {
5490		if (se_err == SE_NO_TRANSPORT) {
5491			cmn_err(CE_WARN, "/devices or /dev may not be current "
5492			    "for driver %s (%s). Run devfsadm -i %s",
5493			    ddi_driver_name(dip), "syseventd not responding",
5494			    ddi_driver_name(dip));
5495		} else {
5496			sysevent_free(ev);
5497			goto fail;
5498		}
5499	}
5500
5501	sysevent_free(ev);
5502	return (DDI_SUCCESS);
5503fail:
5504	cmn_err(CE_WARN, "/devices or /dev may not be current "
5505	    "for driver %s. Run devfsadm -i %s",
5506	    ddi_driver_name(dip), ddi_driver_name(dip));
5507	return (DDI_SUCCESS);
5508}
5509
5510/*
5511 * failing to remove a minor node is not of interest
5512 * therefore we do not generate an error message
5513 */
5514static int
5515i_log_devfs_minor_remove(dev_info_t *dip, char *minor_name)
5516{
5517	char *pathname, *class_name;
5518	sysevent_t *ev;
5519	sysevent_id_t eid;
5520	sysevent_value_t se_val;
5521	sysevent_attr_list_t *ev_attr_list = NULL;
5522
5523	/*
5524	 * only log ddi_remove_minor_node() calls outside the scope
5525	 * of attach/detach reconfigurations and when the dip is
5526	 * still initialized.
5527	 */
5528	if (DEVI_IS_ATTACHING(dip) || DEVI_IS_DETACHING(dip) ||
5529	    (i_ddi_node_state(dip) < DS_INITIALIZED)) {
5530		return (DDI_SUCCESS);
5531	}
5532
5533	i_ddi_di_cache_invalidate();
5534
5535	ev = sysevent_alloc(EC_DEVFS, ESC_DEVFS_MINOR_REMOVE, EP_DDI, SE_SLEEP);
5536	if (ev == NULL) {
5537		return (DDI_SUCCESS);
5538	}
5539
5540	pathname = kmem_alloc(MAXPATHLEN, KM_SLEEP);
5541	if (pathname == NULL) {
5542		sysevent_free(ev);
5543		return (DDI_SUCCESS);
5544	}
5545
5546	(void) ddi_pathname(dip, pathname);
5547	ASSERT(strlen(pathname));
5548	se_val.value_type = SE_DATA_TYPE_STRING;
5549	se_val.value.sv_string = pathname;
5550	if (sysevent_add_attr(&ev_attr_list, DEVFS_PATHNAME,
5551	    &se_val, SE_SLEEP) != 0) {
5552		kmem_free(pathname, MAXPATHLEN);
5553		sysevent_free(ev);
5554		return (DDI_SUCCESS);
5555	}
5556
5557	kmem_free(pathname, MAXPATHLEN);
5558
5559	/*
5560	 * allow for NULL minor names
5561	 */
5562	if (minor_name != NULL) {
5563		se_val.value.sv_string = minor_name;
5564		if (sysevent_add_attr(&ev_attr_list, DEVFS_MINOR_NAME,
5565		    &se_val, SE_SLEEP) != 0) {
5566			sysevent_free_attr(ev_attr_list);
5567			goto fail;
5568		}
5569	}
5570
5571	if ((class_name = i_ddi_devi_class(dip)) != NULL) {
5572		/* add the device class, driver name and instance attributes */
5573
5574		se_val.value_type = SE_DATA_TYPE_STRING;
5575		se_val.value.sv_string = class_name;
5576		if (sysevent_add_attr(&ev_attr_list,
5577		    DEVFS_DEVI_CLASS, &se_val, SE_SLEEP) != 0) {
5578			sysevent_free_attr(ev_attr_list);
5579			goto fail;
5580		}
5581
5582		se_val.value_type = SE_DATA_TYPE_STRING;
5583		se_val.value.sv_string = (char *)ddi_driver_name(dip);
5584		if (sysevent_add_attr(&ev_attr_list,
5585		    DEVFS_DRIVER_NAME, &se_val, SE_SLEEP) != 0) {
5586			sysevent_free_attr(ev_attr_list);
5587			goto fail;
5588		}
5589
5590		se_val.value_type = SE_DATA_TYPE_INT32;
5591		se_val.value.sv_int32 = ddi_get_instance(dip);
5592		if (sysevent_add_attr(&ev_attr_list,
5593		    DEVFS_INSTANCE, &se_val, SE_SLEEP) != 0) {
5594			sysevent_free_attr(ev_attr_list);
5595			goto fail;
5596		}
5597
5598	}
5599
5600	if (sysevent_attach_attributes(ev, ev_attr_list) != 0) {
5601		sysevent_free_attr(ev_attr_list);
5602	} else {
5603		(void) log_sysevent(ev, SE_SLEEP, &eid);
5604	}
5605fail:
5606	sysevent_free(ev);
5607	return (DDI_SUCCESS);
5608}
5609
5610/*
5611 * Derive the device class of the node.
5612 * Device class names aren't defined yet. Until this is done we use
5613 * devfs event subclass names as device class names.
5614 */
5615static int
5616derive_devi_class(dev_info_t *dip, char *node_type, int flag)
5617{
5618	int rv = DDI_SUCCESS;
5619
5620	if (i_ddi_devi_class(dip) == NULL) {
5621		if (strncmp(node_type, DDI_NT_BLOCK,
5622		    sizeof (DDI_NT_BLOCK) - 1) == 0 &&
5623		    (node_type[sizeof (DDI_NT_BLOCK) - 1] == '\0' ||
5624		    node_type[sizeof (DDI_NT_BLOCK) - 1] == ':') &&
5625		    strcmp(node_type, DDI_NT_FD) != 0) {
5626
5627			rv = i_ddi_set_devi_class(dip, ESC_DISK, flag);
5628
5629		} else if (strncmp(node_type, DDI_NT_NET,
5630		    sizeof (DDI_NT_NET) - 1) == 0 &&
5631		    (node_type[sizeof (DDI_NT_NET) - 1] == '\0' ||
5632		    node_type[sizeof (DDI_NT_NET) - 1] == ':')) {
5633
5634			rv = i_ddi_set_devi_class(dip, ESC_NETWORK, flag);
5635
5636		} else if (strncmp(node_type, DDI_NT_PRINTER,
5637		    sizeof (DDI_NT_PRINTER) - 1) == 0 &&
5638		    (node_type[sizeof (DDI_NT_PRINTER) - 1] == '\0' ||
5639		    node_type[sizeof (DDI_NT_PRINTER) - 1] == ':')) {
5640
5641			rv = i_ddi_set_devi_class(dip, ESC_PRINTER, flag);
5642
5643		} else if (strncmp(node_type, DDI_PSEUDO,
5644		    sizeof (DDI_PSEUDO) -1) == 0 &&
5645		    (strncmp(ESC_LOFI, ddi_node_name(dip),
5646		    sizeof (ESC_LOFI) -1) == 0)) {
5647			rv = i_ddi_set_devi_class(dip, ESC_LOFI, flag);
5648		}
5649	}
5650
5651	return (rv);
5652}
5653
5654/*
5655 * Check compliance with PSARC 2003/375:
5656 *
5657 * The name must contain only characters a-z, A-Z, 0-9 or _ and it must not
5658 * exceed IFNAMSIZ (16) characters in length.
5659 */
5660static boolean_t
5661verify_name(char *name)
5662{
5663	size_t	len = strlen(name);
5664	char	*cp;
5665
5666	if (len == 0 || len > IFNAMSIZ)
5667		return (B_FALSE);
5668
5669	for (cp = name; *cp != '\0'; cp++) {
5670		if (!isalnum(*cp) && *cp != '_')
5671			return (B_FALSE);
5672	}
5673
5674	return (B_TRUE);
5675}
5676
5677/*
5678 * ddi_create_minor_common:	Create a  ddi_minor_data structure and
5679 *				attach it to the given devinfo node.
5680 */
5681
5682int
5683ddi_create_minor_common(dev_info_t *dip, char *name, int spec_type,
5684    minor_t minor_num, char *node_type, int flag, ddi_minor_type mtype,
5685    const char *read_priv, const char *write_priv, mode_t priv_mode)
5686{
5687	struct ddi_minor_data *dmdp;
5688	major_t major;
5689
5690	if (spec_type != S_IFCHR && spec_type != S_IFBLK)
5691		return (DDI_FAILURE);
5692
5693	if (name == NULL)
5694		return (DDI_FAILURE);
5695
5696	/*
5697	 * Log a message if the minor number the driver is creating
5698	 * is not expressible on the on-disk filesystem (currently
5699	 * this is limited to 18 bits both by UFS). The device can
5700	 * be opened via devfs, but not by device special files created
5701	 * via mknod().
5702	 */
5703	if (minor_num > L_MAXMIN32) {
5704		cmn_err(CE_WARN,
5705		    "%s%d:%s minor 0x%x too big for 32-bit applications",
5706		    ddi_driver_name(dip), ddi_get_instance(dip),
5707		    name, minor_num);
5708		return (DDI_FAILURE);
5709	}
5710
5711	/* dip must be bound and attached */
5712	major = ddi_driver_major(dip);
5713	ASSERT(major != DDI_MAJOR_T_NONE);
5714
5715	/*
5716	 * Default node_type to DDI_PSEUDO and issue notice in debug mode
5717	 */
5718	if (node_type == NULL) {
5719		node_type = DDI_PSEUDO;
5720		NDI_CONFIG_DEBUG((CE_NOTE, "!illegal node_type NULL for %s%d "
5721		    " minor node %s; default to DDI_PSEUDO",
5722		    ddi_driver_name(dip), ddi_get_instance(dip), name));
5723	}
5724
5725	/*
5726	 * If the driver is a network driver, ensure that the name falls within
5727	 * the interface naming constraints specified by PSARC/2003/375.
5728	 */
5729	if (strcmp(node_type, DDI_NT_NET) == 0) {
5730		if (!verify_name(name))
5731			return (DDI_FAILURE);
5732
5733		if (mtype == DDM_MINOR) {
5734			struct devnames *dnp = &devnamesp[major];
5735
5736			/* Mark driver as a network driver */
5737			LOCK_DEV_OPS(&dnp->dn_lock);
5738			dnp->dn_flags |= DN_NETWORK_DRIVER;
5739
5740			/*
5741			 * If this minor node is created during the device
5742			 * attachment, this is a physical network device.
5743			 * Mark the driver as a physical network driver.
5744			 */
5745			if (DEVI_IS_ATTACHING(dip))
5746				dnp->dn_flags |= DN_NETWORK_PHYSDRIVER;
5747			UNLOCK_DEV_OPS(&dnp->dn_lock);
5748		}
5749	}
5750
5751	if (mtype == DDM_MINOR) {
5752		if (derive_devi_class(dip,  node_type, KM_NOSLEEP) !=
5753		    DDI_SUCCESS)
5754			return (DDI_FAILURE);
5755	}
5756
5757	/*
5758	 * Take care of minor number information for the node.
5759	 */
5760
5761	if ((dmdp = kmem_zalloc(sizeof (struct ddi_minor_data),
5762	    KM_NOSLEEP)) == NULL) {
5763		return (DDI_FAILURE);
5764	}
5765	if ((dmdp->ddm_name = i_ddi_strdup(name, KM_NOSLEEP)) == NULL) {
5766		kmem_free(dmdp, sizeof (struct ddi_minor_data));
5767		return (DDI_FAILURE);
5768	}
5769	dmdp->dip = dip;
5770	dmdp->ddm_dev = makedevice(major, minor_num);
5771	dmdp->ddm_spec_type = spec_type;
5772	dmdp->ddm_node_type = node_type;
5773	dmdp->type = mtype;
5774	if (flag & CLONE_DEV) {
5775		dmdp->type = DDM_ALIAS;
5776		dmdp->ddm_dev = makedevice(ddi_driver_major(clone_dip), major);
5777	}
5778	if (flag & PRIVONLY_DEV) {
5779		dmdp->ddm_flags |= DM_NO_FSPERM;
5780	}
5781	if (read_priv || write_priv) {
5782		dmdp->ddm_node_priv =
5783		    devpolicy_priv_by_name(read_priv, write_priv);
5784	}
5785	dmdp->ddm_priv_mode = priv_mode;
5786
5787	ddi_append_minor_node(dip, dmdp);
5788
5789	/*
5790	 * only log ddi_create_minor_node() calls which occur
5791	 * outside the scope of attach(9e)/detach(9e) reconfigurations
5792	 */
5793	if (!(DEVI_IS_ATTACHING(dip) || DEVI_IS_DETACHING(dip)) &&
5794	    mtype != DDM_INTERNAL_PATH) {
5795		(void) i_log_devfs_minor_create(dip, name);
5796	}
5797
5798	/*
5799	 * Check if any dacf rules match the creation of this minor node
5800	 */
5801	dacfc_match_create_minor(name, node_type, dip, dmdp, flag);
5802	return (DDI_SUCCESS);
5803}
5804
5805int
5806ddi_create_minor_node(dev_info_t *dip, char *name, int spec_type,
5807    minor_t minor_num, char *node_type, int flag)
5808{
5809	return (ddi_create_minor_common(dip, name, spec_type, minor_num,
5810	    node_type, flag, DDM_MINOR, NULL, NULL, 0));
5811}
5812
5813int
5814ddi_create_priv_minor_node(dev_info_t *dip, char *name, int spec_type,
5815    minor_t minor_num, char *node_type, int flag,
5816    const char *rdpriv, const char *wrpriv, mode_t priv_mode)
5817{
5818	return (ddi_create_minor_common(dip, name, spec_type, minor_num,
5819	    node_type, flag, DDM_MINOR, rdpriv, wrpriv, priv_mode));
5820}
5821
5822int
5823ddi_create_default_minor_node(dev_info_t *dip, char *name, int spec_type,
5824    minor_t minor_num, char *node_type, int flag)
5825{
5826	return (ddi_create_minor_common(dip, name, spec_type, minor_num,
5827	    node_type, flag, DDM_DEFAULT, NULL, NULL, 0));
5828}
5829
5830/*
5831 * Internal (non-ddi) routine for drivers to export names known
5832 * to the kernel (especially ddi_pathname_to_dev_t and friends)
5833 * but not exported externally to /dev
5834 */
5835int
5836ddi_create_internal_pathname(dev_info_t *dip, char *name, int spec_type,
5837    minor_t minor_num)
5838{
5839	return (ddi_create_minor_common(dip, name, spec_type, minor_num,
5840	    "internal", 0, DDM_INTERNAL_PATH, NULL, NULL, 0));
5841}
5842
5843void
5844ddi_remove_minor_node(dev_info_t *dip, char *name)
5845{
5846	int			circ;
5847	struct ddi_minor_data	*dmdp, *dmdp1;
5848	struct ddi_minor_data	**dmdp_prev;
5849
5850	ndi_devi_enter(dip, &circ);
5851	dmdp_prev = &DEVI(dip)->devi_minor;
5852	dmdp = DEVI(dip)->devi_minor;
5853	while (dmdp != NULL) {
5854		dmdp1 = dmdp->next;
5855		if ((name == NULL || (dmdp->ddm_name != NULL &&
5856		    strcmp(name, dmdp->ddm_name) == 0))) {
5857			if (dmdp->ddm_name != NULL) {
5858				if (dmdp->type != DDM_INTERNAL_PATH)
5859					(void) i_log_devfs_minor_remove(dip,
5860					    dmdp->ddm_name);
5861				kmem_free(dmdp->ddm_name,
5862				    strlen(dmdp->ddm_name) + 1);
5863			}
5864			/*
5865			 * Release device privilege, if any.
5866			 * Release dacf client data associated with this minor
5867			 * node by storing NULL.
5868			 */
5869			if (dmdp->ddm_node_priv)
5870				dpfree(dmdp->ddm_node_priv);
5871			dacf_store_info((dacf_infohdl_t)dmdp, NULL);
5872			kmem_free(dmdp, sizeof (struct ddi_minor_data));
5873			*dmdp_prev = dmdp1;
5874			/*
5875			 * OK, we found it, so get out now -- if we drive on,
5876			 * we will strcmp against garbage.  See 1139209.
5877			 */
5878			if (name != NULL)
5879				break;
5880		} else {
5881			dmdp_prev = &dmdp->next;
5882		}
5883		dmdp = dmdp1;
5884	}
5885	ndi_devi_exit(dip, circ);
5886}
5887
5888
5889int
5890ddi_in_panic()
5891{
5892	return (panicstr != NULL);
5893}
5894
5895
5896/*
5897 * Find first bit set in a mask (returned counting from 1 up)
5898 */
5899
5900int
5901ddi_ffs(long mask)
5902{
5903	return (ffs(mask));
5904}
5905
5906/*
5907 * Find last bit set. Take mask and clear
5908 * all but the most significant bit, and
5909 * then let ffs do the rest of the work.
5910 *
5911 * Algorithm courtesy of Steve Chessin.
5912 */
5913
5914int
5915ddi_fls(long mask)
5916{
5917	while (mask) {
5918		long nx;
5919
5920		if ((nx = (mask & (mask - 1))) == 0)
5921			break;
5922		mask = nx;
5923	}
5924	return (ffs(mask));
5925}
5926
5927/*
5928 * The ddi_soft_state_* routines comprise generic storage management utilities
5929 * for driver soft state structures (in "the old days," this was done with
5930 * statically sized array - big systems and dynamic loading and unloading
5931 * make heap allocation more attractive).
5932 */
5933
5934/*
5935 * Allocate a set of pointers to 'n_items' objects of size 'size'
5936 * bytes.  Each pointer is initialized to nil.
5937 *
5938 * The 'size' and 'n_items' values are stashed in the opaque
5939 * handle returned to the caller.
5940 *
5941 * This implementation interprets 'set of pointers' to mean 'array
5942 * of pointers' but note that nothing in the interface definition
5943 * precludes an implementation that uses, for example, a linked list.
5944 * However there should be a small efficiency gain from using an array
5945 * at lookup time.
5946 *
5947 * NOTE	As an optimization, we make our growable array allocations in
5948 *	powers of two (bytes), since that's how much kmem_alloc (currently)
5949 *	gives us anyway.  It should save us some free/realloc's ..
5950 *
5951 *	As a further optimization, we make the growable array start out
5952 *	with MIN_N_ITEMS in it.
5953 */
5954
5955#define	MIN_N_ITEMS	8	/* 8 void *'s == 32 bytes */
5956
5957int
5958ddi_soft_state_init(void **state_p, size_t size, size_t n_items)
5959{
5960	i_ddi_soft_state	*ss;
5961
5962	if (state_p == NULL || size == 0)
5963		return (EINVAL);
5964
5965	ss = kmem_zalloc(sizeof (*ss), KM_SLEEP);
5966	mutex_init(&ss->lock, NULL, MUTEX_DRIVER, NULL);
5967	ss->size = size;
5968
5969	if (n_items < MIN_N_ITEMS)
5970		ss->n_items = MIN_N_ITEMS;
5971	else {
5972		int bitlog;
5973
5974		if ((bitlog = ddi_fls(n_items)) == ddi_ffs(n_items))
5975			bitlog--;
5976		ss->n_items = 1 << bitlog;
5977	}
5978
5979	ASSERT(ss->n_items >= n_items);
5980
5981	ss->array = kmem_zalloc(ss->n_items * sizeof (void *), KM_SLEEP);
5982
5983	*state_p = ss;
5984	return (0);
5985}
5986
5987/*
5988 * Allocate a state structure of size 'size' to be associated
5989 * with item 'item'.
5990 *
5991 * In this implementation, the array is extended to
5992 * allow the requested offset, if needed.
5993 */
5994int
5995ddi_soft_state_zalloc(void *state, int item)
5996{
5997	i_ddi_soft_state	*ss = (i_ddi_soft_state *)state;
5998	void			**array;
5999	void			*new_element;
6000
6001	if ((state == NULL) || (item < 0))
6002		return (DDI_FAILURE);
6003
6004	mutex_enter(&ss->lock);
6005	if (ss->size == 0) {
6006		mutex_exit(&ss->lock);
6007		cmn_err(CE_WARN, "ddi_soft_state_zalloc: bad handle: %s",
6008		    mod_containing_pc(caller()));
6009		return (DDI_FAILURE);
6010	}
6011
6012	array = ss->array;	/* NULL if ss->n_items == 0 */
6013	ASSERT(ss->n_items != 0 && array != NULL);
6014
6015	/*
6016	 * refuse to tread on an existing element
6017	 */
6018	if (item < ss->n_items && array[item] != NULL) {
6019		mutex_exit(&ss->lock);
6020		return (DDI_FAILURE);
6021	}
6022
6023	/*
6024	 * Allocate a new element to plug in
6025	 */
6026	new_element = kmem_zalloc(ss->size, KM_SLEEP);
6027
6028	/*
6029	 * Check if the array is big enough, if not, grow it.
6030	 */
6031	if (item >= ss->n_items) {
6032		void			**new_array;
6033		size_t			new_n_items;
6034		struct i_ddi_soft_state	*dirty;
6035
6036		/*
6037		 * Allocate a new array of the right length, copy
6038		 * all the old pointers to the new array, then
6039		 * if it exists at all, put the old array on the
6040		 * dirty list.
6041		 *
6042		 * Note that we can't kmem_free() the old array.
6043		 *
6044		 * Why -- well the 'get' operation is 'mutex-free', so we
6045		 * can't easily catch a suspended thread that is just about
6046		 * to dereference the array we just grew out of.  So we
6047		 * cons up a header and put it on a list of 'dirty'
6048		 * pointer arrays.  (Dirty in the sense that there may
6049		 * be suspended threads somewhere that are in the middle
6050		 * of referencing them).  Fortunately, we -can- garbage
6051		 * collect it all at ddi_soft_state_fini time.
6052		 */
6053		new_n_items = ss->n_items;
6054		while (new_n_items < (1 + item))
6055			new_n_items <<= 1;	/* double array size .. */
6056
6057		ASSERT(new_n_items >= (1 + item));	/* sanity check! */
6058
6059		new_array = kmem_zalloc(new_n_items * sizeof (void *),
6060		    KM_SLEEP);
6061		/*
6062		 * Copy the pointers into the new array
6063		 */
6064		bcopy(array, new_array, ss->n_items * sizeof (void *));
6065
6066		/*
6067		 * Save the old array on the dirty list
6068		 */
6069		dirty = kmem_zalloc(sizeof (*dirty), KM_SLEEP);
6070		dirty->array = ss->array;
6071		dirty->n_items = ss->n_items;
6072		dirty->next = ss->next;
6073		ss->next = dirty;
6074
6075		ss->array = (array = new_array);
6076		ss->n_items = new_n_items;
6077	}
6078
6079	ASSERT(array != NULL && item < ss->n_items && array[item] == NULL);
6080
6081	array[item] = new_element;
6082
6083	mutex_exit(&ss->lock);
6084	return (DDI_SUCCESS);
6085}
6086
6087/*
6088 * Fetch a pointer to the allocated soft state structure.
6089 *
6090 * This is designed to be cheap.
6091 *
6092 * There's an argument that there should be more checking for
6093 * nil pointers and out of bounds on the array.. but we do a lot
6094 * of that in the alloc/free routines.
6095 *
6096 * An array has the convenience that we don't need to lock read-access
6097 * to it c.f. a linked list.  However our "expanding array" strategy
6098 * means that we should hold a readers lock on the i_ddi_soft_state
6099 * structure.
6100 *
6101 * However, from a performance viewpoint, we need to do it without
6102 * any locks at all -- this also makes it a leaf routine.  The algorithm
6103 * is 'lock-free' because we only discard the pointer arrays at
6104 * ddi_soft_state_fini() time.
6105 */
6106void *
6107ddi_get_soft_state(void *state, int item)
6108{
6109	i_ddi_soft_state	*ss = (i_ddi_soft_state *)state;
6110
6111	ASSERT((ss != NULL) && (item >= 0));
6112
6113	if (item < ss->n_items && ss->array != NULL)
6114		return (ss->array[item]);
6115	return (NULL);
6116}
6117
6118/*
6119 * Free the state structure corresponding to 'item.'   Freeing an
6120 * element that has either gone or was never allocated is not
6121 * considered an error.  Note that we free the state structure, but
6122 * we don't shrink our pointer array, or discard 'dirty' arrays,
6123 * since even a few pointers don't really waste too much memory.
6124 *
6125 * Passing an item number that is out of bounds, or a null pointer will
6126 * provoke an error message.
6127 */
6128void
6129ddi_soft_state_free(void *state, int item)
6130{
6131	i_ddi_soft_state	*ss = (i_ddi_soft_state *)state;
6132	void			**array;
6133	void			*element;
6134	static char		msg[] = "ddi_soft_state_free:";
6135
6136	if (ss == NULL) {
6137		cmn_err(CE_WARN, "%s null handle: %s",
6138		    msg, mod_containing_pc(caller()));
6139		return;
6140	}
6141
6142	element = NULL;
6143
6144	mutex_enter(&ss->lock);
6145
6146	if ((array = ss->array) == NULL || ss->size == 0) {
6147		cmn_err(CE_WARN, "%s bad handle: %s",
6148		    msg, mod_containing_pc(caller()));
6149	} else if (item < 0 || item >= ss->n_items) {
6150		cmn_err(CE_WARN, "%s item %d not in range [0..%lu]: %s",
6151		    msg, item, ss->n_items - 1, mod_containing_pc(caller()));
6152	} else if (array[item] != NULL) {
6153		element = array[item];
6154		array[item] = NULL;
6155	}
6156
6157	mutex_exit(&ss->lock);
6158
6159	if (element)
6160		kmem_free(element, ss->size);
6161}
6162
6163/*
6164 * Free the entire set of pointers, and any
6165 * soft state structures contained therein.
6166 *
6167 * Note that we don't grab the ss->lock mutex, even though
6168 * we're inspecting the various fields of the data structure.
6169 *
6170 * There is an implicit assumption that this routine will
6171 * never run concurrently with any of the above on this
6172 * particular state structure i.e. by the time the driver
6173 * calls this routine, there should be no other threads
6174 * running in the driver.
6175 */
6176void
6177ddi_soft_state_fini(void **state_p)
6178{
6179	i_ddi_soft_state	*ss, *dirty;
6180	int			item;
6181	static char		msg[] = "ddi_soft_state_fini:";
6182
6183	if (state_p == NULL ||
6184	    (ss = (i_ddi_soft_state *)(*state_p)) == NULL) {
6185		cmn_err(CE_WARN, "%s null handle: %s",
6186		    msg, mod_containing_pc(caller()));
6187		return;
6188	}
6189
6190	if (ss->size == 0) {
6191		cmn_err(CE_WARN, "%s bad handle: %s",
6192		    msg, mod_containing_pc(caller()));
6193		return;
6194	}
6195
6196	if (ss->n_items > 0) {
6197		for (item = 0; item < ss->n_items; item++)
6198			ddi_soft_state_free(ss, item);
6199		kmem_free(ss->array, ss->n_items * sizeof (void *));
6200	}
6201
6202	/*
6203	 * Now delete any dirty arrays from previous 'grow' operations
6204	 */
6205	for (dirty = ss->next; dirty; dirty = ss->next) {
6206		ss->next = dirty->next;
6207		kmem_free(dirty->array, dirty->n_items * sizeof (void *));
6208		kmem_free(dirty, sizeof (*dirty));
6209	}
6210
6211	mutex_destroy(&ss->lock);
6212	kmem_free(ss, sizeof (*ss));
6213
6214	*state_p = NULL;
6215}
6216
6217#define	SS_N_ITEMS_PER_HASH	16
6218#define	SS_MIN_HASH_SZ		16
6219#define	SS_MAX_HASH_SZ		4096
6220
6221int
6222ddi_soft_state_bystr_init(ddi_soft_state_bystr **state_p, size_t size,
6223    int n_items)
6224{
6225	i_ddi_soft_state_bystr	*sss;
6226	int			hash_sz;
6227
6228	ASSERT(state_p && size && n_items);
6229	if ((state_p == NULL) || (size == 0) || (n_items == 0))
6230		return (EINVAL);
6231
6232	/* current implementation is based on hash, convert n_items to hash */
6233	hash_sz = n_items / SS_N_ITEMS_PER_HASH;
6234	if (hash_sz < SS_MIN_HASH_SZ)
6235		hash_sz = SS_MIN_HASH_SZ;
6236	else if (hash_sz > SS_MAX_HASH_SZ)
6237		hash_sz = SS_MAX_HASH_SZ;
6238
6239	/* allocate soft_state pool */
6240	sss = kmem_zalloc(sizeof (*sss), KM_SLEEP);
6241	sss->ss_size = size;
6242	sss->ss_mod_hash = mod_hash_create_strhash("soft_state_bystr",
6243	    hash_sz, mod_hash_null_valdtor);
6244	*state_p = (ddi_soft_state_bystr *)sss;
6245	return (0);
6246}
6247
6248int
6249ddi_soft_state_bystr_zalloc(ddi_soft_state_bystr *state, const char *str)
6250{
6251	i_ddi_soft_state_bystr	*sss = (i_ddi_soft_state_bystr *)state;
6252	void			*sso;
6253	char			*dup_str;
6254
6255	ASSERT(sss && str && sss->ss_mod_hash);
6256	if ((sss == NULL) || (str == NULL) || (sss->ss_mod_hash == NULL))
6257		return (DDI_FAILURE);
6258	sso = kmem_zalloc(sss->ss_size, KM_SLEEP);
6259	dup_str = i_ddi_strdup((char *)str, KM_SLEEP);
6260	if (mod_hash_insert(sss->ss_mod_hash,
6261	    (mod_hash_key_t)dup_str, (mod_hash_val_t)sso) == 0)
6262		return (DDI_SUCCESS);
6263
6264	/*
6265	 * The only error from an strhash insert is caused by a duplicate key.
6266	 * We refuse to tread on an existing elements, so free and fail.
6267	 */
6268	kmem_free(dup_str, strlen(dup_str) + 1);
6269	kmem_free(sso, sss->ss_size);
6270	return (DDI_FAILURE);
6271}
6272
6273void *
6274ddi_soft_state_bystr_get(ddi_soft_state_bystr *state, const char *str)
6275{
6276	i_ddi_soft_state_bystr	*sss = (i_ddi_soft_state_bystr *)state;
6277	void			*sso;
6278
6279	ASSERT(sss && str && sss->ss_mod_hash);
6280	if ((sss == NULL) || (str == NULL) || (sss->ss_mod_hash == NULL))
6281		return (NULL);
6282
6283	if (mod_hash_find(sss->ss_mod_hash,
6284	    (mod_hash_key_t)str, (mod_hash_val_t *)&sso) == 0)
6285		return (sso);
6286	return (NULL);
6287}
6288
6289void
6290ddi_soft_state_bystr_free(ddi_soft_state_bystr *state, const char *str)
6291{
6292	i_ddi_soft_state_bystr	*sss = (i_ddi_soft_state_bystr *)state;
6293	void			*sso;
6294
6295	ASSERT(sss && str && sss->ss_mod_hash);
6296	if ((sss == NULL) || (str == NULL) || (sss->ss_mod_hash == NULL))
6297		return;
6298
6299	(void) mod_hash_remove(sss->ss_mod_hash,
6300	    (mod_hash_key_t)str, (mod_hash_val_t *)&sso);
6301	kmem_free(sso, sss->ss_size);
6302}
6303
6304void
6305ddi_soft_state_bystr_fini(ddi_soft_state_bystr **state_p)
6306{
6307	i_ddi_soft_state_bystr	*sss;
6308
6309	ASSERT(state_p);
6310	if (state_p == NULL)
6311		return;
6312
6313	sss = (i_ddi_soft_state_bystr *)(*state_p);
6314	if (sss == NULL)
6315		return;
6316
6317	ASSERT(sss->ss_mod_hash);
6318	if (sss->ss_mod_hash) {
6319		mod_hash_destroy_strhash(sss->ss_mod_hash);
6320		sss->ss_mod_hash = NULL;
6321	}
6322
6323	kmem_free(sss, sizeof (*sss));
6324	*state_p = NULL;
6325}
6326
6327/*
6328 * The ddi_strid_* routines provide string-to-index management utilities.
6329 */
6330/* allocate and initialize an strid set */
6331int
6332ddi_strid_init(ddi_strid **strid_p, int n_items)
6333{
6334	i_ddi_strid	*ss;
6335	int		hash_sz;
6336
6337	if (strid_p == NULL)
6338		return (DDI_FAILURE);
6339
6340	/* current implementation is based on hash, convert n_items to hash */
6341	hash_sz = n_items / SS_N_ITEMS_PER_HASH;
6342	if (hash_sz < SS_MIN_HASH_SZ)
6343		hash_sz = SS_MIN_HASH_SZ;
6344	else if (hash_sz > SS_MAX_HASH_SZ)
6345		hash_sz = SS_MAX_HASH_SZ;
6346
6347	ss = kmem_alloc(sizeof (*ss), KM_SLEEP);
6348	ss->strid_chunksz = n_items;
6349	ss->strid_spacesz = n_items;
6350	ss->strid_space = id_space_create("strid", 1, n_items);
6351	ss->strid_bystr = mod_hash_create_strhash("strid_bystr", hash_sz,
6352	    mod_hash_null_valdtor);
6353	ss->strid_byid = mod_hash_create_idhash("strid_byid", hash_sz,
6354	    mod_hash_null_valdtor);
6355	*strid_p = (ddi_strid *)ss;
6356	return (DDI_SUCCESS);
6357}
6358
6359/* allocate an id mapping within the specified set for str, return id */
6360static id_t
6361i_ddi_strid_alloc(ddi_strid *strid, char *str)
6362{
6363	i_ddi_strid	*ss = (i_ddi_strid *)strid;
6364	id_t		id;
6365	char		*s;
6366
6367	ASSERT(ss && str);
6368	if ((ss == NULL) || (str == NULL))
6369		return (0);
6370
6371	/*
6372	 * Allocate an id using VM_FIRSTFIT in order to keep allocated id
6373	 * range as compressed as possible.  This is important to minimize
6374	 * the amount of space used when the id is used as a ddi_soft_state
6375	 * index by the caller.
6376	 *
6377	 * If the id list is exhausted, increase the size of the list
6378	 * by the chuck size specified in ddi_strid_init and reattempt
6379	 * the allocation
6380	 */
6381	if ((id = id_allocff_nosleep(ss->strid_space)) == (id_t)-1) {
6382		id_space_extend(ss->strid_space, ss->strid_spacesz,
6383		    ss->strid_spacesz + ss->strid_chunksz);
6384		ss->strid_spacesz += ss->strid_chunksz;
6385		if ((id = id_allocff_nosleep(ss->strid_space)) == (id_t)-1)
6386			return (0);
6387	}
6388
6389	/*
6390	 * NOTE: since we create and destroy in unison we can save space by
6391	 * using bystr key as the byid value.  This means destroy must occur
6392	 * in (byid, bystr) order.
6393	 */
6394	s = i_ddi_strdup(str, KM_SLEEP);
6395	if (mod_hash_insert(ss->strid_bystr, (mod_hash_key_t)s,
6396	    (mod_hash_val_t)(intptr_t)id) != 0) {
6397		ddi_strid_free(strid, id);
6398		return (0);
6399	}
6400	if (mod_hash_insert(ss->strid_byid, (mod_hash_key_t)(intptr_t)id,
6401	    (mod_hash_val_t)s) != 0) {
6402		ddi_strid_free(strid, id);
6403		return (0);
6404	}
6405
6406	/* NOTE: s if freed on mod_hash_destroy by mod_hash_strval_dtor */
6407	return (id);
6408}
6409
6410/* allocate an id mapping within the specified set for str, return id */
6411id_t
6412ddi_strid_alloc(ddi_strid *strid, char *str)
6413{
6414	return (i_ddi_strid_alloc(strid, str));
6415}
6416
6417/* return the id within the specified strid given the str */
6418id_t
6419ddi_strid_str2id(ddi_strid *strid, char *str)
6420{
6421	i_ddi_strid	*ss = (i_ddi_strid *)strid;
6422	id_t		id = 0;
6423	mod_hash_val_t	hv;
6424
6425	ASSERT(ss && str);
6426	if (ss && str && (mod_hash_find(ss->strid_bystr,
6427	    (mod_hash_key_t)str, &hv) == 0))
6428		id = (int)(intptr_t)hv;
6429	return (id);
6430}
6431
6432/* return str within the specified strid given the id */
6433char *
6434ddi_strid_id2str(ddi_strid *strid, id_t id)
6435{
6436	i_ddi_strid	*ss = (i_ddi_strid *)strid;
6437	char		*str = NULL;
6438	mod_hash_val_t	hv;
6439
6440	ASSERT(ss && id > 0);
6441	if (ss && (id > 0) && (mod_hash_find(ss->strid_byid,
6442	    (mod_hash_key_t)(uintptr_t)id, &hv) == 0))
6443		str = (char *)hv;
6444	return (str);
6445}
6446
6447/* free the id mapping within the specified strid */
6448void
6449ddi_strid_free(ddi_strid *strid, id_t id)
6450{
6451	i_ddi_strid	*ss = (i_ddi_strid *)strid;
6452	char		*str;
6453
6454	ASSERT(ss && id > 0);
6455	if ((ss == NULL) || (id <= 0))
6456		return;
6457
6458	/* bystr key is byid value: destroy order must be (byid, bystr) */
6459	str = ddi_strid_id2str(strid, id);
6460	(void) mod_hash_destroy(ss->strid_byid, (mod_hash_key_t)(uintptr_t)id);
6461	id_free(ss->strid_space, id);
6462
6463	if (str)
6464		(void) mod_hash_destroy(ss->strid_bystr, (mod_hash_key_t)str);
6465}
6466
6467/* destroy the strid set */
6468void
6469ddi_strid_fini(ddi_strid **strid_p)
6470{
6471	i_ddi_strid	*ss;
6472
6473	ASSERT(strid_p);
6474	if (strid_p == NULL)
6475		return;
6476
6477	ss = (i_ddi_strid *)(*strid_p);
6478	if (ss == NULL)
6479		return;
6480
6481	/* bystr key is byid value: destroy order must be (byid, bystr) */
6482	if (ss->strid_byid)
6483		mod_hash_destroy_hash(ss->strid_byid);
6484	if (ss->strid_byid)
6485		mod_hash_destroy_hash(ss->strid_bystr);
6486	if (ss->strid_space)
6487		id_space_destroy(ss->strid_space);
6488	kmem_free(ss, sizeof (*ss));
6489	*strid_p = NULL;
6490}
6491
6492/*
6493 * This sets the devi_addr entry in the dev_info structure 'dip' to 'name'.
6494 * Storage is double buffered to prevent updates during devi_addr use -
6495 * double buffering is adaquate for reliable ddi_deviname() consumption.
6496 * The double buffer is not freed until dev_info structure destruction
6497 * (by i_ddi_free_node).
6498 */
6499void
6500ddi_set_name_addr(dev_info_t *dip, char *name)
6501{
6502	char	*buf = DEVI(dip)->devi_addr_buf;
6503	char	*newaddr;
6504
6505	if (buf == NULL) {
6506		buf = kmem_zalloc(2 * MAXNAMELEN, KM_SLEEP);
6507		DEVI(dip)->devi_addr_buf = buf;
6508	}
6509
6510	if (name) {
6511		ASSERT(strlen(name) < MAXNAMELEN);
6512		newaddr = (DEVI(dip)->devi_addr == buf) ?
6513		    (buf + MAXNAMELEN) : buf;
6514		(void) strlcpy(newaddr, name, MAXNAMELEN);
6515	} else
6516		newaddr = NULL;
6517
6518	DEVI(dip)->devi_addr = newaddr;
6519}
6520
6521char *
6522ddi_get_name_addr(dev_info_t *dip)
6523{
6524	return (DEVI(dip)->devi_addr);
6525}
6526
6527void
6528ddi_set_parent_data(dev_info_t *dip, void *pd)
6529{
6530	DEVI(dip)->devi_parent_data = pd;
6531}
6532
6533void *
6534ddi_get_parent_data(dev_info_t *dip)
6535{
6536	return (DEVI(dip)->devi_parent_data);
6537}
6538
6539/*
6540 * ddi_name_to_major: returns the major number of a named module,
6541 * derived from the current driver alias binding.
6542 *
6543 * Caveat: drivers should avoid the use of this function, in particular
6544 * together with ddi_get_name/ddi_binding name, as per
6545 *	major = ddi_name_to_major(ddi_get_name(devi));
6546 * ddi_name_to_major() relies on the state of the device/alias binding,
6547 * which can and does change dynamically as aliases are administered
6548 * over time.  An attached device instance cannot rely on the major
6549 * number returned by ddi_name_to_major() to match its own major number.
6550 *
6551 * For driver use, ddi_driver_major() reliably returns the major number
6552 * for the module to which the device was bound at attach time over
6553 * the life of the instance.
6554 *	major = ddi_driver_major(dev_info_t *)
6555 */
6556major_t
6557ddi_name_to_major(char *name)
6558{
6559	return (mod_name_to_major(name));
6560}
6561
6562/*
6563 * ddi_major_to_name: Returns the module name bound to a major number.
6564 */
6565char *
6566ddi_major_to_name(major_t major)
6567{
6568	return (mod_major_to_name(major));
6569}
6570
6571/*
6572 * Return the name of the devinfo node pointed at by 'dip' in the buffer
6573 * pointed at by 'name.'  A devinfo node is named as a result of calling
6574 * ddi_initchild().
6575 *
6576 * Note: the driver must be held before calling this function!
6577 */
6578char *
6579ddi_deviname(dev_info_t *dip, char *name)
6580{
6581	char *addrname;
6582	char none = '\0';
6583
6584	if (dip == ddi_root_node()) {
6585		*name = '\0';
6586		return (name);
6587	}
6588
6589	if (i_ddi_node_state(dip) < DS_BOUND) {
6590		addrname = &none;
6591	} else {
6592		/*
6593		 * Use ddi_get_name_addr() without checking state so we get
6594		 * a unit-address if we are called after ddi_set_name_addr()
6595		 * by nexus DDI_CTL_INITCHILD code, but before completing
6596		 * node promotion to DS_INITIALIZED.  We currently have
6597		 * two situations where we are called in this state:
6598		 *   o  For framework processing of a path-oriented alias.
6599		 *   o  If a SCSA nexus driver calls ddi_devid_register()
6600		 *	from it's tran_tgt_init(9E) implementation.
6601		 */
6602		addrname = ddi_get_name_addr(dip);
6603		if (addrname == NULL)
6604			addrname = &none;
6605	}
6606
6607	if (*addrname == '\0') {
6608		(void) sprintf(name, "/%s", ddi_node_name(dip));
6609	} else {
6610		(void) sprintf(name, "/%s@%s", ddi_node_name(dip), addrname);
6611	}
6612
6613	return (name);
6614}
6615
6616/*
6617 * Spits out the name of device node, typically name@addr, for a given node,
6618 * using the driver name, not the nodename.
6619 *
6620 * Used by match_parent. Not to be used elsewhere.
6621 */
6622char *
6623i_ddi_parname(dev_info_t *dip, char *name)
6624{
6625	char *addrname;
6626
6627	if (dip == ddi_root_node()) {
6628		*name = '\0';
6629		return (name);
6630	}
6631
6632	ASSERT(i_ddi_node_state(dip) >= DS_INITIALIZED);
6633
6634	if (*(addrname = ddi_get_name_addr(dip)) == '\0')
6635		(void) sprintf(name, "%s", ddi_binding_name(dip));
6636	else
6637		(void) sprintf(name, "%s@%s", ddi_binding_name(dip), addrname);
6638	return (name);
6639}
6640
6641static char *
6642pathname_work(dev_info_t *dip, char *path)
6643{
6644	char *bp;
6645
6646	if (dip == ddi_root_node()) {
6647		*path = '\0';
6648		return (path);
6649	}
6650	(void) pathname_work(ddi_get_parent(dip), path);
6651	bp = path + strlen(path);
6652	(void) ddi_deviname(dip, bp);
6653	return (path);
6654}
6655
6656char *
6657ddi_pathname(dev_info_t *dip, char *path)
6658{
6659	return (pathname_work(dip, path));
6660}
6661
6662char *
6663ddi_pathname_minor(struct ddi_minor_data *dmdp, char *path)
6664{
6665	if (dmdp->dip == NULL)
6666		*path = '\0';
6667	else {
6668		(void) ddi_pathname(dmdp->dip, path);
6669		if (dmdp->ddm_name) {
6670			(void) strcat(path, ":");
6671			(void) strcat(path, dmdp->ddm_name);
6672		}
6673	}
6674	return (path);
6675}
6676
6677static char *
6678pathname_work_obp(dev_info_t *dip, char *path)
6679{
6680	char *bp;
6681	char *obp_path;
6682
6683	/*
6684	 * look up the "obp-path" property, return the path if it exists
6685	 */
6686	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
6687	    "obp-path", &obp_path) == DDI_PROP_SUCCESS) {
6688		(void) strcpy(path, obp_path);
6689		ddi_prop_free(obp_path);
6690		return (path);
6691	}
6692
6693	/*
6694	 * stop at root, no obp path
6695	 */
6696	if (dip == ddi_root_node()) {
6697		return (NULL);