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