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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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