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