xref: /illumos-gate/usr/src/cmd/picl/plugins/sun4u/chicago/envd/piclenvsetup.c (revision 45ede40b2394db7967e59f19288fae9b62efd4aa)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
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.
13  *
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]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * This file contains code for setting up environmental related nodes
29  * and properties in the PICL tree.
30  *
31  */
32 
33 #include <stdio.h>
34 #include <fcntl.h>
35 #include <unistd.h>
36 #include <syslog.h>
37 #include <stdlib.h>
38 #include <limits.h>
39 #include <errno.h>
40 #include <sys/open.h>
41 #include <ctype.h>
42 #include <string.h>
43 #include <alloca.h>
44 #include <libintl.h>
45 #include <sys/systeminfo.h>
46 #include <picl.h>
47 #include <picltree.h>
48 #include <picld_pluginutil.h>
49 #include <pthread.h>
50 #include <sys/utsname.h>
51 #include <sys/systeminfo.h>
52 #include "picldefs.h"
53 #include "envd.h"
54 
55 /*
56  * Volatile property read/write function typedef
57  */
58 typedef int ptree_vol_rdfunc_t(ptree_rarg_t *parg, void *buf);
59 typedef int ptree_vol_wrfunc_t(ptree_warg_t *parg, const void *buf);
60 
61 extern int disk_temp_monitor;
62 extern env_tuneable_t	tuneables[];
63 extern	int errno;
64 extern	int	ntuneables;
65 #define	PROP_FAN_SPEED_UNIT_VALUE	"rpm"
66 
67 /*
68  * Sensor node data structure
69  */
70 typedef struct {
71 	char		*parent_path;	/* parent path */
72 	char		*sensor_name;	/* sensor name */
73 	env_sensor_t	*sensorp;	/* sensor info */
74 	picl_nodehdl_t	nodeh;		/* sensor node handle */
75 	picl_prophdl_t	proph;		/* "Temperature" property handle */
76 	picl_prophdl_t	target_proph;	/* "TargetTemp" property handle */
77 } sensor_node_t;
78 
79 /*
80  * Sensor nodes array
81  */
82 static sensor_node_t sensor_nodes[] = {
83 	{"/platform/ebus@1f,464000/env-monitor@3,0", SENSOR_CPU0,
84 	NULL, 0, 0, 0},
85 	{"/platform/ebus@1f,464000/env-monitor@3,0", SENSOR_CPU1,
86 	NULL, 0, 0, 0},
87 	{"/platform/ebus@1f,464000/env-monitor@3,0", SENSOR_MB,
88 	NULL, 0, 0, 0},
89 	{"/platform/ebus@1f,464000/env-monitor@3,0", SENSOR_ADT7462,
90 	NULL, 0, 0, 0},
91 	{"/platform/ebus@1f,464000/env-monitor@3,0", SENSOR_LM95221,
92 	NULL, 0, 0, 0},
93 	{"/platform/ebus@1f,464000/env-monitor@3,0", SENSOR_FIRE,
94 	NULL, 0, 0, 0},
95 	{"/platform/ebus@1f,464000/env-monitor@3,0", SENSOR_LSI1064,
96 	NULL, 0, 0, 0},
97 	{"/platform/ebus@1f,464000/env-monitor@3,0", SENSOR_FRONT_PANEL,
98 	NULL, 0, 0, 0},
99 	{"/platform/ebus@1f,464000/env-monitor@3,0", SENSOR_PSU,
100 	NULL, 0, 0, 0}
101 };
102 #define	N_SENSOR_NODES	(sizeof (sensor_nodes)/sizeof (sensor_nodes[0]))
103 
104 /*
105  * Fan node data structure
106  */
107 typedef struct {
108 	char		*parent_path;	/* parent node path */
109 	char		*fan_name;	/* fan name */
110 	env_fan_t	*fanp;		/* fan information */
111 	char		*speed_unit;	/* speed unit string */
112 	picl_nodehdl_t	nodeh;		/* "fan" node handle */
113 	picl_prophdl_t	proph;		/* "Speed" property handle */
114 } fan_node_t;
115 
116 /*
117  * Fan node array
118  */
119 static fan_node_t fan_nodes[] =  {
120 	{"/platform/ebus@1f,464000/env-monitor@3,0", ENV_SYSTEM_FAN0,
121 	NULL, PROP_FAN_SPEED_UNIT_VALUE, 0, 0},
122 	{"/platform/ebus@1f,464000/env-monitor@3,0", ENV_SYSTEM_FAN1,
123 	NULL, PROP_FAN_SPEED_UNIT_VALUE, 0, 0},
124 	{"/platform/ebus@1f,464000/env-monitor@3,0", ENV_SYSTEM_FAN2,
125 	NULL, PROP_FAN_SPEED_UNIT_VALUE, 0, 0},
126 	{"/platform/ebus@1f,464000/env-monitor@3,0", ENV_SYSTEM_FAN3,
127 	NULL, PROP_FAN_SPEED_UNIT_VALUE, 0, 0},
128 	{"/platform/ebus@1f,464000/env-monitor@3,0", ENV_SYSTEM_FAN4,
129 	NULL, PROP_FAN_SPEED_UNIT_VALUE, 0, 0}
130 };
131 #define	N_FAN_NODES	(sizeof (fan_nodes)/sizeof (fan_nodes[0]))
132 
133 /*
134  * Disk node data structure
135  */
136 typedef struct {
137 	char		*parent_path;	/* parent node path */
138 	char		*disk_name;	/* disk name */
139 	env_disk_t	*diskp;		/* disk information */
140 	picl_nodehdl_t	nodeh;		/* "disk" node handle */
141 	picl_prophdl_t	proph;		/* "Temperature" property handle */
142 } disk_node_t;
143 
144 /*
145  * Disk node array
146  */
147 static disk_node_t disk_nodes[] =  {
148 	{DISK0_NODE_PATH, ENV_DISK0, NULL, 0, 0},
149 	{DISK1_NODE_PATH, ENV_DISK1, NULL, 0, 0},
150 	{DISK2_NODE_PATH, ENV_DISK2, NULL, 0, 0},
151 	{DISK3_NODE_PATH, ENV_DISK3, NULL, 0, 0}
152 };
153 #define	N_DISK_NODES	(sizeof (disk_nodes)/sizeof (disk_nodes[0]))
154 
155 /*
156  * Miscellaneous declarations
157  */
158 static void delete_sensor_nodes_and_props(void);
159 static void delete_disk_nodes_and_props(void);
160 static void delete_fan_nodes_and_props(void);
161 
162 
163 /*
164  * Read function for volatile "Temperature" property
165  */
166 static int
167 get_current_temp(ptree_rarg_t *parg, void *buf)
168 {
169 	tempr_t		temp;
170 	picl_prophdl_t	proph;
171 	sensor_node_t	*snodep;
172 	int		i;
173 
174 	/*
175 	 * Locate the sensor in our sensor_nodes table by matching the
176 	 * property handle and get its temperature.
177 	 */
178 	proph = parg->proph;
179 	for (i = 0; i < N_SENSOR_NODES; i++) {
180 		snodep = &sensor_nodes[i];
181 		if (snodep->proph != proph)
182 			continue;
183 
184 		if (get_temperature(snodep->sensorp, &temp) < 0)
185 			break;
186 		(void) memcpy(buf, (caddr_t)&temp, sizeof (tempr_t));
187 		return (PICL_SUCCESS);
188 	}
189 	return (PICL_FAILURE);
190 }
191 
192 /*
193  * Read function for volatile "Temperature" property
194  */
195 static int
196 get_disk_temp(ptree_rarg_t *parg, void *buf)
197 {
198 	tempr_t		temp;
199 	picl_prophdl_t	proph;
200 	disk_node_t	*dnodep;
201 	int		i;
202 
203 	/*
204 	 * Locate the sensor in our sensor_nodes table by matching the
205 	 * property handle and get its temperature.
206 	 */
207 	proph = parg->proph;
208 	for (i = 0; i < N_DISK_NODES; i++) {
209 		dnodep = &disk_nodes[i];
210 		if (dnodep->proph != proph)
211 			continue;
212 
213 		if (disk_temperature(dnodep->diskp, &temp) < 0)
214 			break;
215 		(void) memcpy(buf, (caddr_t)&temp, sizeof (tempr_t));
216 		return (PICL_SUCCESS);
217 	}
218 	return (PICL_FAILURE);
219 }
220 
221 /*
222  * Read function for volatile "Speed" property on "fan" class node
223  */
224 static int
225 set_current_speed(ptree_warg_t *parg, const void *buf)
226 {
227 	fanspeed_t	speed;
228 	picl_prophdl_t	proph;
229 	fan_node_t	*fnodep;
230 	int		i, ret;
231 
232 	/*
233 	 * Locate the fan in our fan_nodes table by matching the
234 	 * property handle and get fan speed.
235 	 */
236 	proph = parg->proph;
237 	for (i = 0; i < N_FAN_NODES; i++) {
238 		fnodep = &fan_nodes[i];
239 		if (fnodep->proph != proph)
240 			continue;
241 		if (fnodep->fanp->fd == -1)
242 			continue;
243 
244 		(void) memcpy((caddr_t)&speed, buf, sizeof (speed));
245 
246 		ret = set_fan_speed(fnodep->fanp, speed);
247 
248 		if (ret < 0) {
249 			if (ret == -1 && errno == EBUSY)
250 				return (PICL_NOTWRITABLE);
251 			if (ret == -2)
252 				return (PICL_INVALIDARG);
253 			break;
254 		}
255 
256 
257 		return (PICL_SUCCESS);
258 	}
259 	return (PICL_FAILURE);
260 }
261 
262 
263 /*
264  * Read function for volatile "Speed" property on "fan" class node
265  */
266 static int
267 get_current_speed(ptree_rarg_t *parg, void *buf)
268 {
269 	fanspeed_t	speed;
270 	picl_prophdl_t	proph;
271 	fan_node_t	*fnodep;
272 	int		i;
273 
274 	/*
275 	 * Locate the fan in our fan_nodes table by matching the
276 	 * property handle and get fan speed.
277 	 */
278 	proph = parg->proph;
279 	for (i = 0; i < N_FAN_NODES; i++) {
280 		fnodep = &fan_nodes[i];
281 		if (fnodep->proph != proph)
282 			continue;
283 		if (fnodep->fanp->fd == -1)
284 			continue;
285 		if (get_fan_speed(fnodep->fanp, &speed) < 0)
286 			break;
287 
288 		(void) memcpy(buf, (caddr_t)&speed, sizeof (speed));
289 		return (PICL_SUCCESS);
290 	}
291 	return (PICL_FAILURE);
292 }
293 
294 /*
295  * Create and add the specified regular property
296  */
297 
298 static int
299 add_regular_prop(picl_nodehdl_t nodeh, char *name, int type, int access,
300     int size, void *valbuf, picl_prophdl_t *prophp)
301 {
302 	int			err;
303 	ptree_propinfo_t	propinfo;
304 	picl_prophdl_t		proph;
305 
306 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
307 	    type, access, size, name, NULL, NULL);
308 	if (err != PICL_SUCCESS)
309 		return (err);
310 
311 	err = ptree_create_and_add_prop(nodeh, &propinfo, valbuf, &proph);
312 	if (err == PICL_SUCCESS && prophp)
313 		*prophp = proph;
314 	return (err);
315 }
316 
317 
318 /*
319  * Create and add the specified volatile property
320  */
321 static int
322 add_volatile_prop(picl_nodehdl_t nodeh, char *name, int type, int access,
323     int size, ptree_vol_rdfunc_t *rdfunc, ptree_vol_wrfunc_t *wrfunc,
324     picl_prophdl_t *prophp)
325 {
326 	int			err;
327 	ptree_propinfo_t	propinfo;
328 	picl_prophdl_t		proph;
329 
330 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
331 	    type, (access|PICL_VOLATILE), size, name, rdfunc, wrfunc);
332 	if (err != PICL_SUCCESS)
333 		return (err);
334 
335 	err = ptree_create_and_add_prop(nodeh, &propinfo, NULL, &proph);
336 	if (err == PICL_SUCCESS && prophp)
337 		*prophp = proph;
338 	return (err);
339 }
340 
341 /*
342  * Add temperature threshold properties
343  */
344 static void
345 add_sensor_thresh_props(picl_nodehdl_t nodeh, es_sensor_blk_t *sensor_blkp)
346 {
347 	picl_prophdl_t	proph;
348 
349 	(void) add_regular_prop(nodeh, PICL_PROP_LOW_POWER_OFF,
350 	    PICL_PTYPE_INT, PICL_READ,
351 	    sizeof (sensor_blkp->esb_low_power_off),
352 	    &sensor_blkp->esb_low_power_off, &proph);
353 
354 	(void) add_regular_prop(nodeh, PICL_PROP_LOW_SHUTDOWN,
355 	    PICL_PTYPE_INT, PICL_READ,
356 	    sizeof (sensor_blkp->esb_low_shutdown),
357 	    &sensor_blkp->esb_low_shutdown, &proph);
358 
359 	(void) add_regular_prop(nodeh, PICL_PROP_LOW_WARNING,
360 	    PICL_PTYPE_INT, PICL_READ,
361 	    sizeof (sensor_blkp->esb_low_warning),
362 	    &sensor_blkp->esb_low_warning, &proph);
363 
364 	(void) add_regular_prop(nodeh, PICL_PROP_HIGH_WARNING,
365 	    PICL_PTYPE_INT, PICL_READ,
366 	    sizeof (sensor_blkp->esb_high_warning),
367 	    &sensor_blkp->esb_high_warning, &proph);
368 
369 	(void) add_regular_prop(nodeh, PICL_PROP_HIGH_SHUTDOWN,
370 	    PICL_PTYPE_INT, PICL_READ,
371 	    sizeof (sensor_blkp->esb_high_shutdown),
372 	    &sensor_blkp->esb_high_shutdown, &proph);
373 
374 	(void) add_regular_prop(nodeh, PICL_PROP_HIGH_POWER_OFF,
375 	    PICL_PTYPE_INT, PICL_READ,
376 	    sizeof (sensor_blkp->esb_high_power_off),
377 	    &sensor_blkp->esb_high_power_off, &proph);
378 }
379 
380 
381 /*
382  * Go through the sensor_nodes array and create those nodes
383  * and the Temperature property to report the temperature.
384  */
385 static int
386 add_sensor_nodes_and_props()
387 {
388 	int		err;
389 	char		*pname, *nodename, *devfs_path;
390 	sensor_node_t	*snodep;
391 	picl_nodehdl_t	nodeh, cnodeh;
392 	picl_prophdl_t	proph;
393 	env_sensor_t	*sensorp;
394 	es_sensor_blk_t	*sensor_blkp;
395 	int		i;
396 
397 	for (i = 0; i < N_SENSOR_NODES; i++) {
398 		snodep = &sensor_nodes[i];
399 		/*
400 		 * Get the parent nodeh
401 		 */
402 		err = ptree_get_node_by_path(snodep->parent_path, &nodeh);
403 		if (err != PICL_SUCCESS) {
404 			if (env_debug) {
405 				envd_log(LOG_ERR,
406 				    "failed to get_node_by_path %s\n",
407 				    snodep->parent_path);
408 			}
409 			continue;
410 		}
411 		sensorp = snodep->sensorp;
412 		if (sensorp == NULL)
413 			continue;
414 		if (sensorp->present == B_FALSE)
415 			continue;
416 		/*
417 		 * Create temperature-sensor node
418 		 */
419 		nodename = snodep->sensor_name;
420 		err = ptree_create_and_add_node(nodeh, nodename,
421 		    PICL_CLASS_TEMPERATURE_SENSOR, &cnodeh);
422 		if (env_debug)
423 			envd_log(LOG_ERR,
424 			    "Creating PICL sensor node '%s' err:%d\n",
425 			    nodename, err);
426 		if (err != PICL_SUCCESS)
427 			break;
428 
429 		/* save node handle */
430 		snodep->nodeh = cnodeh;
431 
432 		/*
433 		 * Add "devfs_path" property in child node
434 		 */
435 		devfs_path = sensorp->devfs_path;
436 		pname = PICL_PROP_DEVFS_PATH;
437 		err = add_regular_prop(cnodeh, pname,
438 		    PICL_PTYPE_CHARSTRING, PICL_READ,
439 		    strlen(devfs_path)+1, (void *)devfs_path, &proph);
440 		if (err != PICL_SUCCESS)
441 			break;
442 
443 		/*
444 		 * Now add volatile "temperature" volatile property
445 		 * in this "temperature-sensor" class node.
446 		 */
447 		pname = PICL_PROP_TEMPERATURE;
448 		err = add_volatile_prop(cnodeh, pname,
449 		    PICL_PTYPE_INT, PICL_READ, sizeof (tempr_t),
450 		    get_current_temp, NULL, &proph);
451 		if (err != PICL_SUCCESS)
452 			break;
453 
454 		/* Save prop handle */
455 		snodep->proph = proph;
456 
457 		/*
458 		 * Add threshold related properties
459 		 */
460 		sensor_blkp = sensorp->es;
461 		if (sensor_blkp != NULL)
462 			add_sensor_thresh_props(cnodeh, sensor_blkp);
463 	}
464 
465 	if (err != PICL_SUCCESS) {
466 		delete_sensor_nodes_and_props();
467 		if (env_debug)
468 			envd_log(LOG_INFO,
469 			    "Can't create prop/node for sensor '%s'\n",
470 			    nodename);
471 		return (err);
472 	}
473 	return (PICL_SUCCESS);
474 }
475 
476 /*
477  * Delete all sensor nodes and related properties created by the
478  * add_sensor_prop() for each sensor node in the PICL tree.
479  */
480 static void
481 delete_sensor_nodes_and_props(void)
482 {
483 	sensor_node_t	*snodep;
484 	int		i;
485 
486 	/*
487 	 * Delete/destroy any property created in the sensed device
488 	 * as well as the sensor node and all properties under it.
489 	 * Note that deleiing/destroying a node deletes/destroys
490 	 * all properties within that node.
491 	 */
492 
493 	for (i = 0; i < N_SENSOR_NODES; i++) {
494 		snodep = &sensor_nodes[i];
495 		if (snodep->nodeh != 0) {
496 			/* delete node and all properties under it */
497 			(void) ptree_delete_node(snodep->nodeh);
498 			(void) ptree_destroy_node(snodep->nodeh);
499 			snodep->nodeh = 0;
500 			snodep->proph = 0;
501 		}
502 	}
503 }
504 
505 /*
506  * Go through the disk_nodes array and create those nodes
507  * and the Temperature property to report the temperature.
508  */
509 static int
510 add_disk_nodes_and_props()
511 {
512 	int		err;
513 	char		*pname, *nodename, *devfs_path;
514 	disk_node_t	*dnodep;
515 	picl_nodehdl_t	nodeh, cnodeh;
516 	picl_prophdl_t	proph;
517 	env_disk_t	*diskp;
518 	int		i;
519 
520 	for (i = 0; i < N_DISK_NODES; i++) {
521 		if (env_debug)
522 			envd_log(LOG_ERR, "adding disk nodes...\n");
523 		dnodep = &disk_nodes[i];
524 		/*
525 		 * Get the parent nodeh
526 		 */
527 		err = ptree_get_node_by_path(dnodep->parent_path, &nodeh);
528 		if (err != PICL_SUCCESS) {
529 			if (env_debug)
530 				envd_log(LOG_ERR,
531 				    "failed to get node for path %s\n",
532 				    dnodep->parent_path);
533 
534 			err = PICL_SUCCESS;
535 			continue;
536 		}
537 		diskp = dnodep->diskp;
538 		if (diskp == NULL)
539 			continue;
540 		if (diskp->present == B_FALSE)
541 			continue;
542 		/*
543 		 * Create temperature-sensor node
544 		 */
545 		nodename = dnodep->disk_name;
546 		err = ptree_create_and_add_node(nodeh, nodename,
547 		    PICL_CLASS_TEMPERATURE_SENSOR, &cnodeh);
548 		if (env_debug)
549 			envd_log(LOG_ERR,
550 			    "Creating PICL disk node '%s' err:%d\n",
551 			    nodename, err);
552 		if (err != PICL_SUCCESS)
553 			break;
554 
555 		/* save node handle */
556 		dnodep->nodeh = cnodeh;
557 
558 		/*
559 		 * Add "devfs_path" property in child node
560 		 */
561 		devfs_path = diskp->devfs_path;
562 		pname = PICL_PROP_DEVFS_PATH;
563 		err = add_regular_prop(cnodeh, pname,
564 		    PICL_PTYPE_CHARSTRING, PICL_READ,
565 		    strlen(devfs_path)+1, (void *)devfs_path, &proph);
566 		if (err != PICL_SUCCESS)
567 			break;
568 
569 		/*
570 		 * Now add volatile "temperature" volatile property
571 		 * in this "temperature-sensor" class node.
572 		 */
573 		pname = PICL_PROP_TEMPERATURE;
574 		err = add_volatile_prop(cnodeh, pname,
575 		    PICL_PTYPE_INT, PICL_READ, sizeof (tempr_t),
576 		    get_disk_temp, NULL, &proph);
577 		if (err != PICL_SUCCESS)
578 			break;
579 
580 		/* Save prop handle */
581 		dnodep->proph = proph;
582 
583 		/*
584 		 * Add threshold related properties
585 		 */
586 
587 		(void) add_regular_prop(cnodeh, PICL_PROP_LOW_SHUTDOWN,
588 		    PICL_PTYPE_INT, PICL_READ,
589 		    sizeof (diskp->low_shutdown),
590 		    (void *)&(diskp->low_shutdown), &proph);
591 
592 		(void) add_regular_prop(cnodeh, PICL_PROP_LOW_WARNING,
593 		    PICL_PTYPE_INT, PICL_READ,
594 		    sizeof (diskp->low_warning),
595 		    (void *)&(diskp->low_warning), &proph);
596 
597 		(void) add_regular_prop(cnodeh, PICL_PROP_HIGH_WARNING,
598 		    PICL_PTYPE_INT, PICL_READ,
599 		    sizeof (diskp->high_warning),
600 		    (void *)&(diskp->high_warning), &proph);
601 
602 		(void) add_regular_prop(cnodeh, PICL_PROP_HIGH_SHUTDOWN,
603 		    PICL_PTYPE_INT, PICL_READ,
604 		    sizeof (diskp->high_shutdown),
605 		    (void *)&(diskp->high_shutdown), &proph);
606 
607 	}
608 	if (err != PICL_SUCCESS) {
609 		delete_disk_nodes_and_props();
610 		if (env_debug)
611 			envd_log(LOG_INFO,
612 			    "Can't create prop/node for disk '%s'\n",
613 			    nodename);
614 		return (err);
615 	}
616 	return (PICL_SUCCESS);
617 }
618 
619 /*
620  * Delete all disk nodes and related properties created by the
621  * add_disk_props() for each disk node in the PICL tree.
622  */
623 static void
624 delete_disk_nodes_and_props(void)
625 {
626 	disk_node_t	*dnodep;
627 	int		i;
628 
629 	/*
630 	 * Delete/destroy disk node and all properties under it.
631 	 * Note that deleting/destroying a node deletes/destroys
632 	 * all properties within that node.
633 	 */
634 
635 	for (i = 0; i < N_DISK_NODES; i++) {
636 		dnodep = &disk_nodes[i];
637 		if (dnodep->nodeh != 0) {
638 			(void) ptree_delete_node(dnodep->nodeh);
639 			(void) ptree_destroy_node(dnodep->nodeh);
640 			dnodep->nodeh = 0;
641 			dnodep->proph = 0;
642 		}
643 	}
644 }
645 
646 /*
647  * For each entry in fan_nodes[] array, do the following:
648  *	- Create specified "fan" class node.
649  *	- Create "Speed" volatile propery under "fan" class node.
650  *	- Create "SpeedUnit" property under "fan" class node.
651  */
652 static int
653 add_fan_nodes_and_props()
654 {
655 	int		err = PICL_FAILURE;
656 	char		*pname, *nodename, *devfs_path;
657 	env_fan_t	*fanp;
658 	fan_node_t	*fnodep;
659 	picl_nodehdl_t	nodeh, cnodeh;
660 	picl_prophdl_t	proph;
661 	int		i;
662 
663 	for (i = 0; i < N_FAN_NODES; i++) {
664 		/*
665 		 * Add various fan nodes and properties
666 		 */
667 		fnodep = &fan_nodes[i];
668 		if (fnodep == NULL)
669 			continue;
670 		if (fnodep->fanp == NULL)
671 			continue;
672 		if (fnodep->fanp->present == B_FALSE)
673 			continue;
674 		/*
675 		 * get parent nodeh
676 		 */
677 		err = ptree_get_node_by_path(fnodep->parent_path, &nodeh);
678 		if (err != PICL_SUCCESS) {
679 			if (env_debug)
680 				envd_log(LOG_ERR,
681 		"node for %s NOT FOUND.\n", fnodep->parent_path);
682 			err = PICL_SUCCESS;
683 			continue;
684 		}
685 		/*
686 		 * Create "fan" class node and save node handle
687 		 */
688 		nodename = fnodep->fan_name;
689 		err = ptree_create_and_add_node(nodeh, nodename,
690 		    PICL_CLASS_FAN, &cnodeh);
691 		if (env_debug)
692 			envd_log(LOG_ERR,
693 			    "Creating PICL fan node '%s' err:%d\n",
694 			    nodename, err);
695 
696 		if (err != PICL_SUCCESS)
697 			break;
698 		fnodep->nodeh = cnodeh;
699 
700 		/*
701 		 * Add "devfs_path" property in child node
702 		 */
703 		fanp = fnodep->fanp;
704 		devfs_path  = fanp->devfs_path;
705 		pname = PICL_PROP_DEVFS_PATH;
706 		err = add_regular_prop(cnodeh, pname,
707 		    PICL_PTYPE_CHARSTRING, PICL_READ,
708 		    strlen(devfs_path)+1, (void *)devfs_path, &proph);
709 
710 		if (err != PICL_SUCCESS)
711 
712 			break;
713 
714 		/*
715 		 * Add "Speed" volatile property in this "fan"
716 		 * class node and save prop handle.
717 		 */
718 		pname = PICL_PROP_FAN_SPEED;
719 
720 		err = add_volatile_prop(cnodeh, pname, PICL_PTYPE_INT,
721 		    PICL_READ|PICL_WRITE, sizeof (fanspeed_t),
722 		    get_current_speed, set_current_speed, &proph);
723 
724 		if (err != PICL_SUCCESS)
725 			break;
726 		fnodep->proph = proph;
727 
728 		/*
729 		 * Add other "fan" class properties
730 		 */
731 		pname = PICL_PROP_FAN_SPEED_UNIT;
732 		err = add_regular_prop(cnodeh, pname,
733 		    PICL_PTYPE_CHARSTRING, PICL_READ,
734 		    strlen(fnodep->speed_unit)+1,
735 		    (void *)fnodep->speed_unit, &proph);
736 
737 		if (err != PICL_SUCCESS)
738 			break;
739 
740 		pname = PICL_PROP_LOW_WARNING;
741 		err = add_regular_prop(cnodeh, pname,
742 		    PICL_PTYPE_INT, PICL_READ,
743 		    sizeof (fanspeed_t),
744 		    &(fnodep->fanp->speed_min), &proph);
745 
746 		if (err != PICL_SUCCESS)
747 			break;
748 	}
749 	if (err != PICL_SUCCESS) {
750 		delete_fan_nodes_and_props();
751 		return (err);
752 	}
753 	return (PICL_SUCCESS);
754 }
755 
756 
757 /*
758  * Delete all fan nodes and related properties created by the
759  * add_fan_props() for each fan node in the PICL tree.
760  */
761 static void
762 delete_fan_nodes_and_props(void)
763 {
764 	fan_node_t	*fnodep;
765 	int		i;
766 
767 	/*
768 	 * Delete/destroy fan node and all properties under it.
769 	 * Note that deleting/destroying a node deletes/destroys
770 	 * all properties within that node.
771 	 */
772 
773 	for (i = 0; i < N_FAN_NODES; i++) {
774 		fnodep = &fan_nodes[i];
775 		if (fnodep->nodeh != 0) {
776 			(void) ptree_delete_node(fnodep->nodeh);
777 			(void) ptree_destroy_node(fnodep->nodeh);
778 			fnodep->nodeh = 0;
779 		}
780 	}
781 }
782 /*
783  * Tuneables publishing functions
784  */
785 static int
786 copy_persistent_tuneable(env_tuneable_t *tune, char *buf)
787 {
788 
789 	switch (tune->type) {
790 	case PICL_PTYPE_INT : {
791 		(void) memcpy((int *)tune->value,
792 		    buf, tune->nbytes);
793 		break;
794 	}
795 	case PICL_PTYPE_CHARSTRING : {
796 		(void) memcpy((caddr_t)tune->value,
797 		    buf, tune->nbytes);
798 		break;
799 	}
800 	default	: {
801 		return (PICL_FAILURE);
802 	}
803 	}
804 	return (PICL_SUCCESS);
805 }
806 
807 static void
808 env_parse_tunables(picl_nodehdl_t rooth)
809 {
810 	char	nmbuf[SYS_NMLN];
811 	char    pname[PATH_MAX];
812 
813 	if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) {
814 		(void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
815 		(void) strlcat(pname, TUNABLE_CONF_FILE, PATH_MAX);
816 		if (access(pname, R_OK) == 0) {
817 			(void) picld_pluginutil_parse_config_file(rooth, pname);
818 			return;
819 		}
820 	}
821 }
822 
823 int
824 env_picl_setup_tuneables(void)
825 {
826 	int		err;
827 	int		i;
828 	picl_nodehdl_t	nodeh;
829 	picl_nodehdl_t	rooth;
830 	picl_prophdl_t	proph;
831 	env_tuneable_t	*tuneablep;
832 	char		read_buf[BUFSIZ];
833 
834 	if (ptree_get_root(&rooth) != PICL_SUCCESS) {
835 		return (PICL_FAILURE);
836 	}
837 	err = ptree_create_and_add_node(rooth, PICL_PLUGINS_NODE,
838 	    PICL_CLASS_PICL, &nodeh);
839 	if (err != PICL_SUCCESS)
840 		return (PICL_FAILURE);
841 	err = ptree_create_and_add_node(nodeh, PICL_ENVIRONMENTAL_NODE,
842 	    PICL_CLASS_PICL, &nodeh);
843 	if (err != PICL_SUCCESS) {
844 		return (PICL_FAILURE);
845 	}
846 
847 	/*
848 	 * Parse the conf file
849 	 */
850 	if (env_debug)
851 		envd_log(LOG_ERR, "parsing tuneables...\n");
852 	env_parse_tunables(rooth);
853 	for (i = 0; i < ntuneables; i++) {
854 		if (env_debug)
855 			envd_log(LOG_ERR, "tuneable %d being added\n", i);
856 		tuneablep = &tuneables[i];
857 		err = ptree_get_propval_by_name(nodeh, tuneablep->name,
858 		    read_buf, tuneablep->nbytes);
859 
860 		if (err != PICL_SUCCESS) {
861 			/*
862 			 * Add volitle functions to environmental node
863 			 */
864 			err = add_volatile_prop(nodeh, tuneablep->name,
865 			    tuneablep->type,
866 			    PICL_READ|PICL_WRITE, tuneablep->nbytes,
867 			    tuneablep->rfunc,
868 			    tuneablep->wfunc, &proph);
869 
870 			tuneablep->proph = proph;
871 		} else {
872 			/*
873 			 * property is persistent
874 			 */
875 			(void) copy_persistent_tuneable(tuneablep,
876 			    read_buf);
877 		}
878 	}
879 
880 	return	(PICL_SUCCESS);
881 }
882 
883 /*
884  * Find the ENVMODEL_CONF_FILE file.
885  */
886 static int
887 get_envmodel_conf_file(char *outfilename)
888 {
889 	char	nmbuf[SYS_NMLN];
890 	char    pname[PATH_MAX];
891 
892 	if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) {
893 		(void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
894 		(void) strlcat(pname, ENV_CONF_FILE, PATH_MAX);
895 		if (access(pname, R_OK) == 0) {
896 			(void) strlcpy(outfilename, pname, PATH_MAX);
897 			return (0);
898 		}
899 	}
900 
901 	if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) {
902 		(void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
903 		(void) strlcat(pname, ENV_CONF_FILE, PATH_MAX);
904 		if (access(pname, R_OK) == 0) {
905 			(void) strlcpy(outfilename, pname, PATH_MAX);
906 			return (0);
907 		}
908 	}
909 
910 	(void) snprintf(pname, PATH_MAX, "%s/%s", PICLD_COMMON_PLUGIN_DIR,
911 	    ENV_CONF_FILE);
912 
913 	if (access(pname, R_OK) == 0) {
914 		(void) strlcpy(outfilename, pname, PATH_MAX);
915 		return (0);
916 	}
917 
918 	return (-1);
919 }
920 
921 /* Delete all sensor/fan nodes and any properties created by this plugin */
922 void
923 env_picl_destroy(void)
924 {
925 	delete_fan_nodes_and_props();
926 	delete_sensor_nodes_and_props();
927 	delete_disk_nodes_and_props();
928 }
929 
930 void
931 env_picl_setup(void)
932 {
933 	int		err, sensor_err, fan_err, disk_err;
934 	sensor_node_t	*snodep;
935 	fan_node_t	*fnodep;
936 	disk_node_t	*dnodep;
937 	picl_nodehdl_t	plath;
938 	char		fullfilename[PATH_MAX];
939 	picl_nodehdl_t  rooth;
940 	int		i;
941 
942 
943 	/*
944 	 * Initialize sensorp and other fields in the sensor_nodes[] array
945 	 */
946 
947 	for (i = 0; i < N_SENSOR_NODES; i++) {
948 		snodep = &sensor_nodes[i];
949 		snodep->sensorp = sensor_lookup(snodep->sensor_name);
950 		snodep->nodeh = 0;
951 		snodep->proph = 0;
952 		snodep->target_proph = 0;
953 	}
954 
955 	/*
956 	 * Initialize fanp and other fields in the fan_nodes[] array
957 	 */
958 	for (i = 0; i < N_FAN_NODES; i++) {
959 		fnodep = &fan_nodes[i];
960 		fnodep->fanp = fan_lookup(fnodep->fan_name);
961 		fnodep->nodeh = 0;
962 		fnodep->proph = 0;
963 	}
964 
965 	/*
966 	 * Initialize diskp and other fields in the disk_nodes[] array
967 	 */
968 	for (i = 0; i < N_DISK_NODES; i++) {
969 		dnodep = &disk_nodes[i];
970 		dnodep->diskp = disk_lookup(dnodep->disk_name);
971 		dnodep->nodeh = 0;
972 		dnodep->proph = 0;
973 	}
974 
975 	/*
976 	 * Get platform handle and populate PICL tree with environmental
977 	 * nodes and properties
978 	 */
979 	err = ptree_get_node_by_path("/platform", &plath);
980 
981 	if (err == PICL_SUCCESS) {
982 		sensor_err = add_sensor_nodes_and_props();
983 		fan_err = add_fan_nodes_and_props();
984 		if (disk_temp_monitor)
985 			disk_err = add_disk_nodes_and_props();
986 	}
987 
988 	/*
989 	 * We can safely call delete_xxx_nodes_and_props even
990 	 * if nodes were not added.
991 	 */
992 
993 	if (err != PICL_SUCCESS) {
994 		if (fan_err != PICL_SUCCESS)
995 			delete_fan_nodes_and_props();
996 		if (disk_err != PICL_SUCCESS)
997 			delete_disk_nodes_and_props();
998 		if (sensor_err != PICL_SUCCESS)
999 			delete_sensor_nodes_and_props();
1000 
1001 	envd_log(LOG_CRIT, ENVD_PICL_SETUP_FAILED);
1002 		return;
1003 	}
1004 	if (env_debug)
1005 		envd_log(LOG_ERR, "parsing the envmodel.conf file...\n");
1006 
1007 	/*
1008 	 * Parse the envmodel.conf file and populate the PICL tree
1009 	 */
1010 	if (get_envmodel_conf_file(fullfilename) < 0)
1011 		envd_log(LOG_CRIT, ENVD_PICL_SETUP_FAILED);
1012 	if (ptree_get_root(&rooth) != PICL_SUCCESS)
1013 		envd_log(LOG_CRIT, ENVD_PICL_SETUP_FAILED);
1014 	err = picld_pluginutil_parse_config_file(rooth, fullfilename);
1015 
1016 	if (err != PICL_SUCCESS)
1017 		envd_log(LOG_CRIT, ENVD_PICL_SETUP_FAILED);
1018 }
1019