dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libpicl / picl.c
blob449aacb4c0218abf510373a332239a769624b4c2
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * This module implements the PICL Interface used by PICL clients
31 * to access services of the PICL daemon
33 * Locking Strategy
34 * A single reader/writer lock (icl_lock) protects the access to the interface
35 * to the picl daemon, and the reference count, refcnt, variable.
36 * A reader lock is obtained to send a request to the daemon.
37 * A writer lock is obtained to initialize, reinitialize, or shutdown
38 * the interface.
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45 #include <alloca.h>
46 #include <fcntl.h>
47 #include <libintl.h>
48 #include <errno.h>
49 #include <sys/mman.h>
50 #include <door.h>
51 #include <sys/door.h>
52 #include <sys/time.h>
53 #include <assert.h>
54 #include <synch.h>
55 #include <limits.h>
56 #include <picl.h>
57 #include "picl2door.h"
60 * Module variables
62 static int door_handle = -1;
63 static uint32_t refcnt = 0;
64 static rwlock_t picl_lock = DEFAULTRWLOCK;
66 static char *picl_errmsg[] = {
67 "No error",
68 "General system failure",
69 "Daemon not responding",
70 "Unknown PICL service",
71 "Session not initialized",
72 "Invalid arguments",
73 "Argument too big",
74 "Property not found",
75 "Not a table property handle",
76 "Not a node handle",
77 "Not a property handle",
78 "End of property list",
79 "Property already exists",
80 "Property not writable",
81 "Insufficient permissions",
82 "Invalid handle",
83 "Stale handle",
84 "Unsupported version",
85 "Wait timed out",
86 "Attempting to destroy before delete",
87 "PICL Tree is busy",
88 "Already has a parent",
89 "Property name is reserved",
90 "Invalid reference value",
91 "Continue tree walk",
92 "Terminate tree walk",
93 "Node not found",
94 "Not enough space available",
95 "Property not readable",
96 "Property value unavailable"
99 #define N_ERRORS (sizeof (picl_errmsg)/sizeof (picl_errmsg[0]))
100 #define SEND_REQ_TRYCOUNT 1
103 * This function sends the client request to the daemon using a door call.
104 * If door_handle is -1, it returns PICL_NOTINITIALIZED.
105 * If the door_call fails, it returns PICL_NORESPONSE. Otherwise, it
106 * checks the response from the daemon for error. If an error is returned
107 * this function returns the error code returned and unmaps any
108 * memory mapped by the door call. For successful results, the caller is
109 * responsible to unmap the mapped memory after retrieving the results.
111 * This function does not attempt to reinitialize the interface if the
112 * initial door_call fails. It is called from handshake() , shutdown()
113 * and trysend_req() routines.
115 static int
116 post_req(door_arg_t *dargp, void *data_ptr, size_t data_size,
117 door_desc_t *desc_ptr, uint_t desc_num, void *rbuf, size_t rsize)
119 int err;
120 picl_service_t *ret;
121 int req_cnum;
123 req_cnum = ((picl_service_t *)data_ptr)->in.cnum;
124 dargp->data_ptr = data_ptr;
125 dargp->data_size = data_size;
126 dargp->desc_ptr = desc_ptr;
127 dargp->desc_num = desc_num;
128 dargp->rbuf = rbuf;
129 dargp->rsize = rsize;
131 if (door_call(door_handle, dargp) < 0)
132 return (PICL_NORESPONSE);
134 /*LINTED*/
135 ret = (picl_service_t *)dargp->rbuf;
136 if (ret->in.cnum == req_cnum)
137 return (PICL_SUCCESS);
138 else if ((ret->in.cnum == PICL_CNUM_ERROR) &&
139 (ret->ret_error.in_cnum == req_cnum))
140 err = ret->ret_error.errnum;
141 else
142 err = PICL_UNKNOWNSERVICE;
143 if (dargp->rbuf != rbuf)
144 (void) munmap(dargp->rbuf, dargp->rsize);
145 return (err);
149 * This function posts an INIT message to the daemon to
150 * verify communication channel.
152 static int
153 handshake(void)
155 int err;
156 door_arg_t darg;
157 picl_reqinit_t req;
158 picl_retinit_t outargs;
160 req.cnum = PICL_CNUM_INIT;
161 req.clrev = PICL_VERSION_1;
163 if ((err = post_req(&darg, &req, sizeof (picl_reqinit_t), NULL,
164 0, &outargs, sizeof (picl_retinit_t))) != PICL_SUCCESS)
165 return (err);
167 if (darg.rbuf != (char *)&outargs)
168 (void) munmap(darg.rbuf, darg.rsize);
169 return (PICL_SUCCESS);
173 * This function calls post_req() to make door_call and reinitializes
174 * the interface is post_req() fails.
176 static int
177 trysend_req(door_arg_t *dargp, void *data_ptr, size_t data_size,
178 door_desc_t *desc_ptr, uint_t desc_num, void *rbuf, size_t rsize,
179 unsigned int trycount)
181 int err;
182 int write_locked;
184 write_locked = 0;
185 (void) rw_rdlock(&picl_lock);
186 if (refcnt == 0) {
187 (void) rw_unlock(&picl_lock); /* read unlock */
188 return (PICL_NOTINITIALIZED);
191 while ((err = post_req(dargp, data_ptr, data_size, desc_ptr, desc_num,
192 rbuf, rsize)) == PICL_NORESPONSE) {
193 if (trycount == 0) /* no more retry */
194 break;
196 if (write_locked == 1) { /* close and open door */
197 (void) close(door_handle);
198 if ((door_handle = open(PICLD_DOOR, O_RDONLY)) < 0) {
199 err = PICL_NORESPONSE;
200 break;
202 --trycount;
203 continue;
206 * Upgrade read to a write lock
208 (void) rw_unlock(&picl_lock);
209 (void) rw_wrlock(&picl_lock);
212 * if picl_shutdown happens during lock upgrade
214 if (refcnt == 0) {
215 err = PICL_NOTINITIALIZED;
216 break;
218 write_locked = 1;
219 continue;
221 (void) rw_unlock(&picl_lock); /* read or write unlock */
222 return (err);
226 * Initialize the PICL interface
227 * Increment the reference count.
230 picl_initialize(void)
232 int err;
234 (void) rw_wrlock(&picl_lock);
235 if (refcnt > 0) { /* previously initialized */
236 err = handshake();
237 if (err == PICL_SUCCESS) {
238 ++refcnt;
239 (void) rw_unlock(&picl_lock); /* write unlock */
240 return (err);
242 if (err != PICL_NORESPONSE) {
243 (void) rw_unlock(&picl_lock); /* write unlock */
244 return (err);
246 (void) close(door_handle); /* close bad door */
250 * Open picld door and initialize door_handle
252 if ((door_handle = open(PICLD_DOOR, O_RDONLY)) < 0) {
253 (void) rw_unlock(&picl_lock); /* write unlock */
254 return (PICL_NORESPONSE);
257 err = handshake();
258 if (err != PICL_SUCCESS)
259 (void) close(door_handle);
260 else
261 ++refcnt;
262 (void) rw_unlock(&picl_lock); /* write unlock */
263 return (err);
267 * Shutdown the PICL interface
268 * Decrement the reference count and close the door_handle if refcnt is zero
271 picl_shutdown(void)
273 int err;
274 door_arg_t darg;
275 picl_reqfini_t req_fini;
276 picl_retfini_t outargs;
278 (void) rw_wrlock(&picl_lock); /* write lock */
279 if (refcnt == 0) {
280 (void) rw_unlock(&picl_lock); /* write unlock */
281 return (PICL_NOTINITIALIZED);
283 req_fini.cnum = PICL_CNUM_FINI;
284 err = post_req(&darg, &req_fini, sizeof (picl_reqfini_t),
285 NULL, 0, &outargs, sizeof (picl_retfini_t));
286 --refcnt;
287 if (refcnt == 0)
288 (void) close(door_handle);
289 (void) rw_unlock(&picl_lock); /* write unlock */
290 if (err != PICL_SUCCESS)
291 return (err);
292 if (darg.rbuf != (char *)&outargs)
293 (void) munmap(darg.rbuf, darg.rsize);
294 return (PICL_SUCCESS);
298 * This function waits for the specified number of seconds for a PICL
299 * tree refresh.
302 picl_wait(unsigned int secs)
304 door_arg_t darg;
305 picl_reqwait_t req_wait;
306 picl_retwait_t outargs;
307 picl_service_t *ret;
308 int err;
310 req_wait.cnum = PICL_CNUM_WAIT;
311 req_wait.secs = secs;
312 err = trysend_req(&darg, &req_wait, sizeof (picl_reqwait_t),
313 NULL, 0, &outargs, sizeof (picl_retwait_t), SEND_REQ_TRYCOUNT);
314 if (err != PICL_SUCCESS)
315 return (err);
317 /*LINTED*/
318 ret = (picl_service_t *)darg.rbuf;
319 err = ret->ret_wait.retcode;
320 if (darg.rbuf != (char *)&outargs)
321 (void) munmap(darg.rbuf, darg.rsize);
322 return (err);
326 * This function copies the handle of the root node of the PICL tree into
327 * the buffer <rooth>
330 picl_get_root(picl_nodehdl_t *rooth)
332 door_arg_t darg;
333 picl_reqroot_t req_root;
334 picl_retroot_t outargs;
335 picl_service_t *ret;
336 int err;
338 req_root.cnum = PICL_CNUM_GETROOT;
339 err = trysend_req(&darg, &req_root, sizeof (picl_reqroot_t), NULL,
340 0, &outargs, sizeof (picl_retroot_t), SEND_REQ_TRYCOUNT);
341 if (err != PICL_SUCCESS)
342 return (err);
343 /*LINTED*/
344 ret = (picl_service_t *)darg.rbuf;
345 *rooth = ret->ret_root.rnode;
346 if (darg.rbuf != (char *)&outargs)
347 (void) munmap(darg.rbuf, darg.rsize);
348 return (PICL_SUCCESS);
352 * This function copies the value of the property specified by its handle
353 * into the buffer <valbuf>.
356 picl_get_propval(picl_prophdl_t proph, void *valbuf, size_t nbytes)
358 door_arg_t darg;
359 picl_reqattrval_t req_attrval;
360 picl_service_t *ret;
361 picl_retattrval_t *outargs;
362 int err;
364 req_attrval.cnum = PICL_CNUM_GETATTRVAL;
365 req_attrval.attr = proph;
366 req_attrval.bufsize = (uint32_t)nbytes;
367 if ((size_t)req_attrval.bufsize != nbytes)
368 return (PICL_VALUETOOBIG);
369 outargs = alloca(sizeof (picl_retattrval_t) + nbytes);
371 err = trysend_req(&darg, &req_attrval, sizeof (picl_reqattrval_t),
372 NULL, 0, outargs, sizeof (picl_retattrval_t) + nbytes,
373 SEND_REQ_TRYCOUNT);
374 if (err != PICL_SUCCESS)
375 return (err);
377 /*LINTED*/
378 ret = (picl_service_t *)darg.rbuf;
379 if (ret->ret_attrval.nbytes > (uint32_t)nbytes)
380 err = PICL_VALUETOOBIG;
381 else
382 (void) memcpy(valbuf, ret->ret_attrval.ret_buf,
383 (size_t)ret->ret_attrval.nbytes);
384 if (darg.rbuf != (char *)outargs)
385 (void) munmap(darg.rbuf, darg.rsize);
386 return (err);
390 * This function copies the value of the property specified by its
391 * name into the buffer <valbuf>
394 picl_get_propval_by_name(picl_nodehdl_t nodeh, const char *propname,
395 void *valbuf, size_t nbytes)
397 door_arg_t darg;
398 picl_reqattrvalbyname_t req_attrvalbyname;
399 picl_service_t *ret;
400 picl_retattrvalbyname_t *outargs;
401 int err;
403 req_attrvalbyname.cnum = PICL_CNUM_GETATTRVALBYNAME;
404 req_attrvalbyname.nodeh = nodeh;
405 (void) strcpy(req_attrvalbyname.propname, propname);
406 req_attrvalbyname.bufsize = (uint32_t)nbytes;
407 if ((size_t)req_attrvalbyname.bufsize != nbytes)
408 return (PICL_VALUETOOBIG);
409 outargs = alloca(sizeof (picl_retattrvalbyname_t) + nbytes);
411 err = trysend_req(&darg, &req_attrvalbyname,
412 sizeof (picl_reqattrvalbyname_t), NULL, 0, outargs,
413 sizeof (picl_retattrvalbyname_t) + nbytes, SEND_REQ_TRYCOUNT);
414 if (err != PICL_SUCCESS)
415 return (err);
417 /*LINTED*/
418 ret = (picl_service_t *)darg.rbuf;
419 if (ret->ret_attrvalbyname.nbytes > (uint32_t)nbytes)
420 err = PICL_VALUETOOBIG;
421 else
422 (void) memcpy(valbuf, ret->ret_attrvalbyname.ret_buf,
423 (size_t)ret->ret_attrvalbyname.nbytes);
424 if (darg.rbuf != (char *)outargs)
425 (void) munmap(darg.rbuf, darg.rsize);
426 return (err);
430 * This function sets the value of the property specified by its
431 * handle with the value specified in <valbuf>.
434 picl_set_propval(picl_prophdl_t proph, void *valbuf, size_t nbytes)
436 door_arg_t darg;
437 picl_reqsetattrval_t ret_setattrval;
438 picl_reqsetattrval_t *inargs;
439 int err;
441 if (nbytes >= (size_t)PICL_PROPSIZE_MAX)
442 return (PICL_VALUETOOBIG);
444 inargs = alloca(sizeof (picl_reqsetattrval_t) + nbytes);
445 inargs->cnum = PICL_CNUM_SETATTRVAL;
446 inargs->attr = proph;
447 inargs->bufsize = (uint32_t)nbytes;
448 if ((size_t)inargs->bufsize != nbytes)
449 return (PICL_VALUETOOBIG);
450 (void) memcpy(inargs->valbuf, valbuf, nbytes);
452 err = trysend_req(&darg, inargs, sizeof (picl_reqsetattrval_t) +
453 nbytes, NULL, 0, &ret_setattrval,
454 sizeof (picl_retsetattrval_t), SEND_REQ_TRYCOUNT);
455 if (err != PICL_SUCCESS)
456 return (err);
458 if (darg.rbuf != (char *)&ret_setattrval)
459 (void) munmap(darg.rbuf, darg.rsize);
460 return (PICL_SUCCESS);
464 * This function sets the value of the property specified by its
465 * name with the value given in <valbuf>
468 picl_set_propval_by_name(picl_nodehdl_t nodeh, const char *propname,
469 void *valbuf, size_t nbytes)
471 door_arg_t darg;
472 picl_retsetattrvalbyname_t ret_setattrvalbyname;
473 picl_reqsetattrvalbyname_t *inargs;
474 int err;
476 if (nbytes >= (size_t)PICL_PROPSIZE_MAX)
477 return (PICL_VALUETOOBIG);
479 inargs = alloca(sizeof (picl_reqsetattrvalbyname_t) + nbytes);
480 inargs->cnum = PICL_CNUM_SETATTRVALBYNAME;
481 inargs->nodeh = nodeh;
482 (void) strcpy(inargs->propname, propname);
483 inargs->bufsize = (uint32_t)nbytes;
484 if ((size_t)inargs->bufsize != nbytes)
485 return (PICL_VALUETOOBIG);
486 (void) memcpy(inargs->valbuf, valbuf, nbytes);
488 err = trysend_req(&darg, inargs,
489 sizeof (picl_reqsetattrvalbyname_t) + nbytes, NULL, 0,
490 &ret_setattrvalbyname, sizeof (picl_retsetattrvalbyname_t),
491 SEND_REQ_TRYCOUNT);
492 if (err != PICL_SUCCESS)
493 return (err);
495 if (darg.rbuf != (char *)&ret_setattrvalbyname)
496 (void) munmap(darg.rbuf, darg.rsize);
497 return (PICL_SUCCESS);
501 * This function copies the information of the specified property
502 * into <pinfo>
505 picl_get_propinfo(picl_prophdl_t proph, picl_propinfo_t *pinfo)
507 door_arg_t darg;
508 picl_reqattrinfo_t req_attrinfo;
509 picl_service_t *ret;
510 picl_retattrinfo_t outargs;
511 int err;
513 req_attrinfo.cnum = PICL_CNUM_GETATTRINFO;
514 req_attrinfo.attr = proph;
516 err = trysend_req(&darg, &req_attrinfo,
517 sizeof (picl_reqattrinfo_t), NULL, 0, &outargs,
518 sizeof (picl_retattrinfo_t), SEND_REQ_TRYCOUNT);
519 if (err != PICL_SUCCESS)
520 return (err);
522 /*LINTED*/
523 ret = (picl_service_t *)darg.rbuf;
524 pinfo->type = ret->ret_attrinfo.type;
525 pinfo->accessmode = ret->ret_attrinfo.accessmode;
526 pinfo->size = (size_t)ret->ret_attrinfo.size;
527 (void) strcpy(pinfo->name, ret->ret_attrinfo.name);
528 if (darg.rbuf != (char *)&outargs)
529 (void) munmap(darg.rbuf, darg.rsize);
530 return (PICL_SUCCESS);
534 * This function copies the handle of the first property of a node into
535 * <proph>
538 picl_get_first_prop(picl_nodehdl_t nodeh, picl_prophdl_t *proph)
540 door_arg_t darg;
541 picl_reqfirstattr_t req_firstattr;
542 picl_service_t *ret;
543 picl_retfirstattr_t outargs;
544 int err;
546 req_firstattr.cnum = PICL_CNUM_GETFIRSTATTR;
547 req_firstattr.nodeh = nodeh;
549 err = trysend_req(&darg, &req_firstattr,
550 sizeof (picl_reqfirstattr_t), NULL, 0, &outargs,
551 sizeof (picl_retfirstattr_t), SEND_REQ_TRYCOUNT);
552 if (err != PICL_SUCCESS)
553 return (err);
555 /*LINTED*/
556 ret = (picl_service_t *)darg.rbuf;
557 *proph = ret->ret_firstattr.attr;
558 if (darg.rbuf != (char *)&outargs)
559 (void) munmap(darg.rbuf, darg.rsize);
560 return (PICL_SUCCESS);
564 * This function copies the handle of the next property in list
565 * into <nextprop>.
568 picl_get_next_prop(picl_prophdl_t proph, picl_prophdl_t *nextprop)
570 door_arg_t darg;
571 picl_reqnextattr_t req_nextattr;
572 picl_service_t *ret;
573 picl_retnextattr_t outargs;
574 int err;
577 req_nextattr.cnum = PICL_CNUM_GETNEXTATTR;
578 req_nextattr.attr = proph;
580 err = trysend_req(&darg, &req_nextattr,
581 sizeof (picl_reqnextattr_t), NULL, 0, &outargs,
582 sizeof (picl_retnextattr_t), SEND_REQ_TRYCOUNT);
583 if (err != PICL_SUCCESS)
584 return (err);
586 /*LINTED*/
587 ret = (picl_service_t *)darg.rbuf;
588 *nextprop = ret->ret_nextattr.nextattr;
589 if (darg.rbuf != (char *)&outargs)
590 (void) munmap(darg.rbuf, darg.rsize);
591 return (PICL_SUCCESS);
595 * This function copies the handle of the property specified by its
596 * name into <proph>.
599 picl_get_prop_by_name(picl_nodehdl_t nodeh, const char *name,
600 picl_prophdl_t *proph)
602 door_arg_t darg;
603 picl_reqattrbyname_t req_attrbyname;
604 picl_service_t *ret;
605 picl_retattrbyname_t outargs;
606 int err;
608 req_attrbyname.cnum = PICL_CNUM_GETATTRBYNAME;
609 req_attrbyname.nodeh = nodeh;
610 (void) strcpy(req_attrbyname.propname, name);
612 err = trysend_req(&darg, &req_attrbyname,
613 sizeof (picl_reqattrbyname_t), NULL, 0, &outargs,
614 sizeof (picl_retattrbyname_t), SEND_REQ_TRYCOUNT);
615 if (err != PICL_SUCCESS)
616 return (err);
618 /*LINTED*/
619 ret = (picl_service_t *)darg.rbuf;
620 *proph = ret->ret_attrbyname.attr;
621 if (darg.rbuf != (char *)&outargs)
622 (void) munmap(darg.rbuf, darg.rsize);
623 return (PICL_SUCCESS);
627 * This function copies the handle of the next property on the same
628 * row of the table into <rowproph>.
629 * When proph is the table handle, the handle of the property that is
630 * in first row and first column is copied.
633 picl_get_next_by_row(picl_prophdl_t proph, picl_prophdl_t *rowproph)
635 door_arg_t darg;
636 picl_reqattrbyrow_t req_attrbyrow;
637 picl_service_t *ret;
638 picl_retattrbyrow_t outargs;
639 int err;
641 req_attrbyrow.cnum = PICL_CNUM_GETATTRBYROW;
642 req_attrbyrow.attr = proph;
644 err = trysend_req(&darg, &req_attrbyrow,
645 sizeof (picl_reqattrbyrow_t), NULL, 0, &outargs,
646 sizeof (picl_retattrbyrow_t), SEND_REQ_TRYCOUNT);
647 if (err != PICL_SUCCESS)
648 return (err);
650 /*LINTED*/
651 ret = (picl_service_t *)darg.rbuf;
652 *rowproph = ret->ret_attrbyrow.rowattr;
653 if (darg.rbuf != (char *)&outargs)
654 (void) munmap(darg.rbuf, darg.rsize);
655 return (PICL_SUCCESS);
659 * This function copies the handle of the next property on the same
660 * column of the table into <colproph>.
661 * When proph is the table handle, the handle of the property that is
662 * in the first row and first column is copied.
665 picl_get_next_by_col(picl_prophdl_t proph, picl_prophdl_t *colproph)
667 door_arg_t darg;
668 picl_reqattrbycol_t req_attrbycol;
669 picl_service_t *ret;
670 picl_retattrbycol_t outargs;
671 int err;
673 req_attrbycol.cnum = PICL_CNUM_GETATTRBYCOL;
674 req_attrbycol.attr = proph;
676 err = trysend_req(&darg, (char *)&req_attrbycol,
677 sizeof (picl_reqattrbycol_t), NULL, 0, (char *)&outargs,
678 sizeof (picl_retattrbycol_t), SEND_REQ_TRYCOUNT);
679 if (err != PICL_SUCCESS)
680 return (err);
682 /*LINTED*/
683 ret = (picl_service_t *)darg.rbuf;
684 *colproph = ret->ret_attrbycol.colattr;
685 if (darg.rbuf != (char *)&outargs)
686 (void) munmap(darg.rbuf, darg.rsize);
687 return (PICL_SUCCESS);
691 * This function returns the picl error messages corresponding to the
692 * error number.
694 char *
695 picl_strerror(int err)
697 if ((err < N_ERRORS) && (err >= 0)) {
698 return (gettext(picl_errmsg[err]));
700 return (NULL);
704 * recursively visit all nodes
706 static int
707 do_walk(picl_nodehdl_t rooth, const char *classname,
708 void *c_args, int (*callback_fn)(picl_nodehdl_t hdl, void *args))
710 int err;
711 picl_nodehdl_t chdh;
712 char classval[PICL_CLASSNAMELEN_MAX];
714 err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh,
715 sizeof (chdh));
716 while (err == PICL_SUCCESS) {
717 err = picl_get_propval_by_name(chdh, PICL_PROP_CLASSNAME,
718 classval, sizeof (classval));
719 if (err != PICL_SUCCESS)
720 return (err);
722 if ((classname == NULL) || (strcmp(classname, classval) == 0)) {
723 err = callback_fn(chdh, c_args);
724 if (err != PICL_WALK_CONTINUE)
725 return (err);
728 if ((err = do_walk(chdh, classname, c_args, callback_fn)) !=
729 PICL_WALK_CONTINUE)
730 return (err);
732 err = picl_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh,
733 sizeof (chdh));
735 if (err == PICL_PROPNOTFOUND) /* end of a branch */
736 return (PICL_WALK_CONTINUE);
737 return (err);
742 * This function walks the tree by class and invokes the callback
743 * function on class name matches.
746 picl_walk_tree_by_class(picl_nodehdl_t rooth, const char *classname,
747 void *c_args, int (*callback_fn)(picl_nodehdl_t hdl, void *args))
749 int err;
751 if (callback_fn == NULL)
752 return (PICL_INVALIDARG);
753 err = do_walk(rooth, classname, c_args, callback_fn);
754 if ((err == PICL_WALK_CONTINUE) || (err == PICL_WALK_TERMINATE))
755 return (PICL_SUCCESS);
756 return (err);
760 * This function gets propinfo and prop handle of the named property
763 picl_get_propinfo_by_name(picl_nodehdl_t nodeh, const char *prop_name,
764 picl_propinfo_t *pinfo, picl_prophdl_t *proph)
766 int err;
767 picl_prophdl_t tmpproph;
768 picl_propinfo_t tmppinfo;
770 err = picl_get_prop_by_name(nodeh, prop_name, &tmpproph);
771 if (err != PICL_SUCCESS)
772 return (err);
774 err = picl_get_propinfo(tmpproph, &tmppinfo);
775 if (err != PICL_SUCCESS)
776 return (err);
778 *proph = tmpproph;
779 *pinfo = tmppinfo;
780 return (PICL_SUCCESS);
784 picl_get_node_by_path(const char *piclpath, picl_nodehdl_t *nodeh)
786 door_arg_t darg;
787 picl_reqnodebypath_t req;
788 picl_retnodebypath_t out;
789 picl_service_t *ret;
790 int err;
792 req.cnum = PICL_CNUM_NODEBYPATH;
793 req.psize = PATH_MAX;
794 if (strlen(piclpath) >= PATH_MAX)
795 return (PICL_VALUETOOBIG);
796 (void) strncpy(req.pathbuf, piclpath, PATH_MAX);
798 err = trysend_req(&darg, &req, sizeof (req), NULL, 0, &out,
799 sizeof (out), SEND_REQ_TRYCOUNT);
800 if (err != PICL_SUCCESS)
801 return (err);
803 /*LINTED*/
804 ret = (picl_service_t *)darg.rbuf;
805 *nodeh = ret->ret_nodebypath.nodeh;
806 if (darg.rbuf != (char *)&out)
807 (void) munmap(darg.rbuf, darg.rsize);
808 return (err);
812 picl_find_node(picl_nodehdl_t rooth, char *pname, picl_prop_type_t ptype,
813 void *pval, size_t valsize, picl_nodehdl_t *retnodeh)
815 door_arg_t darg;
816 picl_reqfindnode_t *req;
817 picl_service_t *ret;
818 picl_retfindnode_t out;
819 int err;
821 req = alloca(sizeof (picl_reqfindnode_t) + valsize);
822 req->cnum = PICL_CNUM_FINDNODE;
823 req->nodeh = rooth;
824 if (strlen(pname) >= PICL_PROPNAMELEN_MAX)
825 return (PICL_VALUETOOBIG);
826 (void) strncpy(req->propname, pname, PICL_PROPNAMELEN_MAX);
827 req->ptype = ptype;
828 req->valsize = (uint32_t)valsize;
829 if ((size_t)req->valsize != valsize)
830 return (PICL_VALUETOOBIG);
831 (void) memcpy(req->valbuf, pval, valsize);
833 err = trysend_req(&darg, req, sizeof (picl_reqfindnode_t) + valsize,
834 NULL, 0, &out, sizeof (out), SEND_REQ_TRYCOUNT);
835 if (err != PICL_SUCCESS)
836 return (err);
838 /*LINTED*/
839 ret = (picl_service_t *)darg.rbuf;
840 *retnodeh = ret->ret_findnode.rnodeh;
841 if (darg.rbuf != (char *)&out)
842 (void) munmap(darg.rbuf, darg.rsize);
843 return (err);
847 picl_get_frutree_parent(picl_nodehdl_t devh, picl_nodehdl_t *fruh)
849 door_arg_t darg;
850 picl_reqfruparent_t req;
851 picl_retfruparent_t out;
852 picl_service_t *ret;
853 int err;
855 req.cnum = PICL_CNUM_FRUTREEPARENT;
856 req.devh = devh;
858 err = trysend_req(&darg, &req, sizeof (req), NULL, 0, &out,
859 sizeof (out), SEND_REQ_TRYCOUNT);
860 if (err != PICL_SUCCESS)
861 return (err);
863 /*LINTED*/
864 ret = (picl_service_t *)darg.rbuf;
865 *fruh = ret->ret_fruparent.fruh;
866 if (darg.rbuf != (char *)&out)
867 (void) munmap(darg.rbuf, darg.rsize);
868 return (err);