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