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