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