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 (c) 1999-2001 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29/*
30 * This file contains code for setting up environmental related nodes
31 * and properties in the PICL tree.
32 *
33 * For each temperature-device class node, it does the following:
34 *	- Create cpu and cpu-ambient temperautre-sensor class nodes.
35 *	- Create "devfs-path" property under each temperature-sensor class node
36 *	- Create "Temperature" volatile property under these nodes.
37 *	- Create various temperature threshold properties under each node.
38 *	- Create "Temperature" and "AmbientTemperature" volatile properties
39 *	  under corresponding "cpu" class node.
40 *
41 * For the "fan-control" node, it does the following:
42 *	- Create system-fan node
43 *	- Create "devfs-path" property under "fan" class node
44 *	- Create "Speed" volatile propery under each node.
45 *	- Create "SpeedUnit" property under each node.
46 */
47
48#include <stdio.h>
49#include <fcntl.h>
50#include <unistd.h>
51#include <syslog.h>
52#include <stdlib.h>
53#include <limits.h>
54#include <sys/open.h>
55#include <ctype.h>
56#include <string.h>
57#include <alloca.h>
58#include <libintl.h>
59#include <sys/systeminfo.h>
60#include <picl.h>
61#include <picltree.h>
62#include <picld_pluginutil.h>
63#include <pthread.h>
64#include <sys/utsname.h>
65#include <sys/systeminfo.h>
66#include "envd.h"
67
68
69/*
70 * Volatile property read/write function typedef
71 */
72typedef int ptree_vol_rdfunc_t(ptree_rarg_t *parg, void *buf);
73typedef int ptree_vol_wrfunc_t(ptree_warg_t *parg, const void *buf);
74
75/*
76 * PICL Classes and standard property names
77 */
78#define	PICL_CLASS_CPU		"cpu"
79#define	PICL_CLASS_FAN		"fan"
80#define	PICL_CLASS_FAN_CONTROL	"fan-control"
81#define	PICL_CLASS_TEMP_DEVICE	"temperature-device"
82#define	PICL_CLASS_TEMP_SENSOR	"temperature-sensor"
83
84#define	PICL_PROP_REG		"reg"
85#define	PICL_PROP_DEVFS_PATH	"devfs-path"
86#define	PICL_PROP_UNIT_ADDRESS	"UnitAddress"
87#define	UNITADDR_LEN_MAX	256	/* max length for UnitAddress */
88
89/*
90 * temperature properties
91 */
92#define	PROP_TEMPERATURE	"Temperature"
93#define	PROP_CPU_AMB_TEMP	"AmbientTemperature"
94#define	PROP_CPU_DIE_TEMP	"Temperature"
95
96/*
97 * Various temperature threshold property names
98 */
99#define	PROP_LOW_POWER_OFF	"LowPowerOffThreshold"
100#define	PROP_LOW_SHUTDOWN	"LowShutdownThreshold"
101#define	PROP_LOW_WARNING	"LowWarningThreshold"
102#define	PROP_HIGH_POWER_OFF	"HighPowerOffThreshold"
103#define	PROP_HIGH_SHUTDOWN	"HighShutdownThreshold"
104#define	PROP_HIGH_WARNING	"HighWarningThreshold"
105
106/*
107 * fan properties
108 */
109#define	PROP_FAN_SPEED		"Speed"
110#define	PROP_FAN_SPEED_UNIT	"SpeedUnit"
111#define	PROP_FAN_SPEED_UNIT_VALUE	"%"
112
113/*
114 * PICL class path for CPU nodes
115 */
116#define	CPU_PLAT_PATH		"_class:/upa/cpu?ID=0"
117
118/*
119 * "UnitAddress" propval for various temperature devices (platform dependent)
120 */
121#define	CPU_TEMPDEV_UNITADDR	"0,30"
122
123/*
124 * Sensor node data structure
125 */
126typedef struct {
127	char		*sensor_name;	/* sensor name */
128	env_sensor_t	*sensorp;	/* sensor info */
129	char		*unitaddr;	/* parent's UnitAddress propval */
130	char		*sdev_node;	/* sensed device node name */
131	char		*sdev_pname;	/* sensed device "temp" prop name */
132	picl_nodehdl_t	nodeh;		/* sensor node handle */
133	picl_prophdl_t	proph;		/* "Temperature" property handle */
134	picl_prophdl_t	sdev_proph;	/* property handle for sensed dev */
135} sensor_node_t;
136
137
138/*
139 * Sensor nodes array
140 */
141static sensor_node_t sensor_nodes[] = {
142	{SENSOR_CPU_DIE, NULL, CPU_TEMPDEV_UNITADDR,
143	    CPU_PLAT_PATH, PROP_CPU_DIE_TEMP},
144
145	{SENSOR_CPU_AMB, NULL, CPU_TEMPDEV_UNITADDR,
146	    CPU_PLAT_PATH, PROP_CPU_AMB_TEMP},
147
148	{NULL, NULL, NULL, NULL, NULL}
149};
150
151
152/*
153 * Fan node data structure
154 */
155typedef struct {
156	char		*fan_name;	/* fan name */
157	env_fan_t 	*fanp;		/* fan information */
158	char		*speed_unit;	/* speed unit string */
159	picl_nodehdl_t	nodeh;		/* "fan" node handle */
160	picl_prophdl_t	proph;		/* "Speed" property handle */
161} fan_node_t;
162
163
164/*
165 * Fan node array
166 */
167static fan_node_t fan_nodes[] =  {
168	{ENV_SYSTEM_FAN, NULL, PROP_FAN_SPEED_UNIT_VALUE},
169	{NULL, NULL, NULL}
170};
171
172/*
173 * Miscellaneous declarations
174 */
175typedef struct node_list {
176	picl_nodehdl_t		nodeh;
177	struct node_list	*next;
178} node_list_t;
179
180static void delete_sensor_nodes_and_props(void);
181static void delete_fan_nodes_and_props(void);
182
183
184
185/*
186 * Read function for volatile "Temperature" property
187 */
188static int
189get_current_temp(ptree_rarg_t *parg, void *buf)
190{
191	tempr_t 	temp;
192	picl_prophdl_t	proph;
193	sensor_node_t	*snodep;
194
195	/*
196	 * Locate the sensor in our sensor_nodes table by matching the
197	 * property handle and get its temperature.
198	 */
199	proph = parg->proph;
200	for (snodep = &sensor_nodes[0]; snodep->sensor_name != NULL; snodep++) {
201		if (snodep->proph != proph &&
202		    snodep->sdev_proph != proph)
203			continue;
204
205		if (get_temperature(snodep->sensorp, &temp) < 0)
206			return (PICL_FAILURE);
207		(void) memcpy(buf, (caddr_t)&temp, sizeof (tempr_t));
208		return (PICL_SUCCESS);
209	}
210	return (PICL_FAILURE);
211}
212
213
214/*
215 * Read function for volatile "Speed" property on "fan" class node
216 */
217static int
218get_current_speed(ptree_rarg_t *parg, void *buf)
219{
220	fanspeed_t	speed;
221	picl_prophdl_t	proph;
222	fan_node_t	*fnodep;
223
224	/*
225	 * Locate the fan in our fan_nodes table by matching the
226	 * property handle and get fan speed.
227	 */
228	proph = parg->proph;
229	for (fnodep = &fan_nodes[0]; fnodep->fan_name != NULL; fnodep++) {
230		if (fnodep->proph != proph)
231			continue;
232		if (get_fan_speed(fnodep->fanp, &speed) < 0)
233			return (PICL_FAILURE);
234
235		(void) memcpy(buf, (caddr_t)&speed, sizeof (speed));
236		return (PICL_SUCCESS);
237	}
238	return (PICL_FAILURE);
239}
240
241
242static node_list_t *
243add_node_to_list(picl_nodehdl_t nodeh, node_list_t *listp)
244{
245	node_list_t	*el;
246	node_list_t	*tmp;
247
248	el = malloc(sizeof (node_list_t));
249	if (el == NULL)
250		return (listp);
251	el->nodeh = nodeh;
252	el->next = NULL;
253	if (listp == NULL) {
254		listp = el;
255		return (listp);
256	}
257
258	/*
259	 * append to the end to preserve the order found
260	 */
261	tmp = listp;
262	while (tmp->next != NULL)
263		tmp = tmp->next;
264
265	tmp->next = el;
266	return (listp);
267}
268
269
270
271/*
272 * Get a list of nodes of the specified classname under nodeh
273 * Once a node of the specified class is found, it's children are not
274 * searched.
275 */
276static node_list_t *
277get_node_list_by_class(picl_nodehdl_t nodeh, const char *classname,
278	node_list_t *listp)
279{
280	int		err;
281	char		clname[PICL_CLASSNAMELEN_MAX+1];
282	picl_nodehdl_t	chdh;
283
284	/*
285	 * go through the children
286	 */
287	err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, &chdh,
288	    sizeof (picl_nodehdl_t));
289
290	while (err == PICL_SUCCESS) {
291		err = ptree_get_propval_by_name(chdh, PICL_PROP_CLASSNAME,
292		    clname, strlen(classname) + 1);
293
294		if ((err == PICL_SUCCESS) && (strcmp(clname, classname) == 0))
295			listp = add_node_to_list(chdh, listp);
296		else
297			listp = get_node_list_by_class(chdh, classname, listp);
298
299		err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh,
300		    sizeof (picl_nodehdl_t));
301	}
302	return (listp);
303}
304
305
306/*
307 * Free memory allocated to build the specified node list.
308 */
309static void
310free_node_list(node_list_t *listp)
311{
312	node_list_t	*next;
313
314	for (; listp != NULL; listp = next) {
315		next = listp->next;
316		free(listp);
317	}
318}
319
320/*
321 * Get PICL_PTYPE_CHARSTRING "UnitAddress" property
322 */
323static int
324get_unit_address_prop(picl_nodehdl_t nodeh, void *buf, size_t len)
325{
326	int			err;
327	picl_prophdl_t		proph;
328	ptree_propinfo_t	pinfo;
329
330	err = ptree_get_prop_by_name(nodeh, PICL_PROP_UNIT_ADDRESS, &proph);
331	if (err == PICL_SUCCESS)
332		err = ptree_get_propinfo(proph, &pinfo);
333
334	if (err != PICL_SUCCESS)
335		return (err);
336
337	if (pinfo.piclinfo.type != PICL_PTYPE_CHARSTRING ||
338	    pinfo.piclinfo.size > len)
339		return (PICL_FAILURE);
340
341	err = ptree_get_propval(proph, buf, pinfo.piclinfo.size);
342	return (err);
343}
344
345
346/*
347 * Create and add the specified regular property
348 */
349
350static int
351add_regular_prop(picl_nodehdl_t nodeh, char *name, int type, int access,
352    int size, void *valbuf, picl_prophdl_t *prophp)
353{
354	int			err;
355	ptree_propinfo_t	propinfo;
356	picl_prophdl_t		proph;
357
358	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
359	    type, access, size, name, NULL, NULL);
360	if (err != PICL_SUCCESS)
361		return (err);
362
363	err = ptree_create_and_add_prop(nodeh, &propinfo, valbuf, &proph);
364	if (err == PICL_SUCCESS && prophp)
365		*prophp = proph;
366	return (err);
367}
368
369
370/*
371 * Create and add the specified volatile property
372 */
373static int
374add_volatile_prop(picl_nodehdl_t nodeh, char *name, int type, int access,
375    int size, ptree_vol_rdfunc_t *rdfunc, ptree_vol_wrfunc_t *wrfunc,
376    picl_prophdl_t *prophp)
377{
378	int			err;
379	ptree_propinfo_t	propinfo;
380	picl_prophdl_t		proph;
381
382	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
383	    type, (access|PICL_VOLATILE), size, name, rdfunc, wrfunc);
384	if (err != PICL_SUCCESS)
385		return (err);
386
387	err = ptree_create_and_add_prop(nodeh, &propinfo, NULL, &proph);
388	if (err == PICL_SUCCESS && prophp)
389		*prophp = proph;
390	return (err);
391}
392
393/*
394 * Add temperature threshold properties
395 */
396static void
397add_sensor_thresh_props(picl_nodehdl_t nodeh, sensor_thresh_t *threshp)
398{
399	picl_prophdl_t	proph;
400
401	(void) add_regular_prop(nodeh, PROP_LOW_POWER_OFF,
402	    PICL_PTYPE_INT, PICL_READ,
403	    sizeof (threshp->low_power_off),
404	    (void *)&(threshp->low_power_off), &proph);
405
406	(void) add_regular_prop(nodeh, PROP_LOW_SHUTDOWN,
407	    PICL_PTYPE_INT, PICL_READ,
408	    sizeof (threshp->low_shutdown),
409	    (void *)&(threshp->low_shutdown), &proph);
410
411	(void) add_regular_prop(nodeh, PROP_LOW_WARNING,
412	    PICL_PTYPE_INT, PICL_READ,
413	    sizeof (threshp->low_warning),
414	    (void *)&(threshp->low_warning), &proph);
415
416	(void) add_regular_prop(nodeh, PROP_HIGH_WARNING,
417	    PICL_PTYPE_INT, PICL_READ,
418	    sizeof (threshp->high_warning),
419	    (void *)&(threshp->high_warning), &proph);
420
421	(void) add_regular_prop(nodeh, PROP_HIGH_SHUTDOWN,
422	    PICL_PTYPE_INT, PICL_READ,
423	    sizeof (threshp->high_shutdown),
424	    (void *)&(threshp->high_shutdown), &proph);
425
426	(void) add_regular_prop(nodeh, PROP_HIGH_POWER_OFF,
427	    PICL_PTYPE_INT, PICL_READ,
428	    sizeof (threshp->high_power_off),
429	    (void *)&(threshp->high_power_off), &proph);
430}
431
432
433/*
434 * Lookup "temperature-device" class nodes and create "temperature-sensor"
435 * class nodes and relevant properties under those nodes.
436 *
437 * For each entry in sensor_nodes[] array, do the following:
438 *	- Create specified (cpu-die or cpu-ambient) "temperautre-sensor" class
439 *	  node.
440 *	- Create "devfs-path" property under this node.
441 *	- Create "Temperature" volatile property under this node.
442 *	- Create various temperature threshold properties under this node.
443 *	- Create specified ("Temperature" or "AmbientTemperature") volatile
444 *	  temperature property under specified sdev_node node.
445 */
446
447static int
448add_sensor_nodes_and_props(picl_nodehdl_t plath)
449{
450	int		err;
451	char		*pname, *nodename, *refnode, *devfs_path;
452	node_list_t	*node_list, *listp;
453	sensor_node_t	*snodep;
454	sensor_thresh_t *threshp;
455	picl_nodehdl_t	nodeh, refnodeh, cnodeh;
456	picl_prophdl_t	proph;
457	char		unitaddr[UNITADDR_LEN_MAX];
458	env_sensor_t	*sensorp;
459
460	node_list =
461	    get_node_list_by_class(plath, PICL_CLASS_TEMP_DEVICE, NULL);
462
463	if (node_list == NULL)
464		return (PICL_FAILURE);
465
466	for (listp = node_list; listp != NULL; listp = listp->next) {
467		/*
468		 * Get "reg" property. Skip if no "reg" property found.
469		 */
470		nodeh = listp->nodeh;
471		err = get_unit_address_prop(nodeh, (void *)unitaddr,
472		    sizeof (unitaddr));
473		if (err != PICL_SUCCESS)
474			continue;
475
476		for (snodep = sensor_nodes; snodep->sensor_name != NULL;
477		    snodep++) {
478
479			/* Match "UnitAddress" property */
480			if (strcasecmp(unitaddr, snodep->unitaddr) != 0)
481				continue;
482
483			/*
484			 * Skip if already initialized or no sensor info
485			 */
486			sensorp = snodep->sensorp;
487			if (snodep->nodeh != NULL || sensorp == NULL)
488				continue;
489
490			/*
491			 * Create temperature-sensor node
492			 */
493			nodename = snodep->sensor_name;
494			err = ptree_create_and_add_node(nodeh, nodename,
495			    PICL_CLASS_TEMP_SENSOR, &cnodeh);
496			if (env_debug)
497				envd_log(LOG_INFO,
498				    "Creating PICL sensor node '%s' err:%d\n",
499				    nodename, err);
500			if (err != PICL_SUCCESS)
501				break;
502
503			/* save node handle */
504			snodep->nodeh = cnodeh;
505
506			/*
507			 * Add "devfs_path" property in child node
508			 */
509			devfs_path = sensorp->devfs_path;
510			pname = PICL_PROP_DEVFS_PATH;
511			err = add_regular_prop(cnodeh, pname,
512			    PICL_PTYPE_CHARSTRING, PICL_READ,
513			    strlen(devfs_path)+1, (void *)devfs_path, &proph);
514			if (err != PICL_SUCCESS)
515				break;
516
517			/*
518			 * Now add volatile "temperature" volatile property
519			 * in this "temperature-sensor" class node.
520			 */
521			pname = PROP_TEMPERATURE;
522			err = add_volatile_prop(cnodeh, pname,
523			    PICL_PTYPE_INT, PICL_READ, sizeof (tempr_t),
524			    get_current_temp, NULL, &proph);
525			if (err != PICL_SUCCESS)
526				break;
527
528			/* Save prop handle */
529			snodep->proph = proph;
530
531			/*
532			 * Add threshold related properties
533			 */
534			threshp = sensorp->temp_thresh;
535			if (threshp != NULL)
536				add_sensor_thresh_props(cnodeh, threshp);
537
538			/*
539			 * Finally create property in the sensed device
540			 * (if one specified)
541			 */
542			refnode =  snodep->sdev_node;
543			pname =  snodep->sdev_pname;
544			if (refnode == NULL || pname == NULL)
545				continue;
546
547			err = ptree_get_node_by_path(refnode, &refnodeh);
548			if (err == PICL_SUCCESS) {
549				err = add_volatile_prop(refnodeh, pname,
550				    PICL_PTYPE_INT, PICL_READ,
551				    sizeof (tempr_t), get_current_temp,
552				    NULL, &proph);
553			}
554
555			if (err != PICL_SUCCESS)
556				break;
557
558			/* Save prop handle */
559			snodep->sdev_proph = proph;
560		}
561		if (err != PICL_SUCCESS) {
562			delete_sensor_nodes_and_props();
563			free_node_list(node_list);
564			if (env_debug)
565				envd_log(LOG_INFO,
566				    "Can't create prop/node for sensor '%s'\n",
567				    nodename);
568			return (err);
569		}
570	}
571
572	free_node_list(node_list);
573	return (PICL_SUCCESS);
574}
575
576/*
577 * Delete all sensor nodes and related properties created by the
578 * add_sensor_prop() for each sensor node in the PICL tree.
579 */
580static void
581delete_sensor_nodes_and_props(void)
582{
583	sensor_node_t	*snodep;
584
585	/*
586	 * Delete/destroy any property created in the sensed device
587	 * as well as the sensor node and all properties under it.
588	 * Note that deleiing/destroying a node deletes/destroys
589	 * all properties within that node.
590	 */
591
592	for (snodep = sensor_nodes; snodep->sensor_name != NULL; snodep++) {
593		if (snodep->sdev_proph != NULL) {
594			(void) ptree_delete_prop(snodep->sdev_proph);
595			(void) ptree_destroy_prop(snodep->sdev_proph);
596			snodep->sdev_proph = NULL;
597		}
598
599		if (snodep->nodeh != NULL) {
600			/* delete node and all properties under it */
601			(void) ptree_delete_node(snodep->nodeh);
602			(void) ptree_destroy_node(snodep->nodeh);
603			snodep->nodeh = NULL;
604			snodep->proph = NULL;
605		}
606	}
607}
608
609
610/*
611 * Lookup "fan-control" class node and create "fan" class nodes and
612 * relevant properties under those nodes.
613 *
614 * For each entry in fan_nodes[] array, do the following:
615 *	- Create specified "fan" class node.
616 *	- Create "devfs-path" property under "fan" class node
617 *	- Create "Speed" volatile propery under "fan" class node.
618 *	- Create "SpeedUnit" property under "fan" class node.
619 */
620
621static int
622add_fan_nodes_and_props(picl_nodehdl_t plath)
623{
624	int		err;
625	char		*pname, *nodename, *devfs_path;
626	env_fan_t	*fanp;
627	fan_node_t	*fnodep;
628	picl_nodehdl_t	nodeh, cnodeh;
629	picl_prophdl_t	proph;
630	node_list_t	*node_list, *listp;
631
632	node_list =
633	    get_node_list_by_class(plath, PICL_CLASS_FAN_CONTROL, NULL);
634
635	if (node_list == NULL)
636		return (PICL_FAILURE);
637
638	for (listp = node_list; listp != NULL; listp = listp->next) {
639		/*
640		 * Add various fan nodes and properties
641		 */
642		nodeh = listp->nodeh;
643		err = PICL_SUCCESS;
644		for (fnodep = fan_nodes; fnodep->fan_name != NULL; fnodep++) {
645
646			/* Skip if already initialized or no fan info */
647			if (fnodep->nodeh != NULL || fnodep->fanp == NULL)
648				continue;
649
650			/*
651			 * Create "fan" class node and save node handle
652			 */
653			nodename = fnodep->fan_name;
654			err = ptree_create_and_add_node(nodeh, nodename,
655			    PICL_CLASS_FAN, &cnodeh);
656			if (env_debug)
657				envd_log(LOG_INFO,
658				    "Creating PICL fan node '%s' err:%d\n",
659				    nodename, err);
660
661			if (err != PICL_SUCCESS)
662				break;
663			fnodep->nodeh = cnodeh;
664
665			/*
666			 * Add "devfs_path" property in child node
667			 */
668			fanp = fnodep->fanp;
669			devfs_path  = fanp->devfs_path;
670			pname = PICL_PROP_DEVFS_PATH;
671			err = add_regular_prop(cnodeh, pname,
672			    PICL_PTYPE_CHARSTRING, PICL_READ,
673			    strlen(devfs_path)+1, (void *)devfs_path, &proph);
674
675			if (err != PICL_SUCCESS)
676				break;
677
678			/*
679			 * Add "Speed" volatile property in this "fan"
680			 * class node and save prop handle.
681			 */
682			pname = PROP_FAN_SPEED;
683			err = add_volatile_prop(cnodeh, pname, PICL_PTYPE_INT,
684			    PICL_READ, sizeof (fanspeed_t), get_current_speed,
685			    NULL, &proph);
686
687			if (err != PICL_SUCCESS)
688				break;
689			fnodep->proph = proph;
690
691			/*
692			 * Add other "fan" class properties
693			 */
694			pname = PROP_FAN_SPEED_UNIT,
695			err = add_regular_prop(cnodeh, pname,
696			    PICL_PTYPE_CHARSTRING, PICL_READ,
697			    strlen(fnodep->speed_unit)+1,
698			    (void *)fnodep->speed_unit, &proph);
699
700			if (err != PICL_SUCCESS)
701				break;
702		}
703		if (err != PICL_SUCCESS) {
704			delete_fan_nodes_and_props();
705			free_node_list(node_list);
706			if (env_debug)
707				envd_log(LOG_WARNING,
708				    "Can't create prop/node for fan '%s'\n",
709				    nodename);
710			return (err);
711		}
712	}
713
714	free_node_list(node_list);
715	return (PICL_SUCCESS);
716}
717
718
719/*
720 * Delete all fan nodes and related properties created by the
721 * add_fan_props() for each fan node in the PICL tree.
722 */
723static void
724delete_fan_nodes_and_props(void)
725{
726	fan_node_t	*fnodep;
727
728	/*
729	 * Delete/destroy fan node and all properties under it.
730	 * Note that deleiing/destroying a node deletes/destroys
731	 * all properties within that node.
732	 */
733
734	for (fnodep = fan_nodes; fnodep->fan_name != NULL; fnodep++) {
735		if (fnodep->nodeh != NULL) {
736			(void) ptree_delete_node(fnodep->nodeh);
737			(void) ptree_destroy_node(fnodep->nodeh);
738			fnodep->nodeh = NULL;
739		}
740	}
741}
742
743/*
744 * Find the ENVMODEL_CONF_FILE file.
745 */
746static int
747get_envmodel_conf_file(char *outfilename)
748{
749	char	nmbuf[SYS_NMLN];
750	char    pname[PATH_MAX];
751
752	if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) {
753		(void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
754		(void) strlcat(pname, ENVMODEL_CONF_FILE, PATH_MAX);
755		if (access(pname, R_OK) == 0) {
756			(void) strlcpy(outfilename, pname, PATH_MAX);
757			return (0);
758		}
759	}
760
761	if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) {
762		(void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
763		(void) strlcat(pname, ENVMODEL_CONF_FILE, PATH_MAX);
764		if (access(pname, R_OK) == 0) {
765			(void) strlcpy(outfilename, pname, PATH_MAX);
766			return (0);
767		}
768	}
769
770	(void) snprintf(pname, PATH_MAX, "%s/%s", PICLD_COMMON_PLUGIN_DIR,
771		ENVMODEL_CONF_FILE);
772
773	if (access(pname, R_OK) == 0) {
774		(void) strlcpy(outfilename, pname, PATH_MAX);
775		return (0);
776	}
777
778	return (-1);
779}
780
781void
782env_picl_setup(void)
783{
784	int		err;
785	sensor_node_t	*snodep;
786	fan_node_t	*fnodep;
787	picl_nodehdl_t	plath;
788	char		fullfilename[PATH_MAX];
789	picl_nodehdl_t	rooth;
790
791	/*
792	 * Initialize sensorp and other fields in the sensor_nodes[] array
793	 */
794	for (snodep = sensor_nodes; snodep->sensor_name != NULL; snodep++) {
795		snodep->sensorp = sensor_lookup(snodep->sensor_name);
796		snodep->nodeh = NULL;
797		snodep->proph = NULL;
798		snodep->sdev_proph = NULL;
799	}
800
801	/*
802	 * Initialize fanp and other fields in the fan_nodes[] array
803	 */
804	for (fnodep = fan_nodes; fnodep->fan_name != NULL; fnodep++) {
805		fnodep->fanp = fan_lookup(fnodep->fan_name);
806		fnodep->nodeh = NULL;
807		fnodep->proph = NULL;
808	}
809
810	/*
811	 * Get platform handle and populate PICL tree with environmental
812	 * nodes and properties
813	 */
814	err = ptree_get_node_by_path("/platform", &plath);
815
816	if (err == PICL_SUCCESS) {
817		err = add_sensor_nodes_and_props(plath);
818		if (err == PICL_SUCCESS)
819			err = add_fan_nodes_and_props(plath);
820	}
821
822	if (err != PICL_SUCCESS) {
823		envd_log(LOG_CRIT, ENVD_PICL_SETUP_FAILED);
824		return;
825	}
826
827	/*
828	 * Parse the envmodel.conf file and populate the PICL tree
829	 */
830	if (get_envmodel_conf_file(fullfilename) < 0)
831		envd_log(LOG_CRIT, ENVD_PICL_SETUP_FAILED);
832	if (ptree_get_root(&rooth) != PICL_SUCCESS)
833		envd_log(LOG_CRIT, ENVD_PICL_SETUP_FAILED);
834	err = picld_pluginutil_parse_config_file(rooth, fullfilename);
835
836	if (err != PICL_SUCCESS)
837		envd_log(LOG_CRIT, ENVD_PICL_SETUP_FAILED);
838}
839