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