xref: /illumos-gate/usr/src/uts/common/os/sunddi.c (revision 3df2e8b2)
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 
93 extern	pri_t	minclsyspri;
94 
95 extern	rctl_hndl_t rc_project_locked_mem;
96 extern	rctl_hndl_t rc_zone_locked_mem;
97 
98 #ifdef DEBUG
99 static int sunddi_debug = 0;
100 #endif /* DEBUG */
101 
102 /* ddi_umem_unlock miscellaneous */
103 
104 static	void	i_ddi_umem_unlock_thread_start(void);
105 
106 static	kmutex_t	ddi_umem_unlock_mutex; /* unlock list mutex */
107 static	kcondvar_t	ddi_umem_unlock_cv; /* unlock list block/unblock */
108 static	kthread_t	*ddi_umem_unlock_thread;
109 /*
110  * The ddi_umem_unlock FIFO list.  NULL head pointer indicates empty list.
111  */
112 static	struct	ddi_umem_cookie *ddi_umem_unlock_head = NULL;
113 static	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  */
123 char	*chosen_reg = "chosen-reg";
124 #endif
125 
126 /*
127  * Function used to ring system console bell
128  */
129 void (*ddi_console_bell_func)(clock_t duration);
130 
131 /*
132  * Creating register mappings and handling interrupts:
133  */
134 
135 /*
136  * Generic ddi_map: Call parent to fulfill request...
137  */
138 
139 int
ddi_map(dev_info_t * dp,ddi_map_req_t * mp,off_t offset,off_t len,caddr_t * addrp)140 ddi_map(dev_info_t *dp, ddi_map_req_t *mp, off_t offset,
141     off_t len, caddr_t *addrp)
142 {
143 	dev_info_t *pdip;
144 
145 	ASSERT(dp);
146 	pdip = (dev_info_t *)DEVI(dp)->devi_parent;
147 	return ((DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)(pdip,
148 	    dp, mp, offset, len, addrp));
149 }
150 
151 /*
152  * ddi_apply_range: (Called by nexi only.)
153  * Apply ranges in parent node dp, to child regspec rp...
154  */
155 
156 int
ddi_apply_range(dev_info_t * dp,dev_info_t * rdip,struct regspec * rp)157 ddi_apply_range(dev_info_t *dp, dev_info_t *rdip, struct regspec *rp)
158 {
159 	return (i_ddi_apply_range(dp, rdip, rp));
160 }
161 
162 int
ddi_map_regs(dev_info_t * dip,uint_t rnumber,caddr_t * kaddrp,off_t offset,off_t len)163 ddi_map_regs(dev_info_t *dip, uint_t rnumber, caddr_t *kaddrp, off_t offset,
164     off_t len)
165 {
166 	ddi_map_req_t mr;
167 #if defined(__x86)
168 	struct {
169 		int	bus;
170 		int	addr;
171 		int	size;
172 	} reg, *reglist;
173 	uint_t	length;
174 	int	rc;
175 
176 	/*
177 	 * get the 'registers' or the 'reg' property.
178 	 * We look up the reg property as an array of
179 	 * int's.
180 	 */
181 	rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
182 	    DDI_PROP_DONTPASS, "registers", (int **)&reglist, &length);
183 	if (rc != DDI_PROP_SUCCESS)
184 		rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
185 		    DDI_PROP_DONTPASS, "reg", (int **)&reglist, &length);
186 	if (rc == DDI_PROP_SUCCESS) {
187 		/*
188 		 * point to the required entry.
189 		 */
190 		reg = reglist[rnumber];
191 		reg.addr += offset;
192 		if (len != 0)
193 			reg.size = len;
194 		/*
195 		 * make a new property containing ONLY the required tuple.
196 		 */
197 		if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
198 		    chosen_reg, (int *)&reg, (sizeof (reg)/sizeof (int)))
199 		    != DDI_PROP_SUCCESS) {
200 			cmn_err(CE_WARN, "%s%d: cannot create '%s' "
201 			    "property", DEVI(dip)->devi_name,
202 			    DEVI(dip)->devi_instance, chosen_reg);
203 		}
204 		/*
205 		 * free the memory allocated by
206 		 * ddi_prop_lookup_int_array ().
207 		 */
208 		ddi_prop_free((void *)reglist);
209 	}
210 #endif
211 	mr.map_op = DDI_MO_MAP_LOCKED;
212 	mr.map_type = DDI_MT_RNUMBER;
213 	mr.map_obj.rnumber = rnumber;
214 	mr.map_prot = PROT_READ | PROT_WRITE;
215 	mr.map_flags = DDI_MF_KERNEL_MAPPING;
216 	mr.map_handlep = NULL;
217 	mr.map_vers = DDI_MAP_VERSION;
218 
219 	/*
220 	 * Call my parent to map in my regs.
221 	 */
222 
223 	return (ddi_map(dip, &mr, offset, len, kaddrp));
224 }
225 
226 void
ddi_unmap_regs(dev_info_t * dip,uint_t rnumber,caddr_t * kaddrp,off_t offset,off_t len)227 ddi_unmap_regs(dev_info_t *dip, uint_t rnumber, caddr_t *kaddrp, off_t offset,
228     off_t len)
229 {
230 	ddi_map_req_t mr;
231 
232 	mr.map_op = DDI_MO_UNMAP;
233 	mr.map_type = DDI_MT_RNUMBER;
234 	mr.map_flags = DDI_MF_KERNEL_MAPPING;
235 	mr.map_prot = PROT_READ | PROT_WRITE;	/* who cares? */
236 	mr.map_obj.rnumber = rnumber;
237 	mr.map_handlep = NULL;
238 	mr.map_vers = DDI_MAP_VERSION;
239 
240 	/*
241 	 * Call my parent to unmap my regs.
242 	 */
243 
244 	(void) ddi_map(dip, &mr, offset, len, kaddrp);
245 	*kaddrp = (caddr_t)0;
246 #if defined(__x86)
247 	(void) ddi_prop_remove(DDI_DEV_T_NONE, dip, chosen_reg);
248 #endif
249 }
250 
251 int
ddi_bus_map(dev_info_t * dip,dev_info_t * rdip,ddi_map_req_t * mp,off_t offset,off_t len,caddr_t * vaddrp)252 ddi_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
253     off_t offset, off_t len, caddr_t *vaddrp)
254 {
255 	return (i_ddi_bus_map(dip, rdip, mp, offset, len, vaddrp));
256 }
257 
258 /*
259  * nullbusmap:	The/DDI default bus_map entry point for nexi
260  *		not conforming to the reg/range paradigm (i.e. scsi, etc.)
261  *		with no HAT/MMU layer to be programmed at this level.
262  *
263  *		If the call is to map by rnumber, return an error,
264  *		otherwise pass anything else up the tree to my parent.
265  */
266 int
nullbusmap(dev_info_t * dip,dev_info_t * rdip,ddi_map_req_t * mp,off_t offset,off_t len,caddr_t * vaddrp)267 nullbusmap(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
268     off_t offset, off_t len, caddr_t *vaddrp)
269 {
270 	_NOTE(ARGUNUSED(rdip))
271 	if (mp->map_type == DDI_MT_RNUMBER)
272 		return (DDI_ME_UNSUPPORTED);
273 
274 	return (ddi_map(dip, mp, offset, len, vaddrp));
275 }
276 
277 /*
278  * ddi_rnumber_to_regspec: Not for use by leaf drivers.
279  *			   Only for use by nexi using the reg/range paradigm.
280  */
281 struct regspec *
ddi_rnumber_to_regspec(dev_info_t * dip,int rnumber)282 ddi_rnumber_to_regspec(dev_info_t *dip, int rnumber)
283 {
284 	return (i_ddi_rnumber_to_regspec(dip, rnumber));
285 }
286 
287 
288 /*
289  * Note that we allow the dip to be nil because we may be called
290  * prior even to the instantiation of the devinfo tree itself - all
291  * regular leaf and nexus drivers should always use a non-nil dip!
292  *
293  * We treat peek in a somewhat cavalier fashion .. assuming that we'll
294  * simply get a synchronous fault as soon as we touch a missing address.
295  *
296  * Poke is rather more carefully handled because we might poke to a write
297  * buffer, "succeed", then only find some time later that we got an
298  * asynchronous fault that indicated that the address we were writing to
299  * was not really backed by hardware.
300  */
301 
302 static int
i_ddi_peekpoke(dev_info_t * devi,ddi_ctl_enum_t cmd,size_t size,void * addr,void * value_p)303 i_ddi_peekpoke(dev_info_t *devi, ddi_ctl_enum_t cmd, size_t size,
304     void *addr, void *value_p)
305 {
306 	union {
307 		uint64_t	u64;
308 		uint32_t	u32;
309 		uint16_t	u16;
310 		uint8_t		u8;
311 	} peekpoke_value;
312 
313 	peekpoke_ctlops_t peekpoke_args;
314 	uint64_t dummy_result;
315 	int rval;
316 
317 	/* Note: size is assumed to be correct;  it is not checked. */
318 	peekpoke_args.size = size;
319 	peekpoke_args.dev_addr = (uintptr_t)addr;
320 	peekpoke_args.handle = NULL;
321 	peekpoke_args.repcount = 1;
322 	peekpoke_args.flags = 0;
323 
324 	if (cmd == DDI_CTLOPS_POKE) {
325 		switch (size) {
326 		case sizeof (uint8_t):
327 			peekpoke_value.u8 = *(uint8_t *)value_p;
328 			break;
329 		case sizeof (uint16_t):
330 			peekpoke_value.u16 = *(uint16_t *)value_p;
331 			break;
332 		case sizeof (uint32_t):
333 			peekpoke_value.u32 = *(uint32_t *)value_p;
334 			break;
335 		case sizeof (uint64_t):
336 			peekpoke_value.u64 = *(uint64_t *)value_p;
337 			break;
338 		}
339 	}
340 
341 	peekpoke_args.host_addr = (uintptr_t)&peekpoke_value.u64;
342 
343 	if (devi != NULL)
344 		rval = ddi_ctlops(devi, devi, cmd, &peekpoke_args,
345 		    &dummy_result);
346 	else
347 		rval = peekpoke_mem(cmd, &peekpoke_args);
348 
349 	/*
350 	 * A NULL value_p is permitted by ddi_peek(9F); discard the result.
351 	 */
352 	if ((cmd == DDI_CTLOPS_PEEK) & (value_p != NULL)) {
353 		switch (size) {
354 		case sizeof (uint8_t):
355 			*(uint8_t *)value_p = peekpoke_value.u8;
356 			break;
357 		case sizeof (uint16_t):
358 			*(uint16_t *)value_p = peekpoke_value.u16;
359 			break;
360 		case sizeof (uint32_t):
361 			*(uint32_t *)value_p = peekpoke_value.u32;
362 			break;
363 		case sizeof (uint64_t):
364 			*(uint64_t *)value_p = peekpoke_value.u64;
365 			break;
366 		}
367 	}
368 
369 	return (rval);
370 }
371 
372 /*
373  * Keep ddi_peek() and ddi_poke() in case 3rd parties are calling this.
374  * they shouldn't be, but the 9f manpage kind of pseudo exposes it.
375  */
376 int
ddi_peek(dev_info_t * devi,size_t size,void * addr,void * value_p)377 ddi_peek(dev_info_t *devi, size_t size, void *addr, void *value_p)
378 {
379 	switch (size) {
380 	case sizeof (uint8_t):
381 	case sizeof (uint16_t):
382 	case sizeof (uint32_t):
383 	case sizeof (uint64_t):
384 		break;
385 	default:
386 		return (DDI_FAILURE);
387 	}
388 
389 	return (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, size, addr, value_p));
390 }
391 
392 int
ddi_poke(dev_info_t * devi,size_t size,void * addr,void * value_p)393 ddi_poke(dev_info_t *devi, size_t size, void *addr, void *value_p)
394 {
395 	switch (size) {
396 	case sizeof (uint8_t):
397 	case sizeof (uint16_t):
398 	case sizeof (uint32_t):
399 	case sizeof (uint64_t):
400 		break;
401 	default:
402 		return (DDI_FAILURE);
403 	}
404 
405 	return (i_ddi_peekpoke(devi, DDI_CTLOPS_POKE, size, addr, value_p));
406 }
407 
408 int
ddi_peek8(dev_info_t * dip,int8_t * addr,int8_t * val_p)409 ddi_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 
415 int
ddi_peek16(dev_info_t * dip,int16_t * addr,int16_t * val_p)416 ddi_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 
422 int
ddi_peek32(dev_info_t * dip,int32_t * addr,int32_t * val_p)423 ddi_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 
429 int
ddi_peek64(dev_info_t * dip,int64_t * addr,int64_t * val_p)430 ddi_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 int
ddi_poke8(dev_info_t * dip,int8_t * addr,int8_t val)437 ddi_poke8(dev_info_t *dip, int8_t *addr, int8_t val)
438 {
439 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
440 }
441 
442 int
ddi_poke16(dev_info_t * dip,int16_t * addr,int16_t val)443 ddi_poke16(dev_info_t *dip, int16_t *addr, int16_t val)
444 {
445 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
446 }
447 
448 int
ddi_poke32(dev_info_t * dip,int32_t * addr,int32_t val)449 ddi_poke32(dev_info_t *dip, int32_t *addr, int32_t val)
450 {
451 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
452 }
453 
454 int
ddi_poke64(dev_info_t * dip,int64_t * addr,int64_t val)455 ddi_poke64(dev_info_t *dip, int64_t *addr, int64_t val)
456 {
457 	return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val));
458 }
459 
460 /*
461  * ddi_peekpokeio() is used primarily by the mem drivers for moving
462  * data to and from uio structures via peek and poke.  Note that we
463  * use "internal" routines ddi_peek and ddi_poke to make this go
464  * slightly faster, avoiding the call overhead ..
465  */
466 int
ddi_peekpokeio(dev_info_t * devi,struct uio * uio,enum uio_rw rw,caddr_t addr,size_t len,uint_t xfersize)467 ddi_peekpokeio(dev_info_t *devi, struct uio *uio, enum uio_rw rw,
468     caddr_t addr, size_t len, uint_t xfersize)
469 {
470 	int64_t	ibuffer;
471 	int8_t w8;
472 	size_t sz;
473 	int o;
474 
475 	if (xfersize > sizeof (long))
476 		xfersize = sizeof (long);
477 
478 	while (len != 0) {
479 		if ((len | (uintptr_t)addr) & 1) {
480 			sz = sizeof (int8_t);
481 			if (rw == UIO_WRITE) {
482 				if ((o = uwritec(uio)) == -1)
483 					return (DDI_FAILURE);
484 				if (ddi_poke8(devi, (int8_t *)addr,
485 				    (int8_t)o) != DDI_SUCCESS)
486 					return (DDI_FAILURE);
487 			} else {
488 				if (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, sz,
489 				    (int8_t *)addr, &w8) != DDI_SUCCESS)
490 					return (DDI_FAILURE);
491 				if (ureadc(w8, uio))
492 					return (DDI_FAILURE);
493 			}
494 		} else {
495 			switch (xfersize) {
496 			case sizeof (int64_t):
497 				if (((len | (uintptr_t)addr) &
498 				    (sizeof (int64_t) - 1)) == 0) {
499 					sz = xfersize;
500 					break;
501 				}
502 				/*FALLTHROUGH*/
503 			case sizeof (int32_t):
504 				if (((len | (uintptr_t)addr) &
505 				    (sizeof (int32_t) - 1)) == 0) {
506 					sz = xfersize;
507 					break;
508 				}
509 				/*FALLTHROUGH*/
510 			default:
511 				/*
512 				 * This still assumes that we might have an
513 				 * I/O bus out there that permits 16-bit
514 				 * transfers (and that it would be upset by
515 				 * 32-bit transfers from such locations).
516 				 */
517 				sz = sizeof (int16_t);
518 				break;
519 			}
520 
521 			if (rw == UIO_READ) {
522 				if (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, sz,
523 				    addr, &ibuffer) != DDI_SUCCESS)
524 					return (DDI_FAILURE);
525 			}
526 
527 			if (uiomove(&ibuffer, sz, rw, uio))
528 				return (DDI_FAILURE);
529 
530 			if (rw == UIO_WRITE) {
531 				if (i_ddi_peekpoke(devi, DDI_CTLOPS_POKE, sz,
532 				    addr, &ibuffer) != DDI_SUCCESS)
533 					return (DDI_FAILURE);
534 			}
535 		}
536 		addr += sz;
537 		len -= sz;
538 	}
539 	return (DDI_SUCCESS);
540 }
541 
542 /*
543  * These routines are used by drivers that do layered ioctls
544  * On sparc, they're implemented in assembler to avoid spilling
545  * register windows in the common (copyin) case ..
546  */
547 #if !defined(__sparc)
548 int
ddi_copyin(const void * buf,void * kernbuf,size_t size,int flags)549 ddi_copyin(const void *buf, void *kernbuf, size_t size, int flags)
550 {
551 	if (flags & FKIOCTL)
552 		return (kcopy(buf, kernbuf, size) ? -1 : 0);
553 	return (copyin(buf, kernbuf, size));
554 }
555 
556 int
ddi_copyout(const void * buf,void * kernbuf,size_t size,int flags)557 ddi_copyout(const void *buf, void *kernbuf, size_t size, int flags)
558 {
559 	if (flags & FKIOCTL)
560 		return (kcopy(buf, kernbuf, size) ? -1 : 0);
561 	return (copyout(buf, kernbuf, size));
562 }
563 #endif	/* !__sparc */
564 
565 /*
566  * Conversions in nexus pagesize units.  We don't duplicate the
567  * 'nil dip' semantics of peek/poke because btopr/btop/ptob are DDI/DKI
568  * routines anyway.
569  */
570 unsigned long
ddi_btop(dev_info_t * dip,unsigned long bytes)571 ddi_btop(dev_info_t *dip, unsigned long bytes)
572 {
573 	unsigned long pages;
574 
575 	(void) ddi_ctlops(dip, dip, DDI_CTLOPS_BTOP, &bytes, &pages);
576 	return (pages);
577 }
578 
579 unsigned long
ddi_btopr(dev_info_t * dip,unsigned long bytes)580 ddi_btopr(dev_info_t *dip, unsigned long bytes)
581 {
582 	unsigned long pages;
583 
584 	(void) ddi_ctlops(dip, dip, DDI_CTLOPS_BTOPR, &bytes, &pages);
585 	return (pages);
586 }
587 
588 unsigned long
ddi_ptob(dev_info_t * dip,unsigned long pages)589 ddi_ptob(dev_info_t *dip, unsigned long pages)
590 {
591 	unsigned long bytes;
592 
593 	(void) ddi_ctlops(dip, dip, DDI_CTLOPS_PTOB, &pages, &bytes);
594 	return (bytes);
595 }
596 
597 unsigned int
ddi_enter_critical(void)598 ddi_enter_critical(void)
599 {
600 	return ((uint_t)spl7());
601 }
602 
603 void
ddi_exit_critical(unsigned int spl)604 ddi_exit_critical(unsigned int spl)
605 {
606 	splx((int)spl);
607 }
608 
609 /*
610  * Nexus ctlops punter
611  */
612 
613 #if !defined(__sparc)
614 /*
615  * Request bus_ctl parent to handle a bus_ctl request
616  *
617  * (The sparc version is in sparc_ddi.s)
618  */
619 int
ddi_ctlops(dev_info_t * d,dev_info_t * r,ddi_ctl_enum_t op,void * a,void * v)620 ddi_ctlops(dev_info_t *d, dev_info_t *r, ddi_ctl_enum_t op, void *a, void *v)
621 {
622 	int (*fp)();
623 
624 	if (!d || !r)
625 		return (DDI_FAILURE);
626 
627 	if ((d = (dev_info_t *)DEVI(d)->devi_bus_ctl) == NULL)
628 		return (DDI_FAILURE);
629 
630 	fp = DEVI(d)->devi_ops->devo_bus_ops->bus_ctl;
631 	return ((*fp)(d, r, op, a, v));
632 }
633 
634 #endif
635 
636 /*
637  * DMA/DVMA setup
638  */
639 
640 #if !defined(__sparc)
641 /*
642  * Request bus_dma_ctl parent to fiddle with a dma request.
643  *
644  * (The sparc version is in sparc_subr.s)
645  */
646 int
ddi_dma_mctl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle,enum ddi_dma_ctlops request,off_t * offp,size_t * lenp,caddr_t * objp,uint_t flags)647 ddi_dma_mctl(dev_info_t *dip, dev_info_t *rdip,
648     ddi_dma_handle_t handle, enum ddi_dma_ctlops request,
649     off_t *offp, size_t *lenp, caddr_t *objp, uint_t flags)
650 {
651 	int (*fp)();
652 
653 	if (dip != ddi_root_node())
654 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_ctl;
655 	fp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_ctl;
656 	return ((*fp) (dip, rdip, handle, request, offp, lenp, objp, flags));
657 }
658 #endif
659 
660 /*
661  * For all DMA control functions, call the DMA control
662  * routine and return status.
663  *
664  * Just plain assume that the parent is to be called.
665  * If a nexus driver or a thread outside the framework
666  * of a nexus driver or a leaf driver calls these functions,
667  * it is up to them to deal with the fact that the parent's
668  * bus_dma_ctl function will be the first one called.
669  */
670 
671 #define	HD	((ddi_dma_impl_t *)h)->dmai_rdip
672 
673 /*
674  * This routine is left in place to satisfy link dependencies
675  * for any 3rd party nexus drivers that rely on it.  It is never
676  * called, though.
677  */
678 /*ARGSUSED*/
679 int
ddi_dma_map(dev_info_t * dip,dev_info_t * rdip,struct ddi_dma_req * dmareqp,ddi_dma_handle_t * handlep)680 ddi_dma_map(dev_info_t *dip, dev_info_t *rdip,
681     struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep)
682 {
683 	return (DDI_FAILURE);
684 }
685 
686 #if !defined(__sparc)
687 
688 /*
689  * The SPARC versions of these routines are done in assembler to
690  * save register windows, so they're in sparc_subr.s.
691  */
692 
693 int
ddi_dma_allochdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_attr_t * attr,int (* waitfp)(caddr_t),caddr_t arg,ddi_dma_handle_t * handlep)694 ddi_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr,
695     int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep)
696 {
697 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_attr_t *,
698 	    int (*)(caddr_t), caddr_t, ddi_dma_handle_t *);
699 
700 	if (dip != ddi_root_node())
701 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl;
702 
703 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_allochdl;
704 	return ((*funcp)(dip, rdip, attr, waitfp, arg, handlep));
705 }
706 
707 int
ddi_dma_freehdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handlep)708 ddi_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handlep)
709 {
710 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t);
711 
712 	if (dip != ddi_root_node())
713 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl;
714 
715 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_freehdl;
716 	return ((*funcp)(dip, rdip, handlep));
717 }
718 
719 int
ddi_dma_bindhdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle,struct ddi_dma_req * dmareq,ddi_dma_cookie_t * cp,uint_t * ccountp)720 ddi_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
721     ddi_dma_handle_t handle, struct ddi_dma_req *dmareq,
722     ddi_dma_cookie_t *cp, uint_t *ccountp)
723 {
724 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t,
725 	    struct ddi_dma_req *, ddi_dma_cookie_t *, uint_t *);
726 
727 	if (dip != ddi_root_node())
728 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_bindhdl;
729 
730 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_bindhdl;
731 	return ((*funcp)(dip, rdip, handle, dmareq, cp, ccountp));
732 }
733 
734 int
ddi_dma_unbindhdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle)735 ddi_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
736     ddi_dma_handle_t handle)
737 {
738 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t);
739 
740 	if (dip != ddi_root_node())
741 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl;
742 
743 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_unbindhdl;
744 	return ((*funcp)(dip, rdip, handle));
745 }
746 
747 
748 int
ddi_dma_flush(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle,off_t off,size_t len,uint_t cache_flags)749 ddi_dma_flush(dev_info_t *dip, dev_info_t *rdip,
750     ddi_dma_handle_t handle, off_t off, size_t len,
751     uint_t cache_flags)
752 {
753 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t,
754 	    off_t, size_t, uint_t);
755 
756 	if (dip != ddi_root_node())
757 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush;
758 
759 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_flush;
760 	return ((*funcp)(dip, rdip, handle, off, len, cache_flags));
761 }
762 
763 int
ddi_dma_win(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle,uint_t win,off_t * offp,size_t * lenp,ddi_dma_cookie_t * cookiep,uint_t * ccountp)764 ddi_dma_win(dev_info_t *dip, dev_info_t *rdip,
765     ddi_dma_handle_t handle, uint_t win, off_t *offp,
766     size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp)
767 {
768 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t,
769 	    uint_t, off_t *, size_t *, ddi_dma_cookie_t *, uint_t *);
770 
771 	if (dip != ddi_root_node())
772 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_win;
773 
774 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_win;
775 	return ((*funcp)(dip, rdip, handle, win, offp, lenp,
776 	    cookiep, ccountp));
777 }
778 
779 int
ddi_dma_sync(ddi_dma_handle_t h,off_t o,size_t l,uint_t whom)780 ddi_dma_sync(ddi_dma_handle_t h, off_t o, size_t l, uint_t whom)
781 {
782 	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)h;
783 	dev_info_t *dip, *rdip;
784 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t, off_t,
785 	    size_t, uint_t);
786 
787 	/*
788 	 * the DMA nexus driver will set DMP_NOSYNC if the
789 	 * platform does not require any sync operation. For
790 	 * example if the memory is uncached or consistent
791 	 * and without any I/O write buffers involved.
792 	 */
793 	if ((hp->dmai_rflags & DMP_NOSYNC) == DMP_NOSYNC)
794 		return (DDI_SUCCESS);
795 
796 	dip = rdip = hp->dmai_rdip;
797 	if (dip != ddi_root_node())
798 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush;
799 	funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_flush;
800 	return ((*funcp)(dip, rdip, h, o, l, whom));
801 }
802 
803 int
ddi_dma_unbind_handle(ddi_dma_handle_t h)804 ddi_dma_unbind_handle(ddi_dma_handle_t h)
805 {
806 	ddi_dma_impl_t *hp = (ddi_dma_impl_t *)h;
807 	dev_info_t *dip, *rdip;
808 	int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t);
809 
810 	dip = rdip = hp->dmai_rdip;
811 	if (dip != ddi_root_node())
812 		dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl;
813 	funcp = DEVI(rdip)->devi_bus_dma_unbindfunc;
814 	return ((*funcp)(dip, rdip, h));
815 }
816 
817 #endif	/* !__sparc */
818 
819 /*
820  * DMA burst sizes, and transfer minimums
821  */
822 
823 int
ddi_dma_burstsizes(ddi_dma_handle_t handle)824 ddi_dma_burstsizes(ddi_dma_handle_t handle)
825 {
826 	ddi_dma_impl_t *dimp = (ddi_dma_impl_t *)handle;
827 
828 	if (!dimp)
829 		return (0);
830 	else
831 		return (dimp->dmai_burstsizes);
832 }
833 
834 /*
835  * Given two DMA attribute structures, apply the attributes
836  * of one to the other, following the rules of attributes
837  * and the wishes of the caller.
838  *
839  * The rules of DMA attribute structures are that you cannot
840  * make things *less* restrictive as you apply one set
841  * of attributes to another.
842  *
843  */
844 void
ddi_dma_attr_merge(ddi_dma_attr_t * attr,ddi_dma_attr_t * mod)845 ddi_dma_attr_merge(ddi_dma_attr_t *attr, ddi_dma_attr_t *mod)
846 {
847 	attr->dma_attr_addr_lo =
848 	    MAX(attr->dma_attr_addr_lo, mod->dma_attr_addr_lo);
849 	attr->dma_attr_addr_hi =
850 	    MIN(attr->dma_attr_addr_hi, mod->dma_attr_addr_hi);
851 	attr->dma_attr_count_max =
852 	    MIN(attr->dma_attr_count_max, mod->dma_attr_count_max);
853 	attr->dma_attr_align =
854 	    MAX(attr->dma_attr_align,  mod->dma_attr_align);
855 	attr->dma_attr_burstsizes =
856 	    (uint_t)(attr->dma_attr_burstsizes & mod->dma_attr_burstsizes);
857 	attr->dma_attr_minxfer =
858 	    maxbit(attr->dma_attr_minxfer, mod->dma_attr_minxfer);
859 	attr->dma_attr_maxxfer =
860 	    MIN(attr->dma_attr_maxxfer, mod->dma_attr_maxxfer);
861 	attr->dma_attr_seg = MIN(attr->dma_attr_seg, mod->dma_attr_seg);
862 	attr->dma_attr_sgllen = MIN((uint_t)attr->dma_attr_sgllen,
863 	    (uint_t)mod->dma_attr_sgllen);
864 	attr->dma_attr_granular =
865 	    MAX(attr->dma_attr_granular, mod->dma_attr_granular);
866 }
867 
868 /*
869  * mmap/segmap interface:
870  */
871 
872 /*
873  * ddi_segmap:		setup the default segment driver. Calls the drivers
874  *			XXmmap routine to validate the range to be mapped.
875  *			Return ENXIO of the range is not valid.  Create
876  *			a seg_dev segment that contains all of the
877  *			necessary information and will reference the
878  *			default segment driver routines. It returns zero
879  *			on success or non-zero on failure.
880  */
881 int
ddi_segmap(dev_t dev,off_t offset,struct as * asp,caddr_t * addrp,off_t len,uint_t prot,uint_t maxprot,uint_t flags,cred_t * credp)882 ddi_segmap(dev_t dev, off_t offset, struct as *asp, caddr_t *addrp, off_t len,
883     uint_t prot, uint_t maxprot, uint_t flags, cred_t *credp)
884 {
885 	extern int spec_segmap(dev_t, off_t, struct as *, caddr_t *,
886 	    off_t, uint_t, uint_t, uint_t, struct cred *);
887 
888 	return (spec_segmap(dev, offset, asp, addrp, len,
889 	    prot, maxprot, flags, credp));
890 }
891 
892 /*
893  * ddi_map_fault:	Resolve mappings at fault time.  Used by segment
894  *			drivers. Allows each successive parent to resolve
895  *			address translations and add its mappings to the
896  *			mapping list supplied in the page structure. It
897  *			returns zero on success	or non-zero on failure.
898  */
899 
900 int
ddi_map_fault(dev_info_t * dip,struct hat * hat,struct seg * seg,caddr_t addr,struct devpage * dp,pfn_t pfn,uint_t prot,uint_t lock)901 ddi_map_fault(dev_info_t *dip, struct hat *hat, struct seg *seg,
902     caddr_t addr, struct devpage *dp, pfn_t pfn, uint_t prot, uint_t lock)
903 {
904 	return (i_ddi_map_fault(dip, dip, hat, seg, addr, dp, pfn, prot, lock));
905 }
906 
907 /*
908  * ddi_device_mapping_check:	Called from ddi_segmap_setup.
909  *	Invokes platform specific DDI to determine whether attributes specified
910  *	in attr(9s) are	valid for the region of memory that will be made
911  *	available for direct access to user process via the mmap(2) system call.
912  */
913 int
ddi_device_mapping_check(dev_t dev,ddi_device_acc_attr_t * accattrp,uint_t rnumber,uint_t * hat_flags)914 ddi_device_mapping_check(dev_t dev, ddi_device_acc_attr_t *accattrp,
915     uint_t rnumber, uint_t *hat_flags)
916 {
917 	ddi_acc_handle_t handle;
918 	ddi_map_req_t mr;
919 	ddi_acc_hdl_t *hp;
920 	int result;
921 	dev_info_t *dip;
922 
923 	/*
924 	 * we use e_ddi_hold_devi_by_dev to search for the devi.  We
925 	 * release it immediately since it should already be held by
926 	 * a devfs vnode.
927 	 */
928 	if ((dip =
929 	    e_ddi_hold_devi_by_dev(dev, E_DDI_HOLD_DEVI_NOATTACH)) == NULL)
930 		return (-1);
931 	ddi_release_devi(dip);		/* for e_ddi_hold_devi_by_dev() */
932 
933 	/*
934 	 * Allocate and initialize the common elements of data
935 	 * access handle.
936 	 */
937 	handle = impl_acc_hdl_alloc(KM_SLEEP, NULL);
938 	if (handle == NULL)
939 		return (-1);
940 
941 	hp = impl_acc_hdl_get(handle);
942 	hp->ah_vers = VERS_ACCHDL;
943 	hp->ah_dip = dip;
944 	hp->ah_rnumber = rnumber;
945 	hp->ah_offset = 0;
946 	hp->ah_len = 0;
947 	hp->ah_acc = *accattrp;
948 
949 	/*
950 	 * Set up the mapping request and call to parent.
951 	 */
952 	mr.map_op = DDI_MO_MAP_HANDLE;
953 	mr.map_type = DDI_MT_RNUMBER;
954 	mr.map_obj.rnumber = rnumber;
955 	mr.map_prot = PROT_READ | PROT_WRITE;
956 	mr.map_flags = DDI_MF_KERNEL_MAPPING;
957 	mr.map_handlep = hp;
958 	mr.map_vers = DDI_MAP_VERSION;
959 	result = ddi_map(dip, &mr, 0, 0, NULL);
960 
961 	/*
962 	 * Region must be mappable, pick up flags from the framework.
963 	 */
964 	*hat_flags = hp->ah_hat_flags;
965 
966 	impl_acc_hdl_free(handle);
967 
968 	/*
969 	 * check for end result.
970 	 */
971 	if (result != DDI_SUCCESS)
972 		return (-1);
973 	return (0);
974 }
975 
976 
977 /*
978  * Property functions:	 See also, ddipropdefs.h.
979  *
980  * These functions are the framework for the property functions,
981  * i.e. they support software defined properties.  All implementation
982  * specific property handling (i.e.: self-identifying devices and
983  * PROM defined properties are handled in the implementation specific
984  * functions (defined in ddi_implfuncs.h).
985  */
986 
987 /*
988  * nopropop:	Shouldn't be called, right?
989  */
990 int
nopropop(dev_t dev,dev_info_t * dip,ddi_prop_op_t prop_op,int mod_flags,char * name,caddr_t valuep,int * lengthp)991 nopropop(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
992     char *name, caddr_t valuep, int *lengthp)
993 {
994 	_NOTE(ARGUNUSED(dev, dip, prop_op, mod_flags, name, valuep, lengthp))
995 	return (DDI_PROP_NOT_FOUND);
996 }
997 
998 #ifdef	DDI_PROP_DEBUG
999 int ddi_prop_debug_flag = 0;
1000 
1001 int
ddi_prop_debug(int enable)1002 ddi_prop_debug(int enable)
1003 {
1004 	int prev = ddi_prop_debug_flag;
1005 
1006 	if ((enable != 0) || (prev != 0))
1007 		printf("ddi_prop_debug: debugging %s\n",
1008 		    enable ? "enabled" : "disabled");
1009 	ddi_prop_debug_flag = enable;
1010 	return (prev);
1011 }
1012 
1013 #endif	/* DDI_PROP_DEBUG */
1014 
1015 /*
1016  * Search a property list for a match, if found return pointer
1017  * to matching prop struct, else return NULL.
1018  */
1019 
1020 ddi_prop_t *
i_ddi_prop_search(dev_t dev,char * name,uint_t flags,ddi_prop_t ** list_head)1021 i_ddi_prop_search(dev_t dev, char *name, uint_t flags, ddi_prop_t **list_head)
1022 {
1023 	ddi_prop_t	*propp;
1024 
1025 	/*
1026 	 * find the property in child's devinfo:
1027 	 * Search order defined by this search function is first matching
1028 	 * property with input dev == DDI_DEV_T_ANY matching any dev or
1029 	 * dev == propp->prop_dev, name == propp->name, and the correct
1030 	 * data type as specified in the flags.  If a DDI_DEV_T_NONE dev
1031 	 * value made it this far then it implies a DDI_DEV_T_ANY search.
1032 	 */
1033 	if (dev == DDI_DEV_T_NONE)
1034 		dev = DDI_DEV_T_ANY;
1035 
1036 	for (propp = *list_head; propp != NULL; propp = propp->prop_next)  {
1037 
1038 		if (!DDI_STRSAME(propp->prop_name, name))
1039 			continue;
1040 
1041 		if ((dev != DDI_DEV_T_ANY) && (propp->prop_dev != dev))
1042 			continue;
1043 
1044 		if (((propp->prop_flags & flags) & DDI_PROP_TYPE_MASK) == 0)
1045 			continue;
1046 
1047 		return (propp);
1048 	}
1049 
1050 	return ((ddi_prop_t *)0);
1051 }
1052 
1053 /*
1054  * Search for property within devnames structures
1055  */
1056 ddi_prop_t *
i_ddi_search_global_prop(dev_t dev,char * name,uint_t flags)1057 i_ddi_search_global_prop(dev_t dev, char *name, uint_t flags)
1058 {
1059 	major_t		major;
1060 	struct devnames	*dnp;
1061 	ddi_prop_t	*propp;
1062 
1063 	/*
1064 	 * Valid dev_t value is needed to index into the
1065 	 * correct devnames entry, therefore a dev_t
1066 	 * value of DDI_DEV_T_ANY is not appropriate.
1067 	 */
1068 	ASSERT(dev != DDI_DEV_T_ANY);
1069 	if (dev == DDI_DEV_T_ANY) {
1070 		return ((ddi_prop_t *)0);
1071 	}
1072 
1073 	major = getmajor(dev);
1074 	dnp = &(devnamesp[major]);
1075 
1076 	if (dnp->dn_global_prop_ptr == NULL)
1077 		return ((ddi_prop_t *)0);
1078 
1079 	LOCK_DEV_OPS(&dnp->dn_lock);
1080 
1081 	for (propp = dnp->dn_global_prop_ptr->prop_list;
1082 	    propp != NULL;
1083 	    propp = (ddi_prop_t *)propp->prop_next) {
1084 
1085 		if (!DDI_STRSAME(propp->prop_name, name))
1086 			continue;
1087 
1088 		if ((!(flags & DDI_PROP_ROOTNEX_GLOBAL)) &&
1089 		    (!(flags & LDI_DEV_T_ANY)) && (propp->prop_dev != dev))
1090 			continue;
1091 
1092 		if (((propp->prop_flags & flags) & DDI_PROP_TYPE_MASK) == 0)
1093 			continue;
1094 
1095 		/* Property found, return it */
1096 		UNLOCK_DEV_OPS(&dnp->dn_lock);
1097 		return (propp);
1098 	}
1099 
1100 	UNLOCK_DEV_OPS(&dnp->dn_lock);
1101 	return ((ddi_prop_t *)0);
1102 }
1103 
1104 static char prop_no_mem_msg[] = "can't allocate memory for ddi property <%s>";
1105 
1106 /*
1107  * ddi_prop_search_global:
1108  *	Search the global property list within devnames
1109  *	for the named property.  Return the encoded value.
1110  */
1111 static int
i_ddi_prop_search_global(dev_t dev,uint_t flags,char * name,void * valuep,uint_t * lengthp)1112 i_ddi_prop_search_global(dev_t dev, uint_t flags, char *name,
1113     void *valuep, uint_t *lengthp)
1114 {
1115 	ddi_prop_t	*propp;
1116 	caddr_t		buffer;
1117 
1118 	propp =  i_ddi_search_global_prop(dev, name, flags);
1119 
1120 	/* Property NOT found, bail */
1121 	if (propp == (ddi_prop_t *)0)
1122 		return (DDI_PROP_NOT_FOUND);
1123 
1124 	if (propp->prop_flags & DDI_PROP_UNDEF_IT)
1125 		return (DDI_PROP_UNDEFINED);
1126 
1127 	if ((buffer = kmem_alloc(propp->prop_len,
1128 	    (flags & DDI_PROP_CANSLEEP) ? KM_SLEEP : KM_NOSLEEP)) == NULL) {
1129 		cmn_err(CE_CONT, prop_no_mem_msg, name);
1130 		return (DDI_PROP_NO_MEMORY);
1131 	}
1132 
1133 	/*
1134 	 * Return the encoded data
1135 	 */
1136 	*(caddr_t *)valuep = buffer;
1137 	*lengthp = propp->prop_len;
1138 	bcopy(propp->prop_val, buffer, propp->prop_len);
1139 
1140 	return (DDI_PROP_SUCCESS);
1141 }
1142 
1143 /*
1144  * ddi_prop_search_common:	Lookup and return the encoded value
1145  */
1146 int
ddi_prop_search_common(dev_t dev,dev_info_t * dip,ddi_prop_op_t prop_op,uint_t flags,char * name,void * valuep,uint_t * lengthp)1147 ddi_prop_search_common(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1148     uint_t flags, char *name, void *valuep, uint_t *lengthp)
1149 {
1150 	ddi_prop_t	*propp;
1151 	int		i;
1152 	caddr_t		buffer = NULL;
1153 	caddr_t		prealloc = NULL;
1154 	int		plength = 0;
1155 	dev_info_t	*pdip;
1156 	int		(*bop)();
1157 
1158 	/*CONSTANTCONDITION*/
1159 	while (1)  {
1160 
1161 		mutex_enter(&(DEVI(dip)->devi_lock));
1162 
1163 
1164 		/*
1165 		 * find the property in child's devinfo:
1166 		 * Search order is:
1167 		 *	1. driver defined properties
1168 		 *	2. system defined properties
1169 		 *	3. driver global properties
1170 		 *	4. boot defined properties
1171 		 */
1172 
1173 		propp = i_ddi_prop_search(dev, name, flags,
1174 		    &(DEVI(dip)->devi_drv_prop_ptr));
1175 		if (propp == NULL)  {
1176 			propp = i_ddi_prop_search(dev, name, flags,
1177 			    &(DEVI(dip)->devi_sys_prop_ptr));
1178 		}
1179 		if ((propp == NULL) && DEVI(dip)->devi_global_prop_list) {
1180 			propp = i_ddi_prop_search(dev, name, flags,
1181 			    &DEVI(dip)->devi_global_prop_list->prop_list);
1182 		}
1183 
1184 		if (propp == NULL)  {
1185 			propp = i_ddi_prop_search(dev, name, flags,
1186 			    &(DEVI(dip)->devi_hw_prop_ptr));
1187 		}
1188 
1189 		/*
1190 		 * Software property found?
1191 		 */
1192 		if (propp != (ddi_prop_t *)0)	{
1193 
1194 			/*
1195 			 * If explicit undefine, return now.
1196 			 */
1197 			if (propp->prop_flags & DDI_PROP_UNDEF_IT) {
1198 				mutex_exit(&(DEVI(dip)->devi_lock));
1199 				if (prealloc)
1200 					kmem_free(prealloc, plength);
1201 				return (DDI_PROP_UNDEFINED);
1202 			}
1203 
1204 			/*
1205 			 * If we only want to know if it exists, return now
1206 			 */
1207 			if (prop_op == PROP_EXISTS) {
1208 				mutex_exit(&(DEVI(dip)->devi_lock));
1209 				ASSERT(prealloc == NULL);
1210 				return (DDI_PROP_SUCCESS);
1211 			}
1212 
1213 			/*
1214 			 * If length only request or prop length == 0,
1215 			 * service request and return now.
1216 			 */
1217 			if ((prop_op == PROP_LEN) ||(propp->prop_len == 0)) {
1218 				*lengthp = propp->prop_len;
1219 
1220 				/*
1221 				 * if prop_op is PROP_LEN_AND_VAL_ALLOC
1222 				 * that means prop_len is 0, so set valuep
1223 				 * also to NULL
1224 				 */
1225 				if (prop_op == PROP_LEN_AND_VAL_ALLOC)
1226 					*(caddr_t *)valuep = NULL;
1227 
1228 				mutex_exit(&(DEVI(dip)->devi_lock));
1229 				if (prealloc)
1230 					kmem_free(prealloc, plength);
1231 				return (DDI_PROP_SUCCESS);
1232 			}
1233 
1234 			/*
1235 			 * If LEN_AND_VAL_ALLOC and the request can sleep,
1236 			 * drop the mutex, allocate the buffer, and go
1237 			 * through the loop again.  If we already allocated
1238 			 * the buffer, and the size of the property changed,
1239 			 * keep trying...
1240 			 */
1241 			if ((prop_op == PROP_LEN_AND_VAL_ALLOC) &&
1242 			    (flags & DDI_PROP_CANSLEEP))  {
1243 				if (prealloc && (propp->prop_len != plength)) {
1244 					kmem_free(prealloc, plength);
1245 					prealloc = NULL;
1246 				}
1247 				if (prealloc == NULL)  {
1248 					plength = propp->prop_len;
1249 					mutex_exit(&(DEVI(dip)->devi_lock));
1250 					prealloc = kmem_alloc(plength,
1251 					    KM_SLEEP);
1252 					continue;
1253 				}
1254 			}
1255 
1256 			/*
1257 			 * Allocate buffer, if required.  Either way,
1258 			 * set `buffer' variable.
1259 			 */
1260 			i = *lengthp;			/* Get callers length */
1261 			*lengthp = propp->prop_len;	/* Set callers length */
1262 
1263 			switch (prop_op) {
1264 
1265 			case PROP_LEN_AND_VAL_ALLOC:
1266 
1267 				if (prealloc == NULL) {
1268 					buffer = kmem_alloc(propp->prop_len,
1269 					    KM_NOSLEEP);
1270 				} else {
1271 					buffer = prealloc;
1272 				}
1273 
1274 				if (buffer == NULL)  {
1275 					mutex_exit(&(DEVI(dip)->devi_lock));
1276 					cmn_err(CE_CONT, prop_no_mem_msg, name);
1277 					return (DDI_PROP_NO_MEMORY);
1278 				}
1279 				/* Set callers buf ptr */
1280 				*(caddr_t *)valuep = buffer;
1281 				break;
1282 
1283 			case PROP_LEN_AND_VAL_BUF:
1284 
1285 				if (propp->prop_len > (i)) {
1286 					mutex_exit(&(DEVI(dip)->devi_lock));
1287 					return (DDI_PROP_BUF_TOO_SMALL);
1288 				}
1289 
1290 				buffer = valuep;  /* Get callers buf ptr */
1291 				break;
1292 
1293 			default:
1294 				break;
1295 			}
1296 
1297 			/*
1298 			 * Do the copy.
1299 			 */
1300 			if (buffer != NULL)
1301 				bcopy(propp->prop_val, buffer, propp->prop_len);
1302 			mutex_exit(&(DEVI(dip)->devi_lock));
1303 			return (DDI_PROP_SUCCESS);
1304 		}
1305 
1306 		mutex_exit(&(DEVI(dip)->devi_lock));
1307 		if (prealloc)
1308 			kmem_free(prealloc, plength);
1309 		prealloc = NULL;
1310 
1311 		/*
1312 		 * Prop not found, call parent bus_ops to deal with possible
1313 		 * h/w layer (possible PROM defined props, etc.) and to
1314 		 * possibly ascend the hierarchy, if allowed by flags.
1315 		 */
1316 		pdip = (dev_info_t *)DEVI(dip)->devi_parent;
1317 
1318 		/*
1319 		 * One last call for the root driver PROM props?
1320 		 */
1321 		if (dip == ddi_root_node())  {
1322 			return (ddi_bus_prop_op(dev, dip, dip, prop_op,
1323 			    flags, name, valuep, (int *)lengthp));
1324 		}
1325 
1326 		/*
1327 		 * We may have been called to check for properties
1328 		 * within a single devinfo node that has no parent -
1329 		 * see make_prop()
1330 		 */
1331 		if (pdip == NULL) {
1332 			ASSERT((flags &
1333 			    (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM)) ==
1334 			    (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM));
1335 			return (DDI_PROP_NOT_FOUND);
1336 		}
1337 
1338 		/*
1339 		 * Instead of recursing, we do iterative calls up the tree.
1340 		 * As a bit of optimization, skip the bus_op level if the
1341 		 * node is a s/w node and if the parent's bus_prop_op function
1342 		 * is `ddi_bus_prop_op', because we know that in this case,
1343 		 * this function does nothing.
1344 		 *
1345 		 * 4225415: If the parent isn't attached, or the child
1346 		 * hasn't been named by the parent yet, use the default
1347 		 * ddi_bus_prop_op as a proxy for the parent.  This
1348 		 * allows property lookups in any child/parent state to
1349 		 * include 'prom' and inherited properties, even when
1350 		 * there are no drivers attached to the child or parent.
1351 		 */
1352 
1353 		bop = ddi_bus_prop_op;
1354 		if (i_ddi_devi_attached(pdip) &&
1355 		    (i_ddi_node_state(dip) >= DS_INITIALIZED))
1356 			bop = DEVI(pdip)->devi_ops->devo_bus_ops->bus_prop_op;
1357 
1358 		i = DDI_PROP_NOT_FOUND;
1359 
1360 		if ((bop != ddi_bus_prop_op) || ndi_dev_is_prom_node(dip)) {
1361 			i = (*bop)(dev, pdip, dip, prop_op,
1362 			    flags | DDI_PROP_DONTPASS,
1363 			    name, valuep, lengthp);
1364 		}
1365 
1366 		if ((flags & DDI_PROP_DONTPASS) ||
1367 		    (i != DDI_PROP_NOT_FOUND))
1368 			return (i);
1369 
1370 		dip = pdip;
1371 	}
1372 	/*NOTREACHED*/
1373 }
1374 
1375 
1376 /*
1377  * ddi_prop_op: The basic property operator for drivers.
1378  *
1379  * In ddi_prop_op, the type of valuep is interpreted based on prop_op:
1380  *
1381  *	prop_op			valuep
1382  *	------			------
1383  *
1384  *	PROP_LEN		<unused>
1385  *
1386  *	PROP_LEN_AND_VAL_BUF	Pointer to callers buffer
1387  *
1388  *	PROP_LEN_AND_VAL_ALLOC	Address of callers pointer (will be set to
1389  *				address of allocated buffer, if successful)
1390  */
1391 int
ddi_prop_op(dev_t dev,dev_info_t * dip,ddi_prop_op_t prop_op,int mod_flags,char * name,caddr_t valuep,int * lengthp)1392 ddi_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
1393     char *name, caddr_t valuep, int *lengthp)
1394 {
1395 	int	i;
1396 
1397 	ASSERT((mod_flags & DDI_PROP_TYPE_MASK) == 0);
1398 
1399 	/*
1400 	 * If this was originally an LDI prop lookup then we bail here.
1401 	 * The reason is that the LDI property lookup interfaces first call
1402 	 * a drivers prop_op() entry point to allow it to override
1403 	 * properties.  But if we've made it here, then the driver hasn't
1404 	 * overriden any properties.  We don't want to continue with the
1405 	 * property search here because we don't have any type inforamtion.
1406 	 * When we return failure, the LDI interfaces will then proceed to
1407 	 * call the typed property interfaces to look up the property.
1408 	 */
1409 	if (mod_flags & DDI_PROP_DYNAMIC)
1410 		return (DDI_PROP_NOT_FOUND);
1411 
1412 	/*
1413 	 * check for pre-typed property consumer asking for typed property:
1414 	 * see e_ddi_getprop_int64.
1415 	 */
1416 	if (mod_flags & DDI_PROP_CONSUMER_TYPED)
1417 		mod_flags |= DDI_PROP_TYPE_INT64;
1418 	mod_flags |= DDI_PROP_TYPE_ANY;
1419 
1420 	i = ddi_prop_search_common(dev, dip, prop_op,
1421 	    mod_flags, name, valuep, (uint_t *)lengthp);
1422 	if (i == DDI_PROP_FOUND_1275)
1423 		return (DDI_PROP_SUCCESS);
1424 	return (i);
1425 }
1426 
1427 /*
1428  * ddi_prop_op_nblocks_blksize: The basic property operator for drivers that
1429  * maintain size in number of blksize blocks.  Provides a dynamic property
1430  * implementation for size oriented properties based on nblocks64 and blksize
1431  * values passed in by the driver.  Fallback to ddi_prop_op if the nblocks64
1432  * is too large.  This interface should not be used with a nblocks64 that
1433  * represents the driver's idea of how to represent unknown, if nblocks is
1434  * unknown use ddi_prop_op.
1435  */
1436 int
ddi_prop_op_nblocks_blksize(dev_t dev,dev_info_t * dip,ddi_prop_op_t prop_op,int mod_flags,char * name,caddr_t valuep,int * lengthp,uint64_t nblocks64,uint_t blksize)1437 ddi_prop_op_nblocks_blksize(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1438     int mod_flags, char *name, caddr_t valuep, int *lengthp,
1439     uint64_t nblocks64, uint_t blksize)
1440 {
1441 	uint64_t size64;
1442 	int	blkshift;
1443 
1444 	/* convert block size to shift value */
1445 	ASSERT(BIT_ONLYONESET(blksize));
1446 	blkshift = highbit(blksize) - 1;
1447 
1448 	/*
1449 	 * There is no point in supporting nblocks64 values that don't have
1450 	 * an accurate uint64_t byte count representation.
1451 	 */
1452 	if (nblocks64 >= (UINT64_MAX >> blkshift))
1453 		return (ddi_prop_op(dev, dip, prop_op, mod_flags,
1454 		    name, valuep, lengthp));
1455 
1456 	size64 = nblocks64 << blkshift;
1457 	return (ddi_prop_op_size_blksize(dev, dip, prop_op, mod_flags,
1458 	    name, valuep, lengthp, size64, blksize));
1459 }
1460 
1461 /*
1462  * ddi_prop_op_nblocks: ddi_prop_op_nblocks_blksize with DEV_BSIZE blksize.
1463  */
1464 int
ddi_prop_op_nblocks(dev_t dev,dev_info_t * dip,ddi_prop_op_t prop_op,int mod_flags,char * name,caddr_t valuep,int * lengthp,uint64_t nblocks64)1465 ddi_prop_op_nblocks(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1466     int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t nblocks64)
1467 {
1468 	return (ddi_prop_op_nblocks_blksize(dev, dip, prop_op,
1469 	    mod_flags, name, valuep, lengthp, nblocks64, DEV_BSIZE));
1470 }
1471 
1472 /*
1473  * ddi_prop_op_size_blksize: The basic property operator for block drivers that
1474  * maintain size in bytes. Provides a of dynamic property implementation for
1475  * size oriented properties based on size64 value and blksize passed in by the
1476  * driver.  Fallback to ddi_prop_op if the size64 is too large. This interface
1477  * should not be used with a size64 that represents the driver's idea of how
1478  * to represent unknown, if size is unknown use ddi_prop_op.
1479  *
1480  * NOTE: the legacy "nblocks"/"size" properties are treated as 32-bit unsigned
1481  * integers. While the most likely interface to request them ([bc]devi_size)
1482  * is declared int (signed) there is no enforcement of this, which means we
1483  * can't enforce limitations here without risking regression.
1484  */
1485 int
ddi_prop_op_size_blksize(dev_t dev,dev_info_t * dip,ddi_prop_op_t prop_op,int mod_flags,char * name,caddr_t valuep,int * lengthp,uint64_t size64,uint_t blksize)1486 ddi_prop_op_size_blksize(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1487     int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t size64,
1488     uint_t blksize)
1489 {
1490 	uint64_t nblocks64;
1491 	int	callers_length;
1492 	caddr_t	buffer;
1493 	int	blkshift;
1494 
1495 	/*
1496 	 * This is a kludge to support capture of size(9P) pure dynamic
1497 	 * properties in snapshots for non-cmlb code (without exposing
1498 	 * i_ddi_prop_dyn changes). When everyone uses cmlb, this code
1499 	 * should be removed.
1500 	 */
1501 	if (i_ddi_prop_dyn_driver_get(dip) == NULL) {
1502 		static i_ddi_prop_dyn_t prop_dyn_size[] = {
1503 		    {"Size",		DDI_PROP_TYPE_INT64,	S_IFCHR},
1504 		    {"Nblocks",		DDI_PROP_TYPE_INT64,	S_IFBLK},
1505 		    {NULL}
1506 		};
1507 		i_ddi_prop_dyn_driver_set(dip, prop_dyn_size);
1508 	}
1509 
1510 	/* convert block size to shift value */
1511 	ASSERT(BIT_ONLYONESET(blksize));
1512 	blkshift = highbit(blksize) - 1;
1513 
1514 	/* compute DEV_BSIZE nblocks value */
1515 	nblocks64 = size64 >> blkshift;
1516 
1517 	/* get callers length, establish length of our dynamic properties */
1518 	callers_length = *lengthp;
1519 
1520 	if (strcmp(name, "Nblocks") == 0)
1521 		*lengthp = sizeof (uint64_t);
1522 	else if (strcmp(name, "Size") == 0)
1523 		*lengthp = sizeof (uint64_t);
1524 	else if ((strcmp(name, "nblocks") == 0) && (nblocks64 < UINT_MAX))
1525 		*lengthp = sizeof (uint32_t);
1526 	else if ((strcmp(name, "size") == 0) && (size64 < UINT_MAX))
1527 		*lengthp = sizeof (uint32_t);
1528 	else if ((strcmp(name, "blksize") == 0) && (blksize < UINT_MAX))
1529 		*lengthp = sizeof (uint32_t);
1530 	else {
1531 		/* fallback to ddi_prop_op */
1532 		return (ddi_prop_op(dev, dip, prop_op, mod_flags,
1533 		    name, valuep, lengthp));
1534 	}
1535 
1536 	/* service request for the length of the property */
1537 	if (prop_op == PROP_LEN)
1538 		return (DDI_PROP_SUCCESS);
1539 
1540 	switch (prop_op) {
1541 	case PROP_LEN_AND_VAL_ALLOC:
1542 		if ((buffer = kmem_alloc(*lengthp,
1543 		    (mod_flags & DDI_PROP_CANSLEEP) ?
1544 		    KM_SLEEP : KM_NOSLEEP)) == NULL)
1545 			return (DDI_PROP_NO_MEMORY);
1546 
1547 		*(caddr_t *)valuep = buffer;	/* set callers buf ptr */
1548 		break;
1549 
1550 	case PROP_LEN_AND_VAL_BUF:
1551 		/* the length of the property and the request must match */
1552 		if (callers_length != *lengthp)
1553 			return (DDI_PROP_INVAL_ARG);
1554 
1555 		buffer = valuep;		/* get callers buf ptr */
1556 		break;
1557 
1558 	default:
1559 		return (DDI_PROP_INVAL_ARG);
1560 	}
1561 
1562 	/* transfer the value into the buffer */
1563 	if (strcmp(name, "Nblocks") == 0)
1564 		*((uint64_t *)buffer) = nblocks64;
1565 	else if (strcmp(name, "Size") == 0)
1566 		*((uint64_t *)buffer) = size64;
1567 	else if (strcmp(name, "nblocks") == 0)
1568 		*((uint32_t *)buffer) = (uint32_t)nblocks64;
1569 	else if (strcmp(name, "size") == 0)
1570 		*((uint32_t *)buffer) = (uint32_t)size64;
1571 	else if (strcmp(name, "blksize") == 0)
1572 		*((uint32_t *)buffer) = (uint32_t)blksize;
1573 	return (DDI_PROP_SUCCESS);
1574 }
1575 
1576 /*
1577  * ddi_prop_op_size: ddi_prop_op_size_blksize with DEV_BSIZE block size.
1578  */
1579 int
ddi_prop_op_size(dev_t dev,dev_info_t * dip,ddi_prop_op_t prop_op,int mod_flags,char * name,caddr_t valuep,int * lengthp,uint64_t size64)1580 ddi_prop_op_size(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1581     int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t size64)
1582 {
1583 	return (ddi_prop_op_size_blksize(dev, dip, prop_op,
1584 	    mod_flags, name, valuep, lengthp, size64, DEV_BSIZE));
1585 }
1586 
1587 /*
1588  * Variable length props...
1589  */
1590 
1591 /*
1592  * ddi_getlongprop:	Get variable length property len+val into a buffer
1593  *		allocated by property provider via kmem_alloc. Requester
1594  *		is responsible for freeing returned property via kmem_free.
1595  *
1596  *	Arguments:
1597  *
1598  *	dev_t:	Input:	dev_t of property.
1599  *	dip:	Input:	dev_info_t pointer of child.
1600  *	flags:	Input:	Possible flag modifiers are:
1601  *		DDI_PROP_DONTPASS:	Don't pass to parent if prop not found.
1602  *		DDI_PROP_CANSLEEP:	Memory allocation may sleep.
1603  *	name:	Input:	name of property.
1604  *	valuep:	Output:	Addr of callers buffer pointer.
1605  *	lengthp:Output:	*lengthp will contain prop length on exit.
1606  *
1607  *	Possible Returns:
1608  *
1609  *		DDI_PROP_SUCCESS:	Prop found and returned.
1610  *		DDI_PROP_NOT_FOUND:	Prop not found
1611  *		DDI_PROP_UNDEFINED:	Prop explicitly undefined.
1612  *		DDI_PROP_NO_MEMORY:	Prop found, but unable to alloc mem.
1613  */
1614 
1615 int
ddi_getlongprop(dev_t dev,dev_info_t * dip,int flags,char * name,caddr_t valuep,int * lengthp)1616 ddi_getlongprop(dev_t dev, dev_info_t *dip, int flags,
1617     char *name, caddr_t valuep, int *lengthp)
1618 {
1619 	return (ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_ALLOC,
1620 	    flags, name, valuep, lengthp));
1621 }
1622 
1623 /*
1624  *
1625  * ddi_getlongprop_buf:		Get long prop into pre-allocated callers
1626  *				buffer. (no memory allocation by provider).
1627  *
1628  *	dev_t:	Input:	dev_t of property.
1629  *	dip:	Input:	dev_info_t pointer of child.
1630  *	flags:	Input:	DDI_PROP_DONTPASS or NULL
1631  *	name:	Input:	name of property
1632  *	valuep:	Input:	ptr to callers buffer.
1633  *	lengthp:I/O:	ptr to length of callers buffer on entry,
1634  *			actual length of property on exit.
1635  *
1636  *	Possible returns:
1637  *
1638  *		DDI_PROP_SUCCESS	Prop found and returned
1639  *		DDI_PROP_NOT_FOUND	Prop not found
1640  *		DDI_PROP_UNDEFINED	Prop explicitly undefined.
1641  *		DDI_PROP_BUF_TOO_SMALL	Prop found, callers buf too small,
1642  *					no value returned, but actual prop
1643  *					length returned in *lengthp
1644  *
1645  */
1646 
1647 int
ddi_getlongprop_buf(dev_t dev,dev_info_t * dip,int flags,char * name,caddr_t valuep,int * lengthp)1648 ddi_getlongprop_buf(dev_t dev, dev_info_t *dip, int flags,
1649     char *name, caddr_t valuep, int *lengthp)
1650 {
1651 	return (ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_BUF,
1652 	    flags, name, valuep, lengthp));
1653 }
1654 
1655 /*
1656  * Integer/boolean sized props.
1657  *
1658  * Call is value only... returns found boolean or int sized prop value or
1659  * defvalue if prop not found or is wrong length or is explicitly undefined.
1660  * Only flag is DDI_PROP_DONTPASS...
1661  *
1662  * By convention, this interface returns boolean (0) sized properties
1663  * as value (int)1.
1664  *
1665  * This never returns an error, if property not found or specifically
1666  * undefined, the input `defvalue' is returned.
1667  */
1668 
1669 int
ddi_getprop(dev_t dev,dev_info_t * dip,int flags,char * name,int defvalue)1670 ddi_getprop(dev_t dev, dev_info_t *dip, int flags, char *name, int defvalue)
1671 {
1672 	int	propvalue = defvalue;
1673 	int	proplength = sizeof (int);
1674 	int	error;
1675 
1676 	error = ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_BUF,
1677 	    flags, name, (caddr_t)&propvalue, &proplength);
1678 
1679 	if ((error == DDI_PROP_SUCCESS) && (proplength == 0))
1680 		propvalue = 1;
1681 
1682 	return (propvalue);
1683 }
1684 
1685 /*
1686  * Get prop length interface: flags are 0 or DDI_PROP_DONTPASS
1687  * if returns DDI_PROP_SUCCESS, length returned in *lengthp.
1688  */
1689 
1690 int
ddi_getproplen(dev_t dev,dev_info_t * dip,int flags,char * name,int * lengthp)1691 ddi_getproplen(dev_t dev, dev_info_t *dip, int flags, char *name, int *lengthp)
1692 {
1693 	return (ddi_prop_op(dev, dip, PROP_LEN, flags, name, NULL, lengthp));
1694 }
1695 
1696 /*
1697  * Allocate a struct prop_driver_data, along with 'size' bytes
1698  * for decoded property data.  This structure is freed by
1699  * calling ddi_prop_free(9F).
1700  */
1701 static void *
ddi_prop_decode_alloc(size_t size,void (* prop_free)(struct prop_driver_data *))1702 ddi_prop_decode_alloc(size_t size, void (*prop_free)(struct prop_driver_data *))
1703 {
1704 	struct prop_driver_data *pdd;
1705 
1706 	/*
1707 	 * Allocate a structure with enough memory to store the decoded data.
1708 	 */
1709 	pdd = kmem_zalloc(sizeof (struct prop_driver_data) + size, KM_SLEEP);
1710 	pdd->pdd_size = (sizeof (struct prop_driver_data) + size);
1711 	pdd->pdd_prop_free = prop_free;
1712 
1713 	/*
1714 	 * Return a pointer to the location to put the decoded data.
1715 	 */
1716 	return ((void *)((caddr_t)pdd + sizeof (struct prop_driver_data)));
1717 }
1718 
1719 /*
1720  * Allocated the memory needed to store the encoded data in the property
1721  * handle.
1722  */
1723 static int
ddi_prop_encode_alloc(prop_handle_t * ph,size_t size)1724 ddi_prop_encode_alloc(prop_handle_t *ph, size_t size)
1725 {
1726 	/*
1727 	 * If size is zero, then set data to NULL and size to 0.  This
1728 	 * is a boolean property.
1729 	 */
1730 	if (size == 0) {
1731 		ph->ph_size = 0;
1732 		ph->ph_data = NULL;
1733 		ph->ph_cur_pos = NULL;
1734 		ph->ph_save_pos = NULL;
1735 	} else {
1736 		if (ph->ph_flags == DDI_PROP_DONTSLEEP) {
1737 			ph->ph_data = kmem_zalloc(size, KM_NOSLEEP);
1738 			if (ph->ph_data == NULL)
1739 				return (DDI_PROP_NO_MEMORY);
1740 		} else
1741 			ph->ph_data = kmem_zalloc(size, KM_SLEEP);
1742 		ph->ph_size = size;
1743 		ph->ph_cur_pos = ph->ph_data;
1744 		ph->ph_save_pos = ph->ph_data;
1745 	}
1746 	return (DDI_PROP_SUCCESS);
1747 }
1748 
1749 /*
1750  * Free the space allocated by the lookup routines.  Each lookup routine
1751  * returns a pointer to the decoded data to the driver.  The driver then
1752  * passes this pointer back to us.  This data actually lives in a struct
1753  * prop_driver_data.  We use negative indexing to find the beginning of
1754  * the structure and then free the entire structure using the size and
1755  * the free routine stored in the structure.
1756  */
1757 void
ddi_prop_free(void * datap)1758 ddi_prop_free(void *datap)
1759 {
1760 	struct prop_driver_data *pdd;
1761 
1762 	/*
1763 	 * Get the structure
1764 	 */
1765 	pdd = (struct prop_driver_data *)
1766 	    ((caddr_t)datap - sizeof (struct prop_driver_data));
1767 	/*
1768 	 * Call the free routine to free it
1769 	 */
1770 	(*pdd->pdd_prop_free)(pdd);
1771 }
1772 
1773 /*
1774  * Free the data associated with an array of ints,
1775  * allocated with ddi_prop_decode_alloc().
1776  */
1777 static void
ddi_prop_free_ints(struct prop_driver_data * pdd)1778 ddi_prop_free_ints(struct prop_driver_data *pdd)
1779 {
1780 	kmem_free(pdd, pdd->pdd_size);
1781 }
1782 
1783 /*
1784  * Free a single string property or a single string contained within
1785  * the argv style return value of an array of strings.
1786  */
1787 static void
ddi_prop_free_string(struct prop_driver_data * pdd)1788 ddi_prop_free_string(struct prop_driver_data *pdd)
1789 {
1790 	kmem_free(pdd, pdd->pdd_size);
1791 
1792 }
1793 
1794 /*
1795  * Free an array of strings.
1796  */
1797 static void
ddi_prop_free_strings(struct prop_driver_data * pdd)1798 ddi_prop_free_strings(struct prop_driver_data *pdd)
1799 {
1800 	kmem_free(pdd, pdd->pdd_size);
1801 }
1802 
1803 /*
1804  * Free the data associated with an array of bytes.
1805  */
1806 static void
ddi_prop_free_bytes(struct prop_driver_data * pdd)1807 ddi_prop_free_bytes(struct prop_driver_data *pdd)
1808 {
1809 	kmem_free(pdd, pdd->pdd_size);
1810 }
1811 
1812 /*
1813  * Reset the current location pointer in the property handle to the
1814  * beginning of the data.
1815  */
1816 void
ddi_prop_reset_pos(prop_handle_t * ph)1817 ddi_prop_reset_pos(prop_handle_t *ph)
1818 {
1819 	ph->ph_cur_pos = ph->ph_data;
1820 	ph->ph_save_pos = ph->ph_data;
1821 }
1822 
1823 /*
1824  * Restore the current location pointer in the property handle to the
1825  * saved position.
1826  */
1827 void
ddi_prop_save_pos(prop_handle_t * ph)1828 ddi_prop_save_pos(prop_handle_t *ph)
1829 {
1830 	ph->ph_save_pos = ph->ph_cur_pos;
1831 }
1832 
1833 /*
1834  * Save the location that the current location pointer is pointing to..
1835  */
1836 void
ddi_prop_restore_pos(prop_handle_t * ph)1837 ddi_prop_restore_pos(prop_handle_t *ph)
1838 {
1839 	ph->ph_cur_pos = ph->ph_save_pos;
1840 }
1841 
1842 /*
1843  * Property encode/decode functions
1844  */
1845 
1846 /*
1847  * Decode a single integer property
1848  */
1849 static int
ddi_prop_fm_decode_int(prop_handle_t * ph,void * data,uint_t * nelements)1850 ddi_prop_fm_decode_int(prop_handle_t *ph, void *data, uint_t *nelements)
1851 {
1852 	int	i;
1853 	int	tmp;
1854 
1855 	/*
1856 	 * If there is nothing to decode return an error
1857 	 */
1858 	if (ph->ph_size == 0)
1859 		return (DDI_PROP_END_OF_DATA);
1860 
1861 	/*
1862 	 * Decode the property as a single integer and return it
1863 	 * in data if we were able to decode it.
1864 	 */
1865 	i = DDI_PROP_INT(ph, DDI_PROP_CMD_DECODE, &tmp);
1866 	if (i < DDI_PROP_RESULT_OK) {
1867 		switch (i) {
1868 		case DDI_PROP_RESULT_EOF:
1869 			return (DDI_PROP_END_OF_DATA);
1870 
1871 		case DDI_PROP_RESULT_ERROR:
1872 			return (DDI_PROP_CANNOT_DECODE);
1873 		}
1874 	}
1875 
1876 	*(int *)data = tmp;
1877 	*nelements = 1;
1878 	return (DDI_PROP_SUCCESS);
1879 }
1880 
1881 /*
1882  * Decode a single 64 bit integer property
1883  */
1884 static int
ddi_prop_fm_decode_int64(prop_handle_t * ph,void * data,uint_t * nelements)1885 ddi_prop_fm_decode_int64(prop_handle_t *ph, void *data, uint_t *nelements)
1886 {
1887 	int	i;
1888 	int64_t	tmp;
1889 
1890 	/*
1891 	 * If there is nothing to decode return an error
1892 	 */
1893 	if (ph->ph_size == 0)
1894 		return (DDI_PROP_END_OF_DATA);
1895 
1896 	/*
1897 	 * Decode the property as a single integer and return it
1898 	 * in data if we were able to decode it.
1899 	 */
1900 	i = DDI_PROP_INT64(ph, DDI_PROP_CMD_DECODE, &tmp);
1901 	if (i < DDI_PROP_RESULT_OK) {
1902 		switch (i) {
1903 		case DDI_PROP_RESULT_EOF:
1904 			return (DDI_PROP_END_OF_DATA);
1905 
1906 		case DDI_PROP_RESULT_ERROR:
1907 			return (DDI_PROP_CANNOT_DECODE);
1908 		}
1909 	}
1910 
1911 	*(int64_t *)data = tmp;
1912 	*nelements = 1;
1913 	return (DDI_PROP_SUCCESS);
1914 }
1915 
1916 /*
1917  * Decode an array of integers property
1918  */
1919 static int
ddi_prop_fm_decode_ints(prop_handle_t * ph,void * data,uint_t * nelements)1920 ddi_prop_fm_decode_ints(prop_handle_t *ph, void *data, uint_t *nelements)
1921 {
1922 	int	i;
1923 	int	cnt = 0;
1924 	int	*tmp;
1925 	int	*intp;
1926 	int	n;
1927 
1928 	/*
1929 	 * Figure out how many array elements there are by going through the
1930 	 * data without decoding it first and counting.
1931 	 */
1932 	for (;;) {
1933 		i = DDI_PROP_INT(ph, DDI_PROP_CMD_SKIP, NULL);
1934 		if (i < 0)
1935 			break;
1936 		cnt++;
1937 	}
1938 
1939 	/*
1940 	 * If there are no elements return an error
1941 	 */
1942 	if (cnt == 0)
1943 		return (DDI_PROP_END_OF_DATA);
1944 
1945 	/*
1946 	 * If we cannot skip through the data, we cannot decode it
1947 	 */
1948 	if (i == DDI_PROP_RESULT_ERROR)
1949 		return (DDI_PROP_CANNOT_DECODE);
1950 
1951 	/*
1952 	 * Reset the data pointer to the beginning of the encoded data
1953 	 */
1954 	ddi_prop_reset_pos(ph);
1955 
1956 	/*
1957 	 * Allocated memory to store the decoded value in.
1958 	 */
1959 	intp = ddi_prop_decode_alloc((cnt * sizeof (int)),
1960 	    ddi_prop_free_ints);
1961 
1962 	/*
1963 	 * Decode each element and place it in the space we just allocated
1964 	 */
1965 	tmp = intp;
1966 	for (n = 0; n < cnt; n++, tmp++) {
1967 		i = DDI_PROP_INT(ph, DDI_PROP_CMD_DECODE, tmp);
1968 		if (i < DDI_PROP_RESULT_OK) {
1969 			/*
1970 			 * Free the space we just allocated
1971 			 * and return an error.
1972 			 */
1973 			ddi_prop_free(intp);
1974 			switch (i) {
1975 			case DDI_PROP_RESULT_EOF:
1976 				return (DDI_PROP_END_OF_DATA);
1977 
1978 			case DDI_PROP_RESULT_ERROR:
1979 				return (DDI_PROP_CANNOT_DECODE);
1980 			}
1981 		}
1982 	}
1983 
1984 	*nelements = cnt;
1985 	*(int **)data = intp;
1986 
1987 	return (DDI_PROP_SUCCESS);
1988 }
1989 
1990 /*
1991  * Decode a 64 bit integer array property
1992  */
1993 static int
ddi_prop_fm_decode_int64_array(prop_handle_t * ph,void * data,uint_t * nelements)1994 ddi_prop_fm_decode_int64_array(prop_handle_t *ph, void *data, uint_t *nelements)
1995 {
1996 	int	i;
1997 	int	n;
1998 	int	cnt = 0;
1999 	int64_t	*tmp;
2000 	int64_t	*intp;
2001 
2002 	/*
2003 	 * Count the number of array elements by going
2004 	 * through the data without decoding it.
2005 	 */
2006 	for (;;) {
2007 		i = DDI_PROP_INT64(ph, DDI_PROP_CMD_SKIP, NULL);
2008 		if (i < 0)
2009 			break;
2010 		cnt++;
2011 	}
2012 
2013 	/*
2014 	 * If there are no elements return an error
2015 	 */
2016 	if (cnt == 0)
2017 		return (DDI_PROP_END_OF_DATA);
2018 
2019 	/*
2020 	 * If we cannot skip through the data, we cannot decode it
2021 	 */
2022 	if (i == DDI_PROP_RESULT_ERROR)
2023 		return (DDI_PROP_CANNOT_DECODE);
2024 
2025 	/*
2026 	 * Reset the data pointer to the beginning of the encoded data
2027 	 */
2028 	ddi_prop_reset_pos(ph);
2029 
2030 	/*
2031 	 * Allocate memory to store the decoded value.
2032 	 */
2033 	intp = ddi_prop_decode_alloc((cnt * sizeof (int64_t)),
2034 	    ddi_prop_free_ints);
2035 
2036 	/*
2037 	 * Decode each element and place it in the space allocated
2038 	 */
2039 	tmp = intp;
2040 	for (n = 0; n < cnt; n++, tmp++) {
2041 		i = DDI_PROP_INT64(ph, DDI_PROP_CMD_DECODE, tmp);
2042 		if (i < DDI_PROP_RESULT_OK) {
2043 			/*
2044 			 * Free the space we just allocated
2045 			 * and return an error.
2046 			 */
2047 			ddi_prop_free(intp);
2048 			switch (i) {
2049 			case DDI_PROP_RESULT_EOF:
2050 				return (DDI_PROP_END_OF_DATA);
2051 
2052 			case DDI_PROP_RESULT_ERROR:
2053 				return (DDI_PROP_CANNOT_DECODE);
2054 			}
2055 		}
2056 	}
2057 
2058 	*nelements = cnt;
2059 	*(int64_t **)data = intp;
2060 
2061 	return (DDI_PROP_SUCCESS);
2062 }
2063 
2064 /*
2065  * Encode an array of integers property (Can be one element)
2066  */
2067 int
ddi_prop_fm_encode_ints(prop_handle_t * ph,void * data,uint_t nelements)2068 ddi_prop_fm_encode_ints(prop_handle_t *ph, void *data, uint_t nelements)
2069 {
2070 	int	i;
2071 	int	*tmp;
2072 	int	cnt;
2073 	int	size;
2074 
2075 	/*
2076 	 * If there is no data, we cannot do anything
2077 	 */
2078 	if (nelements == 0)
2079 		return (DDI_PROP_CANNOT_ENCODE);
2080 
2081 	/*
2082 	 * Get the size of an encoded int.
2083 	 */
2084 	size = DDI_PROP_INT(ph, DDI_PROP_CMD_GET_ESIZE, NULL);
2085 
2086 	if (size < DDI_PROP_RESULT_OK) {
2087 		switch (size) {
2088 		case DDI_PROP_RESULT_EOF:
2089 			return (DDI_PROP_END_OF_DATA);
2090 
2091 		case DDI_PROP_RESULT_ERROR:
2092 			return (DDI_PROP_CANNOT_ENCODE);
2093 		}
2094 	}
2095 
2096 	/*
2097 	 * Allocate space in the handle to store the encoded int.
2098 	 */
2099 	if (ddi_prop_encode_alloc(ph, size * nelements) !=
2100 	    DDI_PROP_SUCCESS)
2101 		return (DDI_PROP_NO_MEMORY);
2102 
2103 	/*
2104 	 * Encode the array of ints.
2105 	 */
2106 	tmp = (int *)data;
2107 	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
2108 		i = DDI_PROP_INT(ph, DDI_PROP_CMD_ENCODE, tmp);
2109 		if (i < DDI_PROP_RESULT_OK) {
2110 			switch (i) {
2111 			case DDI_PROP_RESULT_EOF:
2112 				return (DDI_PROP_END_OF_DATA);
2113 
2114 			case DDI_PROP_RESULT_ERROR:
2115 				return (DDI_PROP_CANNOT_ENCODE);
2116 			}
2117 		}
2118 	}
2119 
2120 	return (DDI_PROP_SUCCESS);
2121 }
2122 
2123 
2124 /*
2125  * Encode a 64 bit integer array property
2126  */
2127 int
ddi_prop_fm_encode_int64(prop_handle_t * ph,void * data,uint_t nelements)2128 ddi_prop_fm_encode_int64(prop_handle_t *ph, void *data, uint_t nelements)
2129 {
2130 	int i;
2131 	int cnt;
2132 	int size;
2133 	int64_t *tmp;
2134 
2135 	/*
2136 	 * If there is no data, we cannot do anything
2137 	 */
2138 	if (nelements == 0)
2139 		return (DDI_PROP_CANNOT_ENCODE);
2140 
2141 	/*
2142 	 * Get the size of an encoded 64 bit int.
2143 	 */
2144 	size = DDI_PROP_INT64(ph, DDI_PROP_CMD_GET_ESIZE, NULL);
2145 
2146 	if (size < DDI_PROP_RESULT_OK) {
2147 		switch (size) {
2148 		case DDI_PROP_RESULT_EOF:
2149 			return (DDI_PROP_END_OF_DATA);
2150 
2151 		case DDI_PROP_RESULT_ERROR:
2152 			return (DDI_PROP_CANNOT_ENCODE);
2153 		}
2154 	}
2155 
2156 	/*
2157 	 * Allocate space in the handle to store the encoded int.
2158 	 */
2159 	if (ddi_prop_encode_alloc(ph, size * nelements) !=
2160 	    DDI_PROP_SUCCESS)
2161 		return (DDI_PROP_NO_MEMORY);
2162 
2163 	/*
2164 	 * Encode the array of ints.
2165 	 */
2166 	tmp = (int64_t *)data;
2167 	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
2168 		i = DDI_PROP_INT64(ph, DDI_PROP_CMD_ENCODE, tmp);
2169 		if (i < DDI_PROP_RESULT_OK) {
2170 			switch (i) {
2171 			case DDI_PROP_RESULT_EOF:
2172 				return (DDI_PROP_END_OF_DATA);
2173 
2174 			case DDI_PROP_RESULT_ERROR:
2175 				return (DDI_PROP_CANNOT_ENCODE);
2176 			}
2177 		}
2178 	}
2179 
2180 	return (DDI_PROP_SUCCESS);
2181 }
2182 
2183 /*
2184  * Decode a single string property
2185  */
2186 static int
ddi_prop_fm_decode_string(prop_handle_t * ph,void * data,uint_t * nelements)2187 ddi_prop_fm_decode_string(prop_handle_t *ph, void *data, uint_t *nelements)
2188 {
2189 	char		*tmp;
2190 	char		*str;
2191 	int		i;
2192 	int		size;
2193 
2194 	/*
2195 	 * If there is nothing to decode return an error
2196 	 */
2197 	if (ph->ph_size == 0)
2198 		return (DDI_PROP_END_OF_DATA);
2199 
2200 	/*
2201 	 * Get the decoded size of the encoded string.
2202 	 */
2203 	size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL);
2204 	if (size < DDI_PROP_RESULT_OK) {
2205 		switch (size) {
2206 		case DDI_PROP_RESULT_EOF:
2207 			return (DDI_PROP_END_OF_DATA);
2208 
2209 		case DDI_PROP_RESULT_ERROR:
2210 			return (DDI_PROP_CANNOT_DECODE);
2211 		}
2212 	}
2213 
2214 	/*
2215 	 * Allocated memory to store the decoded value in.
2216 	 */
2217 	str = ddi_prop_decode_alloc((size_t)size, ddi_prop_free_string);
2218 
2219 	ddi_prop_reset_pos(ph);
2220 
2221 	/*
2222 	 * Decode the str and place it in the space we just allocated
2223 	 */
2224 	tmp = str;
2225 	i = DDI_PROP_STR(ph, DDI_PROP_CMD_DECODE, tmp);
2226 	if (i < DDI_PROP_RESULT_OK) {
2227 		/*
2228 		 * Free the space we just allocated
2229 		 * and return an error.
2230 		 */
2231 		ddi_prop_free(str);
2232 		switch (i) {
2233 		case DDI_PROP_RESULT_EOF:
2234 			return (DDI_PROP_END_OF_DATA);
2235 
2236 		case DDI_PROP_RESULT_ERROR:
2237 			return (DDI_PROP_CANNOT_DECODE);
2238 		}
2239 	}
2240 
2241 	*(char **)data = str;
2242 	*nelements = 1;
2243 
2244 	return (DDI_PROP_SUCCESS);
2245 }
2246 
2247 /*
2248  * Decode an array of strings.
2249  */
2250 int
ddi_prop_fm_decode_strings(prop_handle_t * ph,void * data,uint_t * nelements)2251 ddi_prop_fm_decode_strings(prop_handle_t *ph, void *data, uint_t *nelements)
2252 {
2253 	int		cnt = 0;
2254 	char		**strs;
2255 	char		**tmp;
2256 	char		*ptr;
2257 	int		i;
2258 	int		n;
2259 	int		size;
2260 	size_t		nbytes;
2261 
2262 	/*
2263 	 * Figure out how many array elements there are by going through the
2264 	 * data without decoding it first and counting.
2265 	 */
2266 	for (;;) {
2267 		i = DDI_PROP_STR(ph, DDI_PROP_CMD_SKIP, NULL);
2268 		if (i < 0)
2269 			break;
2270 		cnt++;
2271 	}
2272 
2273 	/*
2274 	 * If there are no elements return an error
2275 	 */
2276 	if (cnt == 0)
2277 		return (DDI_PROP_END_OF_DATA);
2278 
2279 	/*
2280 	 * If we cannot skip through the data, we cannot decode it
2281 	 */
2282 	if (i == DDI_PROP_RESULT_ERROR)
2283 		return (DDI_PROP_CANNOT_DECODE);
2284 
2285 	/*
2286 	 * Reset the data pointer to the beginning of the encoded data
2287 	 */
2288 	ddi_prop_reset_pos(ph);
2289 
2290 	/*
2291 	 * Figure out how much memory we need for the sum total
2292 	 */
2293 	nbytes = (cnt + 1) * sizeof (char *);
2294 
2295 	for (n = 0; n < cnt; n++) {
2296 		/*
2297 		 * Get the decoded size of the current encoded string.
2298 		 */
2299 		size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL);
2300 		if (size < DDI_PROP_RESULT_OK) {
2301 			switch (size) {
2302 			case DDI_PROP_RESULT_EOF:
2303 				return (DDI_PROP_END_OF_DATA);
2304 
2305 			case DDI_PROP_RESULT_ERROR:
2306 				return (DDI_PROP_CANNOT_DECODE);
2307 			}
2308 		}
2309 
2310 		nbytes += size;
2311 	}
2312 
2313 	/*
2314 	 * Allocate memory in which to store the decoded strings.
2315 	 */
2316 	strs = ddi_prop_decode_alloc(nbytes, ddi_prop_free_strings);
2317 
2318 	/*
2319 	 * Set up pointers for each string by figuring out yet
2320 	 * again how long each string is.
2321 	 */
2322 	ddi_prop_reset_pos(ph);
2323 	ptr = (caddr_t)strs + ((cnt + 1) * sizeof (char *));
2324 	for (tmp = strs, n = 0; n < cnt; n++, tmp++) {
2325 		/*
2326 		 * Get the decoded size of the current encoded string.
2327 		 */
2328 		size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL);
2329 		if (size < DDI_PROP_RESULT_OK) {
2330 			ddi_prop_free(strs);
2331 			switch (size) {
2332 			case DDI_PROP_RESULT_EOF:
2333 				return (DDI_PROP_END_OF_DATA);
2334 
2335 			case DDI_PROP_RESULT_ERROR:
2336 				return (DDI_PROP_CANNOT_DECODE);
2337 			}
2338 		}
2339 
2340 		*tmp = ptr;
2341 		ptr += size;
2342 	}
2343 
2344 	/*
2345 	 * String array is terminated by a NULL
2346 	 */
2347 	*tmp = NULL;
2348 
2349 	/*
2350 	 * Finally, we can decode each string
2351 	 */
2352 	ddi_prop_reset_pos(ph);
2353 	for (tmp = strs, n = 0; n < cnt; n++, tmp++) {
2354 		i = DDI_PROP_STR(ph, DDI_PROP_CMD_DECODE, *tmp);
2355 		if (i < DDI_PROP_RESULT_OK) {
2356 			/*
2357 			 * Free the space we just allocated
2358 			 * and return an error
2359 			 */
2360 			ddi_prop_free(strs);
2361 			switch (i) {
2362 			case DDI_PROP_RESULT_EOF:
2363 				return (DDI_PROP_END_OF_DATA);
2364 
2365 			case DDI_PROP_RESULT_ERROR:
2366 				return (DDI_PROP_CANNOT_DECODE);
2367 			}
2368 		}
2369 	}
2370 
2371 	*(char ***)data = strs;
2372 	*nelements = cnt;
2373 
2374 	return (DDI_PROP_SUCCESS);
2375 }
2376 
2377 /*
2378  * Encode a string.
2379  */
2380 int
ddi_prop_fm_encode_string(prop_handle_t * ph,void * data,uint_t nelements)2381 ddi_prop_fm_encode_string(prop_handle_t *ph, void *data, uint_t nelements)
2382 {
2383 	char		**tmp;
2384 	int		size;
2385 	int		i;
2386 
2387 	/*
2388 	 * If there is no data, we cannot do anything
2389 	 */
2390 	if (nelements == 0)
2391 		return (DDI_PROP_CANNOT_ENCODE);
2392 
2393 	/*
2394 	 * Get the size of the encoded string.
2395 	 */
2396 	tmp = (char **)data;
2397 	size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_ESIZE, *tmp);
2398 	if (size < DDI_PROP_RESULT_OK) {
2399 		switch (size) {
2400 		case DDI_PROP_RESULT_EOF:
2401 			return (DDI_PROP_END_OF_DATA);
2402 
2403 		case DDI_PROP_RESULT_ERROR:
2404 			return (DDI_PROP_CANNOT_ENCODE);
2405 		}
2406 	}
2407 
2408 	/*
2409 	 * Allocate space in the handle to store the encoded string.
2410 	 */
2411 	if (ddi_prop_encode_alloc(ph, size) != DDI_PROP_SUCCESS)
2412 		return (DDI_PROP_NO_MEMORY);
2413 
2414 	ddi_prop_reset_pos(ph);
2415 
2416 	/*
2417 	 * Encode the string.
2418 	 */
2419 	tmp = (char **)data;
2420 	i = DDI_PROP_STR(ph, DDI_PROP_CMD_ENCODE, *tmp);
2421 	if (i < DDI_PROP_RESULT_OK) {
2422 		switch (i) {
2423 		case DDI_PROP_RESULT_EOF:
2424 			return (DDI_PROP_END_OF_DATA);
2425 
2426 		case DDI_PROP_RESULT_ERROR:
2427 			return (DDI_PROP_CANNOT_ENCODE);
2428 		}
2429 	}
2430 
2431 	return (DDI_PROP_SUCCESS);
2432 }
2433 
2434 
2435 /*
2436  * Encode an array of strings.
2437  */
2438 int
ddi_prop_fm_encode_strings(prop_handle_t * ph,void * data,uint_t nelements)2439 ddi_prop_fm_encode_strings(prop_handle_t *ph, void *data, uint_t nelements)
2440 {
2441 	int		cnt = 0;
2442 	char		**tmp;
2443 	int		size;
2444 	uint_t		total_size;
2445 	int		i;
2446 
2447 	/*
2448 	 * If there is no data, we cannot do anything
2449 	 */
2450 	if (nelements == 0)
2451 		return (DDI_PROP_CANNOT_ENCODE);
2452 
2453 	/*
2454 	 * Get the total size required to encode all the strings.
2455 	 */
2456 	total_size = 0;
2457 	tmp = (char **)data;
2458 	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
2459 		size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_ESIZE, *tmp);
2460 		if (size < DDI_PROP_RESULT_OK) {
2461 			switch (size) {
2462 			case DDI_PROP_RESULT_EOF:
2463 				return (DDI_PROP_END_OF_DATA);
2464 
2465 			case DDI_PROP_RESULT_ERROR:
2466 				return (DDI_PROP_CANNOT_ENCODE);
2467 			}
2468 		}
2469 		total_size += (uint_t)size;
2470 	}
2471 
2472 	/*
2473 	 * Allocate space in the handle to store the encoded strings.
2474 	 */
2475 	if (ddi_prop_encode_alloc(ph, total_size) != DDI_PROP_SUCCESS)
2476 		return (DDI_PROP_NO_MEMORY);
2477 
2478 	ddi_prop_reset_pos(ph);
2479 
2480 	/*
2481 	 * Encode the array of strings.
2482 	 */
2483 	tmp = (char **)data;
2484 	for (cnt = 0; cnt < nelements; cnt++, tmp++) {
2485 		i = DDI_PROP_STR(ph, DDI_PROP_CMD_ENCODE, *tmp);
2486 		if (i < DDI_PROP_RESULT_OK) {
2487 			switch (i) {
2488 			case DDI_PROP_RESULT_EOF:
2489 				return (DDI_PROP_END_OF_DATA);
2490 
2491 			case DDI_PROP_RESULT_ERROR:
2492 				return (DDI_PROP_CANNOT_ENCODE);
2493 			}
2494 		}
2495 	}
2496 
2497 	return (DDI_PROP_SUCCESS);
2498 }
2499 
2500 
2501 /*
2502  * Decode an array of bytes.
2503  */
2504 static int
ddi_prop_fm_decode_bytes(prop_handle_t * ph,void * data,uint_t * nelements)2505 ddi_prop_fm_decode_bytes(prop_handle_t *ph, void *data, uint_t *nelements)
2506 {
2507 	uchar_t		*tmp;
2508 	int		nbytes;
2509 	int		i;
2510 
2511 	/*
2512 	 * If there are no elements return an error
2513 	 */
2514 	if (ph->ph_size == 0)
2515 		return (DDI_PROP_END_OF_DATA);
2516 
2517 	/*
2518 	 * Get the size of the encoded array of bytes.
2519 	 */
2520 	nbytes = DDI_PROP_BYTES(ph, DDI_PROP_CMD_GET_DSIZE,
2521 	    data, ph->ph_size);
2522 	if (nbytes < DDI_PROP_RESULT_OK) {
2523 		switch (nbytes) {
2524 		case DDI_PROP_RESULT_EOF:
2525 			return (DDI_PROP_END_OF_DATA);
2526 
2527 		case DDI_PROP_RESULT_ERROR:
2528 			return (DDI_PROP_CANNOT_DECODE);
2529 		}
2530 	}
2531 
2532 	/*
2533 	 * Allocated memory to store the decoded value in.
2534 	 */
2535 	tmp = ddi_prop_decode_alloc(nbytes, ddi_prop_free_bytes);
2536 
2537 	/*
2538 	 * Decode each element and place it in the space we just allocated
2539 	 */
2540 	i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_DECODE, tmp, nbytes);
2541 	if (i < DDI_PROP_RESULT_OK) {
2542 		/*
2543 		 * Free the space we just allocated
2544 		 * and return an error
2545 		 */
2546 		ddi_prop_free(tmp);
2547 		switch (i) {
2548 		case DDI_PROP_RESULT_EOF:
2549 			return (DDI_PROP_END_OF_DATA);
2550 
2551 		case DDI_PROP_RESULT_ERROR:
2552 			return (DDI_PROP_CANNOT_DECODE);
2553 		}
2554 	}
2555 
2556 	*(uchar_t **)data = tmp;
2557 	*nelements = nbytes;
2558 
2559 	return (DDI_PROP_SUCCESS);
2560 }
2561 
2562 /*
2563  * Encode an array of bytes.
2564  */
2565 int
ddi_prop_fm_encode_bytes(prop_handle_t * ph,void * data,uint_t nelements)2566 ddi_prop_fm_encode_bytes(prop_handle_t *ph, void *data, uint_t nelements)
2567 {
2568 	int		size;
2569 	int		i;
2570 
2571 	/*
2572 	 * If there are no elements, then this is a boolean property,
2573 	 * so just create a property handle with no data and return.
2574 	 */
2575 	if (nelements == 0) {
2576 		(void) ddi_prop_encode_alloc(ph, 0);
2577 		return (DDI_PROP_SUCCESS);
2578 	}
2579 
2580 	/*
2581 	 * Get the size of the encoded array of bytes.
2582 	 */
2583 	size = DDI_PROP_BYTES(ph, DDI_PROP_CMD_GET_ESIZE, (uchar_t *)data,
2584 	    nelements);
2585 	if (size < DDI_PROP_RESULT_OK) {
2586 		switch (size) {
2587 		case DDI_PROP_RESULT_EOF:
2588 			return (DDI_PROP_END_OF_DATA);
2589 
2590 		case DDI_PROP_RESULT_ERROR:
2591 			return (DDI_PROP_CANNOT_DECODE);
2592 		}
2593 	}
2594 
2595 	/*
2596 	 * Allocate space in the handle to store the encoded bytes.
2597 	 */
2598 	if (ddi_prop_encode_alloc(ph, (uint_t)size) != DDI_PROP_SUCCESS)
2599 		return (DDI_PROP_NO_MEMORY);
2600 
2601 	/*
2602 	 * Encode the array of bytes.
2603 	 */
2604 	i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_ENCODE, (uchar_t *)data,
2605 	    nelements);
2606 	if (i < DDI_PROP_RESULT_OK) {
2607 		switch (i) {
2608 		case DDI_PROP_RESULT_EOF:
2609 			return (DDI_PROP_END_OF_DATA);
2610 
2611 		case DDI_PROP_RESULT_ERROR:
2612 			return (DDI_PROP_CANNOT_ENCODE);
2613 		}
2614 	}
2615 
2616 	return (DDI_PROP_SUCCESS);
2617 }
2618 
2619 /*
2620  * OBP 1275 integer, string and byte operators.
2621  *
2622  * DDI_PROP_CMD_DECODE:
2623  *
2624  *	DDI_PROP_RESULT_ERROR:		cannot decode the data
2625  *	DDI_PROP_RESULT_EOF:		end of data
2626  *	DDI_PROP_OK:			data was decoded
2627  *
2628  * DDI_PROP_CMD_ENCODE:
2629  *
2630  *	DDI_PROP_RESULT_ERROR:		cannot encode the data
2631  *	DDI_PROP_RESULT_EOF:		end of data
2632  *	DDI_PROP_OK:			data was encoded
2633  *
2634  * DDI_PROP_CMD_SKIP:
2635  *
2636  *	DDI_PROP_RESULT_ERROR:		cannot skip the data
2637  *	DDI_PROP_RESULT_EOF:		end of data
2638  *	DDI_PROP_OK:			data was skipped
2639  *
2640  * DDI_PROP_CMD_GET_ESIZE:
2641  *
2642  *	DDI_PROP_RESULT_ERROR:		cannot get encoded size
2643  *	DDI_PROP_RESULT_EOF:		end of data
2644  *	> 0:				the encoded size
2645  *
2646  * DDI_PROP_CMD_GET_DSIZE:
2647  *
2648  *	DDI_PROP_RESULT_ERROR:		cannot get decoded size
2649  *	DDI_PROP_RESULT_EOF:		end of data
2650  *	> 0:				the decoded size
2651  */
2652 
2653 /*
2654  * OBP 1275 integer operator
2655  *
2656  * OBP properties are a byte stream of data, so integers may not be
2657  * properly aligned.  Therefore we need to copy them one byte at a time.
2658  */
2659 int
ddi_prop_1275_int(prop_handle_t * ph,uint_t cmd,int * data)2660 ddi_prop_1275_int(prop_handle_t *ph, uint_t cmd, int *data)
2661 {
2662 	int	i;
2663 
2664 	switch (cmd) {
2665 	case DDI_PROP_CMD_DECODE:
2666 		/*
2667 		 * Check that there is encoded data
2668 		 */
2669 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0)
2670 			return (DDI_PROP_RESULT_ERROR);
2671 		if (ph->ph_flags & PH_FROM_PROM) {
2672 			i = MIN(ph->ph_size, PROP_1275_INT_SIZE);
2673 			if ((int *)ph->ph_cur_pos > ((int *)ph->ph_data +
2674 			    ph->ph_size - i))
2675 				return (DDI_PROP_RESULT_ERROR);
2676 		} else {
2677 			if (ph->ph_size < sizeof (int) ||
2678 			    ((int *)ph->ph_cur_pos > ((int *)ph->ph_data +
2679 			    ph->ph_size - sizeof (int))))
2680 				return (DDI_PROP_RESULT_ERROR);
2681 		}
2682 
2683 		/*
2684 		 * Copy the integer, using the implementation-specific
2685 		 * copy function if the property is coming from the PROM.
2686 		 */
2687 		if (ph->ph_flags & PH_FROM_PROM) {
2688 			*data = impl_ddi_prop_int_from_prom(
2689 			    (uchar_t *)ph->ph_cur_pos,
2690 			    (ph->ph_size < PROP_1275_INT_SIZE) ?
2691 			    ph->ph_size : PROP_1275_INT_SIZE);
2692 		} else {
2693 			bcopy(ph->ph_cur_pos, data, sizeof (int));
2694 		}
2695 
2696 		/*
2697 		 * Move the current location to the start of the next
2698 		 * bit of undecoded data.
2699 		 */
2700 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
2701 		    PROP_1275_INT_SIZE;
2702 		return (DDI_PROP_RESULT_OK);
2703 
2704 	case DDI_PROP_CMD_ENCODE:
2705 		/*
2706 		 * Check that there is room to encoded the data
2707 		 */
2708 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
2709 		    ph->ph_size < PROP_1275_INT_SIZE ||
2710 		    ((int *)ph->ph_cur_pos > ((int *)ph->ph_data +
2711 		    ph->ph_size - sizeof (int))))
2712 			return (DDI_PROP_RESULT_ERROR);
2713 
2714 		/*
2715 		 * Encode the integer into the byte stream one byte at a
2716 		 * time.
2717 		 */
2718 		bcopy(data, ph->ph_cur_pos, sizeof (int));
2719 
2720 		/*
2721 		 * Move the current location to the start of the next bit of
2722 		 * space where we can store encoded data.
2723 		 */
2724 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE;
2725 		return (DDI_PROP_RESULT_OK);
2726 
2727 	case DDI_PROP_CMD_SKIP:
2728 		/*
2729 		 * Check that there is encoded data
2730 		 */
2731 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
2732 		    ph->ph_size < PROP_1275_INT_SIZE)
2733 			return (DDI_PROP_RESULT_ERROR);
2734 
2735 
2736 		if ((caddr_t)ph->ph_cur_pos ==
2737 		    (caddr_t)ph->ph_data + ph->ph_size) {
2738 			return (DDI_PROP_RESULT_EOF);
2739 		} else if ((caddr_t)ph->ph_cur_pos >
2740 		    (caddr_t)ph->ph_data + ph->ph_size) {
2741 			return (DDI_PROP_RESULT_EOF);
2742 		}
2743 
2744 		/*
2745 		 * Move the current location to the start of the next bit of
2746 		 * undecoded data.
2747 		 */
2748 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE;
2749 		return (DDI_PROP_RESULT_OK);
2750 
2751 	case DDI_PROP_CMD_GET_ESIZE:
2752 		/*
2753 		 * Return the size of an encoded integer on OBP
2754 		 */
2755 		return (PROP_1275_INT_SIZE);
2756 
2757 	case DDI_PROP_CMD_GET_DSIZE:
2758 		/*
2759 		 * Return the size of a decoded integer on the system.
2760 		 */
2761 		return (sizeof (int));
2762 
2763 	default:
2764 #ifdef DEBUG
2765 		panic("ddi_prop_1275_int: %x impossible", cmd);
2766 		/*NOTREACHED*/
2767 #else
2768 		return (DDI_PROP_RESULT_ERROR);
2769 #endif	/* DEBUG */
2770 	}
2771 }
2772 
2773 /*
2774  * 64 bit integer operator.
2775  *
2776  * This is an extension, defined by Sun, to the 1275 integer
2777  * operator.  This routine handles the encoding/decoding of
2778  * 64 bit integer properties.
2779  */
2780 int
ddi_prop_int64_op(prop_handle_t * ph,uint_t cmd,int64_t * data)2781 ddi_prop_int64_op(prop_handle_t *ph, uint_t cmd, int64_t *data)
2782 {
2783 
2784 	switch (cmd) {
2785 	case DDI_PROP_CMD_DECODE:
2786 		/*
2787 		 * Check that there is encoded data
2788 		 */
2789 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0)
2790 			return (DDI_PROP_RESULT_ERROR);
2791 		if (ph->ph_flags & PH_FROM_PROM) {
2792 			return (DDI_PROP_RESULT_ERROR);
2793 		} else {
2794 			if (ph->ph_size < sizeof (int64_t) ||
2795 			    ((int64_t *)ph->ph_cur_pos >
2796 			    ((int64_t *)ph->ph_data +
2797 			    ph->ph_size - sizeof (int64_t))))
2798 				return (DDI_PROP_RESULT_ERROR);
2799 		}
2800 		/*
2801 		 * Copy the integer, using the implementation-specific
2802 		 * copy function if the property is coming from the PROM.
2803 		 */
2804 		if (ph->ph_flags & PH_FROM_PROM) {
2805 			return (DDI_PROP_RESULT_ERROR);
2806 		} else {
2807 			bcopy(ph->ph_cur_pos, data, sizeof (int64_t));
2808 		}
2809 
2810 		/*
2811 		 * Move the current location to the start of the next
2812 		 * bit of undecoded data.
2813 		 */
2814 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
2815 		    sizeof (int64_t);
2816 		return (DDI_PROP_RESULT_OK);
2817 
2818 	case DDI_PROP_CMD_ENCODE:
2819 		/*
2820 		 * Check that there is room to encoded the data
2821 		 */
2822 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
2823 		    ph->ph_size < sizeof (int64_t) ||
2824 		    ((int64_t *)ph->ph_cur_pos > ((int64_t *)ph->ph_data +
2825 		    ph->ph_size - sizeof (int64_t))))
2826 			return (DDI_PROP_RESULT_ERROR);
2827 
2828 		/*
2829 		 * Encode the integer into the byte stream one byte at a
2830 		 * time.
2831 		 */
2832 		bcopy(data, ph->ph_cur_pos, sizeof (int64_t));
2833 
2834 		/*
2835 		 * Move the current location to the start of the next bit of
2836 		 * space where we can store encoded data.
2837 		 */
2838 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
2839 		    sizeof (int64_t);
2840 		return (DDI_PROP_RESULT_OK);
2841 
2842 	case DDI_PROP_CMD_SKIP:
2843 		/*
2844 		 * Check that there is encoded data
2845 		 */
2846 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
2847 		    ph->ph_size < sizeof (int64_t))
2848 			return (DDI_PROP_RESULT_ERROR);
2849 
2850 		if ((caddr_t)ph->ph_cur_pos ==
2851 		    (caddr_t)ph->ph_data + ph->ph_size) {
2852 			return (DDI_PROP_RESULT_EOF);
2853 		} else if ((caddr_t)ph->ph_cur_pos >
2854 		    (caddr_t)ph->ph_data + ph->ph_size) {
2855 			return (DDI_PROP_RESULT_EOF);
2856 		}
2857 
2858 		/*
2859 		 * Move the current location to the start of
2860 		 * the next bit of undecoded data.
2861 		 */
2862 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
2863 		    sizeof (int64_t);
2864 		return (DDI_PROP_RESULT_OK);
2865 
2866 	case DDI_PROP_CMD_GET_ESIZE:
2867 		/*
2868 		 * Return the size of an encoded integer on OBP
2869 		 */
2870 		return (sizeof (int64_t));
2871 
2872 	case DDI_PROP_CMD_GET_DSIZE:
2873 		/*
2874 		 * Return the size of a decoded integer on the system.
2875 		 */
2876 		return (sizeof (int64_t));
2877 
2878 	default:
2879 #ifdef DEBUG
2880 		panic("ddi_prop_int64_op: %x impossible", cmd);
2881 		/*NOTREACHED*/
2882 #else
2883 		return (DDI_PROP_RESULT_ERROR);
2884 #endif  /* DEBUG */
2885 	}
2886 }
2887 
2888 /*
2889  * OBP 1275 string operator.
2890  *
2891  * OBP strings are NULL terminated.
2892  */
2893 int
ddi_prop_1275_string(prop_handle_t * ph,uint_t cmd,char * data)2894 ddi_prop_1275_string(prop_handle_t *ph, uint_t cmd, char *data)
2895 {
2896 	int	n;
2897 	char	*p;
2898 	char	*end;
2899 
2900 	switch (cmd) {
2901 	case DDI_PROP_CMD_DECODE:
2902 		/*
2903 		 * Check that there is encoded data
2904 		 */
2905 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0) {
2906 			return (DDI_PROP_RESULT_ERROR);
2907 		}
2908 
2909 		/*
2910 		 * Match DDI_PROP_CMD_GET_DSIZE logic for when to stop and
2911 		 * how to NULL terminate result.
2912 		 */
2913 		p = (char *)ph->ph_cur_pos;
2914 		end = (char *)ph->ph_data + ph->ph_size;
2915 		if (p >= end)
2916 			return (DDI_PROP_RESULT_EOF);
2917 
2918 		while (p < end) {
2919 			*data++ = *p;
2920 			if (*p++ == 0) {	/* NULL from OBP */
2921 				ph->ph_cur_pos = p;
2922 				return (DDI_PROP_RESULT_OK);
2923 			}
2924 		}
2925 
2926 		/*
2927 		 * If OBP did not NULL terminate string, which happens
2928 		 * (at least) for 'true'/'false' boolean values, account for
2929 		 * the space and store null termination on decode.
2930 		 */
2931 		ph->ph_cur_pos = p;
2932 		*data = 0;
2933 		return (DDI_PROP_RESULT_OK);
2934 
2935 	case DDI_PROP_CMD_ENCODE:
2936 		/*
2937 		 * Check that there is room to encoded the data
2938 		 */
2939 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0) {
2940 			return (DDI_PROP_RESULT_ERROR);
2941 		}
2942 
2943 		n = strlen(data) + 1;
2944 		if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
2945 		    ph->ph_size - n)) {
2946 			return (DDI_PROP_RESULT_ERROR);
2947 		}
2948 
2949 		/*
2950 		 * Copy the NULL terminated string
2951 		 */
2952 		bcopy(data, ph->ph_cur_pos, n);
2953 
2954 		/*
2955 		 * Move the current location to the start of the next bit of
2956 		 * space where we can store encoded data.
2957 		 */
2958 		ph->ph_cur_pos = (char *)ph->ph_cur_pos + n;
2959 		return (DDI_PROP_RESULT_OK);
2960 
2961 	case DDI_PROP_CMD_SKIP:
2962 		/*
2963 		 * Check that there is encoded data
2964 		 */
2965 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0) {
2966 			return (DDI_PROP_RESULT_ERROR);
2967 		}
2968 
2969 		/*
2970 		 * Return the string length plus one for the NULL
2971 		 * We know the size of the property, we need to
2972 		 * ensure that the string is properly formatted,
2973 		 * since we may be looking up random OBP data.
2974 		 */
2975 		p = (char *)ph->ph_cur_pos;
2976 		end = (char *)ph->ph_data + ph->ph_size;
2977 		if (p >= end)
2978 			return (DDI_PROP_RESULT_EOF);
2979 
2980 		while (p < end) {
2981 			if (*p++ == 0) {	/* NULL from OBP */
2982 				ph->ph_cur_pos = p;
2983 				return (DDI_PROP_RESULT_OK);
2984 			}
2985 		}
2986 
2987 		/*
2988 		 * Accommodate the fact that OBP does not always NULL
2989 		 * terminate strings.
2990 		 */
2991 		ph->ph_cur_pos = p;
2992 		return (DDI_PROP_RESULT_OK);
2993 
2994 	case DDI_PROP_CMD_GET_ESIZE:
2995 		/*
2996 		 * Return the size of the encoded string on OBP.
2997 		 */
2998 		return (strlen(data) + 1);
2999 
3000 	case DDI_PROP_CMD_GET_DSIZE:
3001 		/*
3002 		 * Return the string length plus one for the NULL.
3003 		 * We know the size of the property, we need to
3004 		 * ensure that the string is properly formatted,
3005 		 * since we may be looking up random OBP data.
3006 		 */
3007 		p = (char *)ph->ph_cur_pos;
3008 		end = (char *)ph->ph_data + ph->ph_size;
3009 		if (p >= end)
3010 			return (DDI_PROP_RESULT_EOF);
3011 
3012 		for (n = 0; p < end; n++) {
3013 			if (*p++ == 0) {	/* NULL from OBP */
3014 				ph->ph_cur_pos = p;
3015 				return (n + 1);
3016 			}
3017 		}
3018 
3019 		/*
3020 		 * If OBP did not NULL terminate string, which happens for
3021 		 * 'true'/'false' boolean values, account for the space
3022 		 * to store null termination here.
3023 		 */
3024 		ph->ph_cur_pos = p;
3025 		return (n + 1);
3026 
3027 	default:
3028 #ifdef DEBUG
3029 		panic("ddi_prop_1275_string: %x impossible", cmd);
3030 		/*NOTREACHED*/
3031 #else
3032 		return (DDI_PROP_RESULT_ERROR);
3033 #endif	/* DEBUG */
3034 	}
3035 }
3036 
3037 /*
3038  * OBP 1275 byte operator
3039  *
3040  * Caller must specify the number of bytes to get.  OBP encodes bytes
3041  * as a byte so there is a 1-to-1 translation.
3042  */
3043 int
ddi_prop_1275_bytes(prop_handle_t * ph,uint_t cmd,uchar_t * data,uint_t nelements)3044 ddi_prop_1275_bytes(prop_handle_t *ph, uint_t cmd, uchar_t *data,
3045     uint_t nelements)
3046 {
3047 	switch (cmd) {
3048 	case DDI_PROP_CMD_DECODE:
3049 		/*
3050 		 * Check that there is encoded data
3051 		 */
3052 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
3053 		    ph->ph_size < nelements ||
3054 		    ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
3055 		    ph->ph_size - nelements)))
3056 			return (DDI_PROP_RESULT_ERROR);
3057 
3058 		/*
3059 		 * Copy out the bytes
3060 		 */
3061 		bcopy(ph->ph_cur_pos, data, nelements);
3062 
3063 		/*
3064 		 * Move the current location
3065 		 */
3066 		ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements;
3067 		return (DDI_PROP_RESULT_OK);
3068 
3069 	case DDI_PROP_CMD_ENCODE:
3070 		/*
3071 		 * Check that there is room to encode the data
3072 		 */
3073 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
3074 		    ph->ph_size < nelements ||
3075 		    ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
3076 		    ph->ph_size - nelements)))
3077 			return (DDI_PROP_RESULT_ERROR);
3078 
3079 		/*
3080 		 * Copy in the bytes
3081 		 */
3082 		bcopy(data, ph->ph_cur_pos, nelements);
3083 
3084 		/*
3085 		 * Move the current location to the start of the next bit of
3086 		 * space where we can store encoded data.
3087 		 */
3088 		ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements;
3089 		return (DDI_PROP_RESULT_OK);
3090 
3091 	case DDI_PROP_CMD_SKIP:
3092 		/*
3093 		 * Check that there is encoded data
3094 		 */
3095 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
3096 		    ph->ph_size < nelements)
3097 			return (DDI_PROP_RESULT_ERROR);
3098 
3099 		if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
3100 		    ph->ph_size - nelements))
3101 			return (DDI_PROP_RESULT_EOF);
3102 
3103 		/*
3104 		 * Move the current location
3105 		 */
3106 		ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements;
3107 		return (DDI_PROP_RESULT_OK);
3108 
3109 	case DDI_PROP_CMD_GET_ESIZE:
3110 		/*
3111 		 * The size in bytes of the encoded size is the
3112 		 * same as the decoded size provided by the caller.
3113 		 */
3114 		return (nelements);
3115 
3116 	case DDI_PROP_CMD_GET_DSIZE:
3117 		/*
3118 		 * Just return the number of bytes specified by the caller.
3119 		 */
3120 		return (nelements);
3121 
3122 	default:
3123 #ifdef DEBUG
3124 		panic("ddi_prop_1275_bytes: %x impossible", cmd);
3125 		/*NOTREACHED*/
3126 #else
3127 		return (DDI_PROP_RESULT_ERROR);
3128 #endif	/* DEBUG */
3129 	}
3130 }
3131 
3132 /*
3133  * Used for properties that come from the OBP, hardware configuration files,
3134  * or that are created by calls to ddi_prop_update(9F).
3135  */
3136 static struct prop_handle_ops prop_1275_ops = {
3137 	ddi_prop_1275_int,
3138 	ddi_prop_1275_string,
3139 	ddi_prop_1275_bytes,
3140 	ddi_prop_int64_op
3141 };
3142 
3143 
3144 /*
3145  * Interface to create/modify a managed property on child's behalf...
3146  * Flags interpreted are:
3147  *	DDI_PROP_CANSLEEP:	Allow memory allocation to sleep.
3148  *	DDI_PROP_SYSTEM_DEF:	Manipulate system list rather than driver list.
3149  *
3150  * Use same dev_t when modifying or undefining a property.
3151  * Search for properties with DDI_DEV_T_ANY to match first named
3152  * property on the list.
3153  *
3154  * Properties are stored LIFO and subsequently will match the first
3155  * `matching' instance.
3156  */
3157 
3158 /*
3159  * ddi_prop_add:	Add a software defined property
3160  */
3161 
3162 /*
3163  * define to get a new ddi_prop_t.
3164  * km_flags are KM_SLEEP or KM_NOSLEEP.
3165  */
3166 
3167 #define	DDI_NEW_PROP_T(km_flags)	\
3168 	(kmem_zalloc(sizeof (ddi_prop_t), km_flags))
3169 
3170 static int
ddi_prop_add(dev_t dev,dev_info_t * dip,int flags,char * name,caddr_t value,int length)3171 ddi_prop_add(dev_t dev, dev_info_t *dip, int flags,
3172     char *name, caddr_t value, int length)
3173 {
3174 	ddi_prop_t	*new_propp, *propp;
3175 	ddi_prop_t	**list_head = &(DEVI(dip)->devi_drv_prop_ptr);
3176 	int		km_flags = KM_NOSLEEP;
3177 	int		name_buf_len;
3178 
3179 	/*
3180 	 * If dev_t is DDI_DEV_T_ANY or name's length is zero return error.
3181 	 */
3182 
3183 	if (dev == DDI_DEV_T_ANY || name == (char *)0 || strlen(name) == 0)
3184 		return (DDI_PROP_INVAL_ARG);
3185 
3186 	if (flags & DDI_PROP_CANSLEEP)
3187 		km_flags = KM_SLEEP;
3188 
3189 	if (flags & DDI_PROP_SYSTEM_DEF)
3190 		list_head = &(DEVI(dip)->devi_sys_prop_ptr);
3191 	else if (flags & DDI_PROP_HW_DEF)
3192 		list_head = &(DEVI(dip)->devi_hw_prop_ptr);
3193 
3194 	if ((new_propp = DDI_NEW_PROP_T(km_flags)) == NULL)  {
3195 		cmn_err(CE_CONT, prop_no_mem_msg, name);
3196 		return (DDI_PROP_NO_MEMORY);
3197 	}
3198 
3199 	/*
3200 	 * If dev is major number 0, then we need to do a ddi_name_to_major
3201 	 * to get the real major number for the device.  This needs to be
3202 	 * done because some drivers need to call ddi_prop_create in their
3203 	 * attach routines but they don't have a dev.  By creating the dev
3204 	 * ourself if the major number is 0, drivers will not have to know what
3205 	 * their major number.	They can just create a dev with major number
3206 	 * 0 and pass it in.  For device 0, we will be doing a little extra
3207 	 * work by recreating the same dev that we already have, but its the
3208 	 * price you pay :-).
3209 	 *
3210 	 * This fixes bug #1098060.
3211 	 */
3212 	if (getmajor(dev) == DDI_MAJOR_T_UNKNOWN) {
3213 		new_propp->prop_dev =
3214 		    makedevice(ddi_name_to_major(DEVI(dip)->devi_binding_name),
3215 		    getminor(dev));
3216 	} else
3217 		new_propp->prop_dev = dev;
3218 
3219 	/*
3220 	 * Allocate space for property name and copy it in...
3221 	 */
3222 
3223 	name_buf_len = strlen(name) + 1;
3224 	new_propp->prop_name = kmem_alloc(name_buf_len, km_flags);
3225 	if (new_propp->prop_name == 0)	{
3226 		kmem_free(new_propp, sizeof (ddi_prop_t));
3227 		cmn_err(CE_CONT, prop_no_mem_msg, name);
3228 		return (DDI_PROP_NO_MEMORY);
3229 	}
3230 	bcopy(name, new_propp->prop_name, name_buf_len);
3231 
3232 	/*
3233 	 * Set the property type
3234 	 */
3235 	new_propp->prop_flags = flags & DDI_PROP_TYPE_MASK;
3236 
3237 	/*
3238 	 * Set length and value ONLY if not an explicit property undefine:
3239 	 * NOTE: value and length are zero for explicit undefines.
3240 	 */
3241 
3242 	if (flags & DDI_PROP_UNDEF_IT) {
3243 		new_propp->prop_flags |= DDI_PROP_UNDEF_IT;
3244 	} else {
3245 		if ((new_propp->prop_len = length) != 0) {
3246 			new_propp->prop_val = kmem_alloc(length, km_flags);
3247 			if (new_propp->prop_val == 0)  {
3248 				kmem_free(new_propp->prop_name, name_buf_len);
3249 				kmem_free(new_propp, sizeof (ddi_prop_t));
3250 				cmn_err(CE_CONT, prop_no_mem_msg, name);
3251 				return (DDI_PROP_NO_MEMORY);
3252 			}
3253 			bcopy(value, new_propp->prop_val, length);
3254 		}
3255 	}
3256 
3257 	/*
3258 	 * Link property into beginning of list. (Properties are LIFO order.)
3259 	 */
3260 
3261 	mutex_enter(&(DEVI(dip)->devi_lock));
3262 	propp = *list_head;
3263 	new_propp->prop_next = propp;
3264 	*list_head = new_propp;
3265 	mutex_exit(&(DEVI(dip)->devi_lock));
3266 	return (DDI_PROP_SUCCESS);
3267 }
3268 
3269 
3270 /*
3271  * ddi_prop_change:	Modify a software managed property value
3272  *
3273  *			Set new length and value if found.
3274  *			returns DDI_PROP_INVAL_ARG if dev is DDI_DEV_T_ANY or
3275  *			input name is the NULL string.
3276  *			returns DDI_PROP_NO_MEMORY if unable to allocate memory
3277  *
3278  *			Note: an undef can be modified to be a define,
3279  *			(you can't go the other way.)
3280  */
3281 
3282 static int
ddi_prop_change(dev_t dev,dev_info_t * dip,int flags,char * name,caddr_t value,int length)3283 ddi_prop_change(dev_t dev, dev_info_t *dip, int flags,
3284     char *name, caddr_t value, int length)
3285 {
3286 	ddi_prop_t	*propp;
3287 	ddi_prop_t	**ppropp;
3288 	caddr_t		p = NULL;
3289 
3290 	if ((dev == DDI_DEV_T_ANY) || (name == NULL) || (strlen(name) == 0))
3291 		return (DDI_PROP_INVAL_ARG);
3292 
3293 	/*
3294 	 * Preallocate buffer, even if we don't need it...
3295 	 */
3296 	if (length != 0)  {
3297 		p = kmem_alloc(length, (flags & DDI_PROP_CANSLEEP) ?
3298 		    KM_SLEEP : KM_NOSLEEP);
3299 		if (p == NULL)	{
3300 			cmn_err(CE_CONT, prop_no_mem_msg, name);
3301 			return (DDI_PROP_NO_MEMORY);
3302 		}
3303 	}
3304 
3305 	/*
3306 	 * If the dev_t value contains DDI_MAJOR_T_UNKNOWN for the major
3307 	 * number, a real dev_t value should be created based upon the dip's
3308 	 * binding driver.  See ddi_prop_add...
3309 	 */
3310 	if (getmajor(dev) == DDI_MAJOR_T_UNKNOWN)
3311 		dev = makedevice(
3312 		    ddi_name_to_major(DEVI(dip)->devi_binding_name),
3313 		    getminor(dev));
3314 
3315 	/*
3316 	 * Check to see if the property exists.  If so we modify it.
3317 	 * Else we create it by calling ddi_prop_add().
3318 	 */
3319 	mutex_enter(&(DEVI(dip)->devi_lock));
3320 	ppropp = &DEVI(dip)->devi_drv_prop_ptr;
3321 	if (flags & DDI_PROP_SYSTEM_DEF)
3322 		ppropp = &DEVI(dip)->devi_sys_prop_ptr;
3323 	else if (flags & DDI_PROP_HW_DEF)
3324 		ppropp = &DEVI(dip)->devi_hw_prop_ptr;
3325 
3326 	if ((propp = i_ddi_prop_search(dev, name, flags, ppropp)) != NULL) {
3327 		/*
3328 		 * Need to reallocate buffer?  If so, do it
3329 		 * carefully (reuse same space if new prop
3330 		 * is same size and non-NULL sized).
3331 		 */
3332 		if (length != 0)
3333 			bcopy(value, p, length);
3334 
3335 		if (propp->prop_len != 0)
3336 			kmem_free(propp->prop_val, propp->prop_len);
3337 
3338 		propp->prop_len = length;
3339 		propp->prop_val = p;
3340 		propp->prop_flags &= ~DDI_PROP_UNDEF_IT;
3341 		mutex_exit(&(DEVI(dip)->devi_lock));
3342 		return (DDI_PROP_SUCCESS);
3343 	}
3344 
3345 	mutex_exit(&(DEVI(dip)->devi_lock));
3346 	if (length != 0)
3347 		kmem_free(p, length);
3348 
3349 	return (ddi_prop_add(dev, dip, flags, name, value, length));
3350 }
3351 
3352 /*
3353  * Common update routine used to update and encode a property.	Creates
3354  * a property handle, calls the property encode routine, figures out if
3355  * the property already exists and updates if it does.	Otherwise it
3356  * creates if it does not exist.
3357  */
3358 int
ddi_prop_update_common(dev_t match_dev,dev_info_t * dip,int flags,char * name,void * data,uint_t nelements,int (* prop_create)(prop_handle_t *,void * data,uint_t nelements))3359 ddi_prop_update_common(dev_t match_dev, dev_info_t *dip, int flags,
3360     char *name, void *data, uint_t nelements,
3361     int (*prop_create)(prop_handle_t *, void *data, uint_t nelements))
3362 {
3363 	prop_handle_t	ph;
3364 	int		rval;
3365 	uint_t		ourflags;
3366 
3367 	/*
3368 	 * If dev_t is DDI_DEV_T_ANY or name's length is zero,
3369 	 * return error.
3370 	 */
3371 	if (match_dev == DDI_DEV_T_ANY || name == NULL || strlen(name) == 0)
3372 		return (DDI_PROP_INVAL_ARG);
3373 
3374 	/*
3375 	 * Create the handle
3376 	 */
3377 	ph.ph_data = NULL;
3378 	ph.ph_cur_pos = NULL;
3379 	ph.ph_save_pos = NULL;
3380 	ph.ph_size = 0;
3381 	ph.ph_ops = &prop_1275_ops;
3382 
3383 	/*
3384 	 * ourflags:
3385 	 * For compatibility with the old interfaces.  The old interfaces
3386 	 * didn't sleep by default and slept when the flag was set.  These
3387 	 * interfaces to the opposite.	So the old interfaces now set the
3388 	 * DDI_PROP_DONTSLEEP flag by default which tells us not to sleep.
3389 	 *
3390 	 * ph.ph_flags:
3391 	 * Blocked data or unblocked data allocation
3392 	 * for ph.ph_data in ddi_prop_encode_alloc()
3393 	 */
3394 	if (flags & DDI_PROP_DONTSLEEP) {
3395 		ourflags = flags;
3396 		ph.ph_flags = DDI_PROP_DONTSLEEP;
3397 	} else {
3398 		ourflags = flags | DDI_PROP_CANSLEEP;
3399 		ph.ph_flags = DDI_PROP_CANSLEEP;
3400 	}
3401 
3402 	/*
3403 	 * Encode the data and store it in the property handle by
3404 	 * calling the prop_encode routine.
3405 	 */
3406 	if ((rval = (*prop_create)(&ph, data, nelements)) !=
3407 	    DDI_PROP_SUCCESS) {
3408 		if (rval == DDI_PROP_NO_MEMORY)
3409 			cmn_err(CE_CONT, prop_no_mem_msg, name);
3410 		if (ph.ph_size != 0)
3411 			kmem_free(ph.ph_data, ph.ph_size);
3412 		return (rval);
3413 	}
3414 
3415 	/*
3416 	 * The old interfaces use a stacking approach to creating
3417 	 * properties.	If we are being called from the old interfaces,
3418 	 * the DDI_PROP_STACK_CREATE flag will be set, so we just do a
3419 	 * create without checking.
3420 	 */
3421 	if (flags & DDI_PROP_STACK_CREATE) {
3422 		rval = ddi_prop_add(match_dev, dip,
3423 		    ourflags, name, ph.ph_data, ph.ph_size);
3424 	} else {
3425 		rval = ddi_prop_change(match_dev, dip,
3426 		    ourflags, name, ph.ph_data, ph.ph_size);
3427 	}
3428 
3429 	/*
3430 	 * Free the encoded data allocated in the prop_encode routine.
3431 	 */
3432 	if (ph.ph_size != 0)
3433 		kmem_free(ph.ph_data, ph.ph_size);
3434 
3435 	return (rval);
3436 }
3437 
3438 
3439 /*
3440  * ddi_prop_create:	Define a managed property:
3441  *			See above for details.
3442  */
3443 
3444 int
ddi_prop_create(dev_t dev,dev_info_t * dip,int flag,char * name,caddr_t value,int length)3445 ddi_prop_create(dev_t dev, dev_info_t *dip, int flag,
3446     char *name, caddr_t value, int length)
3447 {
3448 	if (!(flag & DDI_PROP_CANSLEEP)) {
3449 		flag |= DDI_PROP_DONTSLEEP;
3450 #ifdef DDI_PROP_DEBUG
3451 		if (length != 0)
3452 			cmn_err(CE_NOTE, "!ddi_prop_create: interface obsolete,"
3453 			    "use ddi_prop_update (prop = %s, node = %s%d)",
3454 			    name, ddi_driver_name(dip), ddi_get_instance(dip));
3455 #endif /* DDI_PROP_DEBUG */
3456 	}
3457 	flag &= ~DDI_PROP_SYSTEM_DEF;
3458 	flag |= DDI_PROP_STACK_CREATE | DDI_PROP_TYPE_ANY;
3459 	return (ddi_prop_update_common(dev, dip, flag, name,
3460 	    value, length, ddi_prop_fm_encode_bytes));
3461 }
3462 
3463 int
e_ddi_prop_create(dev_t dev,dev_info_t * dip,int flag,char * name,caddr_t value,int length)3464 e_ddi_prop_create(dev_t dev, dev_info_t *dip, int flag,
3465     char *name, caddr_t value, int length)
3466 {
3467 	if (!(flag & DDI_PROP_CANSLEEP))
3468 		flag |= DDI_PROP_DONTSLEEP;
3469 	flag |= DDI_PROP_SYSTEM_DEF | DDI_PROP_STACK_CREATE | DDI_PROP_TYPE_ANY;
3470 	return (ddi_prop_update_common(dev, dip, flag,
3471 	    name, value, length, ddi_prop_fm_encode_bytes));
3472 }
3473 
3474 int
ddi_prop_modify(dev_t dev,dev_info_t * dip,int flag,char * name,caddr_t value,int length)3475 ddi_prop_modify(dev_t dev, dev_info_t *dip, int flag,
3476     char *name, caddr_t value, int length)
3477 {
3478 	ASSERT((flag & DDI_PROP_TYPE_MASK) == 0);
3479 
3480 	/*
3481 	 * If dev_t is DDI_DEV_T_ANY or name's length is zero,
3482 	 * return error.
3483 	 */
3484 	if (dev == DDI_DEV_T_ANY || name == NULL || strlen(name) == 0)
3485 		return (DDI_PROP_INVAL_ARG);
3486 
3487 	if (!(flag & DDI_PROP_CANSLEEP))
3488 		flag |= DDI_PROP_DONTSLEEP;
3489 	flag &= ~DDI_PROP_SYSTEM_DEF;
3490 	if (ddi_prop_exists(dev, dip, (flag | DDI_PROP_NOTPROM), name) == 0)
3491 		return (DDI_PROP_NOT_FOUND);
3492 
3493 	return (ddi_prop_update_common(dev, dip,
3494 	    (flag | DDI_PROP_TYPE_BYTE), name,
3495 	    value, length, ddi_prop_fm_encode_bytes));
3496 }
3497 
3498 int
e_ddi_prop_modify(dev_t dev,dev_info_t * dip,int flag,char * name,caddr_t value,int length)3499 e_ddi_prop_modify(dev_t dev, dev_info_t *dip, int flag,
3500     char *name, caddr_t value, int length)
3501 {
3502 	ASSERT((flag & DDI_PROP_TYPE_MASK) == 0);
3503 
3504 	/*
3505 	 * If dev_t is DDI_DEV_T_ANY or name's length is zero,
3506 	 * return error.
3507 	 */
3508 	if (dev == DDI_DEV_T_ANY || name == NULL || strlen(name) == 0)
3509 		return (DDI_PROP_INVAL_ARG);
3510 
3511 	if (ddi_prop_exists(dev, dip, (flag | DDI_PROP_SYSTEM_DEF), name) == 0)
3512 		return (DDI_PROP_NOT_FOUND);
3513 
3514 	if (!(flag & DDI_PROP_CANSLEEP))
3515 		flag |= DDI_PROP_DONTSLEEP;
3516 	return (ddi_prop_update_common(dev, dip,
3517 	    (flag | DDI_PROP_SYSTEM_DEF | DDI_PROP_TYPE_BYTE),
3518 	    name, value, length, ddi_prop_fm_encode_bytes));
3519 }
3520 
3521 
3522 /*
3523  * Common lookup routine used to lookup and decode a property.
3524  * Creates a property handle, searches for the raw encoded data,
3525  * fills in the handle, and calls the property decode functions
3526  * passed in.
3527  *
3528  * This routine is not static because ddi_bus_prop_op() which lives in
3529  * ddi_impl.c calls it.  No driver should be calling this routine.
3530  */
3531 int
ddi_prop_lookup_common(dev_t match_dev,dev_info_t * dip,uint_t flags,char * name,void * data,uint_t * nelements,int (* prop_decoder)(prop_handle_t *,void * data,uint_t * nelements))3532 ddi_prop_lookup_common(dev_t match_dev, dev_info_t *dip,
3533     uint_t flags, char *name, void *data, uint_t *nelements,
3534     int (*prop_decoder)(prop_handle_t *, void *data, uint_t *nelements))
3535 {
3536 	int		rval;
3537 	uint_t		ourflags;
3538 	prop_handle_t	ph;
3539 
3540 	if ((match_dev == DDI_DEV_T_NONE) ||
3541 	    (name == NULL) || (strlen(name) == 0))
3542 		return (DDI_PROP_INVAL_ARG);
3543 
3544 	ourflags = (flags & DDI_PROP_DONTSLEEP) ? flags :
3545 	    flags | DDI_PROP_CANSLEEP;
3546 
3547 	/*
3548 	 * Get the encoded data
3549 	 */
3550 	bzero(&ph, sizeof (prop_handle_t));
3551 
3552 	if ((flags & DDI_UNBND_DLPI2) || (flags & DDI_PROP_ROOTNEX_GLOBAL)) {
3553 		/*
3554 		 * For rootnex and unbound dlpi style-2 devices, index into
3555 		 * the devnames' array and search the global
3556 		 * property list.
3557 		 */
3558 		ourflags &= ~DDI_UNBND_DLPI2;
3559 		rval = i_ddi_prop_search_global(match_dev,
3560 		    ourflags, name, &ph.ph_data, &ph.ph_size);
3561 	} else {
3562 		rval = ddi_prop_search_common(match_dev, dip,
3563 		    PROP_LEN_AND_VAL_ALLOC, ourflags, name,
3564 		    &ph.ph_data, &ph.ph_size);
3565 
3566 	}
3567 
3568 	if (rval != DDI_PROP_SUCCESS && rval != DDI_PROP_FOUND_1275) {
3569 		ASSERT(ph.ph_data == NULL);
3570 		ASSERT(ph.ph_size == 0);
3571 		return (rval);
3572 	}
3573 
3574 	/*
3575 	 * If the encoded data came from a OBP or software
3576 	 * use the 1275 OBP decode/encode routines.
3577 	 */
3578 	ph.ph_cur_pos = ph.ph_data;
3579 	ph.ph_save_pos = ph.ph_data;
3580 	ph.ph_ops = &prop_1275_ops;
3581 	ph.ph_flags = (rval == DDI_PROP_FOUND_1275) ? PH_FROM_PROM : 0;
3582 
3583 	rval = (*prop_decoder)(&ph, data, nelements);
3584 
3585 	/*
3586 	 * Free the encoded data
3587 	 */
3588 	if (ph.ph_size != 0)
3589 		kmem_free(ph.ph_data, ph.ph_size);
3590 
3591 	return (rval);
3592 }
3593 
3594 /*
3595  * Lookup and return an array of composite properties.  The driver must
3596  * provide the decode routine.
3597  */
3598 int
ddi_prop_lookup(dev_t match_dev,dev_info_t * dip,uint_t flags,char * name,void * data,uint_t * nelements,int (* prop_decoder)(prop_handle_t *,void * data,uint_t * nelements))3599 ddi_prop_lookup(dev_t match_dev, dev_info_t *dip,
3600     uint_t flags, char *name, void *data, uint_t *nelements,
3601     int (*prop_decoder)(prop_handle_t *, void *data, uint_t *nelements))
3602 {
3603 	return (ddi_prop_lookup_common(match_dev, dip,
3604 	    (flags | DDI_PROP_TYPE_COMPOSITE), name,
3605 	    data, nelements, prop_decoder));
3606 }
3607 
3608 /*
3609  * Return 1 if a property exists (no type checking done).
3610  * Return 0 if it does not exist.
3611  */
3612 int
ddi_prop_exists(dev_t match_dev,dev_info_t * dip,uint_t flags,char * name)3613 ddi_prop_exists(dev_t match_dev, dev_info_t *dip, uint_t flags, char *name)
3614 {
3615 	int	i;
3616 	uint_t	x = 0;
3617 
3618 	i = ddi_prop_search_common(match_dev, dip, PROP_EXISTS,
3619 	    flags | DDI_PROP_TYPE_MASK, name, NULL, &x);
3620 	return (i == DDI_PROP_SUCCESS || i == DDI_PROP_FOUND_1275);
3621 }
3622 
3623 
3624 /*
3625  * Update an array of composite properties.  The driver must
3626  * provide the encode routine.
3627  */
3628 int
ddi_prop_update(dev_t match_dev,dev_info_t * dip,char * name,void * data,uint_t nelements,int (* prop_create)(prop_handle_t *,void * data,uint_t nelements))3629 ddi_prop_update(dev_t match_dev, dev_info_t *dip,
3630     char *name, void *data, uint_t nelements,
3631     int (*prop_create)(prop_handle_t *, void *data, uint_t nelements))
3632 {
3633 	return (ddi_prop_update_common(match_dev, dip, DDI_PROP_TYPE_COMPOSITE,
3634 	    name, data, nelements, prop_create));
3635 }
3636 
3637 /*
3638  * Get a single integer or boolean property and return it.
3639  * If the property does not exists, or cannot be decoded,
3640  * then return the defvalue passed in.
3641  *
3642  * This routine always succeeds.
3643  */
3644 int
ddi_prop_get_int(dev_t match_dev,dev_info_t * dip,uint_t flags,char * name,int defvalue)3645 ddi_prop_get_int(dev_t match_dev, dev_info_t *dip, uint_t flags,
3646     char *name, int defvalue)
3647 {
3648 	int	data;
3649 	uint_t	nelements;
3650 	int	rval;
3651 
3652 	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3653 	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
3654 #ifdef DEBUG
3655 		if (dip != NULL) {
3656 			cmn_err(CE_WARN, "ddi_prop_get_int: invalid flag"
3657 			    " 0x%x (prop = %s, node = %s%d)", flags,
3658 			    name, ddi_driver_name(dip), ddi_get_instance(dip));
3659 		}
3660 #endif /* DEBUG */
3661 		flags &= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3662 		    LDI_DEV_T_ANY | DDI_UNBND_DLPI2;
3663 	}
3664 
3665 	if ((rval = ddi_prop_lookup_common(match_dev, dip,
3666 	    (flags | DDI_PROP_TYPE_INT), name, &data, &nelements,
3667 	    ddi_prop_fm_decode_int)) != DDI_PROP_SUCCESS) {
3668 		if (rval == DDI_PROP_END_OF_DATA)
3669 			data = 1;
3670 		else
3671 			data = defvalue;
3672 	}
3673 	return (data);
3674 }
3675 
3676 /*
3677  * Get a single 64 bit integer or boolean property and return it.
3678  * If the property does not exists, or cannot be decoded,
3679  * then return the defvalue passed in.
3680  *
3681  * This routine always succeeds.
3682  */
3683 int64_t
ddi_prop_get_int64(dev_t match_dev,dev_info_t * dip,uint_t flags,char * name,int64_t defvalue)3684 ddi_prop_get_int64(dev_t match_dev, dev_info_t *dip, uint_t flags,
3685     char *name, int64_t defvalue)
3686 {
3687 	int64_t	data;
3688 	uint_t	nelements;
3689 	int	rval;
3690 
3691 	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3692 	    LDI_DEV_T_ANY | DDI_UNBND_DLPI2 | DDI_PROP_ROOTNEX_GLOBAL)) {
3693 #ifdef DEBUG
3694 		if (dip != NULL) {
3695 			cmn_err(CE_WARN, "ddi_prop_get_int64: invalid flag"
3696 			    " 0x%x (prop = %s, node = %s%d)", flags,
3697 			    name, ddi_driver_name(dip), ddi_get_instance(dip));
3698 		}
3699 #endif /* DEBUG */
3700 		return (DDI_PROP_INVAL_ARG);
3701 	}
3702 
3703 	if ((rval = ddi_prop_lookup_common(match_dev, dip,
3704 	    (flags | DDI_PROP_TYPE_INT64 | DDI_PROP_NOTPROM),
3705 	    name, &data, &nelements, ddi_prop_fm_decode_int64))
3706 	    != DDI_PROP_SUCCESS) {
3707 		if (rval == DDI_PROP_END_OF_DATA)
3708 			data = 1;
3709 		else
3710 			data = defvalue;
3711 	}
3712 	return (data);
3713 }
3714 
3715 /*
3716  * Get an array of integer property
3717  */
3718 int
ddi_prop_lookup_int_array(dev_t match_dev,dev_info_t * dip,uint_t flags,char * name,int ** data,uint_t * nelements)3719 ddi_prop_lookup_int_array(dev_t match_dev, dev_info_t *dip, uint_t flags,
3720     char *name, int **data, uint_t *nelements)
3721 {
3722 	if (flags & ~(DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
3723