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 1999-2003 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 * Littleneck platform specific environment monitoring policies 31 */ 32 33 #include <syslog.h> 34 #include <unistd.h> 35 #include <stdio.h> 36 #include <libintl.h> 37 #include <string.h> 38 #include <stdlib.h> 39 #include <errno.h> 40 #include <sys/types.h> 41 #include <fcntl.h> 42 #include <sys/time.h> 43 #include <sys/time_impl.h> 44 #include <sys/signal.h> 45 #include <sys/devctl.h> 46 #include <libdevinfo.h> 47 #include <libdevice.h> 48 #include <picl.h> 49 #include <picltree.h> 50 51 #include <psvc_objects.h> 52 53 /*LINTLIBRARY*/ 54 55 #define LOWTEMP_CRITICAL_MSG \ 56 gettext("CRITICAL : LOW TEMPERATURE DETECTED %d, %s") 57 #define LOWTEMP_WARNING_MSG \ 58 gettext("WARNING : LOW TEMPERATURE DETECTED %d, %s") 59 #define HIGHTEMP_CRITICAL_MSG \ 60 gettext("CRITICAL : HIGH TEMPERATURE DETECTED %d, %s") 61 #define HIGHTEMP_WARNING_MSG \ 62 gettext("WARNING : HIGH TEMPERATURE DETECTED %d, %s") 63 #define DEVICE_INSERTED_MSG gettext("Device %s inserted") 64 #define DEVICE_REMOVED_MSG gettext("Device %s removed") 65 #define PS_TYPE_MSG \ 66 gettext("WARNING: Incorrect type power supply inserted, device %s") 67 #define DEVICE_FAILURE_MSG \ 68 gettext("WARNING: Device %s failure detected by sensor %s\n") 69 #define DEVICE_OK_MSG gettext("Device %s OK") 70 #define DEVTREE_NODE_CREATE_FAILED \ 71 gettext("psvc PICL plugin: Failed to create node for %s, errno = %d") 72 #define DEVTREE_NODE_DELETE_FAILED \ 73 gettext("psvc PICL plugin: Failed to delete node for %s, errno = %d") 74 #define NO_FRU_INFO \ 75 gettext("No FRU Information for %s using default temperatures\n") 76 77 static char *shutdown_string = "shutdown -y -g 60 -i 5 \"OVERTEMP condition\""; 78 79 typedef struct seg_desc { 80 int32_t segdesc; 81 int16_t segoffset; 82 int16_t seglength; 83 } seg_desc_t; 84 85 static int32_t find_segment(psvc_opaque_t hdlp, char *fru, seg_desc_t *segment, 86 char *seg_to_find); 87 88 static int temp_attr[] = { 89 PSVC_HW_HI_SHUT_ATTR, PSVC_HI_SHUT_ATTR, PSVC_HI_WARN_ATTR, 90 PSVC_LO_WARN_ATTR, PSVC_LO_SHUT_ATTR, PSVC_HW_LO_SHUT_ATTR 91 }; 92 93 #define MAX_TEMP_ATTR (sizeof (temp_attr)/sizeof (temp_attr[0])) 94 #define TEMP_OFFSET 12 95 #define PART_NO_OFFSET 152 96 #define NUM_OF_SEG_ADDR 0x1805 97 #define SEG_DESC_START 0x1806 98 #define PSVC_NO_DEVICE -2 99 100 int32_t 101 find_segment(psvc_opaque_t hdlp, char *fru, seg_desc_t *segment, 102 char seg_to_find[2]) 103 { 104 int32_t seg_found = 0, status; 105 int32_t seg_desc_start = SEG_DESC_START, j; 106 int8_t seg_count; 107 char seg_name[2]; 108 fru_info_t fru_data; 109 110 /* 111 * Read the number of segments in the Read Only section 112 */ 113 fru_data.buf_start = NUM_OF_SEG_ADDR; 114 fru_data.buf = (char *)&seg_count; 115 fru_data.read_size = 1; 116 117 status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 118 &fru_data); 119 /* 120 * We test for ENOENT and ENXIO because Littleneck does not 121 * have actual presence sensors and so the only way to see 122 * if a part is there or not is to actually make a call to 123 * that part. 124 */ 125 if (status != PSVC_SUCCESS) { 126 if ((errno == ENOENT) || (errno == ENXIO)) 127 return (PSVC_NO_DEVICE); 128 else 129 return (PSVC_FAILURE); 130 } 131 /* 132 * Read in each segment to find the segment we are looking for 133 */ 134 for (j = 0; (j < seg_count) && (!(seg_found)); j++) { 135 fru_data.buf_start = seg_desc_start; 136 fru_data.buf = seg_name; 137 fru_data.read_size = 2; 138 139 status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 140 &fru_data); 141 142 seg_desc_start = seg_desc_start + 2; 143 fru_data.buf_start = seg_desc_start; 144 fru_data.buf = (char *)segment; 145 fru_data.read_size = sizeof (seg_desc_t); 146 147 status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 148 &fru_data); 149 if (status != PSVC_SUCCESS) { 150 syslog(LOG_ERR, 151 "Failed psvc_get_attr for FRU info\n"); 152 return (PSVC_FAILURE); 153 } 154 seg_desc_start = seg_desc_start + sizeof (seg_desc_t); 155 if (memcmp(seg_name, seg_to_find, 2) == 0) { 156 seg_found = 1; 157 } 158 } 159 return (seg_found); 160 } 161 162 int32_t 163 psvc_update_thresholds_0(psvc_opaque_t hdlp, char *id) 164 { 165 int32_t status = PSVC_SUCCESS; 166 fru_info_t fru_data; 167 char *fru, part_no[7]; 168 int16_t data_offset; 169 int32_t fru_count, i, j, temp_address; 170 int32_t seg_found, temp; 171 seg_desc_t segment; 172 int8_t temps[MAX_TEMP_ATTR]; 173 int32_t num_of_parts = 2; 174 char fruless_parts[2][7] = {"5015988", "5015675"}; 175 int fd; 176 FILE *fp; 177 178 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &fru_count, 179 PSVC_FRU); 180 if (status == PSVC_FAILURE) 181 return (status); 182 183 for (i = 0; i < fru_count; i++) { 184 seg_found = 0; 185 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 186 &fru, PSVC_FRU, i); 187 if (status != PSVC_SUCCESS) 188 return (status); 189 seg_found = find_segment(hdlp, fru, &segment, "ES"); 190 if (seg_found == PSVC_FAILURE) 191 return (PSVC_FAILURE); 192 else if (seg_found == PSVC_NO_DEVICE) 193 return (PSVC_SUCCESS); 194 if (seg_found) { 195 /* 196 * For Littleneck we need to read the offset of the 197 * die-sensor data record 198 */ 199 temp_address = segment.segoffset + TEMP_OFFSET; 200 fru_data.buf_start = temp_address; 201 fru_data.buf = (char *)&data_offset; 202 fru_data.read_size = sizeof (data_offset); 203 status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 204 &fru_data); 205 if (status != PSVC_SUCCESS) { 206 syslog(LOG_ERR, 207 "Failed psvc_get_attr for FRU info\n"); 208 return (status); 209 } 210 211 /* 212 * Now go and get the new temperature settings 213 */ 214 temp_address = segment.segoffset + data_offset; 215 fru_data.buf_start = temp_address; 216 fru_data.buf = (char *)&temps; 217 fru_data.read_size = sizeof (temps); 218 status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 219 &fru_data); 220 if (status != PSVC_SUCCESS) { 221 syslog(LOG_ERR, 222 "Failed psvc_get_attr for FRU info\n"); 223 return (status); 224 } else { 225 /* 226 * Now set the updated Thresholds 227 */ 228 for (j = 0; j < MAX_TEMP_ATTR; j++) { 229 temp = temps[j]; 230 status = psvc_set_attr(hdlp, id, 231 temp_attr[j], &temp); 232 } 233 } 234 } else { 235 /* 236 * For Littleneck only we need to check for the part 237 * number of the CPU as there are parts that do not 238 * have the ES segment programmed. 239 */ 240 seg_found = find_segment(hdlp, fru, &segment, "SD"); 241 if (seg_found == PSVC_FAILURE) 242 return (PSVC_FAILURE); 243 if (seg_found) { 244 /* 245 * We now goto the SD segment to get the part 246 * number. 247 */ 248 fru_data.buf_start = 249 segment.segoffset + PART_NO_OFFSET; 250 fru_data.buf = part_no; 251 fru_data.read_size = sizeof (part_no); 252 status = psvc_get_attr(hdlp, fru, 253 PSVC_FRU_INFO_ATTR, &fru_data); 254 if (status != PSVC_SUCCESS) { 255 syslog(LOG_ERR, "Failed psvc_get_attr" 256 "for FRU info\n"); 257 return (status); 258 } 259 /* 260 * We are go through the parts list to see 261 * if the part number from the FRU is in 262 * this list. If it is we simply return 263 * as the FRU is not programmed. 264 */ 265 for (j = 0; j < num_of_parts; j++) { 266 if (memcmp(fruless_parts[j], part_no, 267 7) == 0) { 268 return (status); 269 } 270 } 271 } 272 273 /* 274 * If the Part is not in the Part list and we 275 * get to here this means that the FRU is 276 * considered broken (no ES segment found) 277 * and we need to report this. 278 */ 279 /* 280 * We make this open, write, close, call 281 * because picld starts in rcS.d while print 282 * services does not start until later 283 * (either rc2.d or rc3.d). 284 */ 285 fd = open("/dev/console", O_WRONLY | O_NOCTTY); 286 if (fd != -1) { 287 fp = fdopen(fd, "w+"); 288 if (fp != NULL) { 289 fprintf(fp, NO_FRU_INFO, id); 290 fclose(fp); 291 } 292 close(fd); 293 } 294 syslog(LOG_NOTICE, NO_FRU_INFO, id); 295 } 296 } 297 return (status); 298 } 299 300 int32_t 301 psvc_check_temperature_policy_0(psvc_opaque_t hdlp, char *id) 302 { 303 int32_t lo_warn, hi_warn, lo_shut, hi_shut; 304 uint64_t features; 305 int32_t temp; 306 char previous_state[32]; 307 char state[32]; 308 char fault[32]; 309 char label[32]; 310 boolean_t pr; 311 int32_t status = PSVC_SUCCESS; 312 313 status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &pr); 314 if ((status != PSVC_SUCCESS) || (pr != PSVC_PRESENT)) { 315 return (status); 316 } 317 318 status = psvc_get_attr(hdlp, id, PSVC_SENSOR_VALUE_ATTR, &temp); 319 if (status != PSVC_SUCCESS) { 320 if ((errno == ENOENT) || (errno == ENXIO)) 321 return (PSVC_SUCCESS); 322 else 323 return (PSVC_FAILURE); 324 } 325 326 status = psvc_get_attr(hdlp, id, PSVC_FEATURES_ATTR, &features); 327 if (status != PSVC_SUCCESS) 328 return (status); 329 330 status = psvc_get_attr(hdlp, id, PSVC_LO_WARN_ATTR, &lo_warn); 331 if (status != PSVC_SUCCESS) 332 return (status); 333 334 status = psvc_get_attr(hdlp, id, PSVC_LO_SHUT_ATTR, &lo_shut); 335 if (status != PSVC_SUCCESS) 336 return (status); 337 338 status = psvc_get_attr(hdlp, id, PSVC_HI_WARN_ATTR, &hi_warn); 339 if (status != PSVC_SUCCESS) 340 return (status); 341 342 status = psvc_get_attr(hdlp, id, PSVC_HI_SHUT_ATTR, &hi_shut); 343 if (status != PSVC_SUCCESS) 344 return (status); 345 346 status = psvc_get_attr(hdlp, id, PSVC_LABEL_ATTR, label); 347 if (status != PSVC_SUCCESS) 348 return (status); 349 350 if ((features & PSVC_LOW_SHUT) && temp <= lo_shut) { 351 strcpy(state, PSVC_ERROR); 352 strcpy(fault, PSVC_TEMP_LO_SHUT); 353 syslog(LOG_ERR, LOWTEMP_CRITICAL_MSG, temp, label); 354 } else if ((features & PSVC_LOW_WARN) && temp <= lo_warn) { 355 strcpy(state, PSVC_ERROR); 356 strcpy(fault, PSVC_TEMP_LO_WARN); 357 syslog(LOG_ERR, LOWTEMP_WARNING_MSG, temp, label); 358 } else if ((features & PSVC_HIGH_SHUT) && temp >= hi_shut) { 359 strcpy(state, PSVC_ERROR); 360 strcpy(fault, PSVC_TEMP_HI_SHUT); 361 syslog(LOG_ERR, HIGHTEMP_CRITICAL_MSG, temp, label); 362 } else if ((features & PSVC_HIGH_WARN) && temp >= hi_warn) { 363 strcpy(state, PSVC_ERROR); 364 strcpy(fault, PSVC_TEMP_HI_WARN); 365 syslog(LOG_ERR, HIGHTEMP_WARNING_MSG, temp, label); 366 } else { 367 /* within limits */ 368 strcpy(state, PSVC_OK); 369 strcpy(fault, PSVC_NO_FAULT); 370 } 371 372 status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state); 373 if (status != PSVC_SUCCESS) 374 return (status); 375 status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, fault); 376 if (status != PSVC_SUCCESS) 377 return (status); 378 status = psvc_get_attr(hdlp, id, PSVC_PREV_STATE_ATTR, 379 previous_state); 380 if (status != PSVC_SUCCESS) 381 return (status); 382 383 if (strcmp(previous_state, state) != 0) { 384 char *led_id; 385 uint8_t _8bit_val; 386 387 led_id = "SYSTEM_FAULT_LED_WR"; 388 389 status = psvc_get_attr(hdlp, led_id, 390 PSVC_GPIO_VALUE_ATTR, &_8bit_val); 391 if (status != PSVC_SUCCESS) 392 return (status); 393 if (strcmp(state, PSVC_ERROR) == 0) 394 _8bit_val &= 0xef; /* clear bit 4 */ 395 else 396 _8bit_val |= 0x10; /* set bit 4 */ 397 _8bit_val |= 0xe4; /* set bits 3, 5, 6, 7 */ 398 399 status = psvc_set_attr(hdlp, led_id, 400 PSVC_GPIO_VALUE_ATTR, &_8bit_val); 401 if (status != PSVC_SUCCESS) 402 return (status); 403 404 } 405 406 return (PSVC_SUCCESS); 407 } 408 409 static int32_t ps0_addr[] = {0, 0xac}; 410 static int32_t ps1_addr[] = {0, 0xae}; 411 412 int32_t 413 psvc_ps_hotplug_policy_0(psvc_opaque_t hdlp, char *id) 414 { 415 boolean_t presence, previous_presence; 416 int32_t status = PSVC_SUCCESS; 417 char label[32]; 418 int i; 419 int32_t led_count; 420 char state[32], fault[32]; 421 boolean_t ps_type; 422 char *sensor_id, *led_id; 423 char led_state[32]; 424 picl_nodehdl_t parent_node; 425 char parent_path[256]; 426 picl_nodehdl_t child_node; 427 int ps_instance; 428 devctl_hdl_t bus_handle, dev_handle; 429 devctl_ddef_t ddef_hdl; 430 char devpath[256]; 431 432 status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &presence); 433 if (status != PSVC_SUCCESS) 434 return (status); 435 status = psvc_get_attr(hdlp, id, PSVC_PREV_PRESENCE_ATTR, 436 &previous_presence); 437 if (status != PSVC_SUCCESS) 438 return (status); 439 440 if (presence == previous_presence) { 441 /* No change */ 442 return (status); 443 } 444 445 status = psvc_get_attr(hdlp, id, PSVC_LABEL_ATTR, label); 446 if (status != PSVC_SUCCESS) 447 return (status); 448 449 /* Convert name to node and parent path */ 450 psvcplugin_lookup(id, parent_path, &child_node); 451 452 if (presence == PSVC_PRESENT) { 453 454 /* may detect presence before all connections are made */ 455 sleep(1); 456 457 /* Device added */ 458 syslog(LOG_ERR, DEVICE_INSERTED_MSG, label); 459 460 461 /* Verify P/S is correct type */ 462 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 463 &sensor_id, PSVC_DEV_TYPE_SENSOR, 0); 464 if (status != PSVC_SUCCESS) 465 return (status); 466 status = psvc_get_attr(hdlp, sensor_id, 467 PSVC_GPIO_VALUE_ATTR, &ps_type); 468 if (status != PSVC_SUCCESS) 469 return (status); 470 471 if (ps_type == 1) { /* correct p/s */ 472 strcpy(state, PSVC_OK); 473 strcpy(fault, PSVC_NO_FAULT); 474 strcpy(led_state, PSVC_LED_OFF); 475 } else { /* wrong type */ 476 strcpy(state, PSVC_ERROR); 477 strcpy(fault, PSVC_PS_TYPE_FLT); 478 strcpy(led_state, PSVC_LED_ON); 479 syslog(LOG_ERR, PS_TYPE_MSG, label); 480 481 } 482 status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state); 483 if (status != PSVC_SUCCESS) 484 return (status); 485 status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, fault); 486 if (status != PSVC_SUCCESS) 487 return (status); 488 489 /* Set state of fault LEDs */ 490 status = psvc_get_attr(hdlp, sensor_id, PSVC_ASSOC_MATCHES_ATTR, 491 &led_count, PSVC_DEV_FAULT_LED); 492 if (status != PSVC_SUCCESS) { 493 syslog(LOG_ERR, 494 gettext("Failed for PSVC_DEV_FAULT_LED\n")); 495 return (status); 496 } 497 for (i = 0; i < led_count; ++i) { 498 status = psvc_get_attr(hdlp, sensor_id, 499 PSVC_ASSOC_ID_ATTR, &led_id, 500 PSVC_DEV_FAULT_LED, i); 501 if (status != PSVC_SUCCESS) 502 return (status); 503 status = psvc_set_attr(hdlp, led_id, 504 PSVC_LED_STATE_ATTR, led_state); 505 if (status != PSVC_SUCCESS) 506 return (status); 507 } 508 ptree_get_node_by_path(parent_path, &parent_node); 509 ptree_add_node(parent_node, child_node); 510 } else { 511 /* Device removed */ 512 syslog(LOG_ERR, DEVICE_REMOVED_MSG, label); 513 ptree_delete_node(child_node); 514 } 515 516 status = psvc_set_attr(hdlp, id, PSVC_PREV_PRESENCE_ATTR, &presence); 517 if (status != PSVC_SUCCESS) 518 return (status); 519 520 status = psvc_get_attr(hdlp, id, PSVC_INSTANCE_ATTR, &ps_instance); 521 if (status != PSVC_SUCCESS) 522 return (status); 523 524 if (presence != PSVC_PRESENT) { 525 if (ps_instance == 0) 526 strcpy(devpath, 527 "/devices/pci@8,700000/ebus@5/i2c@1,30/power-supply@0,ac:power-supply"); 528 else 529 strcpy(devpath, 530 "/devices/pci@8,700000/ebus@5/i2c@1,30/power-supply@0,ae:power-supply"); 531 532 dev_handle = devctl_device_acquire(devpath, 0); 533 534 if (devctl_device_remove(dev_handle)) { 535 syslog(LOG_ERR, DEVTREE_NODE_DELETE_FAILED, label, 536 errno); 537 status = PSVC_FAILURE; 538 } else { 539 devctl_release(dev_handle); 540 status = PSVC_SUCCESS; 541 } 542 return (status); 543 } 544 545 /* 546 * We fall through to here if the device has been inserted. 547 * Add the devinfo tree node entry for the seeprom and attach 548 * the i2c seeprom driver 549 */ 550 ddef_hdl = devctl_ddef_alloc("power-supply", 0); 551 (void) devctl_ddef_string(ddef_hdl, "compatible", "i2c-at24c64"); 552 if (ps_instance == 0) { 553 (void) devctl_ddef_int_array(ddef_hdl, "reg", 2, ps0_addr); 554 } else { 555 (void) devctl_ddef_int_array(ddef_hdl, "reg", 2, ps1_addr); 556 } 557 558 bus_handle = devctl_bus_acquire( 559 "/devices/pci@8,700000/ebus@5/i2c@1,30:i2c", 0); 560 if (devctl_bus_dev_create(bus_handle, ddef_hdl, 0, &dev_handle)) { 561 syslog(LOG_ERR, DEVTREE_NODE_CREATE_FAILED, label, errno); 562 status = PSVC_FAILURE; 563 } else 564 devctl_release(dev_handle); 565 566 devctl_release(bus_handle); 567 devctl_ddef_free(ddef_hdl); 568 569 return (status); 570 } 571 572 int32_t 573 psvc_device_fail_notifier_policy_0(psvc_opaque_t hdlp, char *id) 574 { 575 int32_t sensor_count; 576 char *led_id, *sensor_id; 577 int i; 578 char state[32], fault[32], previous_state[32]; 579 int32_t status = PSVC_SUCCESS; 580 boolean_t present; 581 582 status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present); 583 if (status == PSVC_FAILURE) 584 return (status); 585 586 if (present == PSVC_ABSENT) { 587 errno = ENODEV; 588 return (PSVC_FAILURE); 589 } 590 591 psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &sensor_count, 592 PSVC_DEV_FAULT_SENSOR); 593 for (i = 0; i < sensor_count; ++i) { 594 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 595 &sensor_id, PSVC_DEV_FAULT_SENSOR, i); 596 if (status != PSVC_SUCCESS) 597 return (status); 598 599 status = psvc_get_attr(hdlp, sensor_id, 600 PSVC_SWITCH_STATE_ATTR, state); 601 if (status != PSVC_SUCCESS) 602 return (status); 603 604 if (strcmp(state, PSVC_SWITCH_ON) == 0) { 605 strcpy(state, PSVC_ERROR); 606 strcpy(fault, PSVC_GEN_FAULT); 607 } else { 608 strcpy(state, PSVC_OK); 609 strcpy(fault, PSVC_NO_FAULT); 610 } 611 612 status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state); 613 if (status != PSVC_SUCCESS) 614 return (status); 615 status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, fault); 616 if (status != PSVC_SUCCESS) 617 return (status); 618 status = psvc_get_attr(hdlp, id, PSVC_PREV_STATE_ATTR, 619 previous_state); 620 if (status != PSVC_SUCCESS) 621 return (status); 622 623 if (strcmp(state, previous_state) != 0) { 624 char sensor_label[32]; 625 char dev_label[32]; 626 uint8_t _8bit_val; 627 628 psvc_get_attr(hdlp, id, PSVC_LABEL_ATTR, dev_label); 629 psvc_get_attr(hdlp, sensor_id, PSVC_LABEL_ATTR, 630 sensor_label); 631 if (strcmp(state, PSVC_ERROR) == 0) 632 syslog(LOG_ERR, DEVICE_FAILURE_MSG, dev_label, 633 sensor_label); 634 else 635 syslog(LOG_ERR, DEVICE_OK_MSG, dev_label); 636 637 led_id = "SYSTEM_FAULT_LED_WR"; 638 639 status = psvc_get_attr(hdlp, led_id, 640 PSVC_GPIO_VALUE_ATTR, &_8bit_val); 641 if (status != PSVC_SUCCESS) 642 return (status); 643 644 if (strcmp(state, PSVC_ERROR) == 0) 645 _8bit_val &= 0xef; /* clear bit 4 */ 646 else 647 _8bit_val |= 0x10; /* set bit 4 */ 648 _8bit_val |= 0xe4; /* set bits 3, 5, 6, 7 */ 649 650 status = psvc_set_attr(hdlp, led_id, 651 PSVC_GPIO_VALUE_ATTR, &_8bit_val); 652 if (status != PSVC_SUCCESS) 653 return (status); 654 655 } 656 } 657 658 return (PSVC_SUCCESS); 659 } 660 661 int32_t 662 psvc_init_led_policy_0(psvc_opaque_t hdlp, char *id) 663 { 664 int32_t status = PSVC_SUCCESS; 665 uint8_t _8bit_val; 666 667 status = psvc_get_attr(hdlp, id, 668 PSVC_GPIO_VALUE_ATTR, &_8bit_val); 669 if (status != PSVC_SUCCESS) 670 return (status); 671 672 _8bit_val &= 0xef; /* clear bit 4 */ 673 _8bit_val |= 0xf4; /* set bits 3, 5, 6, 7 */ 674 675 status = psvc_set_attr(hdlp, id, 676 PSVC_GPIO_VALUE_ATTR, &_8bit_val); 677 if (status != PSVC_SUCCESS) 678 return (status); 679 680 return (status); 681 } 682 683 static int32_t 684 check_cpu_temp_fault(psvc_opaque_t hdlp, char *cpu, int32_t cpu_count) 685 { 686 char *sensorid; 687 int32_t sensor_count; 688 int32_t status = PSVC_SUCCESS; 689 int32_t i; 690 char fault[32]; 691 692 psvc_get_attr(hdlp, cpu, PSVC_ASSOC_MATCHES_ATTR, &sensor_count, 693 PSVC_DEV_TEMP_SENSOR); 694 for (i = 0; i < sensor_count; ++i) { 695 status = psvc_get_attr(hdlp, cpu, PSVC_ASSOC_ID_ATTR, 696 &sensorid, PSVC_DEV_TEMP_SENSOR, i); 697 if (status == PSVC_FAILURE) 698 return (status); 699 700 status = psvc_get_attr(hdlp, sensorid, PSVC_FAULTID_ATTR, 701 fault); 702 if (status == PSVC_FAILURE) 703 return (status); 704 705 if ((strcmp(fault, PSVC_TEMP_HI_SHUT) == 0) || 706 (strcmp(fault, PSVC_TEMP_LO_SHUT) == 0)) { 707 system(shutdown_string); 708 } 709 } 710 711 return (status); 712 } 713 714 int32_t 715 psvc_shutdown_policy_0(psvc_opaque_t hdlp, char *id) 716 { 717 int32_t cpu_count; 718 char *cpuid; 719 int32_t i; 720 boolean_t present; 721 int32_t status = PSVC_SUCCESS; 722 723 psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &cpu_count, 724 PSVC_CPU); 725 for (i = 0; i < cpu_count; ++i) { 726 727 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, &cpuid, 728 PSVC_CPU, i); 729 if (status == PSVC_FAILURE) 730 return (status); 731 732 status = psvc_get_attr(hdlp, cpuid, 733 PSVC_PRESENCE_ATTR, &present); 734 if (status == PSVC_FAILURE && present == PSVC_PRESENT) 735 return (status); 736 if (present == PSVC_PRESENT) { 737 status = check_cpu_temp_fault(hdlp, cpuid, cpu_count); 738 if (status == PSVC_FAILURE && errno != ENODEV) 739 return (status); 740 } 741 } 742 743 return (PSVC_SUCCESS); 744 } 745