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