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 = NULL;
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			if (buffer != NULL)
1374				bcopy(propp->prop_val, buffer, propp->prop_len);
1375			mutex_exit(&(DEVI(dip)->devi_lock));
1376			return (DDI_PROP_SUCCESS);
1377		}
1378
1379		mutex_exit(&(DEVI(dip)->devi_lock));
1380		if (prealloc)
1381			kmem_free(prealloc, plength);
1382		prealloc = NULL;
1383
1384		/*
1385		 * Prop not found, call parent bus_ops to deal with possible
1386		 * h/w layer (possible PROM defined props, etc.) and to
1387		 * possibly ascend the hierarchy, if allowed by flags.
1388		 */
1389		pdip = (dev_info_t *)DEVI(dip)->devi_parent;
1390
1391		/*
1392		 * One last call for the root driver PROM props?
1393		 */
1394		if (dip == ddi_root_node())  {
1395			return (ddi_bus_prop_op(dev, dip, dip, prop_op,
1396			    flags, name, valuep, (int *)lengthp));
1397		}
1398
1399		/*
1400		 * We may have been called to check for properties
1401		 * within a single devinfo node that has no parent -
1402		 * see make_prop()
1403		 */
1404		if (pdip == NULL) {
1405			ASSERT((flags &
1406			    (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM)) ==
1407			    (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM));
1408			return (DDI_PROP_NOT_FOUND);
1409		}
1410
1411		/*
1412		 * Instead of recursing, we do iterative calls up the tree.
1413		 * As a bit of optimization, skip the bus_op level if the
1414		 * node is a s/w node and if the parent's bus_prop_op function
1415		 * is `ddi_bus_prop_op', because we know that in this case,
1416		 * this function does nothing.
1417		 *
1418		 * 4225415: If the parent isn't attached, or the child
1419		 * hasn't been named by the parent yet, use the default
1420		 * ddi_bus_prop_op as a proxy for the parent.  This
1421		 * allows property lookups in any child/parent state to
1422		 * include 'prom' and inherited properties, even when
1423		 * there are no drivers attached to the child or parent.
1424		 */
1425
1426		bop = ddi_bus_prop_op;
1427		if (i_ddi_devi_attached(pdip) &&
1428		    (i_ddi_node_state(dip) >= DS_INITIALIZED))
1429			bop = DEVI(pdip)->devi_ops->devo_bus_ops->bus_prop_op;
1430
1431		i = DDI_PROP_NOT_FOUND;
1432
1433		if ((bop != ddi_bus_prop_op) || ndi_dev_is_prom_node(dip)) {
1434			i = (*bop)(dev, pdip, dip, prop_op,
1435			    flags | DDI_PROP_DONTPASS,
1436			    name, valuep, lengthp);
1437		}
1438
1439		if ((flags & DDI_PROP_DONTPASS) ||
1440		    (i != DDI_PROP_NOT_FOUND))
1441			return (i);
1442
1443		dip = pdip;
1444	}
1445	/*NOTREACHED*/
1446}
1447
1448
1449/*
1450 * ddi_prop_op: The basic property operator for drivers.
1451 *
1452 * In ddi_prop_op, the type of valuep is interpreted based on prop_op:
1453 *
1454 *	prop_op			valuep
1455 *	------			------
1456 *
1457 *	PROP_LEN		<unused>
1458 *
1459 *	PROP_LEN_AND_VAL_BUF	Pointer to callers buffer
1460 *
1461 *	PROP_LEN_AND_VAL_ALLOC	Address of callers pointer (will be set to
1462 *				address of allocated buffer, if successful)
1463 */
1464int
1465ddi_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
1466    char *name, caddr_t valuep, int *lengthp)
1467{
1468	int	i;
1469
1470	ASSERT((mod_flags & DDI_PROP_TYPE_MASK) == 0);
1471
1472	/*
1473	 * If this was originally an LDI prop lookup then we bail here.
1474	 * The reason is that the LDI property lookup interfaces first call
1475	 * a drivers prop_op() entry point to allow it to override
1476	 * properties.  But if we've made it here, then the driver hasn't
1477	 * overriden any properties.  We don't want to continue with the
1478	 * property search here because we don't have any type inforamtion.
1479	 * When we return failure, the LDI interfaces will then proceed to
1480	 * call the typed property interfaces to look up the property.
1481	 */
1482	if (mod_flags & DDI_PROP_DYNAMIC)
1483		return (DDI_PROP_NOT_FOUND);
1484
1485	/*
1486	 * check for pre-typed property consumer asking for typed property:
1487	 * see e_ddi_getprop_int64.
1488	 */
1489	if (mod_flags & DDI_PROP_CONSUMER_TYPED)
1490		mod_flags |= DDI_PROP_TYPE_INT64;
1491	mod_flags |= DDI_PROP_TYPE_ANY;
1492
1493	i = ddi_prop_search_common(dev, dip, prop_op,
1494	    mod_flags, name, valuep, (uint_t *)lengthp);
1495	if (i == DDI_PROP_FOUND_1275)
1496		return (DDI_PROP_SUCCESS);
1497	return (i);
1498}
1499
1500/*
1501 * ddi_prop_op_nblocks_blksize: The basic property operator for drivers that
1502 * maintain size in number of blksize blocks.  Provides a dynamic property
1503 * implementation for size oriented properties based on nblocks64 and blksize
1504 * values passed in by the driver.  Fallback to ddi_prop_op if the nblocks64
1505 * is too large.  This interface should not be used with a nblocks64 that
1506 * represents the driver's idea of how to represent unknown, if nblocks is
1507 * unknown use ddi_prop_op.
1508 */
1509int
1510ddi_prop_op_nblocks_blksize(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1511    int mod_flags, char *name, caddr_t valuep, int *lengthp,
1512    uint64_t nblocks64, uint_t blksize)
1513{
1514	uint64_t size64;
1515	int	blkshift;
1516
1517	/* convert block size to shift value */
1518	ASSERT(BIT_ONLYONESET(blksize));
1519	blkshift = highbit(blksize) - 1;
1520
1521	/*
1522	 * There is no point in supporting nblocks64 values that don't have
1523	 * an accurate uint64_t byte count representation.
1524	 */
1525	if (nblocks64 >= (UINT64_MAX >> blkshift))
1526		return (ddi_prop_op(dev, dip, prop_op, mod_flags,
1527		    name, valuep, lengthp));
1528
1529	size64 = nblocks64 << blkshift;
1530	return (ddi_prop_op_size_blksize(dev, dip, prop_op, mod_flags,
1531	    name, valuep, lengthp, size64, blksize));
1532}
1533
1534/*
1535 * ddi_prop_op_nblocks: ddi_prop_op_nblocks_blksize with DEV_BSIZE blksize.
1536 */
1537int
1538ddi_prop_op_nblocks(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1539    int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t nblocks64)
1540{
1541	return (ddi_prop_op_nblocks_blksize(dev, dip, prop_op,
1542	    mod_flags, name, valuep, lengthp, nblocks64, DEV_BSIZE));
1543}
1544
1545/*
1546 * ddi_prop_op_size_blksize: The basic property operator for block drivers that
1547 * maintain size in bytes. Provides a of dynamic property implementation for
1548 * size oriented properties based on size64 value and blksize passed in by the
1549 * driver.  Fallback to ddi_prop_op if the size64 is too large. This interface
1550 * should not be used with a size64 that represents the driver's idea of how
1551 * to represent unknown, if size is unknown use ddi_prop_op.
1552 *
1553 * NOTE: the legacy "nblocks"/"size" properties are treated as 32-bit unsigned
1554 * integers. While the most likely interface to request them ([bc]devi_size)
1555 * is declared int (signed) there is no enforcement of this, which means we
1556 * can't enforce limitations here without risking regression.
1557 */
1558int
1559ddi_prop_op_size_blksize(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1560    int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t size64,
1561    uint_t blksize)
1562{
1563	uint64_t nblocks64;
1564	int	callers_length;
1565	caddr_t	buffer;
1566	int	blkshift;
1567
1568	/*
1569	 * This is a kludge to support capture of size(9P) pure dynamic
1570	 * properties in snapshots for non-cmlb code (without exposing
1571	 * i_ddi_prop_dyn changes). When everyone uses cmlb, this code
1572	 * should be removed.
1573	 */
1574	if (i_ddi_prop_dyn_driver_get(dip) == NULL) {
1575		static i_ddi_prop_dyn_t prop_dyn_size[] = {
1576		    {"Size",		DDI_PROP_TYPE_INT64,	S_IFCHR},
1577		    {"Nblocks",		DDI_PROP_TYPE_INT64,	S_IFBLK},
1578		    {NULL}
1579		};
1580		i_ddi_prop_dyn_driver_set(dip, prop_dyn_size);
1581	}
1582
1583	/* convert block size to shift value */
1584	ASSERT(BIT_ONLYONESET(blksize));
1585	blkshift = highbit(blksize) - 1;
1586
1587	/* compute DEV_BSIZE nblocks value */
1588	nblocks64 = size64 >> blkshift;
1589
1590	/* get callers length, establish length of our dynamic properties */
1591	callers_length = *lengthp;
1592
1593	if (strcmp(name, "Nblocks") == 0)
1594		*lengthp = sizeof (uint64_t);
1595	else if (strcmp(name, "Size") == 0)
1596		*lengthp = sizeof (uint64_t);
1597	else if ((strcmp(name, "nblocks") == 0) && (nblocks64 < UINT_MAX))
1598		*lengthp = sizeof (uint32_t);
1599	else if ((strcmp(name, "size") == 0) && (size64 < UINT_MAX))
1600		*lengthp = sizeof (uint32_t);
1601	else if ((strcmp(name, "blksize") == 0) && (blksize < UINT_MAX))
1602		*lengthp = sizeof (uint32_t);
1603	else {
1604		/* fallback to ddi_prop_op */
1605		return (ddi_prop_op(dev, dip, prop_op, mod_flags,
1606		    name, valuep, lengthp));
1607	}
1608
1609	/* service request for the length of the property */
1610	if (prop_op == PROP_LEN)
1611		return (DDI_PROP_SUCCESS);
1612
1613	switch (prop_op) {
1614	case PROP_LEN_AND_VAL_ALLOC:
1615		if ((buffer = kmem_alloc(*lengthp,
1616		    (mod_flags & DDI_PROP_CANSLEEP) ?
1617		    KM_SLEEP : KM_NOSLEEP)) == NULL)
1618			return (DDI_PROP_NO_MEMORY);
1619
1620		*(caddr_t *)valuep = buffer;	/* set callers buf ptr */
1621		break;
1622
1623	case PROP_LEN_AND_VAL_BUF:
1624		/* the length of the property and the request must match */
1625		if (callers_length != *lengthp)
1626			return (DDI_PROP_INVAL_ARG);
1627
1628		buffer = valuep;		/* get callers buf ptr */
1629		break;
1630
1631	default:
1632		return (DDI_PROP_INVAL_ARG);
1633	}
1634
1635	/* transfer the value into the buffer */
1636	if (strcmp(name, "Nblocks") == 0)
1637		*((uint64_t *)buffer) = nblocks64;
1638	else if (strcmp(name, "Size") == 0)
1639		*((uint64_t *)buffer) = size64;
1640	else if (strcmp(name, "nblocks") == 0)
1641		*((uint32_t *)buffer) = (uint32_t)nblocks64;
1642	else if (strcmp(name, "size") == 0)
1643		*((uint32_t *)buffer) = (uint32_t)size64;
1644	else if (strcmp(name, "blksize") == 0)
1645		*((uint32_t *)buffer) = (uint32_t)blksize;
1646	return (DDI_PROP_SUCCESS);
1647}
1648
1649/*
1650 * ddi_prop_op_size: ddi_prop_op_size_blksize with DEV_BSIZE block size.
1651 */
1652int
1653ddi_prop_op_size(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1654    int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t size64)
1655{
1656	return (ddi_prop_op_size_blksize(dev, dip, prop_op,
1657	    mod_flags, name, valuep, lengthp, size64, DEV_BSIZE));
1658}
1659
1660/*
1661 * Variable length props...
1662 */
1663
1664/*
1665 * ddi_getlongprop:	Get variable length property len+val into a buffer
1666 *		allocated by property provider via kmem_alloc. Requester
1667 *		is responsible for freeing returned property via kmem_free.
1668 *
1669 *	Arguments:
1670 *
1671 *	dev_t:	Input:	dev_t of property.
1672 *	dip:	Input:	dev_info_t pointer of child.
1673 *	flags:	Input:	Possible flag modifiers are:
1674 *		DDI_PROP_DONTPASS:	Don't pass to parent if prop not found.
1675 *		DDI_PROP_CANSLEEP:	Memory allocation may sleep.
1676 *	name:	Input:	name of property.
1677 *	valuep:	Output:	Addr of callers buffer pointer.
1678 *	lengthp:Output:	*lengthp will contain prop length on exit.
1679 *
1680 *	Possible Returns:
1681 *
1682 *		DDI_PROP_SUCCESS:	Prop found and returned.
1683 *		DDI_PROP_NOT_FOUND:	Prop not found
1684 *		DDI_PROP_UNDEFINED:	Prop explicitly undefined.
1685 *		DDI_PROP_NO_MEMORY:	Prop found, but unable to alloc mem.
1686 */
1687
1688int
1689ddi_getlongprop(dev_t dev, dev_info_t *dip, int flags,
1690    char *name, caddr_t valuep, int *lengthp)
1691{
1692	return (ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_ALLOC,
1693	    flags, name, valuep, lengthp));
1694}
1695
1696/*
1697 *
1698 * ddi_getlongprop_buf:		Get long prop into pre-allocated callers
1699 *				buffer. (no memory allocation by provider).
1700 *
1701 *	dev_t:	Input:	dev_t of property.
1702 *	dip:	Input:	dev_info_t pointer of child.
1703 *	flags:	Input:	DDI_PROP_DONTPASS or NULL
1704 *	name:	Input:	name of property
1705 *	valuep:	Input:	ptr to callers buffer.
1706 *	lengthp:I/O:	ptr to length of callers buffer on entry,
1707 *			actual length of property on exit.
1708 *
1709 *	Possible returns:
1710 *
1711 *		DDI_PROP_SUCCESS	Prop found and returned
1712 *		DDI_PROP_NOT_FOUND	Prop not found
1713 *		DDI_PROP_UNDEFINED	Prop explicitly undefined.
1714 *		DDI_PROP_BUF_TOO_SMALL	Prop found, callers buf too small,
1715 *					no value returned, but actual prop
1716 *					length returned in *lengthp
1717 *
1718 */
1719
1720int
1721ddi_getlongprop_buf(dev_t dev, dev_info_t *dip, int flags,
1722    char *name, caddr_t valuep, int *lengthp)
1723{
1724	return (ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_BUF,
1725	    flags, name, valuep, lengthp));
1726}
1727
1728/*
1729 * Integer/boolean sized props.
1730 *
1731 * Call is value only... returns found boolean or int sized prop value or
1732 * defvalue if prop not found or is wrong length or is explicitly undefined.
1733 * Only flag is DDI_PROP_DONTPASS...
1734 *
1735 * By convention, this interface returns boolean (0) sized properties
1736 * as value (int)1.
1737 *
1738 * This never returns an error, if property not found or specifically
1739 * undefined, the input `defvalue' is returned.
1740 */
1741
1742int
1743ddi_getprop(dev_t dev, dev_info_t *dip, int flags, char *name, int defvalue)
1744{
1745	int	propvalue = defvalue;
1746	int	proplength = sizeof (int);
1747	int	error;
1748
1749	error = ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_BUF,
1750	    flags, name, (caddr_t)&propvalue, &proplength);
1751
1752	if ((error == DDI_PROP_SUCCESS) && (proplength == 0))
1753		propvalue = 1;
1754
1755	return (propvalue);
1756}
1757
1758/*
1759 * Get prop length interface: flags are 0 or DDI_PROP_DONTPASS
1760 * if returns DDI_PROP_SUCCESS, length returned in *lengthp.
1761 */
1762
1763int
1764ddi_getproplen(dev_t dev, dev_info_t *dip, int flags, char *name, int *lengthp)
1765{
1766	return (ddi_prop_op(dev, dip, PROP_LEN, flags, name, NULL, lengthp));
1767}
1768
1769/*
1770 * Allocate a struct prop_driver_data, along with 'size' bytes
1771 * for decoded property data.  This structure is freed by
1772 * calling ddi_prop_free(9F).
1773 */
1774static void *
1775ddi_prop_decode_alloc(size_t size, void (*prop_free)(struct prop_driver_data *))
1776{
1777	struct prop_driver_data *pdd;
1778
1779	/*
1780	 * Allocate a structure with enough memory to store the decoded data.
1781	 */
1782	pdd = kmem_zalloc(sizeof (struct prop_driver_data) + size, KM_SLEEP);
1783	pdd->pdd_size = (sizeof (struct prop_driver_data) + size);
1784	pdd->pdd_prop_free = prop_free;
1785
1786	/*
1787	 * Return a pointer to the location to put the decoded data.
1788	 */
1789	return ((void *)((caddr_t)pdd + sizeof (struct prop_driver_data)));
1790}
1791
1792/*
1793 * Allocated the memory needed to store the encoded data in the property
1794 * handle.
1795 */
1796static int
1797ddi_prop_encode_alloc(prop_handle_t *ph, size_t size)
1798{
1799	/*
1800	 * If size is zero, then set data to NULL and size to 0.  This
1801	 * is a boolean property.
1802	 */
1803	if (size == 0) {
1804		ph->ph_size = 0;
1805		ph->ph_data = NULL;
1806		ph->ph_cur_pos = NULL;
1807		ph->ph_save_pos = NULL;
1808	} else {
1809		if (ph->ph_flags == DDI_PROP_DONTSLEEP) {
1810			ph->ph_data = kmem_zalloc(size, KM_NOSLEEP);
1811			if (ph->ph_data == NULL)
1812				return (DDI_PROP_NO_MEMORY);
1813		} else
1814			ph->ph_data = kmem_zalloc(size, KM_SLEEP);
1815		ph->ph_size = size;
1816		ph->ph_cur_pos = ph->ph_data;
1817		ph->ph_save_pos = ph->ph_data;
1818	}
1819	return (DDI_PROP_SUCCESS);
1820}
1821
1822/*
1823 * Free the space allocated by the lookup routines.  Each lookup routine
1824 * returns a pointer to the decoded data to the driver.  The driver then
1825 * passes this pointer back to us.  This data actually lives in a struct
1826 * prop_driver_data.  We use negative indexing to find the beginning of
1827 * the structure and then free the entire structure using the size and
1828 * the free routine stored in the structure.
1829 */
1830void
1831ddi_prop_free(void *datap)
1832{
1833	struct prop_driver_data *pdd;
1834
1835	/*
1836	 * Get the structure
1837	 */
1838	pdd = (struct prop_driver_data *)
1839	    ((caddr_t)datap - sizeof (struct prop_driver_data));
1840	/*
1841	 * Call the free routine to free it
1842	 */
1843	(*pdd->pdd_prop_free)(pdd);
1844}
1845
1846/*
1847 * Free the data associated with an array of ints,
1848 * allocated with ddi_prop_decode_alloc().
1849 */
1850static void
1851ddi_prop_free_ints(struct prop_driver_data *pdd)
1852{
1853	kmem_free(pdd, pdd->pdd_size);
1854}
1855
1856/*
1857 * Free a single string property or a single string contained within
1858 * the argv style return value of an array of strings.
1859 */
1860static void
1861ddi_prop_free_string(struct prop_driver_data *pdd)
1862{
1863	kmem_free(pdd, pdd->pdd_size);
1864
1865}
1866
1867/*
1868 * Free an array of strings.
1869 */
1870static void
1871ddi_prop_free_strings(struct prop_driver_data *pdd)
1872{
1873	kmem_free(pdd, pdd->pdd_size);
1874}
1875
1876/*
1877 * Free the data associated with an array of bytes.
1878 */
1879static void
1880ddi_prop_free_bytes(struct prop_driver_data *pdd)
1881{
1882	kmem_free(pdd, pdd->pdd_size);
1883}
1884
1885/*
1886 * Reset the current location pointer in the property handle to the
1887 * beginning of the data.
1888 */
1889void
1890ddi_prop_reset_pos(prop_handle_t *ph)
1891{
1892	ph->ph_cur_pos = ph->ph_data;
1893	ph->ph_save_pos = ph->ph_data;
1894}
1895
1896/*
1897 * Restore the current location pointer in the property handle to the
1898 * saved position.
1899 */
1900void
1901ddi_prop_save_pos(prop_handle_t *ph)
1902{
1903	ph->ph_save_pos = ph->ph_cur_pos;
1904}
1905
1906/*
1907 * Save the location that the current location pointer is pointing to..
1908 */
1909void
1910ddi_prop_restore_pos(prop_handle_t *ph)
1911{
1912	ph->ph_cur_pos = ph->ph_save_pos;
1913}
1914
1915/*
1916 * Property encode/decode functions
1917 */
1918
1919/*
1920 * Decode a single integer property
1921 */
1922static int
1923ddi_prop_fm_decode_int(prop_handle_t *ph, void *data, uint_t *nelements)
1924{
1925	int	i;
1926	int	tmp;
1927
1928	/*
1929	 * If there is nothing to decode return an error
1930	 */
1931	if (ph->ph_size == 0)
1932		return (DDI_PROP_END_OF_DATA);
1933
1934	/*
1935	 * Decode the property as a single integer and return it
1936	 * in data if we were able to decode it.
1937	 */
1938	i = DDI_PROP_INT(ph, DDI_PROP_CMD_DECODE, &tmp);
1939	if (i < DDI_PROP_RESULT_OK) {
1940		switch (i) {
1941		case DDI_PROP_RESULT_EOF:
1942			return (DDI_PROP_END_OF_DATA);
1943
1944		case DDI_PROP_RESULT_ERROR:
1945			return (DDI_PROP_CANNOT_DECODE);
1946		}
1947	}
1948
1949	*(int *)data = tmp;
1950	*nelements = 1;
1951	return (DDI_PROP_SUCCESS);
1952}
1953
1954/*
1955 * Decode a single 64 bit integer property
1956 */
1957static int
1958ddi_prop_fm_decode_int64(prop_handle_t *ph, void *data, uint_t *nelements)
1959{
1960	int	i;
1961	int64_t	tmp;
1962
1963	/*
1964	 * If there is nothing to decode return an error
1965	 */
1966	if (ph->ph_size == 0)
1967		return (DDI_PROP_END_OF_DATA);
1968
1969	/*
1970	 * Decode the property as a single integer and return it
1971	 * in data if we were able to decode it.
1972	 */
1973	i = DDI_PROP_INT64(ph, DDI_PROP_CMD_DECODE, &tmp);
1974	if (i < DDI_PROP_RESULT_OK) {
1975		switch (i) {
1976		case DDI_PROP_RESULT_EOF:
1977			return (DDI_PROP_END_OF_DATA);
1978
1979		case DDI_PROP_RESULT_ERROR:
1980			return (DDI_PROP_CANNOT_DECODE);
1981		}
1982	}
1983
1984	*(int64_t *)data = tmp;
1985	*nelements = 1;
1986	return (DDI_PROP_SUCCESS);
1987}
1988
1989/*
1990 * Decode an array of integers property
1991 */
1992static int
1993ddi_prop_fm_decode_ints(prop_handle_t *ph, void *data, uint_t *nelements)
1994{
1995	int	i;
1996	int	cnt = 0;
1997	int	*tmp;
1998	int	*intp;
1999	int	n;
2000
2001	/*
2002	 * Figure out how many array elements there are by going through the
2003	 * data without decoding it first and counting.
2004	 */
2005	for (;;) {
2006		i = DDI_PROP_INT(ph, DDI_PROP_CMD_SKIP, NULL);
2007		if (i < 0)
2008			break;
2009		cnt++;
2010	}
2011
2012	/*
2013	 * If there are no elements return an error
2014	 */
2015	if (cnt == 0)
2016		return (DDI_PROP_END_OF_DATA);
2017
2018	/*
2019	 * If we cannot skip through the data, we cannot decode it
2020	 */
2021	if (i == DDI_PROP_RESULT_ERROR)
2022		return (DDI_PROP_CANNOT_DECODE);
2023
2024	/*
2025	 * Reset the data pointer to the beginning of the encoded data
2026	 */
2027	ddi_prop_reset_pos(ph);
2028
2029	/*
2030	 * Allocated memory to store the decoded value in.
2031	 */
2032	intp = ddi_prop_decode_alloc((cnt * sizeof (int)),
2033	    ddi_prop_free_ints);
2034
2035	/*
2036	 * Decode each element and place it in the space we just allocated
2037	 */
2038	tmp = intp;
2039	for (n = 0; n < cnt; n++, tmp++) {
2040		i = DDI_PROP_INT(ph, DDI_PROP_CMD_DECODE, tmp);
2041		if (i < DDI_PROP_RESULT_OK) {
2042			/*
2043			 * Free the space we just allocated
2044			 * and return an error.
2045			 */
2046			ddi_prop_free(intp);
2047			switch (i) {
2048			case DDI_PROP_RESULT_EOF:
2049				return (DDI_PROP_END_OF_DATA);
2050
2051			case DDI_PROP_RESULT_ERROR:
2052				return (DDI_PROP_CANNOT_DECODE);
2053			}
2054		}
2055	}
2056
2057	*nelements = cnt;
2058	*(int **)data = intp;
2059
2060	return (DDI_PROP_SUCCESS);
2061}
2062
2063/*
2064 * Decode a 64 bit integer array property
2065 */
2066static int
2067ddi_prop_fm_decode_int64_array(prop_handle_t *ph, void *data, uint_t *nelements)
2068{
2069	int	i;
2070	int	n;
2071	int	cnt = 0;
2072	int64_t	*tmp;
2073	int64_t	*intp;
2074
2075	/*
2076	 * Count the number of array elements by going
2077	 * through the data without decoding it.
2078	 */
2079	for (;;) {
2080		i = DDI_PROP_INT64(ph, DDI_PROP_CMD_SKIP, NULL);
2081		if (i < 0)
2082			break;
2083		cnt++;
2084	}
2085
2086	/*
2087	 * If there are no elements return an error
2088	 */
2089	if (cnt == 0)
2090		return (DDI_PROP_END_OF_DATA);
2091
2092	/*
2093	 * If we cannot skip through the data, we cannot decode it
2094	 */
2095	if (i == DDI_PROP_RESULT_ERROR)
2096		return (DDI_PROP_CANNOT_DECODE);
2097
2098	/*
2099	 * Reset the data pointer to the beginning of the encoded data
2100	 */
2101	ddi_prop_reset_pos(ph);
2102
2103	/*
2104	 * Allocate memory to store the decoded value.
2105	 */
2106	intp = ddi_prop_decode_alloc((cnt * sizeof (int64_t)),
2107	    ddi_prop_free_ints);
2108
2109	/*
2110	 * Decode each element and place it in the space allocated
2111	 */
2112	tmp = intp;
2113	for (n = 0; n < cnt; n++, tmp++) {
2114		i = DDI_PROP_INT64(ph, DDI_PROP_CMD_DECODE, tmp);
2115		if (i < DDI_PROP_RESULT_OK) {
2116			/*
2117			 * Free the space we just allocated
2118			 * and return an error.
2119			 */
2120			ddi_prop_free(intp);
2121			switch (i) {
2122			case DDI_PROP_RESULT_EOF:
2123				return (DDI_PROP_END_OF_DATA);
2124
2125			case DDI_PROP_RESULT_ERROR:
2126				return (DDI_PROP_CANNOT_DECODE);
2127			}
2128		}
2129	}
2130
2131	*nelements = cnt;
2132	*(int64_t **)data = intp;
2133
2134	return (DDI_PROP_SUCCESS);
2135}
2136
2137/*
2138 * Encode an array of integers property (Can be one element)
2139 */
2140int
2141ddi_prop_fm_encode_ints(prop_handle_t *ph, void *data, uint_t nelements)
2142{
2143	int	i;
2144	int	*tmp;
2145	int	cnt;
2146	int	size;
2147
2148	/*
2149	 * If there is no data, we cannot do anything
2150	 */
2151	if (nelements == 0)
2152		return (DDI_PROP_CANNOT_ENCODE);
2153
2154	/*
2155	 * Get the size of an encoded int.
2156	 */
2157	size = DDI_PROP_INT(ph, DDI_PROP_CMD_GET_ESIZE, NULL);
2158
2159	if (size < DDI_PROP_RESULT_OK) {
2160		switch (size) {
2161		case DDI_PROP_RESULT_EOF:
2162			return (DDI_PROP_END_OF_DATA);
2163
2164		case DDI_PROP_RESULT_ERROR:
2165			return (DDI_PROP_CANNOT_ENCODE);
2166		}
2167	}
2168
2169	/*
2170	 * Allocate space in the handle to store the encoded int.
2171	 */
2172	if (ddi_prop_encode_alloc(ph, size * nelements) !=
2173	    DDI_PROP_SUCCESS)
2174		return (DDI_PROP_NO_MEMORY);
2175
2176	/*
2177	 * Encode the array of ints.
2178	 */
2179	tmp = (int *)data;
2180	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
2181		i = DDI_PROP_INT(ph, DDI_PROP_CMD_ENCODE, tmp);
2182		if (i < DDI_PROP_RESULT_OK) {
2183			switch (i) {
2184			case DDI_PROP_RESULT_EOF:
2185				return (DDI_PROP_END_OF_DATA);
2186
2187			case DDI_PROP_RESULT_ERROR:
2188				return (DDI_PROP_CANNOT_ENCODE);
2189			}
2190		}
2191	}
2192
2193	return (DDI_PROP_SUCCESS);
2194}
2195
2196
2197/*
2198 * Encode a 64 bit integer array property
2199 */
2200int
2201ddi_prop_fm_encode_int64(prop_handle_t *ph, void *data, uint_t nelements)
2202{
2203	int i;
2204	int cnt;
2205	int size;
2206	int64_t *tmp;
2207
2208	/*
2209	 * If there is no data, we cannot do anything
2210	 */
2211	if (nelements == 0)
2212		return (DDI_PROP_CANNOT_ENCODE);
2213
2214	/*
2215	 * Get the size of an encoded 64 bit int.
2216	 */
2217	size = DDI_PROP_INT64(ph, DDI_PROP_CMD_GET_ESIZE, NULL);
2218
2219	if (size < DDI_PROP_RESULT_OK) {
2220		switch (size) {
2221		case DDI_PROP_RESULT_EOF:
2222			return (DDI_PROP_END_OF_DATA);
2223
2224		case DDI_PROP_RESULT_ERROR:
2225			return (DDI_PROP_CANNOT_ENCODE);
2226		}
2227	}
2228
2229	/*
2230	 * Allocate space in the handle to store the encoded int.
2231	 */
2232	if (ddi_prop_encode_alloc(ph, size * nelements) !=
2233	    DDI_PROP_SUCCESS)
2234		return (DDI_PROP_NO_MEMORY);
2235
2236	/*
2237	 * Encode the array of ints.
2238	 */
2239	tmp = (int64_t *)data;
2240	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
2241		i = DDI_PROP_INT64(ph, DDI_PROP_CMD_ENCODE, tmp);
2242		if (i < DDI_PROP_RESULT_OK) {
2243			switch (i) {
2244			case DDI_PROP_RESULT_EOF:
2245				return (DDI_PROP_END_OF_DATA);
2246
2247			case DDI_PROP_RESULT_ERROR:
2248				return (DDI_PROP_CANNOT_ENCODE);
2249			}
2250		}
2251	}
2252
2253	return (DDI_PROP_SUCCESS);
2254}
2255
2256/*
2257 * Decode a single string property
2258 */
2259static int
2260ddi_prop_fm_decode_string(prop_handle_t *ph, void *data, uint_t *nelements)
2261{
2262	char		*tmp;
2263	char		*str;
2264	int		i;
2265	int		size;
2266
2267	/*
2268	 * If there is nothing to decode return an error
2269	 */
2270	if (ph->ph_size == 0)
2271		return (DDI_PROP_END_OF_DATA);
2272
2273	/*
2274	 * Get the decoded size of the encoded string.
2275	 */
2276	size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL);
2277	if (size < DDI_PROP_RESULT_OK) {
2278		switch (size) {
2279		case DDI_PROP_RESULT_EOF:
2280			return (DDI_PROP_END_OF_DATA);
2281
2282		case DDI_PROP_RESULT_ERROR:
2283			return (DDI_PROP_CANNOT_DECODE);
2284		}
2285	}
2286
2287	/*
2288	 * Allocated memory to store the decoded value in.
2289	 */
2290	str = ddi_prop_decode_alloc((size_t)size, ddi_prop_free_string);
2291
2292	ddi_prop_reset_pos(ph);
2293
2294	/*
2295	 * Decode the str and place it in the space we just allocated
2296	 */
2297	tmp = str;
2298	i = DDI_PROP_STR(ph, DDI_PROP_CMD_DECODE, tmp);
2299	if (i < DDI_PROP_RESULT_OK) {
2300		/*
2301		 * Free the space we just allocated
2302		 * and return an error.
2303		 */
2304		ddi_prop_free(str);
2305		switch (i) {
2306		case DDI_PROP_RESULT_EOF:
2307			return (DDI_PROP_END_OF_DATA);
2308
2309		case DDI_PROP_RESULT_ERROR:
2310			return (DDI_PROP_CANNOT_DECODE);
2311		}
2312	}
2313
2314	*(char **)data = str;
2315	*nelements = 1;
2316
2317	return (DDI_PROP_SUCCESS);
2318}
2319
2320/*
2321 * Decode an array of strings.
2322 */
2323int
2324ddi_prop_fm_decode_strings(prop_handle_t *ph, void *data, uint_t *nelements)
2325{
2326	int		cnt = 0;
2327	char		**strs;
2328	char		**tmp;
2329	char		*ptr;
2330	int		i;
2331	int		n;
2332	int		size;
2333	size_t		nbytes;
2334
2335	/*
2336	 * Figure out how many array elements there are by going through the
2337	 * data without decoding it first and counting.
2338	 */
2339	for (;;) {
2340		i = DDI_PROP_STR(ph, DDI_PROP_CMD_SKIP, NULL);
2341		if (i < 0)
2342			break;
2343		cnt++;
2344	}
2345
2346	/*
2347	 * If there are no elements return an error
2348	 */
2349	if (cnt == 0)
2350		return (DDI_PROP_END_OF_DATA);
2351
2352	/*
2353	 * If we cannot skip through the data, we cannot decode it
2354	 */
2355	if (i == DDI_PROP_RESULT_ERROR)
2356		return (DDI_PROP_CANNOT_DECODE);
2357
2358	/*
2359	 * Reset the data pointer to the beginning of the encoded data
2360	 */
2361	ddi_prop_reset_pos(ph);
2362
2363	/*
2364	 * Figure out how much memory we need for the sum total
2365	 */
2366	nbytes = (cnt + 1) * sizeof (char *);
2367
2368	for (n = 0; n < cnt; n++) {
2369		/*
2370		 * Get the decoded size of the current encoded string.
2371		 */
2372		size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL);
2373		if (size < DDI_PROP_RESULT_OK) {
2374			switch (size) {
2375			case DDI_PROP_RESULT_EOF:
2376				return (DDI_PROP_END_OF_DATA);
2377
2378			case DDI_PROP_RESULT_ERROR:
2379				return (DDI_PROP_CANNOT_DECODE);
2380			}
2381		}
2382
2383		nbytes += size;
2384	}
2385
2386	/*
2387	 * Allocate memory in which to store the decoded strings.
2388	 */
2389	strs = ddi_prop_decode_alloc(nbytes, ddi_prop_free_strings);
2390
2391	/*
2392	 * Set up pointers for each string by figuring out yet
2393	 * again how long each string is.
2394	 */
2395	ddi_prop_reset_pos(ph);
2396	ptr = (caddr_t)strs + ((cnt + 1) * sizeof (char *));
2397	for (tmp = strs, n = 0; n < cnt; n++, tmp++) {
2398		/*
2399		 * Get the decoded size of the current encoded string.
2400		 */
2401		size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL);
2402		if (size < DDI_PROP_RESULT_OK) {
2403			ddi_prop_free(strs);
2404			switch (size) {
2405			case DDI_PROP_RESULT_EOF:
2406				return (DDI_PROP_END_OF_DATA);
2407
2408			case DDI_PROP_RESULT_ERROR:
2409				return (DDI_PROP_CANNOT_DECODE);
2410			}
2411		}
2412
2413		*tmp = ptr;
2414		ptr += size;
2415	}
2416
2417	/*
2418	 * String array is terminated by a NULL
2419	 */
2420	*tmp = NULL;
2421
2422	/*
2423	 * Finally, we can decode each string
2424	 */
2425	ddi_prop_reset_pos(ph);
2426	for (tmp = strs, n = 0; n < cnt; n++, tmp++) {
2427		i = DDI_PROP_STR(ph, DDI_PROP_CMD_DECODE, *tmp);
2428		if (i < DDI_PROP_RESULT_OK) {
2429			/*
2430			 * Free the space we just allocated
2431			 * and return an error
2432			 */
2433			ddi_prop_free(strs);
2434			switch (i) {
2435			case DDI_PROP_RESULT_EOF:
2436				return (DDI_PROP_END_OF_DATA);
2437
2438			case DDI_PROP_RESULT_ERROR:
2439				return (DDI_PROP_CANNOT_DECODE);
2440			}
2441		}
2442	}
2443
2444	*(char ***)data = strs;
2445	*nelements = cnt;
2446
2447	return (DDI_PROP_SUCCESS);
2448}
2449
2450/*
2451 * Encode a string.
2452 */
2453int
2454ddi_prop_fm_encode_string(prop_handle_t *ph, void *data, uint_t nelements)
2455{
2456	char		**tmp;
2457	int		size;
2458	int		i;
2459
2460	/*
2461	 * If there is no data, we cannot do anything
2462	 */
2463	if (nelements == 0)
2464		return (DDI_PROP_CANNOT_ENCODE);
2465
2466	/*
2467	 * Get the size of the encoded string.
2468	 */
2469	tmp = (char **)data;
2470	size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_ESIZE, *tmp);
2471	if (size < DDI_PROP_RESULT_OK) {
2472		switch (size) {
2473		case DDI_PROP_RESULT_EOF:
2474			return (DDI_PROP_END_OF_DATA);
2475
2476		case DDI_PROP_RESULT_ERROR:
2477			return (DDI_PROP_CANNOT_ENCODE);
2478		}
2479	}
2480
2481	/*
2482	 * Allocate space in the handle to store the encoded string.
2483	 */
2484	if (ddi_prop_encode_alloc(ph, size) != DDI_PROP_SUCCESS)
2485		return (DDI_PROP_NO_MEMORY);
2486
2487	ddi_prop_reset_pos(ph);
2488
2489	/*
2490	 * Encode the string.
2491	 */
2492	tmp = (char **)data;
2493	i = DDI_PROP_STR(ph, DDI_PROP_CMD_ENCODE, *tmp);
2494	if (i < DDI_PROP_RESULT_OK) {
2495		switch (i) {
2496		case DDI_PROP_RESULT_EOF:
2497			return (DDI_PROP_END_OF_DATA);
2498
2499		case DDI_PROP_RESULT_ERROR:
2500			return (DDI_PROP_CANNOT_ENCODE);
2501		}
2502	}
2503
2504	return (DDI_PROP_SUCCESS);
2505}
2506
2507
2508/*
2509 * Encode an array of strings.
2510 */
2511int
2512ddi_prop_fm_encode_strings(prop_handle_t *ph, void *data, uint_t nelements)
2513{
2514	int		cnt = 0;
2515	char		**tmp;
2516	int		size;
2517	uint_t		total_size;
2518	int		i;
2519
2520	/*
2521	 * If there is no data, we cannot do anything
2522	 */
2523	if (nelements == 0)
2524		return (DDI_PROP_CANNOT_ENCODE);
2525
2526	/*
2527	 * Get the total size required to encode all the strings.
2528	 */
2529	total_size = 0;
2530	tmp = (char **)data;
2531	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
2532		size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_ESIZE, *tmp);
2533		if (size < DDI_PROP_RESULT_OK) {
2534			switch (size) {
2535			case DDI_PROP_RESULT_EOF:
2536				return (DDI_PROP_END_OF_DATA);
2537
2538			case DDI_PROP_RESULT_ERROR:
2539				return (DDI_PROP_CANNOT_ENCODE);
2540			}
2541		}
2542		total_size += (uint_t)size;
2543	}
2544
2545	/*
2546	 * Allocate space in the handle to store the encoded strings.
2547	 */
2548	if (ddi_prop_encode_alloc(ph, total_size) != DDI_PROP_SUCCESS)
2549		return (DDI_PROP_NO_MEMORY);
2550
2551	ddi_prop_reset_pos(ph);
2552
2553	/*
2554	 * Encode the array of strings.
2555	 */
2556	tmp = (char **)data;
2557	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
2558		i = DDI_PROP_STR(ph, DDI_PROP_CMD_ENCODE, *tmp);
2559		if (i < DDI_PROP_RESULT_OK) {
2560			switch (i) {
2561			case DDI_PROP_RESULT_EOF:
2562				return (DDI_PROP_END_OF_DATA);
2563
2564			case DDI_PROP_RESULT_ERROR:
2565				return (DDI_PROP_CANNOT_ENCODE);
2566			}
2567		}
2568	}
2569
2570	return (DDI_PROP_SUCCESS);
2571}
2572
2573
2574/*
2575 * Decode an array of bytes.
2576 */
2577static int
2578ddi_prop_fm_decode_bytes(prop_handle_t *ph, void *data, uint_t *nelements)
2579{
2580	uchar_t		*tmp;
2581	int		nbytes;
2582	int		i;
2583
2584	/*
2585	 * If there are no elements return an error
2586	 */
2587	if (ph->ph_size == 0)
2588		return (DDI_PROP_END_OF_DATA);
2589
2590	/*
2591	 * Get the size of the encoded array of bytes.
2592	 */
2593	nbytes = DDI_PROP_BYTES(ph, DDI_PROP_CMD_GET_DSIZE,
2594	    data, ph->ph_size);
2595	if (nbytes < DDI_PROP_RESULT_OK) {
2596		switch (nbytes) {
2597		case DDI_PROP_RESULT_EOF:
2598			return (DDI_PROP_END_OF_DATA);
2599
2600		case DDI_PROP_RESULT_ERROR:
2601			return (DDI_PROP_CANNOT_DECODE);
2602		}
2603	}
2604
2605	/*
2606	 * Allocated memory to store the decoded value in.
2607	 */
2608	tmp = ddi_prop_decode_alloc(nbytes, ddi_prop_free_bytes);
2609
2610	/*
2611	 * Decode each element and place it in the space we just allocated
2612	 */
2613	i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_DECODE, tmp, nbytes);
2614	if (i < DDI_PROP_RESULT_OK) {
2615		/*
2616		 * Free the space we just allocated
2617		 * and return an error
2618		 */
2619		ddi_prop_free(tmp);
2620		switch (i) {
2621		case DDI_PROP_RESULT_EOF:
2622			return (DDI_PROP_END_OF_DATA);
2623
2624		case DDI_PROP_RESULT_ERROR:
2625			return (DDI_PROP_CANNOT_DECODE);
2626		}
2627	}
2628
2629	*(uchar_t **)data = tmp;
2630	*nelements = nbytes;
2631
2632	return (DDI_PROP_SUCCESS);
2633}
2634
2635/*
2636 * Encode an array of bytes.
2637 */
2638int
2639ddi_prop_fm_encode_bytes(prop_handle_t *ph, void *data, uint_t nelements)
2640{
2641	int		size;
2642	int		i;
2643
2644	/*
2645	 * If there are no elements, then this is a boolean property,
2646	 * so just create a property handle with no data and return.
2647	 */
2648	if (nelements == 0) {
2649		(void) ddi_prop_encode_alloc(ph, 0);
2650		return (DDI_PROP_SUCCESS);
2651	}
2652
2653	/*
2654	 * Get the size of the encoded array of bytes.
2655	 */
2656	size = DDI_PROP_BYTES(ph, DDI_PROP_CMD_GET_ESIZE, (uchar_t *)data,
2657	    nelements);
2658	if (size < DDI_PROP_RESULT_OK) {
2659		switch (size) {
2660		case DDI_PROP_RESULT_EOF:
2661			return (DDI_PROP_END_OF_DATA);
2662
2663		case DDI_PROP_RESULT_ERROR:
2664			return (DDI_PROP_CANNOT_DECODE);
2665		}
2666	}
2667
2668	/*
2669	 * Allocate space in the handle to store the encoded bytes.
2670	 */
2671	if (ddi_prop_encode_alloc(ph, (uint_t)size) != DDI_PROP_SUCCESS)
2672		return (DDI_PROP_NO_MEMORY);
2673
2674	/*
2675	 * Encode the array of bytes.
2676	 */
2677	i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_ENCODE, (uchar_t *)data,
2678	    nelements);
2679	if (i < DDI_PROP_RESULT_OK) {
2680		switch (i) {
2681		case DDI_PROP_RESULT_EOF:
2682			return (DDI_PROP_END_OF_DATA);
2683
2684		case DDI_PROP_RESULT_ERROR:
2685			return (DDI_PROP_CANNOT_ENCODE);
2686		}
2687	}
2688
2689	return (DDI_PROP_SUCCESS);
2690}
2691
2692/*
2693 * OBP 1275 integer, string and byte operators.
2694 *
2695 * DDI_PROP_CMD_DECODE:
2696 *
2697 *	DDI_PROP_RESULT_ERROR:		cannot decode the data
2698 *	DDI_PROP_RESULT_EOF:		end of data
2699 *	DDI_PROP_OK:			data was decoded
2700 *
2701 * DDI_PROP_CMD_ENCODE:
2702 *
2703 *	DDI_PROP_RESULT_ERROR:		cannot encode the data
2704 *	DDI_PROP_RESULT_EOF:		end of data
2705 *	DDI_PROP_OK:			data was encoded
2706 *
2707 * DDI_PROP_CMD_SKIP:
2708 *
2709 *	DDI_PROP_RESULT_ERROR:		cannot skip the data
2710 *	DDI_PROP_RESULT_EOF:		end of data
2711 *	DDI_PROP_OK:			data was skipped
2712 *
2713 * DDI_PROP_CMD_GET_ESIZE:
2714 *
2715 *	DDI_PROP_RESULT_ERROR:		cannot get encoded size
2716 *	DDI_PROP_RESULT_EOF:		end of data
2717 *	> 0:				the encoded size
2718 *
2719 * DDI_PROP_CMD_GET_DSIZE:
2720 *
2721 *	DDI_PROP_RESULT_ERROR:		cannot get decoded size
2722 *	DDI_PROP_RESULT_EOF:		end of data
2723 *	> 0:				the decoded size
2724 */
2725
2726/*
2727 * OBP 1275 integer operator
2728 *
2729 * OBP properties are a byte stream of data, so integers may not be
2730 * properly aligned.  Therefore we need to copy them one byte at a time.
2731 */
2732int
2733ddi_prop_1275_int(prop_handle_t *ph, uint_t cmd, int *data)
2734{
2735	int	i;
2736
2737	switch (cmd) {
2738	case DDI_PROP_CMD_DECODE:
2739		/*
2740		 * Check that there is encoded data
2741		 */
2742		if (ph->ph_cur_pos == NULL || ph->ph_size == 0)
2743			return (DDI_PROP_RESULT_ERROR);
2744		if (ph->ph_flags & PH_FROM_PROM) {
2745			i = MIN(ph->ph_size, PROP_1275_INT_SIZE);
2746			if ((int *)ph->ph_cur_pos > ((int *)ph->ph_data +
2747			    ph->ph_size - i))
2748				return (DDI_PROP_RESULT_ERROR);
2749		} else {
2750			if (ph->ph_size < sizeof (int) ||
2751			    ((int *)ph->ph_cur_pos > ((int *)ph->ph_data +
2752			    ph->ph_size - sizeof (int))))
2753				return (DDI_PROP_RESULT_ERROR);
2754		}
2755
2756		/*
2757		 * Copy the integer, using the implementation-specific
2758		 * copy function if the property is coming from the PROM.
2759		 */
2760		if (ph->ph_flags & PH_FROM_PROM) {
2761			*data = impl_ddi_prop_int_from_prom(
2762			    (uchar_t *)ph->ph_cur_pos,
2763			    (ph->ph_size < PROP_1275_INT_SIZE) ?
2764			    ph->ph_size : PROP_1275_INT_SIZE);
2765		} else {
2766			bcopy(ph->ph_cur_pos, data, sizeof (int));
2767		}
2768
2769		/*
2770		 * Move the current location to the start of the next
2771		 * bit of undecoded data.
2772		 */
2773		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
2774		    PROP_1275_INT_SIZE;
2775		return (DDI_PROP_RESULT_OK);
2776
2777	case DDI_PROP_CMD_ENCODE:
2778		/*
2779		 * Check that there is room to encoded the data
2780		 */
2781		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
2782		    ph->ph_size < PROP_1275_INT_SIZE ||
2783		    ((int *)ph->ph_cur_pos > ((int *)ph->ph_data +
2784		    ph->ph_size - sizeof (int))))
2785			return (DDI_PROP_RESULT_ERROR);
2786
2787		/*
2788		 * Encode the integer into the byte stream one byte at a
2789		 * time.
2790		 */
2791		bcopy(data, ph->ph_cur_pos, sizeof (int));
2792
2793		/*
2794		 * Move the current location to the start of the next bit of
2795		 * space where we can store encoded data.
2796		 */
2797		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE;
2798		return (DDI_PROP_RESULT_OK);
2799
2800	case DDI_PROP_CMD_SKIP:
2801		/*
2802		 * Check that there is encoded data
2803		 */
2804		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
2805		    ph->ph_size < PROP_1275_INT_SIZE)
2806			return (DDI_PROP_RESULT_ERROR);
2807
2808
2809		if ((caddr_t)ph->ph_cur_pos ==
2810		    (caddr_t)ph->ph_data + ph->ph_size) {
2811			return (DDI_PROP_RESULT_EOF);
2812		} else if ((caddr_t)ph->ph_cur_pos >
2813		    (caddr_t)ph->ph_data + ph->ph_size) {
2814			return (DDI_PROP_RESULT_EOF);
2815		}
2816
2817		/*
2818		 * Move the current location to the start of the next bit of
2819		 * undecoded data.
2820		 */
2821		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE;
2822		return (DDI_PROP_RESULT_OK);
2823
2824	case DDI_PROP_CMD_GET_ESIZE:
2825		/*
2826		 * Return the size of an encoded integer on OBP
2827		 */
2828		return (PROP_1275_INT_SIZE);
2829
2830	case DDI_PROP_CMD_GET_DSIZE:
2831		/*
2832		 * Return the size of a decoded integer on the system.
2833		 */
2834		return (sizeof (int));
2835
2836	default:
2837#ifdef DEBUG
2838		panic("ddi_prop_1275_int: %x impossible", cmd);
2839		/*NOTREACHED*/
2840#else
2841		return (DDI_PROP_RESULT_ERROR);
2842#endif	/* DEBUG */
2843	}
2844}
2845
2846/*
2847 * 64 bit integer operator.
2848 *
2849 * This is an extension, defined by Sun, to the 1275 integer
2850 * operator.  This routine handles the encoding/decoding of
2851 * 64 bit integer properties.
2852 */
2853int
2854ddi_prop_int64_op(prop_handle_t *ph, uint_t cmd, int64_t *data)
2855{
2856
2857	switch (cmd) {
2858	case DDI_PROP_CMD_DECODE:
2859		/*
2860		 * Check that there is encoded data
2861		 */
2862		if (ph->ph_cur_pos == NULL || ph->ph_size == 0)
2863			return (DDI_PROP_RESULT_ERROR);
2864		if (ph->ph_flags & PH_FROM_PROM) {
2865			return (DDI_PROP_RESULT_ERROR);
2866		} else {
2867			if (ph->ph_size < sizeof (int64_t) ||
2868			    ((int64_t *)ph->ph_cur_pos >
2869			    ((int64_t *)ph->ph_data +
2870			    ph->ph_size - sizeof (int64_t))))
2871				return (DDI_PROP_RESULT_ERROR);
2872		}
2873		/*
2874		 * Copy the integer, using the implementation-specific
2875		 * copy function if the property is coming from the PROM.
2876		 */
2877		if (ph->ph_flags & PH_FROM_PROM) {
2878			return (DDI_PROP_RESULT_ERROR);
2879		} else {
2880			bcopy(ph->ph_cur_pos, data, sizeof (int64_t));
2881		}
2882
2883		/*
2884		 * Move the current location to the start of the next
2885		 * bit of undecoded data.
2886		 */
2887		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
2888		    sizeof (int64_t);
2889			return (DDI_PROP_RESULT_OK);
2890
2891	case DDI_PROP_CMD_ENCODE:
2892		/*
2893		 * Check that there is room to encoded the data
2894		 */
2895		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
2896		    ph->ph_size < sizeof (int64_t) ||
2897		    ((int64_t *)ph->ph_cur_pos > ((int64_t *)ph->ph_data +
2898		    ph->ph_size - sizeof (int64_t))))
2899			return (DDI_PROP_RESULT_ERROR);
2900
2901		/*
2902		 * Encode the integer into the byte stream one byte at a
2903		 * time.
2904		 */
2905		bcopy(data, ph->ph_cur_pos, sizeof (int64_t));
2906
2907		/*
2908		 * Move the current location to the start of the next bit of
2909		 * space where we can store encoded data.
2910		 */
2911		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
2912		    sizeof (int64_t);
2913		return (DDI_PROP_RESULT_OK);
2914
2915	case DDI_PROP_CMD_SKIP:
2916		/*
2917		 * Check that there is encoded data
2918		 */
2919		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
2920		    ph->ph_size < sizeof (int64_t))
2921			return (DDI_PROP_RESULT_ERROR);
2922
2923		if ((caddr_t)ph->ph_cur_pos ==
2924		    (caddr_t)ph->ph_data + ph->ph_size) {
2925			return (DDI_PROP_RESULT_EOF);
2926		} else if ((caddr_t)ph->ph_cur_pos >
2927		    (caddr_t)ph->ph_data + ph->ph_size) {
2928			return (DDI_PROP_RESULT_EOF);
2929		}
2930
2931		/*
2932		 * Move the current location to the start of
2933		 * the next bit of undecoded data.
2934		 */
2935		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
2936		    sizeof (int64_t);
2937			return (DDI_PROP_RESULT_OK);
2938
2939	case DDI_PROP_CMD_GET_ESIZE:
2940		/*
2941		 * Return the size of an encoded integer on OBP
2942		 */
2943		return (sizeof (int64_t));
2944
2945	case DDI_PROP_CMD_GET_DSIZE:
2946		/*
2947		 * Return the size of a decoded integer on the system.
2948		 */
2949		return (sizeof (int64_t));
2950
2951	default:
2952#ifdef DEBUG
2953		panic("ddi_prop_int64_op: %x impossible", cmd);
2954		/*NOTREACHED*/
2955#else
2956		return (DDI_PROP_RESULT_ERROR);
2957#endif  /* DEBUG */
2958	}
2959}
2960
2961/*
2962 * OBP 1275 string operator.
2963 *
2964 * OBP strings are NULL terminated.
2965 */
2966int
2967ddi_prop_1275_string(prop_handle_t *ph, uint_t cmd, char *data)
2968{
2969	int	n;
2970	char	*p;
2971	char	*end;
2972
2973	switch (cmd) {
2974	case DDI_PROP_CMD_DECODE:
2975		/*
2976		 * Check that there is encoded data
2977		 */
2978		if (ph->ph_cur_pos == NULL || ph->ph_size == 0) {
2979			return (DDI_PROP_RESULT_ERROR);
2980		}
2981
2982		/*
2983		 * Match DDI_PROP_CMD_GET_DSIZE logic for when to stop and
2984		 * how to NULL terminate result.
2985		 */
2986		p = (char *)ph->ph_cur_pos;
2987		end = (char *)ph->ph_data + ph->ph_size;
2988		if (p >= end)
2989			return (DDI_PROP_RESULT_EOF);
2990
2991		while (p < end) {
2992			*data++ = *p;
2993			if (*p++ == 0) {	/* NULL from OBP */
2994				ph->ph_cur_pos = p;
2995				return (DDI_PROP_RESULT_OK);
2996			}
2997		}
2998
2999		/*
3000		 * If OBP did not NULL terminate string, which happens
3001		 * (at least) for 'true'/'false' boolean values, account for
3002		 * the space and store null termination on decode.
3003		 */
3004		ph->ph_cur_pos = p;
3005		*data = 0;
3006		return (DDI_PROP_RESULT_OK);
3007
3008	case DDI_PROP_CMD_ENCODE:
3009		/*
3010		 * Check that there is room to encoded the data
3011		 */
3012		if (ph->ph_cur_pos == NULL || ph->ph_size == 0) {
3013			return (DDI_PROP_RESULT_ERROR);
3014		}
3015
3016		n = strlen(data) + 1;
3017		if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
3018		    ph->ph_size - n)) {
3019			return (DDI_PROP_RESULT_ERROR);
3020		}
3021
3022		/*
3023		 * Copy the NULL terminated string
3024		 */
3025		bcopy(data, ph->ph_cur_pos, n);
3026
3027		/*
3028		 * Move the current location to the start of the next bit of
3029		 * space where we can store encoded data.
3030		 */
3031		ph->ph_cur_pos = (char *)ph->ph_cur_pos + n;
3032		return (DDI_PROP_RESULT_OK);
3033
3034	case DDI_PROP_CMD_SKIP:
3035		/*
3036		 * Check that there is encoded data
3037		 */
3038		if (ph->ph_cur_pos == NULL || ph->ph_size == 0) {
3039			return (DDI_PROP_RESULT_ERROR);
3040		}
3041
3042		/*
3043		 * Return the string length plus one for the NULL
3044		 * We know the size of the property, we need to
3045		 * ensure that the string is properly formatted,
3046		 * since we may be looking up random OBP data.
3047		 */
3048		p = (char *)ph->ph_cur_pos;
3049		end = (char *)ph->ph_data + ph->ph_size;
3050		if (p >= end)
3051			return (DDI_PROP_RESULT_EOF);
3052
3053		while (p < end) {
3054			if (*p++ == 0) {	/* NULL from OBP */
3055				ph->ph_cur_pos = p;
3056				return (DDI_PROP_RESULT_OK);
3057			}
3058		}
3059
3060		/*
3061		 * Accommodate the fact that OBP does not always NULL
3062		 * terminate strings.
3063		 */
3064		ph->ph_cur_pos = p;
3065		return (DDI_PROP_RESULT_OK);
3066
3067	case DDI_PROP_CMD_GET_ESIZE:
3068		/*
3069		 * Return the size of the encoded string on OBP.
3070		 */
3071		return (strlen(data) + 1);
3072
3073	case DDI_PROP_CMD_GET_DSIZE:
3074		/*
3075		 * Return the string length plus one for the NULL.
3076		 * We know the size of the property, we need to
3077		 * ensure that the string is properly formatted,
3078		 * since we may be looking up random OBP data.
3079		 */
3080		p = (char *)ph->ph_cur_pos;
3081		end = (char *)ph->ph_data + ph->ph_size;
3082		if (p >= end)
3083			return (DDI_PROP_RESULT_EOF);
3084
3085		for (n = 0; p < end; n++) {
3086			if (*p++ == 0) {	/* NULL from OBP */
3087				ph->ph_cur_pos = p;
3088				return (n + 1);
3089			}
3090		}
3091
3092		/*
3093		 * If OBP did not NULL terminate string, which happens for
3094		 * 'true'/'false' boolean values, account for the space
3095		 * to store null termination here.
3096		 */
3097		ph->ph_cur_pos = p;
3098		return (n + 1);
3099
3100	default:
3101#ifdef DEBUG
3102		panic("ddi_prop_1275_string: %x impossible", cmd);
3103		/*NOTREACHED*/
3104#else
3105		return (DDI_PROP_RESULT_ERROR);
3106#endif	/* DEBUG */
3107	}
3108}
3109
3110/*
3111 * OBP 1275 byte operator
3112 *
3113 * Caller must specify the number of bytes to get.  OBP encodes bytes
3114 * as a byte so there is a 1-to-1 translation.
3115 */
3116int
3117ddi_prop_1275_bytes(prop_handle_t *ph, uint_t cmd, uchar_t *data,
3118	uint_t nelements)
3119{
3120	switch (cmd) {
3121	case DDI_PROP_CMD_DECODE:
3122		/*
3123		 * Check that there is encoded data
3124		 */
3125		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
3126		    ph->ph_size < nelements ||
3127		    ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
3128		    ph->ph_size - nelements)))
3129			return (DDI_PROP_RESULT_ERROR);
3130
3131		/*
3132		 * Copy out the bytes
3133		 */
3134		bcopy(ph->ph_cur_pos, data, nelements);
3135
3136		/*
3137		 * Move the current location
3138		 */
3139		ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements;
3140		return (DDI_PROP_RESULT_OK);
3141
3142	case DDI_PROP_CMD_ENCODE:
3143		/*
3144		 * Check that there is room to encode the data
3145		 */
3146		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
3147		    ph->ph_size < nelements ||
3148		    ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
3149		    ph->ph_size - nelements)))
3150			return (DDI_PROP_RESULT_ERROR);
3151
3152		/*
3153		 * Copy in the bytes
3154		 */
3155		bcopy(data, ph->ph_cur_pos, nelements);
3156
3157		/*
3158		 * Move the current location to the start of the next bit of
3159		 * space where we can store encoded data.
3160		 */
3161		ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements;
3162		return (DDI_PROP_RESULT_OK);
3163
3164	case DDI_PROP_CMD_SKIP:
3165		/*
3166		 * Check that there is encoded data
3167		 */
3168		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
3169		    ph->ph_size < nelements)
3170			return (DDI_PROP_RESULT_ERROR);
3171
3172		if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
3173		    ph->ph_size - nelements))
3174			return (DDI_PROP_RESULT_EOF);
3175
3176		/*
3177		 * Move the current location
3178		 */
3179		ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements;
3180		return (DDI_PROP_RESULT_OK);
3181
3182	case DDI_PROP_CMD_GET_ESIZE:
3183		/*
3184		 * The size in bytes of the encoded size is the
3185		 * same as the decoded size provided by the caller.
3186		 */
3187		return (nelements);
3188
3189	case DDI_PROP_CMD_GET_DSIZE:
3190		/*
3191		 * Just return the number of bytes specified by the caller.
3192		 */
3193		return (nelements);
3194
3195	default:
3196#ifdef DEBUG
3197		panic("ddi_prop_1275_bytes: %x impossible", cmd);
3198		/*NOTREACHED*/
3199#else
3200		return (DDI_PROP_RESULT_ERROR);
3201#endif	/* DEBUG */
3202	}
3203}
3204
3205/*
3206 * Used for properties that come from the OBP, hardware configuration files,
3207 * or that are created by calls to ddi_prop_update(9F).
3208 */
3209static struct prop_handle_ops prop_1275_ops = {
3210	ddi_prop_1275_int,
3211	ddi_prop_1275_string,
3212	ddi_prop_1275_bytes,
3213	ddi_prop_int64_op
3214};
3215
3216
3217/*
3218 * Interface to create/modify a managed property on child's behalf...
3219 * Flags interpreted are:
3220 *	DDI_PROP_CANSLEEP:	Allow memory allocation to sleep.
3221 *	DDI_PROP_SYSTEM_DEF:	Manipulate system list rather than driver list.
3222 *
3223 * Use same dev_t when modifying or undefining a property.
3224 * Search for properties with DDI_DEV_T_ANY to match first named
3225 * property on the list.
3226 *
3227 * Properties are stored LIFO and subsequently will match the first
3228 * `matching' instance.
3229 */
3230
3231/*
3232 * ddi_prop_add:	Add a software defined property
3233 */
3234
3235/*
3236 * define to get a new ddi_prop_t.
3237 * km_flags are KM_SLEEP or KM_NOSLEEP.
3238 */
3239
3240#define	DDI_NEW_PROP_T(km_flags)	\
3241	(kmem_zalloc(sizeof (ddi_prop_t), km_flags))
3242
3243static int
3244ddi_prop_add(dev_t dev, dev_info_t *dip, int flags,
3245    char *name, caddr_t value, int length)
3246{
3247	ddi_prop_t	*new_propp, *propp;
3248	ddi_prop_t	**list_head = &(DEVI(dip)->devi_drv_prop_ptr);
3249	int		km_flags = KM_NOSLEEP;
3250	int		name_buf_len;
3251
3252	/*
3253	 * If dev_t is DDI_DEV_T_ANY or name's length is zero return error.
3254	 */
3255
3256	if (dev == DDI_DEV_T_ANY || name == (char *)0 || strlen(name) == 0)
3257		return (DDI_PROP_INVAL_ARG);
3258
3259	if (flags & DDI_PROP_CANSLEEP)
3260		km_flags = KM_SLEEP;
3261
3262	if (flags & DDI_PROP_SYSTEM_DEF)
3263		list_head = &(DEVI(dip)->devi_sys_prop_ptr);
3264	else if (flags & DDI_PROP_HW_DEF)
3265		list_head = &(DEVI(dip)->devi_hw_prop_ptr);
3266
3267	if ((new_propp = DDI_NEW_PROP_T(km_flags)) == NULL)  {
3268		cmn_err(CE_CONT, prop_no_mem_msg, name);
3269		return (DDI_PROP_NO_MEMORY);
3270	}
3271
3272	/*
3273	 * If dev is major number 0, then we need to do a ddi_name_to_major
3274	 * to get the real major number for the device.  This needs to be
3275	 * done because some drivers need to call ddi_prop_create in their
3276	 * attach routines but they don't have a dev.  By creating the dev
3277	 * ourself if the major number is 0, drivers will not have to know what
3278	 * their major number.	They can just create a dev with major number
3279	 * 0 and pass it in.  For device 0, we will be doing a little extra
3280	 * work by recreating the same dev that we already have, but its the
3281	 * price you pay :-).
3282	 *
3283	 * This fixes bug #1098060.
3284	 */
3285	if (getmajor(dev) == DDI_MAJOR_T_UNKNOWN) {
3286		new_propp->prop_dev =
3287		    makedevice(ddi_name_to_major(DEVI(dip)->devi_binding_name),
3288		    getminor(dev));
3289	} else
3290		new_propp->prop_dev = dev;
3291
3292	/*
3293	 * Allocate space for property name and copy it in...
3294	 */
3295
3296	name_buf_len = strlen(name) + 1;
3297	new_propp->prop_name = kmem_alloc(name_buf_len, km_flags);
3298	if (new_propp->prop_name == 0)	{
3299		kmem_free(new_propp, sizeof (ddi_prop_t));
3300		cmn_err(CE_CONT, prop_no_mem_msg, name);
3301		return (DDI_PROP_NO_MEMORY);
3302	}
3303	bcopy(name, new_propp->prop_name, name_buf_len);
3304
3305	/*
3306	 * Set the property type
3307	 */
3308	new_propp->prop_flags = flags & DDI_PROP_TYPE_MASK;
3309
3310	/*
3311	 * Set length and value ONLY if not an explicit property undefine:
3312	 * NOTE: value and length are zero for explicit undefines.
3313	 */
3314
3315	if (flags & DDI_PROP_UNDEF_IT) {
3316		new_propp->prop_flags |= DDI_PROP_UNDEF_IT;
3317	} else {
3318		if ((new_propp->prop_len = length) != 0) {
3319			new_propp->prop_val = kmem_alloc(length, km_flags);
3320			if (new_propp->prop_val == 0)  {
3321				kmem_free(new_propp->prop_name, name_buf_len);
3322				kmem_free(new_propp, sizeof (ddi_prop_t));
3323				cmn_err(CE_CONT, prop_no_mem_msg, name);
3324				return (DDI_PROP_NO_MEMORY);
3325			}
3326			bcopy(value, new_propp->prop_val, length);
3327		}
3328	}
3329
3330	/*
3331	 * Link property into beginning of list. (Properties are LIFO order.)
3332	 */
3333
3334	mutex_enter(&(DEVI(dip)->devi_lock));
3335	propp = *list_head;
3336	new_propp->prop_next = propp;
3337	*list_head = new_propp;
3338	mutex_exit(&(DEVI(dip)->devi_lock));
3339	return (DDI_PROP_SUCCESS);
3340}
3341
3342
3343/*
3344 * ddi_prop_change:	Modify a software managed property value
3345 *
3346 *			Set new length and value if found.
3347 *			returns DDI_PROP_INVAL_ARG if dev is DDI_DEV_T_ANY or
3348 *			input name is the NULL string.
3349 *			returns DDI_PROP_NO_MEMORY if unable to allocate memory
3350 *
3351 *			Note: an undef can be modified to be a define,
3352 *			(you can't go the other way.)
3353 */
3354
3355static int
3356ddi_prop_change(dev_t dev, dev_info_t *dip, int flags,
3357    char *name, caddr_t value, int length)
3358{
3359	ddi_prop_t	*propp;
3360	ddi_prop_t	**ppropp;
3361	caddr_t		p = NULL;
3362
3363	if ((dev == DDI_DEV_T_ANY) || (name == NULL) || (strlen(name) == 0))
3364		return (DDI_PROP_INVAL_ARG);
3365
3366	/*
3367	 * Preallocate buffer, even if we don't need it...
3368	 */
3369	if (length != 0)  {
3370		p = kmem_alloc(length, (flags & DDI_PROP_CANSLEEP) ?
3371		    KM_SLEEP : KM_NOSLEEP);
3372		if (p == NULL)	{
3373			cmn_err(CE_CONT, prop_no_mem_msg, name);
3374			return (DDI_PROP_NO_MEMORY);
3375		}
3376	}
3377
3378	/*
3379	 * If the dev_t value contains DDI_MAJOR_T_UNKNOWN for the major
3380	 * number, a real dev_t value should be created based upon the dip's
3381	 * binding driver.  See ddi_prop_add...
3382	 */
3383	if (getmajor(dev) == DDI_MAJOR_T_UNKNOWN)
3384		dev = makedevice(
3385		    ddi_name_to_major(DEVI(dip)->devi_binding_name),
3386		    getminor(dev));
3387
3388	/*
3389	 * Check to see if the property exists.  If so we modify it.
3390	 * Else we create it by calling ddi_prop_add().
3391	 */
3392	mutex_enter(&(DEVI(dip)->devi_lock));
3393	ppropp = &DEVI(dip)->devi_drv_prop_ptr;
3394	if (flags & DDI_PROP_SYSTEM_DEF)
3395		ppropp = &DEVI(dip)->devi_sys_prop_ptr;
3396	else if (flags & DDI_PROP_HW_DEF)
3397		ppropp = &DEVI(dip)->devi_hw_prop_ptr;
3398
3399	if ((propp = i_ddi_prop_search(dev, name, flags, ppropp)) != NULL) {
3400		/*
3401		 * Need to reallocate buffer?  If so, do it
3402		 * carefully (reuse same space if new prop
3403		 * is same size and non-NULL sized).
3404		 */
3405		if (length != 0)
3406			bcopy(value, p, length);
3407
3408		if (propp->prop_len != 0)
3409			kmem_free(propp->prop_val, propp->prop_len);
3410
3411		propp->prop_len = length;
3412		propp->prop_val = p;
3413		propp->prop_flags &= ~DDI_PROP_UNDEF_IT;
3414		mutex_exit(&(DEVI(dip)->devi_lock));
3415		return (DDI_PROP_SUCCESS);
3416	}
3417
3418	mutex_exit(&(DEVI(dip)->devi_lock));
3419	if (length != 0)
3420		kmem_free(p, length);
3421
3422	return (ddi_prop_add(dev, dip, flags, name, value, length));
3423}
3424
3425/*
3426 * Common update routine used to update and encode a property.	Creates
3427 * a property handle, calls the property encode routine, figures out if
3428 * the property already exists and updates if it does.	Otherwise it
3429 * creates if it does not exist.
3430 */
3431int
3432ddi_prop_update_common(dev_t match_dev, dev_info_t *dip, int flags,
3433    char *name, void *data, uint_t nelements,
3434    int (*prop_create)(prop_handle_t *, void *data, uint_t nelements))
3435{
3436	prop_handle_t	ph;
3437	int		rval;
3438	uint_t		ourflags;
3439
3440	/*
3441	 * If dev_t is DDI_DEV_T_ANY or name's length is zero,
3442	 * return error.
3443	 */
3444	if (match_dev == DDI_DEV_T_ANY || name == NULL || strlen(name) == 0)
3445		return (DDI_PROP_INVAL_ARG);
3446
3447	/*
3448	 * Create the handle
3449	 */
3450	ph.ph_data = NULL;
3451	ph.ph_cur_pos = NULL;
3452	ph.ph_save_pos = NULL;
3453	ph.ph_size = 0;
3454	ph.ph_ops = &prop_1275_ops;
3455
3456	/*
3457	 * ourflags:
3458	 * For compatibility with the old interfaces.  The old interfaces
3459	 * didn't sleep by default and slept when the flag was set.  These
3460	 * interfaces to the opposite.	So the old interfaces now set the
3461	 * DDI_PROP_DONTSLEEP flag by default which tells us not to sleep.
3462	 *
3463	 * ph.ph_flags:
3464	 * Blocked data or unblocked data allocation
3465	 * for ph.ph_data in ddi_prop_encode_alloc()
3466	 */
3467	if (flags & DDI_PROP_DONTSLEEP) {
3468		ourflags = flags;
3469		ph.ph_flags = DDI_PROP_DONTSLEEP;
3470	} else {
3471		ourflags = flags | DDI_PROP_CANSLEEP;
3472		ph.ph_flags = DDI_PROP_CANSLEEP;
3473	}
3474
3475	/*
3476	 * Encode the data and store it in the property handle by
3477	 * calling the prop_encode routine.
3478	 */
3479	if ((rval = (*prop_create)(&ph, data, nelements)) !=
3480	    DDI_PROP_SUCCESS) {
3481		if (rval == DDI_PROP_NO_MEMORY)
3482			cmn_err(CE_CONT, prop_no_mem_msg, name);
3483		if (ph.ph_size != 0)
3484			kmem_free(ph.ph_data, ph.ph_size);
3485		return (rval);
3486	}
3487
3488	/*
3489	 * The old interfaces use a stacking approach to creating
3490	 * properties.	If we are being called from the old interfaces,
3491	 * the DDI_PROP_STACK_CREATE flag will be set, so we just do a
3492	 * create without checking.
3493	 */
3494	if (flags & DDI_PROP_STACK_CREATE) {
3495		rval = ddi_prop_add(match_dev, dip,
3496		    ourflags, name, ph.ph_data, ph.ph_size);
3497	} else {
3498		rval = ddi_prop_change(match_dev, dip,
3499		    ourflags, name, ph.ph_data, ph.ph_size);
3500	}
3501
3502	/*
3503	 * Free the encoded data allocated in the prop_encode routine.
3504	 */
3505	if (ph.ph_size != 0)
3506		kmem_free(ph.ph_data, ph.ph_size);
3507
3508	return (rval);
3509}
3510
3511
3512/*
3513 * ddi_prop_create:	Define a managed property:
3514 *			See above for details.
3515 */
3516
3517int
3518ddi_prop_create(dev_t dev, dev_info_t *dip, int flag,
3519    char *name, caddr_t value, int length)
3520{
3521	if (!(flag & DDI_PROP_CANSLEEP)) {
3522		flag |= DDI_PROP_DONTSLEEP;
3523#ifdef DDI_PROP_DEBUG
3524		if (length != 0)
3525			cmn_err(CE_NOTE, "!ddi_prop_create: interface obsolete,"
3526			    "use ddi_prop_update (prop = %s, node = %s%d)",
3527			    name, ddi_driver_name(dip), ddi_get_instance(dip));
3528#endif /* DDI_PROP_DEBUG */
3529	}
3530	flag &= ~DDI_PROP_SYSTEM_DEF;
3531	flag |= DDI_PROP_STACK_CREATE | DDI_PROP_TYPE_ANY;
3532	return (ddi_prop_update_common(dev, dip, flag, name,
3533	    value, length, ddi_prop_fm_encode_bytes));
3534}
3535
3536int
3537e_ddi_prop_create(dev_t dev, dev_info_t *dip, int flag,
3538    char *name, caddr_t value, int length)
3539{
3540	if (!(flag & DDI_PROP_CANSLEEP))
3541		flag |= DDI_PROP_DONTSLEEP;
3542	flag |= DDI_PROP_SYSTEM_DEF | DDI_PROP_STACK_CREATE | DDI_PROP_TYPE_ANY;
3543	return (ddi_prop_update_common(dev, dip, flag,
3544	    name, value, length, ddi_prop_fm_encode_bytes));
3545}
3546
3547int
3548ddi_prop_modify(dev_t dev, dev_info_t *dip, int flag,
3549    char *name, caddr_t value, int length)
3550{
3551	ASSERT((flag & DDI_PROP_TYPE_MASK) == 0);
3552
3553	/*
3554	 * If dev_t is DDI_DEV_T_ANY or name's length is zero,
3555	 * return error.
3556	 */
3557	if (dev == DDI_DEV_T_ANY || name == NULL || strlen(name) == 0)
3558		return (DDI_PROP_INVAL_ARG);
3559
3560	if (!(flag & DDI_PROP_CANSLEEP))
3561		flag |= DDI_PROP_DONTSLEEP;
3562	flag &= ~DDI_PROP_SYSTEM_DEF;
3563	if (ddi_prop_exists(dev, dip, (flag | DDI_PROP_NOTPROM), name) == 0)
3564		return (DDI_PROP_NOT_FOUND);
3565
3566	return (ddi_prop_update_common(dev, dip,
3567	    (flag | DDI_PROP_TYPE_BYTE), name,
3568	    value, length, ddi_prop_fm_encode_bytes));
3569}
3570
3571int
3572e_ddi_prop_modify(dev_t dev, dev_info_t *dip, int flag,
3573    char *name, caddr_t value, int length)
3574{
3575	ASSERT((flag & DDI_PROP_TYPE_MASK) == 0);
3576
3577	/*
3578	 * If dev_t is DDI_DEV_T_ANY or name's length is zero,
3579	 * return error.
3580	 */
3581	if (dev == DDI_DEV_T_ANY || name == NULL || strlen(name) == 0)
3582		return (DDI_PROP_INVAL_ARG);
3583
3584	if (ddi_prop_exists(dev, dip, (flag | DDI_PROP_SYSTEM_DEF), name) == 0)
3585		return (DDI_PROP_NOT_FOUND);
3586
3587	if (!(flag & DDI_PROP_CANSLEEP))
3588		flag |= DDI_PROP_DONTSLEEP;
3589	return (ddi_prop_update_common(dev, dip,
3590	    (flag | DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_BYTE),
3591	    name, value, length, ddi_prop_fm_encode_bytes));
3592}
3593
3594
3595/*
3596 * Common lookup routine used to lookup and decode a property.
3597 * Creates a property handle, searches for the raw encoded data,
3598 * fills in the handle, and calls the property decode functions
3599 * passed in.
3600 *
3601 * This routine is not static because ddi_bus_prop_op() which lives in
3602 * ddi_impl.c calls it.  No driver should be calling this routine.
3603 */
3604int
3605ddi_prop_lookup_common(dev_t match_dev, dev_info_t *dip,
3606    uint_t flags, char *name, void *data, uint_t *nelements,
3607    int (*prop_decoder)(prop_handle_t *, void *data, uint_t *nelements))
3608{
3609	int		rval;
3610	uint_t		ourflags;
3611	prop_handle_t	ph;
3612
3613	if ((match_dev == DDI_DEV_T_NONE) ||
3614	    (name == NULL) || (strlen(name) == 0))
3615		return (DDI_PROP_INVAL_ARG);
3616
3617	ourflags = (flags & DDI_PROP_DONTSLEEP) ? flags :
3618	    flags | DDI_PROP_CANSLEEP;
3619
3620	/*
3621	 * Get the encoded data
3622	 */
3623	bzero(&ph, sizeof (prop_handle_t));
3624
3625	if ((flags & DDI_UNBND_DLPI2) || (flags & DDI_PROP_ROOTNEX_GLOBAL)) {
3626		/*
3627		 * For rootnex and unbound dlpi style-2 devices, index into
3628		 * the devnames' array and search the global
3629		 * property list.
3630		 */
3631		ourflags &= ~DDI_UNBND_DLPI2;
3632		rval = i_ddi_prop_search_global(match_dev,
3633		    ourflags, name, &ph.ph_data, &ph.ph_size);
3634	} else {
3635		rval = ddi_prop_search_common(match_dev, dip,
3636		    PROP_LEN_AND_VAL_ALLOC, ourflags, name,
3637		    &ph.ph_data, &ph.ph_size);
3638
3639	}
3640
3641	if (rval != DDI_PROP_SUCCESS && rval != DDI_PROP_FOUND_1275) {
3642		ASSERT(ph.ph_data == NULL);
3643		ASSERT(ph.ph_size == 0);
3644		return (rval);
3645	}
3646
3647	/*
3648	 * If the encoded data came from a OBP or software
3649	 * use the 1275 OBP decode/encode routines.
3650	 */
3651	ph.ph_cur_pos = ph.ph_data;
3652	ph.ph_save_pos = ph.ph_data;
3653	ph.ph_ops = &prop_1275_ops;
3654	ph.ph_flags = (rval == DDI_PROP_FOUND_1275) ? PH_FROM_PROM : 0;
3655
3656	rval = (*prop_decoder)(&ph, data, nelements);
3657
3658	/*
3659	 * Free the encoded data
3660	 */
3661	if (ph.ph_size != 0)
3662		kmem_free(ph.ph_data, ph.ph_size);
3663
3664	return (rval);
3665}
3666
3667/*
3668 * Lookup and return an array of composite properties.  The driver must
3669 * provide the decode routine.
3670 */
3671int
3672ddi_prop_lookup(dev_t match_dev, dev_info_t *dip,
3673    uint_t flags, char *name, void *data, uint_t *nelements,
3674    int (*prop_decoder)(prop_handle_t *, void *data, uint_t *nelements))
3675{
3676	return (ddi_prop_lookup_common(match_dev, dip,
3677	    (flags | DDI_PROP_TYPE_COMPOSITE), name,
3678	    data, nelements, prop_decoder));
3679}
3680
3681/*
3682 * Return 1 if a property exists (no type checking done).
3683 * Return 0 if it does not exist.
3684 */
3685int
3686ddi_prop_exists(dev_t match_dev, dev_info_t *dip, uint_t flags, char *name)
3687{
3688	int	i;
3689	uint_t	x = 0;
3690
3691	i = ddi_prop_search_common(match_dev, dip, PROP_EXISTS,
3692	    flags | DDI_PROP_TYPE_MASK, name, NULL, &x);
3693	return (i == DDI_PROP_SUCCESS || i == DDI_PROP_FOUND_1275);
3694}
3695
3696
3697/*
3698 * Update an array of composite properties.  The driver must
3699 * provide the encode routine.
3700 */
3701int
3702ddi_prop_update(dev_t match_dev, dev_info_t *dip,
3703    char *name, void *data, uint_t nelements,
3704    int (*prop_create)(prop_handle_t *, void *data, uint_t nelements))
3705{
3706	return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_COMPOSITE,
3707	    name, data, nelements, prop_create));
3708}
3709
3710/*
3711 * Get a single integer or boolean property and return it.
3712 * If the property does not exists, or cannot be decoded,
3713 * then return the defvalue passed in.
3714 *
3715 * This routine always succeeds.
3716 */
3717int
3718ddi_prop_get_int(dev_t match_dev, dev_info_t *dip, uint_t flags,
3719    char *name, int defvalue)
3720{
3721	int	data;
3722	uint_t	nelements;
3723	int	rval;
3724
3725	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3726	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
3727#ifdef DEBUG
3728		if (dip != NULL) {
3729			cmn_err(CE_WARN, "ddi_prop_get_int: invalid flag"
3730			    " 0x%x (prop = %s, node = %s%d)", flags,
3731			    name, ddi_driver_name(dip), ddi_get_instance(dip));
3732		}
3733#endif /* DEBUG */
3734		flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3735		    LDI_DEV_T_ANY | DDI_UNBND_DLPI2;
3736	}
3737
3738	if ((rval = ddi_prop_lookup_common(match_dev, dip,
3739	    (flags | DDI_PROP_TYPE_INT), name, &data, &nelements,
3740	    ddi_prop_fm_decode_int)) != DDI_PROP_SUCCESS) {
3741		if (rval == DDI_PROP_END_OF_DATA)
3742			data = 1;
3743		else
3744			data = defvalue;
3745	}
3746	return (data);
3747}
3748
3749/*
3750 * Get a single 64 bit integer or boolean property and return it.
3751 * If the property does not exists, or cannot be decoded,
3752 * then return the defvalue passed in.
3753 *
3754 * This routine always succeeds.
3755 */
3756int64_t
3757ddi_prop_get_int64(dev_t match_dev, dev_info_t *dip, uint_t flags,
3758    char *name, int64_t defvalue)
3759{
3760	int64_t	data;
3761	uint_t	nelements;
3762	int	rval;
3763
3764	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3765	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
3766#ifdef DEBUG
3767		if (dip != NULL) {
3768			cmn_err(CE_WARN, "ddi_prop_get_int64: invalid flag"
3769			    " 0x%x (prop = %s, node = %s%d)", flags,
3770			    name, ddi_driver_name(dip), ddi_get_instance(dip));
3771		}
3772#endif /* DEBUG */
3773		return (DDI_PROP_INVAL_ARG);
3774	}
3775
3776	if ((rval = ddi_prop_lookup_common(match_dev, dip,
3777	    (flags | DDI_PROP_TYPE_INT64 | DDI_PROP_NOTPROM),
3778	    name, &data, &nelements, ddi_prop_fm_decode_int64))
3779	    != DDI_PROP_SUCCESS) {
3780		if (rval == DDI_PROP_END_OF_DATA)
3781			data = 1;
3782		else
3783			data = defvalue;
3784	}
3785	return (data);
3786}
3787
3788/*
3789 * Get an array of integer property
3790 */
3791int
3792ddi_prop_lookup_int_array(dev_t match_dev, dev_info_t *dip, uint_t flags,
3793    char *name, int **data, uint_t *nelements)
3794{
3795	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3796	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
3797#ifdef DEBUG
3798		if (dip != NULL) {
3799			cmn_err(CE_WARN, "ddi_prop_lookup_int_array: "
3800			    "invalid flag 0x%x (prop = %s, node = %s%d)",
3801			    flags, name, ddi_driver_name(dip),
3802			    ddi_get_instance(dip));
3803		}
3804#endif /* DEBUG */
3805		flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3806		    LDI_DEV_T_ANY | DDI_UNBND_DLPI2;
3807	}
3808
3809	return (ddi_prop_lookup_common(match_dev, dip,
3810	    (flags | DDI_PROP_TYPE_INT), name, data,
3811	    nelements, ddi_prop_fm_decode_ints));
3812}
3813
3814/*
3815 * Get an array of 64 bit integer properties
3816 */
3817int
3818ddi_prop_lookup_int64_array(dev_t match_dev, dev_info_t *dip, uint_t flags,
3819    char *name, int64_t **data, uint_t *nelements)
3820{
3821	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3822	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
3823#ifdef DEBUG
3824		if (dip != NULL) {
3825			cmn_err(CE_WARN, "ddi_prop_lookup_int64_array: "
3826			    "invalid flag 0x%x (prop = %s, node = %s%d)",
3827			    flags, name, ddi_driver_name(dip),
3828			    ddi_get_instance(dip));
3829		}
3830#endif /* DEBUG */
3831		return (DDI_PROP_INVAL_ARG);
3832	}
3833
3834	return (ddi_prop_lookup_common(match_dev, dip,
3835	    (flags | DDI_PROP_TYPE_INT64 | DDI_PROP_NOTPROM),
3836	    name, data, nelements, ddi_prop_fm_decode_int64_array));
3837}
3838
3839/*
3840 * Update a single integer property.  If the property exists on the drivers
3841 * property list it updates, else it creates it.
3842 */
3843int
3844ddi_prop_update_int(dev_t match_dev, dev_info_t *dip,
3845    char *name, int data)
3846{
3847	return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_INT,
3848	    name, &data, 1, ddi_prop_fm_encode_ints));
3849}
3850
3851/*
3852 * Update a single 64 bit integer property.
3853 * Update the driver property list if it exists, else create it.
3854 */
3855int
3856ddi_prop_update_int64(dev_t match_dev, dev_info_t *dip,
3857    char *name, int64_t data)
3858{
3859	return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_INT64,
3860	    name, &data, 1, ddi_prop_fm_encode_int64));
3861}
3862
3863int
3864e_ddi_prop_update_int(dev_t match_dev, dev_info_t *dip,
3865    char *name, int data)
3866{
3867	return (ddi_prop_update_common(match_dev, dip,
3868	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_INT,
3869	    name, &data, 1, ddi_prop_fm_encode_ints));
3870}
3871
3872int
3873e_ddi_prop_update_int64(dev_t match_dev, dev_info_t *dip,
3874    char *name, int64_t data)
3875{
3876	return (ddi_prop_update_common(match_dev, dip,
3877	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_INT64,
3878	    name, &data, 1, ddi_prop_fm_encode_int64));
3879}
3880
3881/*
3882 * Update an array of integer property.  If the property exists on the drivers
3883 * property list it updates, else it creates it.
3884 */
3885int
3886ddi_prop_update_int_array(dev_t match_dev, dev_info_t *dip,
3887    char *name, int *data, uint_t nelements)
3888{
3889	return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_INT,
3890	    name, data, nelements, ddi_prop_fm_encode_ints));
3891}
3892
3893/*
3894 * Update an array of 64 bit integer properties.
3895 * Update the driver property list if it exists, else create it.
3896 */
3897int
3898ddi_prop_update_int64_array(dev_t match_dev, dev_info_t *dip,
3899    char *name, int64_t *data, uint_t nelements)
3900{
3901	return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_INT64,
3902	    name, data, nelements, ddi_prop_fm_encode_int64));
3903}
3904
3905int
3906e_ddi_prop_update_int64_array(dev_t match_dev, dev_info_t *dip,
3907    char *name, int64_t *data, uint_t nelements)
3908{
3909	return (ddi_prop_update_common(match_dev, dip,
3910	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_INT64,
3911	    name, data, nelements, ddi_prop_fm_encode_int64));
3912}
3913
3914int
3915e_ddi_prop_update_int_array(dev_t match_dev, dev_info_t *dip,
3916    char *name, int *data, uint_t nelements)
3917{
3918	return (ddi_prop_update_common(match_dev, dip,
3919	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_INT,
3920	    name, data, nelements, ddi_prop_fm_encode_ints));
3921}
3922
3923/*
3924 * Get a single string property.
3925 */
3926int
3927ddi_prop_lookup_string(dev_t match_dev, dev_info_t *dip, uint_t flags,
3928    char *name, char **data)
3929{
3930	uint_t x;
3931
3932	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3933	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
3934#ifdef DEBUG
3935		if (dip != NULL) {
3936			cmn_err(CE_WARN, "%s: invalid flag 0x%x "
3937			    "(prop = %s, node = %s%d); invalid bits ignored",
3938			    "ddi_prop_lookup_string", flags, name,
3939			    ddi_driver_name(dip), ddi_get_instance(dip));
3940		}
3941#endif /* DEBUG */
3942		flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3943		    LDI_DEV_T_ANY | DDI_UNBND_DLPI2;
3944	}
3945
3946	return (ddi_prop_lookup_common(match_dev, dip,
3947	    (flags | DDI_PROP_TYPE_STRING), name, data,
3948	    &x, ddi_prop_fm_decode_string));
3949}
3950
3951/*
3952 * Get an array of strings property.
3953 */
3954int
3955ddi_prop_lookup_string_array(dev_t match_dev, dev_info_t *dip, uint_t flags,
3956    char *name, char ***data, uint_t *nelements)
3957{
3958	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3959	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
3960#ifdef DEBUG
3961		if (dip != NULL) {
3962			cmn_err(CE_WARN, "ddi_prop_lookup_string_array: "
3963			    "invalid flag 0x%x (prop = %s, node = %s%d)",
3964			    flags, name, ddi_driver_name(dip),
3965			    ddi_get_instance(dip));
3966		}
3967#endif /* DEBUG */
3968		flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3969		    LDI_DEV_T_ANY | DDI_UNBND_DLPI2;
3970	}
3971
3972	return (ddi_prop_lookup_common(match_dev, dip,
3973	    (flags | DDI_PROP_TYPE_STRING), name, data,
3974	    nelements, ddi_prop_fm_decode_strings));
3975}
3976
3977/*
3978 * Update a single string property.
3979 */
3980int
3981ddi_prop_update_string(dev_t match_dev, dev_info_t *dip,
3982    char *name, char *data)
3983{
3984	return (ddi_prop_update_common(match_dev, dip,
3985	    DDI_PROP_TYPE_STRING, name, &data, 1,
3986	    ddi_prop_fm_encode_string));
3987}
3988
3989int
3990e_ddi_prop_update_string(dev_t match_dev, dev_info_t *dip,
3991    char *name, char *data)
3992{
3993	return (ddi_prop_update_common(match_dev, dip,
3994	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_STRING,
3995	    name, &data, 1, ddi_prop_fm_encode_string));
3996}
3997
3998
3999/*
4000 * Update an array of strings property.
4001 */
4002int
4003ddi_prop_update_string_array(dev_t match_dev, dev_info_t *dip,
4004    char *name, char **data, uint_t nelements)
4005{
4006	return (ddi_prop_update_common(match_dev, dip,
4007	    DDI_PROP_TYPE_STRING, name, data, nelements,
4008	    ddi_prop_fm_encode_strings));
4009}
4010
4011int
4012e_ddi_prop_update_string_array(dev_t match_dev, dev_info_t *dip,
4013    char *name, char **data, uint_t nelements)
4014{
4015	return (ddi_prop_update_common(match_dev, dip,
4016	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_STRING,
4017	    name, data, nelements,
4018	    ddi_prop_fm_encode_strings));
4019}
4020
4021
4022/*
4023 * Get an array of bytes property.
4024 */
4025int
4026ddi_prop_lookup_byte_array(dev_t match_dev, dev_info_t *dip, uint_t flags,
4027    char *name, uchar_t **data, uint_t *nelements)
4028{
4029	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
4030	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
4031#ifdef DEBUG
4032		if (dip != NULL) {
4033			cmn_err(CE_WARN, "ddi_prop_lookup_byte_array: "
4034			    " invalid flag 0x%x (prop = %s, node = %s%d)",
4035			    flags, name, ddi_driver_name(dip),
4036			    ddi_get_instance(dip));
4037		}
4038#endif /* DEBUG */
4039		flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
4040		    LDI_DEV_T_ANY | DDI_UNBND_DLPI2;
4041	}
4042
4043	return (ddi_prop_lookup_common(match_dev, dip,
4044	    (flags | DDI_PROP_TYPE_BYTE), name, data,
4045	    nelements, ddi_prop_fm_decode_bytes));
4046}
4047
4048/*
4049 * Update an array of bytes property.
4050 */
4051int
4052ddi_prop_update_byte_array(dev_t match_dev, dev_info_t *dip,
4053    char *name, uchar_t *data, uint_t nelements)
4054{
4055	if (nelements == 0)
4056		return (DDI_PROP_INVAL_ARG);
4057
4058	return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_BYTE,
4059	    name, data, nelements, ddi_prop_fm_encode_bytes));
4060}
4061
4062
4063int
4064e_ddi_prop_update_byte_array(dev_t match_dev, dev_info_t *dip,
4065    char *name, uchar_t *data, uint_t nelements)
4066{
4067	if (nelements == 0)
4068		return (DDI_PROP_INVAL_ARG);
4069
4070	return (ddi_prop_update_common(match_dev, dip,
4071	    DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_BYTE,
4072	    name, data, nelements, ddi_prop_fm_encode_bytes));
4073}
4074
4075
4076/*
4077 * ddi_prop_remove_common:	Undefine a managed property:
4078 *			Input dev_t must match dev_t when defined.
4079 *			Returns DDI_PROP_NOT_FOUND, possibly.
4080 *			DDI_PROP_INVAL_ARG is also possible if dev is
4081 *			DDI_DEV_T_ANY or incoming name is the NULL string.
4082 */
4083int
4084ddi_prop_remove_common(dev_t dev, dev_info_t *dip, char *name, int flag)
4085{
4086	ddi_prop_t	**list_head = &(DEVI(dip)->devi_drv_prop_ptr);
4087	ddi_prop_t	*propp;
4088	ddi_prop_t	*lastpropp = NULL;
4089
4090	if ((dev == DDI_DEV_T_ANY) || (name == (char *)0) ||
4091	    (strlen(name) == 0)) {
4092		return (DDI_PROP_INVAL_ARG);
4093	}
4094
4095	if (flag & DDI_PROP_SYSTEM_DEF)
4096		list_head = &(DEVI(dip)->devi_sys_prop_ptr);
4097	else if (flag & DDI_PROP_HW_DEF)
4098		list_head = &(DEVI(dip)->devi_hw_prop_ptr);
4099
4100	mutex_enter(&(DEVI(dip)->devi_lock));
4101
4102	for (propp = *list_head; propp != NULL; propp = propp->prop_next)  {
4103		if (DDI_STRSAME(propp->prop_name, name) &&
4104		    (dev == propp->prop_dev)) {
4105			/*
4106			 * Unlink this propp allowing for it to
4107			 * be first in the list:
4108			 */
4109
4110			if (lastpropp == NULL)
4111				*list_head = propp->prop_next;
4112			else
4113				lastpropp->prop_next = propp->prop_next;
4114
4115			mutex_exit(&(DEVI(dip)->devi_lock));
4116
4117			/*
4118			 * Free memory and return...
4119			 */
4120			kmem_free(propp->prop_name,
4121			    strlen(propp->prop_name) + 1);
4122			if (propp->prop_len != 0)
4123				kmem_free(propp->prop_val, propp->prop_len);
4124			kmem_free(propp, sizeof (ddi_prop_t));
4125			return (DDI_PROP_SUCCESS);
4126		}
4127		lastpropp = propp;
4128	}
4129	mutex_exit(&(DEVI(dip)->devi_lock));
4130	return (DDI_PROP_NOT_FOUND);
4131}
4132
4133int
4134ddi_prop_remove(dev_t dev, dev_info_t *dip, char *name)
4135{
4136	return (ddi_prop_remove_common(dev, dip, name, 0));
4137}
4138
4139int
4140e_ddi_prop_remove(dev_t dev, dev_info_t *dip, char *name)
4141{
4142	return (ddi_prop_remove_common(dev, dip, name, DDI_PROP_SYSTEM_DEF));
4143}
4144
4145/*
4146 * e_ddi_prop_list_delete: remove a list of properties
4147 *	Note that the caller needs to provide the required protection
4148 *	(eg. devi_lock if these properties are still attached to a devi)
4149 */
4150void
4151e_ddi_prop_list_delete(ddi_prop_t *props)
4152{
4153	i_ddi_prop_list_delete(props);
4154}
4155
4156/*
4157 * ddi_prop_remove_all_common:
4158 *	Used before unloading a driver to remove
4159 *	all properties. (undefines all dev_t's props.)
4160 *	Also removes `explicitly undefined' props.
4161 *	No errors possible.
4162 */
4163void
4164ddi_prop_remove_all_common(dev_info_t *dip, int flag)
4165{
4166	ddi_prop_t	**list_head;
4167
4168	mutex_enter(&(DEVI(dip)->devi_lock));
4169	if (flag & DDI_PROP_SYSTEM_DEF) {
4170		list_head = &(DEVI(dip)->devi_sys_prop_ptr);
4171	} else if (flag & DDI_PROP_HW_DEF) {
4172		list_head = &(DEVI(dip)->devi_hw_prop_ptr);
4173	} else {
4174		list_head = &(DEVI(dip)->devi_drv_prop_ptr);
4175	}
4176	i_ddi_prop_list_delete(*list_head);
4177	*list_head = NULL;
4178	mutex_exit(&(DEVI(dip)->devi_lock));
4179}
4180
4181
4182/*
4183 * ddi_prop_remove_all:		Remove all driver prop definitions.
4184 */
4185
4186void
4187ddi_prop_remove_all(dev_info_t *dip)
4188{
4189	i_ddi_prop_dyn_driver_set(dip, NULL);
4190	ddi_prop_remove_all_common(dip, 0);
4191}
4192
4193/*
4194 * e_ddi_prop_remove_all:	Remove all system prop definitions.
4195 */
4196
4197void
4198e_ddi_prop_remove_all(dev_info_t *dip)
4199{
4200	ddi_prop_remove_all_common(dip, (int)DDI_PROP_SYSTEM_DEF);
4201}
4202
4203
4204/*
4205 * ddi_prop_undefine:	Explicitly undefine a property.  Property
4206 *			searches which match this property return
4207 *			the error code DDI_PROP_UNDEFINED.
4208 *
4209 *			Use ddi_prop_remove to negate effect of
4210 *			ddi_prop_undefine
4211 *
4212 *			See above for error returns.
4213 */
4214
4215int
4216ddi_prop_undefine(dev_t dev, dev_info_t *dip, int flag, char *name)
4217{
4218	if (!(flag & DDI_PROP_CANSLEEP))
4219		flag |= DDI_PROP_DONTSLEEP;
4220	flag |= DDI_PROP_STACK_CREATE | DDI_PROP_UNDEF_IT | DDI_PROP_TYPE_ANY;
4221	return (ddi_prop_update_common(dev, dip, flag,
4222	    name, NULL, 0, ddi_prop_fm_encode_bytes));
4223}
4224
4225int
4226e_ddi_prop_undefine(dev_t dev, dev_info_t *dip, int flag, char *name)
4227{
4228	if (!(flag & DDI_PROP_CANSLEEP))
4229		flag |= DDI_PROP_DONTSLEEP;
4230	flag |= DDI_PROP_SYSTEM_DEF | DDI_PROP_STACK_CREATE |
4231	    DDI_PROP_UNDEF_IT | DDI_PROP_TYPE_ANY;
4232	return (ddi_prop_update_common(dev, dip, flag,
4233	    name, NULL, 0, ddi_prop_fm_encode_bytes));
4234}
4235
4236/*
4237 * Support for gathering dynamic properties in devinfo snapshot.
4238 */
4239void
4240i_ddi_prop_dyn_driver_set(dev_info_t *dip, i_ddi_prop_dyn_t *dp)
4241{
4242	DEVI(dip)->devi_prop_dyn_driver = dp;
4243}
4244
4245i_ddi_prop_dyn_t *
4246i_ddi_prop_dyn_driver_get(dev_info_t *dip)
4247{
4248	return (DEVI(dip)->devi_prop_dyn_driver);
4249}
4250
4251void
4252i_ddi_prop_dyn_parent_set(dev_info_t *dip, i_ddi_prop_dyn_t *dp)
4253{
4254	DEVI(dip)->devi_prop_dyn_parent = dp;
4255}
4256
4257i_ddi_prop_dyn_t *
4258i_ddi_prop_dyn_parent_get(dev_info_t *dip)
4259{
4260	return (DEVI(dip)->devi_prop_dyn_parent);
4261}
4262
4263void
4264i_ddi_prop_dyn_cache_invalidate(dev_info_t *dip, i_ddi_prop_dyn_t *dp)
4265{
4266	/* for now we invalidate the entire cached snapshot */
4267	if (dip && dp)
4268		i_ddi_di_cache_invalidate();
4269}
4270
4271/* ARGSUSED */
4272void
4273ddi_prop_cache_invalidate(dev_t dev, dev_info_t *dip, char *name, int flags)
4274{
4275	/* for now we invalidate the entire cached snapshot */
4276	i_ddi_di_cache_invalidate();
4277}
4278
4279
4280/*
4281 * Code to search hardware layer (PROM), if it exists, on behalf of child.
4282 *
4283 * if input dip != child_dip, then call is on behalf of child
4284 * to search PROM, do it via ddi_prop_search_common() and ascend only
4285 * if allowed.
4286 *
4287 * if input dip == ch_dip (child_dip), call is on behalf of root driver,
4288 * to search for PROM defined props only.
4289 *
4290 * Note that the PROM search is done only if the requested dev
4291 * is either DDI_DEV_T_ANY or DDI_DEV_T_NONE. PROM properties
4292 * have no associated dev, thus are automatically associated with
4293 * DDI_DEV_T_NONE.
4294 *
4295 * Modifying flag DDI_PROP_NOTPROM inhibits the search in the h/w layer.
4296 *
4297 * Returns DDI_PROP_FOUND_1275 if found to indicate to framework
4298 * that the property resides in the prom.
4299 */
4300int
4301impl_ddi_bus_prop_op(dev_t dev, dev_info_t *dip, dev_info_t *ch_dip,
4302    ddi_prop_op_t prop_op, int mod_flags,
4303    char *name, caddr_t valuep, int *lengthp)
4304{
4305	int	len;
4306	caddr_t buffer = NULL;
4307
4308	/*
4309	 * If requested dev is DDI_DEV_T_NONE or DDI_DEV_T_ANY, then
4310	 * look in caller's PROM if it's a self identifying device...
4311	 *
4312	 * Note that this is very similar to ddi_prop_op, but we
4313	 * search the PROM instead of the s/w defined properties,
4314	 * and we are called on by the parent driver to do this for
4315	 * the child.
4316	 */
4317
4318	if (((dev == DDI_DEV_T_NONE) || (dev == DDI_DEV_T_ANY)) &&
4319	    ndi_dev_is_prom_node(ch_dip) &&
4320	    ((mod_flags & DDI_PROP_NOTPROM) == 0)) {
4321		len = prom_getproplen((pnode_t)DEVI(ch_dip)->devi_nodeid, name);
4322		if (len == -1) {
4323			return (DDI_PROP_NOT_FOUND);
4324		}
4325
4326		/*
4327		 * If exists only request, we're done
4328		 */
4329		if (prop_op == PROP_EXISTS) {
4330			return (DDI_PROP_FOUND_1275);
4331		}
4332
4333		/*
4334		 * If length only request or prop length == 0, get out
4335		 */
4336		if ((prop_op == PROP_LEN) || (len == 0)) {
4337			*lengthp = len;
4338			return (DDI_PROP_FOUND_1275);
4339		}
4340
4341		/*
4342		 * Allocate buffer if required... (either way `buffer'
4343		 * is receiving address).
4344		 */
4345
4346		switch (prop_op) {
4347
4348		case PROP_LEN_AND_VAL_ALLOC:
4349
4350			buffer = kmem_alloc((size_t)len,
4351			    mod_flags & DDI_PROP_CANSLEEP ?
4352			    KM_SLEEP : KM_NOSLEEP);
4353			if (buffer == NULL) {
4354				return (DDI_PROP_NO_MEMORY);
4355			}
4356			*(caddr_t *)valuep = buffer;
4357			break;
4358
4359		case PROP_LEN_AND_VAL_BUF:
4360
4361			if (len > (*lengthp)) {
4362				*lengthp = len;
4363				return (DDI_PROP_BUF_TOO_SMALL);
4364			}
4365
4366			buffer = valuep;
4367			break;
4368
4369		default:
4370			break;
4371		}
4372
4373		/*
4374		 * Call the PROM function to do the copy.
4375		 */
4376		(void) prom_getprop((pnode_t)DEVI(ch_dip)->devi_nodeid,
4377		    name, buffer);
4378
4379		*lengthp = len; /* return the actual length to the caller */
4380		(void) impl_fix_props(dip, ch_dip, name, len, buffer);
4381		return (DDI_PROP_FOUND_1275);
4382	}
4383
4384	return (DDI_PROP_NOT_FOUND);
4385}
4386
4387/*
4388 * The ddi_bus_prop_op default bus nexus prop op function.
4389 *
4390 * Code to search hardware layer (PROM), if it exists,
4391 * on behalf of child, then, if appropriate, ascend and check
4392 * my own software defined properties...
4393 */
4394int
4395ddi_bus_prop_op(dev_t dev, dev_info_t *dip, dev_info_t *ch_dip,
4396    ddi_prop_op_t prop_op, int mod_flags,
4397    char *name, caddr_t valuep, int *lengthp)
4398{
4399	int	error;
4400
4401	error = impl_ddi_bus_prop_op(dev, dip, ch_dip, prop_op, mod_flags,
4402	    name, valuep, lengthp);
4403
4404	if (error == DDI_PROP_SUCCESS || error == DDI_PROP_FOUND_1275 ||
4405	    error == DDI_PROP_BUF_TOO_SMALL)
4406		return (error);
4407
4408	if (error == DDI_PROP_NO_MEMORY) {
4409		cmn_err(CE_CONT, prop_no_mem_msg, name);
4410		return (DDI_PROP_NO_MEMORY);
4411	}
4412
4413	/*
4414	 * Check the 'options' node as a last resort
4415	 */
4416	if ((mod_flags & DDI_PROP_DONTPASS) != 0)
4417		return (DDI_PROP_NOT_FOUND);
4418
4419	if (ch_dip == ddi_root_node())	{
4420		/*
4421		 * As a last resort, when we've reached
4422		 * the top and still haven't found the
4423		 * property, see if the desired property
4424		 * is attached to the options node.
4425		 *
4426		 * The options dip is attached right after boot.
4427		 */
4428		ASSERT(options_dip != NULL);
4429		/*
4430		 * Force the "don't pass" flag to *just* see
4431		 * what the options node has to offer.
4432		 */
4433		return (ddi_prop_search_common(dev, options_dip, prop_op,
4434		    mod_flags|DDI_PROP_DONTPASS, name, valuep,
4435		    (uint_t *)lengthp));
4436	}
4437
4438	/*
4439	 * Otherwise, continue search with parent's s/w defined properties...
4440	 * NOTE: Using `dip' in following call increments the level.
4441	 */
4442
4443	return (ddi_prop_search_common(dev, dip, prop_op, mod_flags,
4444	    name, valuep, (uint_t *)lengthp));
4445}
4446
4447/*
4448 * External property functions used by other parts of the kernel...
4449 */
4450
4451/*
4452 * e_ddi_getlongprop: See comments for ddi_get_longprop.
4453 */
4454
4455int
4456e_ddi_getlongprop(dev_t dev, vtype_t type, char *name, int flags,
4457    caddr_t valuep, int *lengthp)
4458{
4459	_NOTE(ARGUNUSED(type))
4460	dev_info_t *devi;
4461	ddi_prop_op_t prop_op = PROP_LEN_AND_VAL_ALLOC;
4462	int error;
4463
4464	if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL)
4465		return (DDI_PROP_NOT_FOUND);
4466
4467	error = cdev_prop_op(dev, devi, prop_op, flags, name, valuep, lengthp);
4468	ddi_release_devi(devi);
4469	return (error);
4470}
4471
4472/*
4473 * e_ddi_getlongprop_buf:	See comments for ddi_getlongprop_buf.
4474 */
4475
4476int
4477e_ddi_getlongprop_buf(dev_t dev, vtype_t type, char *name, int flags,
4478    caddr_t valuep, int *lengthp)
4479{
4480	_NOTE(ARGUNUSED(type))
4481	dev_info_t *devi;
4482	ddi_prop_op_t prop_op = PROP_LEN_AND_VAL_BUF;
4483	int error;
4484
4485	if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL)
4486		return (DDI_PROP_NOT_FOUND);
4487
4488	error = cdev_prop_op(dev, devi, prop_op, flags, name, valuep, lengthp);
4489	ddi_release_devi(devi);
4490	return (error);
4491}
4492
4493/*
4494 * e_ddi_getprop:	See comments for ddi_getprop.
4495 */
4496int
4497e_ddi_getprop(dev_t dev, vtype_t type, char *name, int flags, int defvalue)
4498{
4499	_NOTE(ARGUNUSED(type))
4500	dev_info_t *devi;
4501	ddi_prop_op_t prop_op = PROP_LEN_AND_VAL_BUF;
4502	int	propvalue = defvalue;
4503	int	proplength = sizeof (int);
4504	int	error;
4505
4506	if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL)
4507		return (defvalue);
4508
4509	error = cdev_prop_op(dev, devi, prop_op,
4510	    flags, name, (caddr_t)&propvalue, &proplength);
4511	ddi_release_devi(devi);
4512
4513	if ((error == DDI_PROP_SUCCESS) && (proplength == 0))
4514		propvalue = 1;
4515
4516	return (propvalue);
4517}
4518
4519/*
4520 * e_ddi_getprop_int64:
4521 *
4522 * This is a typed interfaces, but predates typed properties. With the
4523 * introduction of typed properties the framework tries to ensure
4524 * consistent use of typed interfaces. This is why TYPE_INT64 is not
4525 * part of TYPE_ANY.  E_ddi_getprop_int64 is a special case where a
4526 * typed interface invokes legacy (non-typed) interfaces:
4527 * cdev_prop_op(), prop_op(9E), ddi_prop_op(9F)).  In this case the
4528 * fact that TYPE_INT64 is not part of TYPE_ANY matters.  To support
4529 * this type of lookup as a single operation we invoke the legacy
4530 * non-typed interfaces with the special CONSUMER_TYPED bit set. The
4531 * framework ddi_prop_op(9F) implementation is expected to check for
4532 * CONSUMER_TYPED and, if set, expand type bits beyond TYPE_ANY
4533 * (currently TYPE_INT64).
4534 */
4535int64_t
4536e_ddi_getprop_int64(dev_t dev, vtype_t type, char *name,
4537    int flags, int64_t defvalue)
4538{
4539	_NOTE(ARGUNUSED(type))
4540	dev_info_t	*devi;
4541	ddi_prop_op_t	prop_op = PROP_LEN_AND_VAL_BUF;
4542	int64_t		propvalue = defvalue;
4543	int		proplength = sizeof (propvalue);
4544	int		error;
4545
4546	if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL)
4547		return (defvalue);
4548
4549	error = cdev_prop_op(dev, devi, prop_op, flags |
4550	    DDI_PROP_CONSUMER_TYPED, name, (caddr_t)&propvalue, &proplength);
4551	ddi_release_devi(devi);
4552
4553	if ((error == DDI_PROP_SUCCESS) && (proplength == 0))
4554		propvalue = 1;
4555
4556	return (propvalue);
4557}
4558
4559/*
4560 * e_ddi_getproplen:	See comments for ddi_getproplen.
4561 */
4562int
4563e_ddi_getproplen(dev_t dev, vtype_t type, char *name, int flags, int *lengthp)
4564{
4565	_NOTE(ARGUNUSED(type))
4566	dev_info_t *devi;
4567	ddi_prop_op_t prop_op = PROP_LEN;
4568	int error;
4569
4570	if ((devi = e_ddi_hold_devi_by_dev(dev, 0)) == NULL)
4571		return (DDI_PROP_NOT_FOUND);
4572
4573	error = cdev_prop_op(dev, devi, prop_op, flags, name, NULL, lengthp);
4574	ddi_release_devi(devi);
4575	return (error);
4576}
4577
4578/*
4579 * Routines to get at elements of the dev_info structure
4580 */
4581
4582/*
4583 * ddi_binding_name: Return the driver binding name of the devinfo node
4584 *		This is the name the OS used to bind the node to a driver.
4585 */
4586char *
4587ddi_binding_name(dev_info_t *dip)
4588{
4589	return (DEVI(dip)->devi_binding_name);
4590}
4591
4592/*
4593 * ddi_driver_major: Return the major number of the driver that
4594 *	the supplied devinfo is bound to.  If not yet bound,
4595 *	DDI_MAJOR_T_NONE.
4596 *
4597 * When used by the driver bound to 'devi', this
4598 * function will reliably return the driver major number.
4599 * Other ways of determining the driver major number, such as
4600 *	major = ddi_name_to_major(ddi_get_name(devi));
4601 *	major = ddi_name_to_major(ddi_binding_name(devi));
4602 * can return a different result as the driver/alias binding
4603 * can change dynamically, and thus should be avoided.
4604 */
4605major_t
4606ddi_driver_major(dev_info_t *devi)
4607{
4608	return (DEVI(devi)->devi_major);
4609}
4610
4611/*
4612 * ddi_driver_name: Return the normalized driver name. this is the
4613 *		actual driver name
4614 */
4615const char *
4616ddi_driver_name(dev_info_t *devi)
4617{
4618	major_t major;
4619
4620	if ((major = ddi_driver_major(devi)) != DDI_MAJOR_T_NONE)
4621		return (ddi_major_to_name(major));
4622
4623	return (ddi_node_name(devi));
4624}
4625
4626/*
4627 * i_ddi_set_binding_name:	Set binding name.
4628 *
4629 *	Set the binding name to the given name.
4630 *	This routine is for use by the ddi implementation, not by drivers.
4631 */
4632void
4633i_ddi_set_binding_name(dev_info_t *dip, char *name)
4634{
4635	DEVI(dip)->devi_binding_name = name;
4636
4637}
4638
4639/*
4640 * ddi_get_name: A synonym of ddi_binding_name() ... returns a name
4641 * the implementation has used to bind the node to a driver.
4642 */
4643char *
4644ddi_get_name(dev_info_t *dip)
4645{
4646	return (DEVI(dip)->devi_binding_name);
4647}
4648
4649/*
4650 * ddi_node_name: Return the name property of the devinfo node
4651 *		This may differ from ddi_binding_name if the node name
4652 *		does not define a binding to a driver (i.e. generic names).
4653 */
4654char *
4655ddi_node_name(dev_info_t *dip)
4656{
4657	return (DEVI(dip)->devi_node_name);
4658}
4659
4660
4661/*
4662 * ddi_get_nodeid:	Get nodeid stored in dev_info structure.
4663 */
4664int
4665ddi_get_nodeid(dev_info_t *dip)
4666{
4667	return (DEVI(dip)->devi_nodeid);
4668}
4669
4670int
4671ddi_get_instance(dev_info_t *dip)
4672{
4673	return (DEVI(dip)->devi_instance);
4674}
4675
4676struct dev_ops *
4677ddi_get_driver(dev_info_t *dip)
4678{
4679	return (DEVI(dip)->devi_ops);
4680}
4681
4682void
4683ddi_set_driver(dev_info_t *dip, struct dev_ops *devo)
4684{
4685	DEVI(dip)->devi_ops = devo;
4686}
4687
4688/*
4689 * ddi_set_driver_private/ddi_get_driver_private:
4690 * Get/set device driver private data in devinfo.
4691 */
4692void
4693ddi_set_driver_private(dev_info_t *dip, void *data)
4694{
4695	DEVI(dip)->devi_driver_data = data;
4696}
4697
4698void *
4699ddi_get_driver_private(dev_info_t *dip)
4700{
4701	return (DEVI(dip)->devi_driver_data);
4702}
4703
4704/*
4705 * ddi_get_parent, ddi_get_child, ddi_get_next_sibling
4706 */
4707
4708dev_info_t *
4709ddi_get_parent(dev_info_t *dip)
4710{
4711	return ((dev_info_t *)DEVI(dip)->devi_parent);
4712}
4713
4714dev_info_t *
4715ddi_get_child(dev_info_t *dip)
4716{
4717	return ((dev_info_t *)DEVI(dip)->devi_child);
4718}
4719
4720dev_info_t *
4721ddi_get_next_sibling(dev_info_t *dip)
4722{
4723	return ((dev_info_t *)DEVI(dip)->devi_sibling);
4724}
4725
4726dev_info_t *
4727ddi_get_next(dev_info_t *dip)
4728{
4729	return ((dev_info_t *)DEVI(dip)->devi_next);
4730}
4731
4732void
4733ddi_set_next(dev_info_t *dip, dev_info_t *nextdip)
4734{
4735	DEVI(dip)->devi_next = DEVI(nextdip);
4736}
4737
4738/*
4739 * ddi_root_node:		Return root node of devinfo tree
4740 */
4741
4742dev_info_t *
4743ddi_root_node(void)
4744{
4745	extern dev_info_t *top_devinfo;
4746
4747	return (top_devinfo);
4748}
4749
4750/*
4751 * Miscellaneous functions:
4752 */
4753
4754/*
4755 * Implementation specific hooks
4756 */
4757
4758void
4759ddi_report_dev(dev_info_t *d)
4760{
4761	char *b;
4762
4763	(void) ddi_ctlops(d, d, DDI_CTLOPS_REPORTDEV, (void *)0, (void *)0);
4764
4765	/*
4766	 * If this devinfo node has cb_ops, it's implicitly accessible from
4767	 * userland, so we print its full name together with the instance
4768	 * number 'abbreviation' that the driver may use internally.
4769	 */
4770	if (DEVI(d)->devi_ops->devo_cb_ops != (struct cb_ops *)0 &&
4771	    (b = kmem_zalloc(MAXPATHLEN, KM_NOSLEEP))) {
4772		cmn_err(CE_CONT, "?%s%d is %s\n",
4773		    ddi_driver_name(d), ddi_get_instance(d),
4774		    ddi_pathname(d, b));
4775		kmem_free(b, MAXPATHLEN);
4776	}
4777}
4778
4779/*
4780 * ddi_ctlops() is described in the assembler not to buy a new register
4781 * window when it's called and can reduce cost in climbing the device tree
4782 * without using the tail call optimization.
4783 */
4784int
4785ddi_dev_regsize(dev_info_t *dev, uint_t rnumber, off_t *result)
4786{
4787	int ret;
4788
4789	ret = ddi_ctlops(dev, dev, DDI_CTLOPS_REGSIZE,
4790	    (void *)&rnumber, (void *)result);
4791
4792	return (ret == DDI_SUCCESS ? DDI_SUCCESS : DDI_FAILURE);
4793}
4794
4795int
4796ddi_dev_nregs(dev_info_t *dev, int *result)
4797{
4798	return (ddi_ctlops(dev, dev, DDI_CTLOPS_NREGS, 0, (void *)result));
4799}
4800
4801int
4802ddi_dev_is_sid(dev_info_t *d)
4803{
4804	return (ddi_ctlops(d, d, DDI_CTLOPS_SIDDEV, (void *)0, (void *)0));
4805}
4806
4807int
4808ddi_slaveonly(dev_info_t *d)
4809{
4810	return (ddi_ctlops(d, d, DDI_CTLOPS_SLAVEONLY, (void *)0, (void *)0));
4811}
4812
4813int
4814ddi_dev_affinity(dev_info_t *a, dev_info_t *b)
4815{
4816	return (ddi_ctlops(a, a, DDI_CTLOPS_AFFINITY, (void *)b, (void *)0));
4817}
4818
4819int
4820ddi_streams_driver(dev_info_t *dip)
4821{
4822	if (i_ddi_devi_attached(dip) &&
4823	    (DEVI(dip)->devi_ops->devo_cb_ops != NULL) &&
4824	    (DEVI(dip)->devi_ops->devo_cb_ops->cb_str != NULL))
4825		return (DDI_SUCCESS);
4826	return (DDI_FAILURE);
4827}
4828
4829/*
4830 * callback free list
4831 */
4832
4833static int ncallbacks;
4834static int nc_low = 170;
4835static int nc_med = 512;
4836static int nc_high = 2048;
4837static struct ddi_callback *callbackq;
4838static struct ddi_callback *callbackqfree;
4839
4840/*
4841 * set/run callback lists
4842 */
4843struct	cbstats	{
4844	kstat_named_t	cb_asked;
4845	kstat_named_t	cb_new;
4846	kstat_named_t	cb_run;
4847	kstat_named_t	cb_delete;
4848	kstat_named_t	cb_maxreq;
4849	kstat_named_t	cb_maxlist;
4850	kstat_named_t	cb_alloc;
4851	kstat_named_t	cb_runouts;
4852	kstat_named_t	cb_L2;
4853	kstat_named_t	cb_grow;
4854} cbstats = {
4855	{"asked",	KSTAT_DATA_UINT32},
4856	{"new",		KSTAT_DATA_UINT32},
4857	{"run",		KSTAT_DATA_UINT32},
4858	{"delete",	KSTAT_DATA_UINT32},
4859	{"maxreq",	KSTAT_DATA_UINT32},
4860	{"maxlist",	KSTAT_DATA_UINT32},
4861	{"alloc",	KSTAT_DATA_UINT32},
4862	{"runouts",	KSTAT_DATA_UINT32},
4863	{"L2",		KSTAT_DATA_UINT32},
4864	{"grow",	KSTAT_DATA_UINT32},
4865};
4866
4867#define	nc_asked	cb_asked.value.ui32
4868#define	nc_new		cb_new.value.ui32
4869#define	nc_run		cb_run.value.ui32
4870#define	nc_delete	cb_delete.value.ui32
4871#define	nc_maxreq	cb_maxreq.value.ui32
4872#define	nc_maxlist	cb_maxlist.value.ui32
4873#define	nc_alloc	cb_alloc.value.ui32
4874#define	nc_runouts	cb_runouts.value.ui32
4875#define	nc_L2		cb_L2.value.ui32
4876#define	nc_grow		cb_grow.value.ui32
4877
4878static kmutex_t ddi_callback_mutex;
4879
4880/*
4881 * callbacks are handled using a L1/L2 cache. The L1 cache
4882 * comes out of kmem_cache_alloc and can expand/shrink dynamically. If
4883 * we can't get callbacks from the L1 cache [because pageout is doing
4884 * I/O at the time freemem is 0], we allocate callbacks out of the
4885 * L2 cache. The L2 cache is static and depends on the memory size.
4886 * [We might also count the number of devices at probe time and
4887 * allocate one structure per device and adjust for deferred attach]
4888 */
4889void
4890impl_ddi_callback_init(void)
4891{
4892	int	i;
4893	uint_t	physmegs;
4894	kstat_t	*ksp;
4895
4896	physmegs = physmem >> (20 - PAGESHIFT);
4897	if (physmegs < 48) {
4898		ncallbacks = nc_low;
4899	} else if (physmegs < 128) {
4900		ncallbacks = nc_med;
4901	} else {
4902		ncallbacks = nc_high;
4903	}
4904
4905	/*
4906	 * init free list
4907	 */
4908	callbackq = kmem_zalloc(
4909	    ncallbacks * sizeof (struct ddi_callback), KM_SLEEP);
4910	for (i = 0; i < ncallbacks-1; i++)
4911		callbackq[i].c_nfree = &callbackq[i+1];
4912	callbackqfree = callbackq;
4913
4914	/* init kstats */
4915	if (ksp = kstat_create("unix", 0, "cbstats", "misc", KSTAT_TYPE_NAMED,
4916	    sizeof (cbstats) / sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL)) {
4917		ksp->ks_data = (void *) &cbstats;
4918		kstat_install(ksp);
4919	}
4920
4921}
4922
4923static void
4924callback_insert(int (*funcp)(caddr_t), caddr_t arg, uintptr_t *listid,
4925	int count)
4926{
4927	struct ddi_callback *list, *marker, *new;
4928	size_t size = sizeof (struct ddi_callback);
4929
4930	list = marker = (struct ddi_callback *)*listid;
4931	while (list != NULL) {
4932		if (list->c_call == funcp && list->c_arg == arg) {
4933			list->c_count += count;
4934			return;
4935		}
4936		marker = list;
4937		list = list->c_nlist;
4938	}
4939	new = kmem_alloc(size, KM_NOSLEEP);
4940	if (new == NULL) {
4941		new = callbackqfree;
4942		if (new == NULL) {
4943			new = kmem_alloc_tryhard(sizeof (struct ddi_callback),
4944			    &size, KM_NOSLEEP | KM_PANIC);
4945			cbstats.nc_grow++;
4946		} else {
4947			callbackqfree = new->c_nfree;
4948			cbstats.nc_L2++;
4949		}
4950	}
4951	if (marker != NULL) {
4952		marker->c_nlist = new;
4953	} else {
4954		*listid = (uintptr_t)new;
4955	}
4956	new->c_size = size;
4957	new->c_nlist = NULL;
4958	new->c_call = funcp;
4959	new->c_arg = arg;
4960	new->c_count = count;
4961	cbstats.nc_new++;
4962	cbstats.nc_alloc++;
4963	if (cbstats.nc_alloc > cbstats.nc_maxlist)
4964		cbstats.nc_maxlist = cbstats.nc_alloc;
4965}
4966
4967void
4968ddi_set_callback(int (*funcp)(caddr_t), caddr_t arg, uintptr_t *listid)
4969{
4970	mutex_enter(&ddi_callback_mutex);
4971	cbstats.nc_asked++;
4972	if ((cbstats.nc_asked - cbstats.nc_run) > cbstats.nc_maxreq)
4973		cbstats.nc_maxreq = (cbstats.nc_asked - cbstats.nc_run);
4974	(void) callback_insert(funcp, arg, listid, 1);
4975	mutex_exit(&ddi_callback_mutex);
4976}
4977
4978static void
4979real_callback_run(void *Queue)
4980{
4981	int (*funcp)(caddr_t);
4982	caddr_t arg;
4983	int count, rval;
4984	uintptr_t *listid;
4985	struct ddi_callback *list, *marker;
4986	int check_pending = 1;
4987	int pending = 0;
4988
4989	do {
4990		mutex_enter(&ddi_callback_mutex);
4991		listid = Queue;
4992		list = (struct ddi_callback *)*listid;
4993		if (list == NULL) {
4994			mutex_exit(&ddi_callback_mutex);
4995			return;
4996		}
4997		if (check_pending) {
4998			marker = list;
4999			while (marker != NULL) {
5000				pending += marker->c_count;
5001				marker = marker->c_nlist;
5002			}
5003			check_pending = 0;
5004		}
5005		ASSERT(pending > 0);
5006		ASSERT(list->c_count > 0);
5007		funcp = list->c_call;
5008		arg = list->c_arg;
5009		count = list->c_count;
5010		*(uintptr_t *)Queue = (uintptr_t)list->c_nlist;
5011		if (list >= &callbackq[0] &&
5012		    list <= &callbackq[ncallbacks-1]) {
5013			list->c_nfree = callbackqfree;
5014			callbackqfree = list;
5015		} else
5016			kmem_free(list, list->c_size);
5017
5018		cbstats.nc_delete++;
5019		cbstats.nc_alloc--;
5020		mutex_exit(&ddi_callback_mutex);
5021
5022		do {
5023			if ((rval = (*funcp)(arg)) == 0) {
5024				pending -= count;
5025				mutex_enter(&ddi_callback_mutex);
5026				(void) callback_insert(funcp, arg, listid,
5027				    count);
5028				cbstats.nc_runouts++;
5029			} else {
5030				pending--;
5031				mutex_enter(&ddi_callback_mutex);
5032				cbstats.nc_run++;
5033			}
5034			mutex_exit(&ddi_callback_mutex);
5035		} while (rval != 0 && (--count > 0));
5036	} while (pending > 0);
5037}
5038
5039void
5040ddi_run_callback(uintptr_t *listid)
5041{
5042	softcall(real_callback_run, listid);
5043}
5044
5045/*
5046 * ddi_periodic_t
5047 * ddi_periodic_add(void (*func)(void *), void *arg, hrtime_t interval,
5048 *     int level)
5049 *
5050 * INTERFACE LEVEL
5051 *      Solaris DDI specific (Solaris DDI)
5052 *
5053 * PARAMETERS
5054 *      func: the callback function
5055 *
5056 *            The callback function will be invoked. The function is invoked
5057 *            in kernel context if the argument level passed is the zero.
5058 *            Otherwise it's invoked in interrupt context at the specified
5059 *            level.
5060 *
5061 *       arg: the argument passed to the callback function
5062 *
5063 *  interval: interval time
5064 *
5065 *    level : callback interrupt level
5066 *
5067 *            If the value is the zero, the callback function is invoked
5068 *            in kernel context. If the value is more than the zero, but
5069 *            less than or equal to ten, the callback function is invoked in
5070 *            interrupt context at the specified interrupt level, which may
5071 *            be used for real time applications.
5072 *
5073 *            This value must be in range of 0-10, which can be a numeric
5074 *            number or a pre-defined macro (DDI_IPL_0, ... , DDI_IPL_10).
5075 *
5076 * DESCRIPTION
5077 *      ddi_periodic_add(9F) schedules the specified function to be
5078 *      periodically invoked in the interval time.
5079 *
5080 *      As well as timeout(9F), the exact time interval over which the function
5081 *      takes effect cannot be guaranteed, but the value given is a close
5082 *      approximation.
5083 *
5084 *      Drivers waiting on behalf of processes with real-time constraints must
5085 *      pass non-zero value with the level argument to ddi_periodic_add(9F).
5086 *
5087 * RETURN VALUES
5088 *      ddi_periodic_add(9F) returns a non-zero opaque value (ddi_periodic_t),
5089 *      which must be used for ddi_periodic_delete(9F) to specify the request.
5090 *
5091 * CONTEXT
5092 *      ddi_periodic_add(9F) can be called in user or kernel context, but
5093 *      it cannot be called in interrupt context, which is different from
5094 *      timeout(9F).
5095 */
5096ddi_periodic_t
5097ddi_periodic_add(void (*func)(void *), void *arg, hrtime_t interval, int level)
5098{
5099	/*
5100	 * Sanity check of the argument level.
5101	 */
5102	if (level < DDI_IPL_0 || level > DDI_IPL_10)
5103		cmn_err(CE_PANIC,
5104		    "ddi_periodic_add: invalid interrupt level (%d).", level);
5105
5106	/*
5107	 * Sanity check of the context. ddi_periodic_add() cannot be
5108	 * called in either interrupt context or high interrupt context.
5109	 */
5110	if (servicing_interrupt())
5111		cmn_err(CE_PANIC,
5112		    "ddi_periodic_add: called in (high) interrupt context.");
5113
5114	return ((ddi_periodic_t)i_timeout(func, arg, interval, level));
5115}
5116
5117/*
5118 * void
5119 * ddi_periodic_delete(ddi_periodic_t req)
5120 *
5121 * INTERFACE LEVEL
5122 *     Solaris DDI specific (Solaris DDI)
5123 *
5124 * PARAMETERS
5125 *     req: ddi_periodic_t opaque value ddi_periodic_add(9F) returned
5126 *     previously.
5127 *
5128 * DESCRIPTION
5129 *     ddi_periodic_delete(9F) cancels the ddi_periodic_add(9F) request
5130 *     previously requested.
5131 *
5132 *     ddi_periodic_delete(9F) will not return until the pending request
5133 *     is canceled or executed.
5134 *
5135 *     As well as untimeout(9F), calling ddi_periodic_delete(9F) for a
5136 *     timeout which is either running on another CPU, or has already
5137 *     completed causes no problems. However, unlike untimeout(9F), there is
5138 *     no restrictions on the lock which might be held across the call to
5139 *     ddi_periodic_delete(9F).
5140 *
5141 *     Drivers should be structured with the understanding that the arrival of
5142 *     both an interrupt and a timeout for that interrupt can occasionally
5143 *     occur, in either order.
5144 *
5145 * CONTEXT
5146 *     ddi_periodic_delete(9F) can be called in user or kernel context, but
5147 *     it cannot be called in interrupt context, which is different from
5148 *     untimeout(9F).
5149 */
5150void
5151ddi_periodic_delete(ddi_periodic_t req)
5152{
5153	/*
5154	 * Sanity check of the context. ddi_periodic_delete() cannot be
5155	 * called in either interrupt context or high interrupt context.
5156	 */
5157	if (servicing_interrupt())
5158		cmn_err(CE_PANIC,
5159		    "ddi_periodic_delete: called in (high) interrupt context.");
5160
5161	i_untimeout((timeout_t)req);
5162}
5163
5164dev_info_t *
5165nodevinfo(dev_t dev, int otyp)
5166{
5167	_NOTE(ARGUNUSED(dev, otyp))
5168	return ((dev_info_t *)0);
5169}
5170
5171/*
5172 * A driver should support its own getinfo(9E) entry point. This function
5173 * is provided as a convenience for ON drivers that don't expect their
5174 * getinfo(9E) entry point to be called. A driver that uses this must not
5175 * call ddi_create_minor_node.
5176 */
5177int
5178ddi_no_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
5179{
5180	_NOTE(ARGUNUSED(dip, infocmd, arg, result))
5181	return (DDI_FAILURE);
5182}
5183
5184/*
5185 * A driver should support its own getinfo(9E) entry point. This function
5186 * is provided as a convenience for ON drivers that where the minor number
5187 * is the instance. Drivers that do not have 1:1 mapping must implement
5188 * their own getinfo(9E) function.
5189 */
5190int
5191ddi_getinfo_1to1(dev_info_t *dip, ddi_info_cmd_t infocmd,
5192    void *arg, void **result)
5193{
5194	_NOTE(ARGUNUSED(dip))
5195	int	instance;
5196
5197	if (infocmd != DDI_INFO_DEVT2INSTANCE)
5198		return (DDI_FAILURE);
5199
5200	instance = getminor((dev_t)(uintptr_t)arg);
5201	*result = (void *)(uintptr_t)instance;
5202	return (DDI_SUCCESS);
5203}
5204
5205int
5206ddifail(dev_info_t *devi, ddi_attach_cmd_t cmd)
5207{
5208	_NOTE(ARGUNUSED(devi, cmd))
5209	return (DDI_FAILURE);
5210}
5211
5212int
5213ddi_no_dma_map(dev_info_t *dip, dev_info_t *rdip,
5214    struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep)
5215{
5216	_NOTE(ARGUNUSED(dip, rdip, dmareqp, handlep))
5217	return (DDI_DMA_NOMAPPING);
5218}
5219
5220int
5221ddi_no_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr,
5222    int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep)
5223{
5224	_NOTE(ARGUNUSED(dip, rdip, attr, waitfp, arg, handlep))
5225	return (DDI_DMA_BADATTR);
5226}
5227
5228int
5229ddi_no_dma_freehdl(dev_info_t *dip, dev_info_t *rdip,
5230    ddi_dma_handle_t handle)
5231{
5232	_NOTE(ARGUNUSED(dip, rdip, handle))
5233	return (DDI_FAILURE);
5234}
5235
5236int
5237ddi_no_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
5238    ddi_dma_handle_t handle, struct ddi_dma_req *dmareq,
5239    ddi_dma_cookie_t *cp, uint_t *ccountp)
5240{
5241	_NOTE(ARGUNUSED(dip, rdip, handle, dmareq, cp, ccountp))
5242	return (DDI_DMA_NOMAPPING);
5243}
5244
5245int
5246ddi_no_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
5247    ddi_dma_handle_t handle)
5248{
5249	_NOTE(ARGUNUSED(dip, rdip, handle))
5250	return (DDI_FAILURE);
5251}
5252
5253int
5254ddi_no_dma_flush(dev_info_t *dip, dev_info_t *rdip,
5255    ddi_dma_handle_t handle, off_t off, size_t len,
5256    uint_t cache_flags)
5257{
5258	_NOTE(ARGUNUSED(dip, rdip, handle, off, len, cache_flags))
5259	return (DDI_FAILURE);
5260}
5261
5262int
5263ddi_no_dma_win(dev_info_t *dip, dev_info_t *rdip,
5264    ddi_dma_handle_t handle, uint_t win, off_t *offp,
5265    size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp)
5266{
5267	_NOTE(ARGUNUSED(dip, rdip, handle, win, offp, lenp, cookiep, ccountp))
5268	return (DDI_FAILURE);
5269}
5270
5271int
5272ddi_no_dma_mctl(dev_info_t *dip, dev_info_t *rdip,
5273    ddi_dma_handle_t handle, enum ddi_dma_ctlops request,
5274    off_t *offp, size_t *lenp, caddr_t *objp, uint_t flags)
5275{
5276	_NOTE(ARGUNUSED(dip, rdip, handle, request, offp, lenp, objp, flags))
5277	return (DDI_FAILURE);
5278}
5279
5280void
5281ddivoid(void)
5282{}
5283
5284int
5285nochpoll(dev_t dev, short events, int anyyet, short *reventsp,
5286    struct pollhead **pollhdrp)
5287{
5288	_NOTE(ARGUNUSED(dev, events, anyyet, reventsp, pollhdrp))
5289	return (ENXIO);
5290}
5291
5292cred_t *
5293ddi_get_cred(void)
5294{
5295	return (CRED());
5296}
5297
5298clock_t
5299ddi_get_lbolt(void)
5300{
5301	return ((clock_t)lbolt_hybrid());
5302}
5303
5304int64_t
5305ddi_get_lbolt64(void)
5306{
5307	return (lbolt_hybrid());
5308}
5309
5310time_t
5311ddi_get_time(void)
5312{
5313	time_t	now;
5314
5315	if ((now = gethrestime_sec()) == 0) {
5316		timestruc_t ts;
5317		mutex_enter(&tod_lock);
5318		ts = tod_get();
5319		mutex_exit(&tod_lock);
5320		return (ts.tv_sec);
5321	} else {
5322		return (now);
5323	}
5324}
5325
5326pid_t
5327ddi_get_pid(void)
5328{
5329	return (ttoproc(curthread)->p_pid);
5330}
5331
5332kt_did_t
5333ddi_get_kt_did(void)
5334{
5335	return (curthread->t_did);
5336}
5337
5338/*
5339 * This function returns B_TRUE if the caller can reasonably expect that a call
5340 * to cv_wait_sig(9F), cv_timedwait_sig(9F), or qwait_sig(9F) could be awakened
5341 * by user-level signal.  If it returns B_FALSE, then the caller should use
5342 * other means to make certain that the wait will not hang "forever."
5343 *
5344 * It does not check the signal mask, nor for reception of any particular
5345 * signal.
5346 *
5347 * Currently, a thread can receive a signal if it's not a kernel thread and it
5348 * is not in the middle of exit(2) tear-down.  Threads that are in that
5349 * tear-down effectively convert cv_wait_sig to cv_wait, cv_timedwait_sig to
5350 * cv_timedwait, and qwait_sig to qwait.
5351 */
5352boolean_t
5353ddi_can_receive_sig(void)
5354{
5355	proc_t *pp;
5356
5357	if (curthread->t_proc_flag & TP_LWPEXIT)
5358		return (B_FALSE);
5359	if ((pp = ttoproc(curthread)) == NULL)
5360		return (B_FALSE);
5361	return (pp->p_as != &kas);
5362}
5363
5364/*
5365 * Swap bytes in 16-bit [half-]words
5366 */
5367void
5368swab(void *src, void *dst, size_t nbytes)
5369{
5370	uchar_t *pf = (uchar_t *)src;
5371	uchar_t *pt = (uchar_t *)dst;
5372	uchar_t tmp;
5373	int nshorts;
5374
5375	nshorts = nbytes >> 1;
5376
5377	while (--nshorts >= 0) {
5378		tmp = *pf++;
5379		*pt++ = *pf++;
5380		*pt++ = tmp;
5381	}
5382}
5383
5384static void
5385ddi_append_minor_node(dev_info_t *ddip, struct ddi_minor_data *dmdp)
5386{
5387	int			circ;
5388	struct ddi_minor_data	*dp;
5389
5390	ndi_devi_enter(ddip, &circ);
5391	if ((dp = DEVI(ddip)->devi_minor) == (struct ddi_minor_data *)NULL) {
5392		DEVI(ddip)->devi_minor = dmdp;
5393	} else {
5394		while (dp->next != (struct ddi_minor_data *)NULL)
5395			dp = dp->next;
5396		dp->next = dmdp;
5397	}
5398	ndi_devi_exit(ddip, circ);
5399}
5400
5401/*
5402 * Part of the obsolete SunCluster DDI Hooks.
5403 * Keep for binary compatibility
5404 */
5405minor_t
5406ddi_getiminor(dev_t dev)
5407{
5408	return (getminor(dev));
5409}
5410
5411static int
5412i_log_devfs_minor_create(dev_info_t *dip, char *minor_name)
5413{
5414	int se_flag;
5415	int kmem_flag;
5416	int se_err;
5417	char *pathname, *class_name;
5418	sysevent_t *ev = NULL;
5419	sysevent_id_t eid;
5420	sysevent_value_t se_val;
5421	sysevent_attr_list_t *ev_attr_list = NULL;
5422
5423	/* determine interrupt context */
5424	se_flag = (servicing_interrupt()) ? SE_NOSLEEP : SE_SLEEP;
5425	kmem_flag = (se_flag == SE_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
5426
5427	i_ddi_di_cache_invalidate();
5428
5429#ifdef DEBUG
5430	if ((se_flag == SE_NOSLEEP) && sunddi_debug) {
5431		cmn_err(CE_CONT, "ddi_create_minor_node: called from "
5432		    "interrupt level by driver %s",
5433		    ddi_driver_name(dip));
5434	}
5435#endif /* DEBUG */
5436
5437	ev = sysevent_alloc(EC_DEVFS, ESC_DEVFS_MINOR_CREATE, EP_DDI, se_flag);
5438	if (ev == NULL) {
5439		goto fail;
5440	}
5441
5442	pathname = kmem_alloc(MAXPATHLEN, kmem_flag);
5443	if (pathname == NULL) {
5444		sysevent_free(ev);
5445		goto fail;
5446	}
5447
5448	(void) ddi_pathname(dip, pathname);
5449	ASSERT(strlen(pathname));
5450	se_val.value_type = SE_DATA_TYPE_STRING;
5451	se_val.value.sv_string = pathname;
5452	if (sysevent_add_attr(&ev_attr_list, DEVFS_PATHNAME,
5453	    &se_val, se_flag) != 0) {
5454		kmem_free(pathname, MAXPATHLEN);
5455		sysevent_free(ev);
5456		goto fail;
5457	}
5458	kmem_free(pathname, MAXPATHLEN);
5459
5460	/* add the device class attribute */
5461	if ((class_name = i_ddi_devi_class(dip)) != NULL) {
5462		se_val.value_type = SE_DATA_TYPE_STRING;
5463		se_val.value.sv_string = class_name;
5464		if (sysevent_add_attr(&ev_attr_list,
5465		    DEVFS_DEVI_CLASS, &se_val, SE_SLEEP) != 0) {
5466			sysevent_free_attr(ev_attr_list);
5467			goto fail;
5468		}
5469	}
5470
5471	/*
5472	 * allow for NULL minor names
5473	 */
5474	if (minor_name != NULL) {
5475		se_val.value.sv_string = minor_name;
5476		if (sysevent_add_attr(&ev_attr_list, DEVFS_MINOR_NAME,
5477		    &se_val, se_flag) != 0) {
5478			sysevent_free_attr(ev_attr_list);
5479			sysevent_free(ev);
5480			goto fail;
5481		}
5482	}
5483
5484	if (sysevent_attach_attributes(ev, ev_attr_list) != 0) {
5485		sysevent_free_attr(ev_attr_list);
5486		sysevent_free(ev);
5487		goto fail;
5488	}
5489
5490	if ((se_err = log_sysevent(ev, se_flag, &eid)) != 0) {
5491		if (se_err == SE_NO_TRANSPORT) {
5492			cmn_err(CE_WARN, "/devices or /dev may not be current "
5493			    "for driver %s (%s). Run devfsadm -i %s",
5494			    ddi_driver_name(dip), "syseventd not responding",
5495			    ddi_driver_name(dip));
5496		} else {
5497			sysevent_free(ev);
5498			goto fail;
5499		}
5500	}
5501
5502	sysevent_free(ev);
5503	return (DDI_SUCCESS);
5504fail:
5505	cmn_err(CE_WARN, "/devices or /dev may not be current "
5506	    "for driver %s. Run devfsadm -i %s",
5507	    ddi_driver_name(dip), ddi_driver_name(dip));
5508	return (DDI_SUCCESS);
5509}
5510
5511/*
5512 * failing to remove a minor node is not of interest
5513 * therefore we do not generate an error message
5514 */
5515static int
5516i_log_devfs_minor_remove(dev_info_t *dip, char *minor_name)
5517{
5518	char *pathname, *class_name;
5519	sysevent_t *ev;
5520	sysevent_id_t eid;
5521	sysevent_value_t se_val;
5522	sysevent_attr_list_t *ev_attr_list = NULL;
5523
5524	/*
5525	 * only log ddi_remove_minor_node() calls outside the scope
5526	 * of attach/detach reconfigurations and when the dip is
5527	 * still initialized.
5528	 */
5529	if (DEVI_IS_ATTACHING(dip) || DEVI_IS_DETACHING(dip) ||
5530	    (i_ddi_node_state(dip) < DS_INITIALIZED)) {
5531		return (DDI_SUCCESS);
5532	}
5533
5534	i_ddi_di_cache_invalidate();
5535
5536	ev = sysevent_alloc(EC_DEVFS, ESC_DEVFS_MINOR_REMOVE, EP_DDI, SE_SLEEP);
5537	if (ev == NULL) {
5538		return (DDI_SUCCESS);
5539	}
5540
5541	pathname = kmem_alloc(MAXPATHLEN, KM_SLEEP);
5542	if (pathname == NULL) {
5543		sysevent_free(ev);
5544		return (DDI_SUCCESS);
5545	}
5546
5547	(void) ddi_pathname(dip, pathname);
5548	ASSERT(strlen(pathname));
5549	se_val.value_type = SE_DATA_TYPE_STRING;
5550	se_val.value.sv_string = pathname;
5551	if (sysevent_add_attr(&ev_attr_list, DEVFS_PATHNAME,
5552	    &se_val, SE_SLEEP) != 0) {
5553		kmem_free(pathname, MAXPATHLEN);
5554		sysevent_free(ev);
5555		return (DDI_SUCCESS);
5556	}
5557
5558	kmem_free(pathname, MAXPATHLEN);
5559
5560	/*
5561	 * allow for NULL minor names
5562	 */
5563	if (minor_name != NULL) {
5564		se_val.value.sv_string = minor_name;
5565		if (sysevent_add_attr(&ev_attr_list, DEVFS_MINOR_NAME,
5566		    &se_val, SE_SLEEP) != 0) {
5567			sysevent_free_attr(ev_attr_list);
5568			goto fail;
5569		}
5570	}
5571
5572	if ((class_name = i_ddi_devi_class(dip)) != NULL) {
5573		/* add the device class, driver name and instance attributes */
5574
5575		se_val.value_type = SE_DATA_TYPE_STRING;
5576		se_val.value.sv_string = class_name;
5577		if (sysevent_add_attr(&ev_attr_list,
5578		    DEVFS_DEVI_CLASS, &se_val, SE_SLEEP) != 0) {
5579			sysevent_free_attr(ev_attr_list);
5580			goto fail;
5581		}
5582
5583		se_val.value_type = SE_DATA_TYPE_STRING;
5584		se_val.value.sv_string = (char *)ddi_driver_name(dip);
5585		if (sysevent_add_attr(&ev_attr_list,
5586		    DEVFS_DRIVER_NAME, &se_val, SE_SLEEP) != 0) {
5587			sysevent_free_attr(ev_attr_list);
5588			goto fail;
5589		}
5590
5591		se_val.value_type = SE_DATA_TYPE_INT32;
5592		se_val.value.sv_int32 = ddi_get_instance(dip);
5593		if (sysevent_add_attr(&ev_attr_list,
5594		    DEVFS_INSTANCE, &se_val, SE_SLEEP) != 0) {
5595			sysevent_free_attr(ev_attr_list);
5596			goto fail;
5597		}
5598
5599	}
5600
5601	if (sysevent_attach_attributes(ev, ev_attr_list) != 0) {
5602		sysevent_free_attr(ev_attr_list);
5603	} else {
5604		(void) log_sysevent(ev, SE_SLEEP, &eid);
5605	}
5606fail:
5607	sysevent_free(ev);
5608	return (DDI_SUCCESS);
5609}
5610
5611/*
5612 * Derive the device class of the node.
5613 * Device class names aren't defined yet. Until this is done we use
5614 * devfs event subclass names as device class names.
5615 */
5616static int
5617derive_devi_class(dev_info_t *dip, const char *node_type, int flag)
5618{
5619	int rv = DDI_SUCCESS;
5620
5621	if (i_ddi_devi_class(dip) == NULL) {
5622		if (strncmp(node_type, DDI_NT_BLOCK,
5623		    sizeof (DDI_NT_BLOCK) - 1) == 0 &&
5624		    (node_type[sizeof (DDI_NT_BLOCK) - 1] == '\0' ||
5625		    node_type[sizeof (DDI_NT_BLOCK) - 1] == ':') &&
5626		    strcmp(node_type, DDI_NT_FD) != 0) {
5627
5628			rv = i_ddi_set_devi_class(dip, ESC_DISK, flag);
5629
5630		} else if (strncmp(node_type, DDI_NT_NET,
5631		    sizeof (DDI_NT_NET) - 1) == 0 &&
5632		    (node_type[sizeof (DDI_NT_NET) - 1] == '\0' ||
5633		    node_type[sizeof (DDI_NT_NET) - 1] == ':')) {
5634
5635			rv = i_ddi_set_devi_class(dip, ESC_NETWORK, flag);
5636
5637		} else if (strncmp(node_type, DDI_NT_PRINTER,
5638		    sizeof (DDI_NT_PRINTER) - 1) == 0 &&
5639		    (node_type[sizeof (DDI_NT_PRINTER) - 1] == '\0' ||
5640		    node_type[sizeof (DDI_NT_PRINTER) - 1] == ':')) {
5641
5642			rv = i_ddi_set_devi_class(dip, ESC_PRINTER, flag);
5643
5644		} else if (strncmp(node_type, DDI_PSEUDO,
5645		    sizeof (DDI_PSEUDO) -1) == 0 &&
5646		    (strncmp(ESC_LOFI, ddi_node_name(dip),
5647		    sizeof (ESC_LOFI) -1) == 0)) {
5648			rv = i_ddi_set_devi_class(dip, ESC_LOFI, flag);
5649		}
5650	}
5651
5652	return (rv);
5653}
5654
5655/*
5656 * Check compliance with PSARC 2003/375:
5657 *
5658 * The name must contain only characters a-z, A-Z, 0-9 or _ and it must not
5659 * exceed IFNAMSIZ (16) characters in length.
5660 */
5661static boolean_t
5662verify_name(const char *name)
5663{
5664	size_t len = strlen(name);
5665	const char *cp;
5666
5667	if (len == 0 || len > IFNAMSIZ)
5668		return (B_FALSE);
5669
5670	for (cp = name; *cp != '\0'; cp++) {
5671		if (!isalnum(*cp) && *cp != '_')
5672			return (B_FALSE);
5673	}
5674
5675	return (B_TRUE);
5676}
5677
5678/*
5679 * ddi_create_minor_common:	Create a  ddi_minor_data structure and
5680 *				attach it to the given devinfo node.
5681 */
5682
5683static int
5684ddi_create_minor_common(dev_info_t *dip, const char *name, int spec_type,
5685    minor_t minor_num, const char *node_type, int flag, ddi_minor_type mtype,
5686    const char *read_priv, const char *write_priv, mode_t priv_mode)
5687{
5688	struct ddi_minor_data *dmdp;
5689	major_t major;
5690
5691	if (spec_type != S_IFCHR && spec_type != S_IFBLK)
5692		return (DDI_FAILURE);
5693
5694	if (name == NULL)
5695		return (DDI_FAILURE);
5696
5697	/*
5698	 * Log a message if the minor number the driver is creating
5699	 * is not expressible on the on-disk filesystem (currently
5700	 * this is limited to 18 bits both by UFS). The device can
5701	 * be opened via devfs, but not by device special files created
5702	 * via mknod().
5703	 */
5704	if (minor_num > L_MAXMIN32) {
5705		cmn_err(CE_WARN,
5706		    "%s%d:%s minor 0x%x too big for 32-bit applications",
5707		    ddi_driver_name(dip), ddi_get_instance(dip),
5708		    name, minor_num);
5709		return (DDI_FAILURE);
5710	}
5711
5712	/* dip must be bound and attached */
5713	major = ddi_driver_major(dip);
5714	ASSERT(major != DDI_MAJOR_T_NONE);
5715
5716	/*
5717	 * Default node_type to DDI_PSEUDO and issue notice in debug mode
5718	 */
5719	if (node_type == NULL) {
5720		node_type = DDI_PSEUDO;
5721		NDI_CONFIG_DEBUG((CE_NOTE, "!illegal node_type NULL for %s%d "
5722		    " minor node %s; default to DDI_PSEUDO",
5723		    ddi_driver_name(dip), ddi_get_instance(dip), name));
5724	}
5725
5726	/*
5727	 * If the driver is a network driver, ensure that the name falls within
5728	 * the interface naming constraints specified by PSARC/2003/375.
5729	 */
5730	if (strcmp(node_type, DDI_NT_NET) == 0) {
5731		if (!verify_name(name))
5732			return (DDI_FAILURE);
5733
5734		if (mtype == DDM_MINOR) {
5735			struct devnames *dnp = &devnamesp[major];
5736
5737			/* Mark driver as a network driver */
5738			LOCK_DEV_OPS(&dnp->dn_lock);
5739			dnp->dn_flags |= DN_NETWORK_DRIVER;
5740
5741			/*
5742			 * If this minor node is created during the device
5743			 * attachment, this is a physical network device.
5744			 * Mark the driver as a physical network driver.
5745			 */
5746			if (DEVI_IS_ATTACHING(dip))
5747				dnp->dn_flags |= DN_NETWORK_PHYSDRIVER;
5748			UNLOCK_DEV_OPS(&dnp->dn_lock);
5749		}
5750	}
5751
5752	if (mtype == DDM_MINOR) {
5753		if (derive_devi_class(dip,  node_type, KM_NOSLEEP) !=
5754		    DDI_SUCCESS)
5755			return (DDI_FAILURE);
5756	}
5757
5758	/*
5759	 * Take care of minor number information for the node.
5760	 */
5761
5762	if ((dmdp = kmem_zalloc(sizeof (struct ddi_minor_data),
5763	    KM_NOSLEEP)) == NULL) {
5764		return (DDI_FAILURE);
5765	}
5766	if ((dmdp->ddm_name = i_ddi_strdup(name, KM_NOSLEEP)) == NULL) {
5767		kmem_free(dmdp, sizeof (struct ddi_minor_data));
5768		return (DDI_FAILURE);
5769	}
5770	dmdp->dip = dip;
5771	dmdp->ddm_dev = makedevice(major, minor_num);
5772	dmdp->ddm_spec_type = spec_type;
5773	dmdp->ddm_node_type = node_type;
5774	dmdp->type = mtype;
5775	if (flag & CLONE_DEV) {
5776		dmdp->type = DDM_ALIAS;
5777		dmdp->ddm_dev = makedevice(ddi_driver_major(clone_dip), major);
5778	}
5779	if (flag & PRIVONLY_DEV) {
5780		dmdp->ddm_flags |= DM_NO_FSPERM;
5781	}
5782	if (read_priv || write_priv) {
5783		dmdp->ddm_node_priv =
5784		    devpolicy_priv_by_name(read_priv, write_priv);
5785	}
5786	dmdp->ddm_priv_mode = priv_mode;
5787
5788	ddi_append_minor_node(dip, dmdp);
5789
5790	/*
5791	 * only log ddi_create_minor_node() calls which occur
5792	 * outside the scope of attach(9e)/detach(9e) reconfigurations
5793	 */
5794	if (!(DEVI_IS_ATTACHING(dip) || DEVI_IS_DETACHING(dip)) &&
5795	    mtype != DDM_INTERNAL_PATH) {
5796		(void) i_log_devfs_minor_create(dip, dmdp->ddm_name);
5797	}
5798
5799	/*
5800	 * Check if any dacf rules match the creation of this minor node
5801	 */
5802	dacfc_match_create_minor(name, node_type, dip, dmdp, flag);
5803	return (DDI_SUCCESS);
5804}
5805
5806int
5807ddi_create_minor_node(dev_info_t *dip, const char *name, int spec_type,
5808    minor_t minor_num, const char *node_type, int flag)
5809{
5810	return (ddi_create_minor_common(dip, name, spec_type, minor_num,
5811	    node_type, flag, DDM_MINOR, NULL, NULL, 0));
5812}
5813
5814int
5815ddi_create_priv_minor_node(dev_info_t *dip, const char *name, int spec_type,
5816    minor_t minor_num, const char *node_type, int flag,
5817    const char *rdpriv, const char *wrpriv, mode_t priv_mode)
5818{
5819	return (ddi_create_minor_common(dip, name, spec_type, minor_num,
5820	    node_type, flag, DDM_MINOR, rdpriv, wrpriv, priv_mode));
5821}
5822
5823int
5824ddi_create_default_minor_node(dev_info_t *dip, const char *name, int spec_type,
5825    minor_t minor_num, const char *node_type, int flag)
5826{
5827	return (ddi_create_minor_common(dip, name, spec_type, minor_num,
5828	    node_type, flag, DDM_DEFAULT, NULL, NULL, 0));
5829}
5830
5831/*
5832 * Internal (non-ddi) routine for drivers to export names known
5833 * to the kernel (especially ddi_pathname_to_dev_t and friends)
5834 * but not exported externally to /dev
5835 */
5836int
5837ddi_create_internal_pathname(dev_info_t *dip, char *name, int spec_type,
5838    minor_t minor_num)
5839{
5840	return (ddi_create_minor_common(dip, name, spec_type, minor_num,
5841	    "internal", 0, DDM_INTERNAL_PATH, NULL, NULL, 0));
5842}
5843
5844void
5845ddi_remove_minor_node(dev_info_t *dip, const char *name)
5846{
5847	int			circ;
5848	struct ddi_minor_data	*dmdp, *dmdp1;
5849	struct ddi_minor_data	**dmdp_prev;
5850
5851	ndi_devi_enter(dip, &circ);
5852	dmdp_prev = &DEVI(dip)->devi_minor;
5853	dmdp = DEVI(dip)->devi_minor;
5854	while (dmdp != NULL) {
5855		dmdp1 = dmdp->next;
5856		if ((name == NULL || (dmdp->ddm_name != NULL &&
5857		    strcmp(name, dmdp->ddm_name) == 0))) {
5858			if (dmdp->ddm_name != NULL) {
5859				if (dmdp->type != DDM_INTERNAL_PATH)
5860					(void) i_log_devfs_minor_remove(dip,
5861					    dmdp->ddm_name);
5862				kmem_free(dmdp->ddm_name,
5863				    strlen(dmdp->ddm_name) + 1);
5864			}
5865			/*
5866			 * Release device privilege, if any.
5867			 * Release dacf client data associated with this minor
5868			 * node by storing NULL.
5869			 */
5870			if (dmdp->ddm_node_priv)
5871				dpfree(dmdp->ddm_node_priv);
5872			dacf_store_info((dacf_infohdl_t)dmdp, NULL);
5873			kmem_free(dmdp, sizeof (struct ddi_minor_data));
5874			*dmdp_prev = dmdp1;
5875			/*
5876			 * OK, we found it, so get out now -- if we drive on,
5877			 * we will strcmp against garbage.  See 1139209.
5878			 */
5879			if (name != NULL)
5880				break;
5881		} else {
5882			dmdp_prev = &dmdp->next;
5883		}
5884		dmdp = dmdp1;
5885	}
5886	ndi_devi_exit(dip, circ);
5887}
5888
5889
5890int
5891ddi_in_panic()
5892{
5893	return (panicstr != NULL);
5894}
5895
5896
5897/*
5898 * Find first bit set in a mask (returned counting from 1 up)
5899 */
5900
5901int
5902ddi_ffs(long mask)
5903{
5904	return (ffs(mask));
5905}
5906
5907/*
5908 * Find last bit set. Take mask and clear
5909 * all but the most significant bit, and
5910 * then let ffs do the rest of the work.
5911 *
5912 * Algorithm courtesy of Steve Chessin.
5913 */
5914
5915int
5916ddi_fls(long mask)
5917{
5918	while (mask) {
5919		long nx;
5920
5921		if ((nx = (mask & (mask - 1))) == 0)
5922			break;
5923		mask = nx;
5924	}
5925	return (ffs(mask));
5926}
5927
5928/*
5929 * The ddi_soft_state_* routines comprise generic storage management utilities
5930 * for driver soft state structures (in "the old days," this was done with
5931 * statically sized array - big systems and dynamic loading and unloading
5932 * make heap allocation more attractive).
5933 */
5934
5935/*
5936 * Allocate a set of pointers to 'n_items' objects of size 'size'
5937 * bytes.  Each pointer is initialized to nil.
5938 *
5939 * The 'size' and 'n_items' values are stashed in the opaque
5940 * handle returned to the caller.
5941 *
5942 * This implementation interprets 'set of pointers' to mean 'array
5943 * of pointers' but note that nothing in the interface definition
5944 * precludes an implementation that uses, for example, a linked list.
5945 * However there should be a small efficiency gain from using an array
5946 * at lookup time.
5947 *
5948 * NOTE	As an optimization, we make our growable array allocations in
5949 *	powers of two (bytes), since that's how much kmem_alloc (currently)
5950 *	gives us anyway.  It should save us some free/realloc's ..
5951 *
5952 *	As a further optimization, we make the growable array start out
5953 *	with MIN_N_ITEMS in it.
5954 */
5955
5956#define	MIN_N_ITEMS	8	/* 8 void *'s == 32 bytes */
5957
5958int
5959ddi_soft_state_init(void **state_p, size_t size, size_t n_items)
5960{
5961	i_ddi_soft_state	*ss;
5962
5963	if (state_p == NULL || size == 0)
5964		return (EINVAL);
5965
5966	ss = kmem_zalloc(sizeof (*ss), KM_SLEEP);
5967	mutex_init(&ss->lock, NULL, MUTEX_DRIVER, NULL);
5968	ss->size = size;
5969
5970	if (n_items < MIN_N_ITEMS)
5971		ss->n_items = MIN_N_ITEMS;
5972	else {
5973		int bitlog;
5974
5975		if ((bitlog = ddi_fls(n_items)) == ddi_ffs(n_items))
5976			bitlog--;
5977		ss->n_items = 1 << bitlog;
5978	}
5979
5980	ASSERT(ss->n_items >= n_items);
5981
5982	ss->array = kmem_zalloc(ss->n_items * sizeof (void *), KM_SLEEP);
5983
5984	*state_p = ss;
5985	return (0);
5986}
5987
5988/*
5989 * Allocate a state structure of size 'size' to be associated
5990 * with item 'item'.
5991 *
5992 * In this implementation, the array is extended to
5993 * allow the requested offset, if needed.
5994 */
5995int
5996ddi_soft_state_zalloc(void *state, int item)
5997{
5998	i_ddi_soft_state	*ss = (i_ddi_soft_state *)state;
5999	void			**array;
6000	void			*new_element;
6001
6002	if ((state == NULL) || (item < 0))
6003		return (DDI_FAILURE);
6004
6005	mutex_enter(&ss->lock);
6006	if (ss->size == 0) {
6007		mutex_exit(&ss->lock);
6008		cmn_err(CE_WARN, "ddi_soft_state_zalloc: bad handle: %s",
6009		    mod_containing_pc(caller()));
6010		return (DDI_FAILURE);
6011	}
6012
6013	array = ss->array;	/* NULL if ss->n_items == 0 */
6014	ASSERT(ss->n_items != 0 && array != NULL);
6015
6016	/*
6017	 * refuse to tread on an existing element
6018	 */
6019	if (item < ss->n_items && array[item] != NULL) {
6020		mutex_exit(&ss->lock);
6021		return (DDI_FAILURE);
6022	}
6023
6024	/*
6025	 * Allocate a new element to plug in
6026	 */
6027	new_element = kmem_zalloc(ss->size, KM_SLEEP);
6028
6029	/*
6030	 * Check if the array is big enough, if not, grow it.
6031	 */
6032	if (item >= ss->n_items) {
6033		void			**new_array;
6034		size_t			new_n_items;
6035		struct i_ddi_soft_state	*dirty;
6036
6037		/*
6038		 * Allocate a new array of the right length, copy
6039		 * all the old pointers to the new array, then
6040		 * if it exists at all, put the old array on the
6041		 * dirty list.
6042		 *
6043		 * Note that we can't kmem_free() the old array.
6044		 *
6045		 * Why -- well the 'get' operation is 'mutex-free', so we
6046		 * can't easily catch a suspended thread that is just about
6047		 * to dereference the array we just grew out of.  So we
6048		 * cons up a header and put it on a list of 'dirty'
6049		 * pointer arrays.  (Dirty in the sense that there may
6050		 * be suspended threads somewhere that are in the middle
6051		 * of referencing them).  Fortunately, we -can- garbage
6052		 * collect it all at ddi_soft_state_fini time.
6053		 */
6054		new_n_items = ss->n_items;
6055		while (new_n_items < (1 + item))
6056			new_n_items <<= 1;	/* double array size .. */
6057
6058		ASSERT(new_n_items >= (1 + item));	/* sanity check! */
6059
6060		new_array = kmem_zalloc(new_n_items * sizeof (void *),
6061		    KM_SLEEP);
6062		/*
6063		 * Copy the pointers into the new array
6064		 */
6065		bcopy(array, new_array, ss->n_items * sizeof (void *));
6066
6067		/*
6068		 * Save the old array on the dirty list
6069		 */
6070		dirty = kmem_zalloc(sizeof (*dirty), KM_SLEEP);
6071		dirty->array = ss->array;
6072		dirty->n_items = ss->n_items;
6073		dirty->next = ss->next;
6074		ss->next = dirty;
6075
6076		ss->array = (array = new_array);
6077		ss->n_items = new_n_items;
6078	}
6079
6080	ASSERT(array != NULL && item < ss->n_items && array[item] == NULL);
6081
6082	array[item] = new_element;
6083
6084	mutex_exit(&ss->lock);
6085	return (DDI_SUCCESS);
6086}
6087
6088/*
6089 * Fetch a pointer to the allocated soft state structure.
6090 *
6091 * This is designed to be cheap.
6092 *
6093 * There's an argument that there should be more checking for
6094 * nil pointers and out of bounds on the array.. but we do a lot
6095 * of that in the alloc/free routines.
6096 *
6097 * An array has the convenience that we don't need to lock read-access
6098 * to it c.f. a linked list.  However our "expanding array" strategy
6099 * means that we should hold a readers lock on the i_ddi_soft_state
6100 * structure.
6101 *
6102 * However, from a performance viewpoint, we need to do it without
6103 * any locks at all -- this also makes it a leaf routine.  The algorithm
6104 * is 'lock-free' because we only discard the pointer arrays at
6105 * ddi_soft_state_fini() time.
6106 */
6107void *
6108ddi_get_soft_state(void *state, int item)
6109{
6110	i_ddi_soft_state	*ss = (i_ddi_soft_state *)state;
6111
6112	ASSERT((ss != NULL) && (item >= 0));
6113
6114	if (item < ss->n_items && ss->array != NULL)
6115		return (ss->array[item]);
6116	return (NULL);
6117}
6118
6119/*
6120 * Free the state structure corresponding to 'item.'   Freeing an
6121 * element that has either gone or was never allocated is not
6122 * considered an error.  Note that we free the state structure, but
6123 * we don't shrink our pointer array, or discard 'dirty' arrays,
6124 * since even a few pointers don't really waste too much memory.
6125 *
6126 * Passing an item number that is out of bounds, or a null pointer will
6127 * provoke an error message.
6128 */
6129void
6130ddi_soft_state_free(void *state, int item)
6131{
6132	i_ddi_soft_state	*ss = (i_ddi_soft_state *)state;
6133	void			**array;
6134	void			*element;
6135	static char		msg[] = "ddi_soft_state_free:";
6136
6137	if (ss == NULL) {
6138		cmn_err(CE_WARN, "%s null handle: %s",
6139		    msg, mod_containing_pc(caller()));
6140		return;
6141	}
6142
6143	element = NULL;
6144
6145	mutex_enter(&ss->lock);
6146
6147	if ((array = ss->array) == NULL || ss->size == 0) {
6148		cmn_err(CE_WARN, "%s bad handle: %s",
6149		    msg, mod_containing_pc(caller()));
6150	} else if (item < 0 || item >= ss->n_items) {
6151		cmn_err(CE_WARN, "%s item %d not in range [0..%lu]: %s",
6152		    msg, item, ss->n_items - 1, mod_containing_pc(caller()));
6153	} else if (array[item] != NULL) {
6154		element = array[item];
6155		array[item] = NULL;
6156	}
6157
6158	mutex_exit(&ss->lock);
6159
6160	if (element)
6161		kmem_free(element, ss->size);
6162}
6163
6164/*
6165 * Free the entire set of pointers, and any
6166 * soft state structures contained therein.
6167 *
6168 * Note that we don't grab the ss->lock mutex, even though
6169 * we're inspecting the various fields of the data structure.
6170 *
6171 * There is an implicit assumption that this routine will
6172 * never run concurrently with any of the above on this
6173 * particular state structure i.e. by the time the driver
6174 * calls this routine, there should be no other threads
6175 * running in the driver.
6176 */
6177void
6178ddi_soft_state_fini(void **state_p)
6179{
6180	i_ddi_soft_state	*ss, *dirty;
6181	int			item;
6182	static char		msg[] = "ddi_soft_state_fini:";
6183
6184	if (state_p == NULL ||
6185	    (ss = (i_ddi_soft_state *)(*state_p)) == NULL) {
6186		cmn_err(CE_WARN, "%s null handle: %s",
6187		    msg, mod_containing_pc(caller()));
6188		return;
6189	}
6190
6191	if (ss->size == 0) {
6192		cmn_err(CE_WARN, "%s bad handle: %s",
6193		    msg, mod_containing_pc(caller()));
6194		return;
6195	}
6196
6197	if (ss->n_items > 0) {
6198		for (item = 0; item < ss->n_items; item++)
6199			ddi_soft_state_free(ss, item);
6200		kmem_free(ss->array, ss->n_items * sizeof (void *));
6201	}
6202
6203	/*
6204	 * Now delete any dirty arrays from previous 'grow' operations
6205	 */
6206	for (dirty = ss->next; dirty; dirty = ss->next) {
6207		ss->next = dirty->next;
6208		kmem_free(dirty->array, dirty->n_items * sizeof (void *));
6209		kmem_free(dirty, sizeof (*dirty));
6210	}
6211
6212	mutex_destroy(&ss->lock);
6213	kmem_free(ss, sizeof (*ss));
6214
6215	*state_p = NULL;
6216}
6217
6218#define	SS_N_ITEMS_PER_HASH	16
6219#define	SS_MIN_HASH_SZ		16
6220#define	SS_MAX_HASH_SZ		4096
6221
6222int
6223ddi_soft_state_bystr_init(ddi_soft_state_bystr **state_p, size_t size,
6224    int n_items)
6225{
6226	i_ddi_soft_state_bystr	*sss;
6227	int			hash_sz;
6228
6229	ASSERT(state_p && size && n_items);
6230	if ((state_p == NULL) || (size == 0) || (n_items == 0))
6231		return (EINVAL);
6232
6233	/* current implementation is based on hash, convert n_items to hash */
6234	hash_sz = n_items / SS_N_ITEMS_PER_HASH;
6235	if (hash_sz < SS_MIN_HASH_SZ)
6236		hash_sz = SS_MIN_HASH_SZ;
6237	else if (hash_sz > SS_MAX_HASH_SZ)
6238		hash_sz = SS_MAX_HASH_SZ;
6239
6240	/* allocate soft_state pool */
6241	sss = kmem_zalloc(sizeof (*sss), KM_SLEEP);
6242	sss->ss_size = size;
6243	sss->ss_mod_hash = mod_hash_create_strhash("soft_state_bystr",
6244	    hash_sz, mod_hash_null_valdtor);
6245	*state_p = (ddi_soft_state_bystr *)sss;
6246	return (0);
6247}
6248
6249int
6250ddi_soft_state_bystr_zalloc(ddi_soft_state_bystr *state, const char *str)
6251{
6252	i_ddi_soft_state_bystr	*sss = (i_ddi_soft_state_bystr *)state;
6253	void			*sso;
6254	char			*dup_str;
6255
6256	ASSERT(sss && str && sss->ss_mod_hash);
6257	if ((sss == NULL) || (str == NULL) || (sss->ss_mod_hash == NULL))
6258		return (DDI_FAILURE);
6259	sso = kmem_zalloc(sss->ss_size, KM_SLEEP);
6260	dup_str = i_ddi_strdup((char *)str, KM_SLEEP);
6261	if (mod_hash_insert(sss->ss_mod_hash,
6262	    (mod_hash_key_t)dup_str, (mod_hash_val_t)sso) == 0)
6263		return (DDI_SUCCESS);
6264
6265	/*
6266	 * The only error from an strhash insert is caused by a duplicate key.
6267	 * We refuse to tread on an existing elements, so free and fail.
6268	 */
6269	kmem_free(dup_str, strlen(dup_str) + 1);
6270	kmem_free(sso, sss->ss_size);
6271	return (DDI_FAILURE);
6272}
6273
6274void *
6275ddi_soft_state_bystr_get(ddi_soft_state_bystr *state, const char *str)
6276{
6277	i_ddi_soft_state_bystr	*sss = (i_ddi_soft_state_bystr *)state;
6278	void			*sso;
6279
6280	ASSERT(sss && str && sss->ss_mod_hash);
6281	if ((sss == NULL) || (str == NULL) || (sss->ss_mod_hash == NULL))
6282		return (NULL);
6283
6284	if (mod_hash_find(sss->ss_mod_hash,
6285	    (mod_hash_key_t)str, (mod_hash_val_t *)&sso) == 0)
6286		return (sso);
6287	return (NULL);
6288}
6289
6290void
6291ddi_soft_state_bystr_free(ddi_soft_state_bystr *state, const char *str)
6292{
6293	i_ddi_soft_state_bystr	*sss = (i_ddi_soft_state_bystr *)state;
6294	void			*sso;
6295
6296	ASSERT(sss && str && sss->ss_mod_hash);
6297	if ((sss == NULL) || (str == NULL) || (sss->ss_mod_hash == NULL))
6298		return;
6299
6300	(void) mod_hash_remove(sss->ss_mod_hash,
6301	    (mod_hash_key_t)str, (mod_hash_val_t *)&sso);
6302	kmem_free(sso, sss->ss_size);
6303}
6304
6305void
6306ddi_soft_state_bystr_fini(ddi_soft_state_bystr **state_p)
6307{
6308	i_ddi_soft_state_bystr	*sss;
6309
6310	ASSERT(state_p);
6311	if (state_p == NULL)
6312		return;
6313
6314	sss = (i_ddi_soft_state_bystr *)(*state_p);
6315	if (sss == NULL)
6316		return;
6317
6318	ASSERT(sss->ss_mod_hash);
6319	if (sss->ss_mod_hash) {
6320		mod_hash_destroy_strhash(sss->ss_mod_hash);
6321		sss->ss_mod_hash = NULL;
6322	}
6323
6324	kmem_free(sss, sizeof (*sss));
6325	*state_p = NULL;
6326}
6327
6328/*
6329 * The ddi_strid_* routines provide string-to-index management utilities.
6330 */
6331/* allocate and initialize an strid set */
6332int
6333ddi_strid_init(ddi_strid **strid_p, int n_items)
6334{
6335	i_ddi_strid	*ss;
6336	int		hash_sz;
6337
6338	if (strid_p == NULL)
6339		return (DDI_FAILURE);
6340
6341	/* current implementation is based on hash, convert n_items to hash */
6342	hash_sz = n_items / SS_N_ITEMS_PER_HASH;
6343	if (hash_sz < SS_MIN_HASH_SZ)
6344		hash_sz = SS_MIN_HASH_SZ;
6345	else if (hash_sz > SS_MAX_HASH_SZ)
6346		hash_sz = SS_MAX_HASH_SZ;
6347
6348	ss = kmem_alloc(sizeof (*ss), KM_SLEEP);
6349	ss->strid_chunksz = n_items;
6350	ss->strid_spacesz = n_items;
6351	ss->strid_space = id_space_create("strid", 1, n_items);
6352	ss->strid_bystr = mod_hash_create_strhash("strid_bystr", hash_sz,
6353	    mod_hash_null_valdtor);
6354	ss->strid_byid = mod_hash_create_idhash("strid_byid", hash_sz,
6355	    mod_hash_null_valdtor);
6356	*strid_p = (ddi_strid *)ss;
6357	return (DDI_SUCCESS);
6358}
6359
6360/* allocate an id mapping within the specified set for str, return id */
6361static id_t
6362i_ddi_strid_alloc(ddi_strid *strid, char *str)
6363{
6364	i_ddi_strid	*ss = (i_ddi_strid *)strid;
6365	id_t		id;
6366	char		*s;
6367
6368	ASSERT(ss && str);
6369	if ((ss == NULL) || (str == NULL))
6370		return (0);
6371
6372	/*
6373	 * Allocate an id using VM_FIRSTFIT in order to keep allocated id
6374	 * range as compressed as possible.  This is important to minimize
6375	 * the amount of space used when the id is used as a ddi_soft_state
6376	 * index by the caller.
6377	 *
6378	 * If the id list is exhausted, increase the size of the list
6379	 * by the chuck size specified in ddi_strid_init and reattempt
6380	 * the allocation
6381	 */
6382	if ((id = id_allocff_nosleep(ss->strid_space)) == (id_t)-1) {
6383		id_space_extend(ss->strid_space, ss->strid_spacesz,
6384		    ss->strid_spacesz + ss->strid_chunksz);
6385		ss->strid_spacesz += ss->strid_chunksz;
6386		if ((id = id_allocff_nosleep(ss->strid_space)) == (id_t)-1)
6387			return (0);
6388	}
6389
6390	/*
6391	 * NOTE: since we create and destroy in unison we can save space by
6392	 * using bystr key as the byid value.  This means destroy must occur
6393	 * in (byid, bystr) order.
6394	 */
6395	s = i_ddi_strdup(str, KM_SLEEP);
6396	if (mod_hash_insert(ss->strid_bystr, (mod_hash_key_t)s,
6397	    (mod_hash_val_t)(intptr_t)id) != 0) {
6398		ddi_strid_free(strid, id);
6399		return (0);
6400	}
6401	if (mod_hash_insert(ss->strid_byid, (mod_hash_key_t)(intptr_t)id,
6402	    (mod_hash_val_t)s) != 0) {
6403		ddi_strid_free(strid, id);
6404		return (0);
6405	}
6406
6407	/* NOTE: s if freed on mod_hash_destroy by mod_hash_strval_dtor */
6408	return (id);
6409}
6410
6411/* allocate an id mapping within the specified set for str, return id */
6412id_t
6413ddi_strid_alloc(ddi_strid *strid, char *str)
6414{
6415	return (i_ddi_strid_alloc(strid, str));
6416}
6417
6418/* return the id within the specified strid given the str */
6419id_t
6420ddi_strid_str2id(ddi_strid *strid, char *str)
6421{
6422	i_ddi_strid	*ss = (i_ddi_strid *)strid;
6423	id_t		id = 0;
6424	mod_hash_val_t	hv;
6425
6426	ASSERT(ss && str);
6427	if (ss && str && (mod_hash_find(ss->strid_bystr,
6428	    (mod_hash_key_t)str, &hv) == 0))
6429		id = (int)(intptr_t)hv;
6430	return (id);
6431}
6432
6433/* return str within the specified strid given the id */
6434char *
6435ddi_strid_id2str(ddi_strid *strid, id_t id)
6436{
6437	i_ddi_strid	*ss = (i_ddi_strid *)strid;
6438	char		*str = NULL;
6439	mod_hash_val_t	hv;
6440
6441	ASSERT(ss && id > 0);
6442	if (ss && (id > 0) && (mod_hash_find(ss->strid_byid,
6443	    (mod_hash_key_t)(uintptr_t)id, &hv) == 0))
6444		str = (char *)hv;
6445	return (str);
6446}
6447
6448/* free the id mapping within the specified strid */
6449void
6450ddi_strid_free(ddi_strid *strid, id_t id)
6451{
6452	i_ddi_strid	*ss = (i_ddi_strid *)strid;
6453	char		*str;
6454
6455	ASSERT(ss && id > 0);
6456	if ((ss == NULL) || (id <= 0))
6457		return;
6458
6459	/* bystr key is byid value: destroy order must be (byid, bystr) */
6460	str = ddi_strid_id2str(strid, id);
6461	(void) mod_hash_destroy(ss->strid_byid, (mod_hash_key_t)(uintptr_t)id);
6462	id_free(ss->strid_space, id);
6463
6464	if (str)
6465		(void) mod_hash_destroy(ss->strid_bystr, (mod_hash_key_t)str);
6466}
6467
6468/* destroy the strid set */
6469void
6470ddi_strid_fini(ddi_strid **strid_p)
6471{
6472	i_ddi_strid	*ss;
6473
6474	ASSERT(strid_p);
6475	if (strid_p == NULL)
6476		return;
6477
6478	ss = (i_ddi_strid *)(*strid_p);
6479	if (ss == NULL)
6480		return;
6481
6482	/* bystr key is byid value: destroy order must be (byid, bystr) */
6483	if (ss->strid_byid)
6484		mod_hash_destroy_hash(ss->strid_byid);
6485	if (ss->strid_byid)
6486		mod_hash_destroy_hash(ss->strid_bystr);
6487	if (ss->strid_space)
6488		id_space_destroy(ss->strid_space);
6489	kmem_free(ss, sizeof (*ss));
6490	*strid_p = NULL;
6491}
6492
6493/*
6494 * This sets the devi_addr entry in the dev_info structure 'dip' to 'name'.
6495 * Storage is double buffered to prevent updates during devi_addr use -
6496 * double buffering is adaquate for reliable ddi_deviname() consumption.
6497 * The double buffer is not freed until dev_info structure destruction
6498 * (by i_ddi_free_node).
6499 */
6500void
6501ddi_set_name_addr(dev_info_t *dip, char *name)
6502{
6503	char	*buf = DEVI(dip)->devi_addr_buf;
6504	char	*newaddr;
6505
6506	if (buf == NULL) {
6507		buf = kmem_zalloc(2 * MAXNAMELEN, KM_SLEEP);
6508		DEVI(dip)->devi_addr_buf = buf;
6509	}
6510
6511	if (name) {
6512		ASSERT(strlen(name) < MAXNAMELEN);
6513		newaddr = (DEVI(dip)->devi_addr == buf) ?
6514		    (buf + MAXNAMELEN) : buf;
6515		(void) strlcpy(newaddr, name, MAXNAMELEN);
6516	} else
6517		newaddr = NULL;
6518
6519	DEVI(dip)->devi_addr = newaddr;
6520}
6521
6522char *
6523ddi_get_name_addr(dev_info_t *dip)
6524{
6525	return (DEVI(dip)->devi_addr);
6526}
6527
6528void
6529ddi_set_parent_data(dev_info_t *dip, void *pd)
6530{
6531	DEVI(dip)->devi_parent_data = pd;
6532}
6533
6534void *
6535ddi_get_parent_data(dev_info_t *dip)
6536{
6537	return (DEVI(dip)->devi_parent_data);
6538}
6539
6540/*
6541 * ddi_name_to_major: returns the major number of a named module,
6542 * derived from the current driver alias binding.
6543 *
6544 * Caveat: drivers should avoid the use of this function, in particular
6545 * together with ddi_get_name/ddi_binding name, as per
6546 *	major = ddi_name_to_major(ddi_get_name(devi));
6547 * ddi_name_to_major() relies on the state of the device/alias binding,
6548 * which can and does change dynamically as aliases are administered
6549 * over time.  An attached device instance cannot rely on the major
6550 * number returned by ddi_name_to_major() to match its own major number.
6551 *
6552 * For driver use, ddi_driver_major() reliably returns the major number
6553 * for the module to which the device was bound at attach time over
6554 * the life of the instance.
6555 *	major = ddi_driver_major(dev_info_t *)
6556 */
6557major_t
6558ddi_name_to_major(char *name)
6559{
6560	return (mod_name_to_major(name));
6561}
6562
6563/*
6564 * ddi_major_to_name: Returns the module name bound to a major number.
6565 */
6566char *
6567ddi_major_to_name(major_t major)
6568{
6569	return (mod_major_to_name(major));
6570}
6571
6572/*
6573 * Return the name of the devinfo node pointed at by 'dip' in the buffer
6574 * pointed at by 'name.'  A devinfo node is named as a result of calling
6575 * ddi_initchild().
6576 *
6577 * Note: the driver must be held before calling this function!
6578 */
6579char *
6580ddi_deviname(dev_info_t *dip, char *name)
6581{
6582	char *addrname;
6583	char none = '\0';
6584
6585	if (dip == ddi_root_node()) {
6586		*name = '\0';
6587		return (name);
6588	}
6589
6590	if (i_ddi_node_state(dip) < DS_BOUND) {
6591		addrname = &none;
6592	} else {
6593		/*
6594		 * Use ddi_get_name_addr() without checking state so we get
6595		 * a unit-address if we are called after ddi_set_name_addr()
6596		 * by nexus DDI_CTL_INITCHILD code, but before completing
6597		 * node promotion to DS_INITIALIZED.  We currently have
6598		 * two situations where we are called in this state:
6599		 *   o  For framework processing of a path-oriented alias.
6600		 *   o  If a SCSA nexus driver calls ddi_devid_register()
6601		 *	from it's tran_tgt_init(9E) implementation.
6602		 */
6603		addrname = ddi_get_name_addr(dip);
6604		if (addrname == NULL)
6605			addrname = &none;
6606	}
6607
6608	if (*addrname == '\0') {
6609		(void) sprintf(name, "/%s", ddi_node_name(dip));
6610	} else {
6611		(void) sprintf(name, "/%s@%s", ddi_node_name(dip), addrname);
6612	}
6613
6614	return (name);
6615}
6616
6617/*
6618 * Spits out the name of device node, typically name@addr, for a given node,
6619 * using the driver name, not the nodename.
6620 *
6621 * Used by match_parent. Not to be used elsewhere.
6622 */
6623char *
6624i_ddi_parname(dev_info_t *dip, char *name)
6625{
6626	char *addrname;
6627
6628	if (dip == ddi_root_node()) {
6629		*name = '\0';
6630		return (name);
6631	}
6632
6633	ASSERT(i_ddi_node_state(dip) >= DS_INITIALIZED);
6634
6635	if (*(addrname = ddi_get_name_addr(dip)) == '\0')
6636		(void) sprintf(name, "%s", ddi_binding_name(dip));
6637	else
6638		(void) sprintf(name, "%s@%s", ddi_binding_name(dip), addrname);
6639	return (name);
6640}
6641
6642static char *
6643pathname_work(dev_info_t *dip, char *path)
6644{
6645	char *bp;
6646
6647	if (dip == ddi_root_node()) {
6648		*path = '\0';
6649		return (path);
6650	}
6651	(void) pathname_work(ddi_get_parent(dip), path);
6652	bp = path + strlen(path);
6653	(void) ddi_deviname(dip, bp);
6654	return (path);
6655}
6656
6657char *
6658ddi_pathname(dev_info_t *dip, char *path)
6659{
6660	return (pathname_work(dip, path));
6661}
6662
6663char *
6664ddi_pathname_minor(struct ddi_minor_data *dmdp, char *path)
6665{
6666	if (dmdp->dip == NULL)
6667		*path = '\0';
6668	else {
6669		(void) ddi_pathname(dmdp->dip, path);
6670		if (dmdp->ddm_name) {
6671			(void) strcat(path, ":");
6672			(void) strcat(path, dmdp->ddm_name);
6673		}
6674	}
6675	return (path);
6676}
6677
6678static char *
6679pathname_work_obp(dev_info_t *dip, char *path)
6680{
6681	char *bp;
6682	char *obp_path;
6683
6684	/*
6685	 * look up the "obp-path" property, return the path if it exists
6686	 */
6687	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
6688	    "obp-path", &obp_path) == DDI_PROP_SUCCESS) {
6689		(void) strcpy(path, obp_path);
6690		ddi_prop_free(obp_path);
6691		return (