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