display_sun4v.c revision bbda49b50a1377654c8b28c2e87b39842f80ffde
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdio.h>
#include <stdlib.h>
#include <alloca.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <kvm.h>
#include <varargs.h>
#include <time.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/openpromio.h>
#include <libintl.h>
#include <syslog.h>
#include <sys/systeminfo.h>
#include <picldefs.h>
#include <math.h>
#include <errno.h>
#include "pdevinfo.h"
#include "display.h"
#include "display_sun4v.h"
#include "libprtdiag.h"
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
#define MOTHERBOARD "MB"
#define NETWORK "network"
#define SUN4V_MACHINE "sun4v"
#define PARENT_NAMES 10
/*
* Additional OBP properties
*/
#define OBP_PROP_COMPATIBLE "compatible"
#define OBP_PROP_MODEL "model"
#define OBP_PROP_SLOT_NAMES "slot-names"
#define OBP_PROP_VERSION "version"
#define PICL_NODE_PHYSICAL_PLATFORM "physical-platform"
#define PICL_NODE_CHASSIS "chassis"
#define MEMORY_SIZE_FIELD 11
#define INVALID_THRESHOLD 1000000
/*
* Additional picl classes
*/
#ifndef PICL_CLASS_SUN4V
#define PICL_CLASS_SUN4V "sun4v"
#endif
#ifndef PICL_PROP_NAC
#define PICL_PROP_NAC "nac"
#endif
extern int sys_clk;
picl_nodehdl_t *);
static picl_nodehdl_t chassish = 0;
static int class_node_found;
static int syserrlog;
static int all_status_ok;
/* local functions */
static int sun4v_get_first_compatible_value(picl_nodehdl_t, char **);
static void sun4v_display_memory_conf(picl_nodehdl_t);
static int sun4v_disp_env_status();
static void sun4v_env_print_fan_sensors();
static void sun4v_env_print_fan_indicators();
static void sun4v_env_print_temp_sensors();
static void sun4v_env_print_temp_indicators();
static void sun4v_env_print_current_sensors();
static void sun4v_env_print_current_indicators();
static void sun4v_env_print_voltage_sensors();
static void sun4v_env_print_voltage_indicators();
static void sun4v_env_print_LEDs();
static void sun4v_print_fru_status();
static int is_fru_absent(picl_nodehdl_t);
static void sun4v_print_fw_rev();
static void sun4v_print_chassis_serial_no();
static void sun4v_print_openprom_rev();
int
{
void *value; /* used for opaque PROM data */
int exit_code = 0;
return (1);
return (1);
/*
* Now display the machine's configuration. We do this if we
* are not logging.
*/
if (!logging) {
/*
* Display system banner
*/
/* display system clock frequency */
"frequency: %d MHz\n"), sys_clk, 0);
}
/* Display the Memory Size */
/* Display the CPU devices */
/* Display the Memory configuration */
class_node_found = 0;
/* Display all the IO cards. */
(void) sun4v_display_pci(plafh);
return (1);
/*
* The physical-platform node may be missing on systems with
* older firmware so don't consider that an error.
*/
&phyplatformh) != PICL_SUCCESS)
return (0);
PICL_PTYPE_CHARSTRING, (void *)PICL_CLASS_CHASSIS,
return (1);
}
return (exit_code);
}
/*
* The binding-name property encodes the bus type.
*/
static void
{
char val[PICL_PROPNAMELEN_MAX], *p, *q;
sizeof (val)) == PICL_SUCCESS) {
else {
/*
* Not perfect: process the binding-name until
* we encounter something that we don't think would
* be part of a bus type. This may get confused a bit
* if a device or vendor id is encoded right after
* the bus class since there's no delimiter. If the
* id number begins with a hex digit [abcdef] then
* this will become part of the bus type string
* reported by prtdiag. This is all an effort to
* print something potentially useful for bus types
*
* We do this because this code will get called for
* non-PCI class devices like the xaui (class sun4v.)
*/
else
p = val;
q = p;
while (*p != '\0') {
*p = '\0';
break;
}
*p = (char)_toupper((int)*p);
++p;
}
}
}
}
/*
* Fetch the Label property for this device. If none is found then
* search all the siblings with the same device ID for a
* Label and return that Label. The plug-in can only match the canonical
* path from the PRI with a specific devfs path. So we take care of
* devices with multiple functions here. A leaf device downstream of
* a bridge should fall out of here with PICL_PROPNOTFOUND, and the
* caller can walk back up the tree in search of the slot's Label.
*/
static picl_errno_t
{
char val[PICL_PROPNAMELEN_MAX];
/*
* If there's a Label at this node then return it - we're
* done.
*/
sizeof (val));
if (err == PICL_SUCCESS) {
return (err);
} else if (err != PICL_PROPNOTFOUND)
return (err);
/*
* At this point we're starting to extrapolate what the Label
* should be since there is none at this specific node.
* Note that until the value of "err" is overwritten in the
* loop below, its value should be PICL_PROPNOTFOUND.
*/
/*
* The device must be attached, and we can figure that out if
* the instance number is present and is not equal to -1.
* This will prevent is from returning a Label for a sibling
* node when the node passed in would have a unique Label if the
* device were attached. But if the device is downstream of a
* node with a Label then pci_callback() will still find that
* and use it.
*/
sizeof (instance)) != PICL_SUCCESS)
return (err);
if (instance == -1)
return (err);
/*
* Narrow the search to just the one device ID.
*/
sizeof (devid)) != PICL_SUCCESS)
return (err);
/*
* Go find the first child of the parent so we can search
* all of the siblings.
*/
sizeof (pnodeh)) != PICL_SUCCESS)
return (err);
sizeof (pnodeh)) != PICL_SUCCESS)
return (err);
/*
* If the child's device ID matches, then fetch the Label and
* associated with it.
*/
do {
PICL_SUCCESS) {
break;
}
}
}
sizeof (pnodeh)) == PICL_SUCCESS);
return (err);
}
static void
{
int i;
err = PICL_SUCCESS;
while (err == PICL_SUCCESS) {
sizeof (pnodeh)) != PICL_SUCCESS) {
return;
}
break;
}
}
sizeof (uaddr)) != PICL_SUCCESS) {
return;
}
if (!pval) {
return;
}
return;
}
dev_mask = 0;
for (i = 0; i < sizeof (dev_mask); i++)
if (uaddr[i] == ',') {
uaddr[i] = '\0';
break;
}
}
} else {
int count = 0; /* count # of 1's in x */
int i = 0;
while (x != 0) {
count++;
x &= x-1;
}
while (count > 1) {
while (p[i++] != '\0')
;
count--;
}
}
}
/*
* add all io devices under pci in io list
*/
/* ARGSUSED */
static int
{
char path[PICL_PROPNAMELEN_MAX];
char class[PICL_CLASSNAMELEN_MAX];
char name[PICL_PROPNAMELEN_MAX];
char model[PICL_PROPNAMELEN_MAX];
char binding_name[PICL_PROPNAMELEN_MAX];
char val[PICL_PROPNAMELEN_MAX];
char *compatible;
/* Walk through the children */
sizeof (picl_nodehdl_t));
while (err == PICL_SUCCESS) {
if (err != PICL_SUCCESS)
return (err);
if (args) {
sizeof (picl_nodehdl_t));
continue;
sizeof (picl_nodehdl_t));
continue;
sizeof (picl_nodehdl_t));
continue;
}
}
if (err != PICL_SUCCESS)
return (err);
/*
* No Label at this node, maybe we're looking at a device
* downstream of a bridge. Walk back up and find a Label and
* record that node in "pnodeh".
*/
while (err != PICL_SUCCESS) {
if (err != PICL_PROPNOTFOUND)
break;
else if (picl_get_propval_by_name(pnodeh,
else
break;
}
/*
* Can't find a Label for this device in the PCI heirarchy.
* Try to synthesize a slot name from atoms. This depends
* on the OBP slot_names property being implemented, and this
* so far doesn't seem to be on sun4v. But just in case that
* is resurrected, the code is here.
*/
if (err != PICL_SUCCESS) {
}
/*
* Passing in pnodeh instead of nodeh will cause prtdiag
* to display the type of IO slot for the leaf node. For
* built-in devices and a lot of IO cards these will be
* the same thing. But for IO cards with bridge chips or
* for things like expansion chassis, prtdiag will report
* the bus type of the IO slot and not the leaf, which
* could be different things.
*/
sizeof (name));
if (err == PICL_PROPNOTFOUND)
else if (err != PICL_SUCCESS)
return (err);
sizeof (val));
if (err == PICL_PROPNOTFOUND)
else if (err != PICL_SUCCESS)
return (err);
/*
* Get the name of this card. If binding_name is found,
* name will be <nodename>-<binding_name>.
*/
binding_name, sizeof (binding_name));
if (err == PICL_SUCCESS) {
sizeof (name));
}
} else if (err == PICL_PROPNOTFOUND) {
/*
* if compatible prop is not found, name will be
* <nodename>-<compatible>
*/
&compatible);
if (err == PICL_SUCCESS) {
sizeof (name));
}
} else
return (err);
/* Get the model of this card */
if (err == PICL_PROPNOTFOUND)
else if (err != PICL_SUCCESS)
return (err);
/* Print NAC name */
/* Print IO Type */
/* Printf Card Name */
/* Print Card Model */
log_printf("\n");
/* Print Status */
/* Print IO Type */
/* Print Parent Path */
log_printf("\n");
sizeof (picl_nodehdl_t));
}
return (PICL_WALK_CONTINUE);
}
/*
* display_pci
* Display all the PCI IO cards on this board.
*/
void
{
char *fmt = "%-17s %-5s %-33s %-8s";
/* Have we printed the column headings? */
log_printf("\n");
log_printf("================================");
log_printf(" IO Devices ");
log_printf("================================");
log_printf("\n");
log_printf("\n");
log_printf("\n");
log_printf("---------------------------------"
"-------------------------------------------\n");
}
}
/*
* return the first compatible value
*/
static int
{
char *pval;
if (err != PICL_SUCCESS)
return (err);
return (PICL_FAILURE);
if (err != PICL_SUCCESS) {
return (err);
}
return (PICL_SUCCESS);
}
return (PICL_FAILURE);
/* get first string from table */
if (err != PICL_SUCCESS)
return (err);
if (err != PICL_SUCCESS)
return (err);
if (err != PICL_SUCCESS)
return (err);
return (PICL_FAILURE);
if (err != PICL_SUCCESS) {
return (err);
}
return (PICL_SUCCESS);
}
/*
* print size of a memory segment
*/
static void
{
char buf[MEMORY_SIZE_FIELD];
else
else
else
} else {
else
}
}
/*
* Enumerate banks and dimms within a memory segment. We're handed
* the first bank within the segment - we assume there are dimms
* (memory-module) nodes underneath.
*/
static void
{
char val[PICL_PROPNAMELEN_MAX];
int flag = 0;
do {
continue;
if (!flag) {
} else {
log_printf(" "
" ");
flag = 0;
}
}
do {
continue;
else {
if (!flag) {
flag = 1;
} else {
log_printf("%s%s\n",
" "
" ",
val);
}
}
&module_nodeh, sizeof (picl_nodehdl_t)) ==
}
/*
* Search node where _class=="memory-segment"
* print "Base Address", "Size", etc
*/
/*ARGSUSED*/
static int
{
if (class_node_found == 0) {
class_node_found = 1;
return (PICL_WALK_TERMINATE);
}
while (err == PICL_SUCCESS) {
if (err != PICL_SUCCESS)
break;
if (err != PICL_SUCCESS)
break;
sizeof (ifactor));
if (err != PICL_SUCCESS)
break;
if (err == PICL_SUCCESS)
log_printf("\n");
sizeof (picl_nodehdl_t));
}
return (PICL_WALK_CONTINUE);
}
/*ARGSUSED*/
void
{
char *fmt = "%-14s %-8s %-11s %-8s %-s";
if (class_node_found == 0)
return;
log_printf("\n");
log_printf("=======================");
log_printf(" Physical Memory Configuration ");
log_printf("========================");
log_printf("\n");
log_printf("Segment Table:\n");
"--------------------------------------------------------------\n");
log_printf("\n");
log_printf("\n");
"--------------------------------------------------------------\n");
}
void
{
char *fmt = "%-6s %-9s %-22s %-6s";
/*
* Display the table header for CPUs . Then display the CPU
* frequency, cache size, and processor revision of all cpus.
*/
"\n"
"================================"
" Virtual CPUs "
"================================"
"\n"
"\n"));
log_printf("\n");
"Status", 0);
log_printf("\n");
"----------------------", "-------", 0);
log_printf("\n");
}
/*
* Display the CPUs present on this board.
*/
/*ARGSUSED*/
int
{
int status;
int *int_value;
int cpuid;
char *comp_value;
char *no_prop_value = " ";
/*
* Get cpuid property and print it and the NAC name
*/
&proph);
if (status == PICL_SUCCESS) {
if (status != PICL_SUCCESS) {
} else {
}
} else {
}
&proph);
if (status == PICL_SUCCESS) {
goto compatible;
}
if (status != PICL_SUCCESS) {
} else {
/* Running frequency */
}
} else
&proph);
if (status == PICL_SUCCESS) {
/*
* Compatible Property only has 1 value
*/
if (comp_value == NULL) {
goto state;
}
if (status != PICL_SUCCESS)
else
/*
* Compatible Property has multiple values
*/
if (status != PICL_SUCCESS) {
goto state;
}
if (status != PICL_SUCCESS) {
goto state;
}
if (status != PICL_SUCCESS) {
goto state;
}
if (comp_value == NULL) {
goto state;
}
if (status != PICL_SUCCESS)
else
}
} else
if (status == PICL_SUCCESS) {
if (status != PICL_SUCCESS) {
} else {
}
} else
done:
log_printf("\n");
return (PICL_WALK_CONTINUE);
}
void
{
#ifdef lint
#endif
/*
* This function is intentionally empty
*/
}
void
display_boardnum(int num)
{
}
static int
{
int exit_code = 0;
if (phyplatformh == 0)
return (0);
log_printf("\n");
log_printf("============================");
log_printf(" Environmental Status ");
log_printf("============================");
log_printf("\n");
class_node_found = 0;
all_status_ok = 1;
exit_code |= (!all_status_ok);
class_node_found = 0;
all_status_ok = 1;
exit_code |= (!all_status_ok);
class_node_found = 0;
all_status_ok = 1;
exit_code |= (!all_status_ok);
class_node_found = 0;
all_status_ok = 1;
exit_code |= (!all_status_ok);
class_node_found = 0;
all_status_ok = 1;
exit_code |= (!all_status_ok);
class_node_found = 0;
all_status_ok = 1;
exit_code |= (!all_status_ok);
class_node_found = 0;
all_status_ok = 1;
exit_code |= (!all_status_ok);
class_node_found = 0;
all_status_ok = 1;
exit_code |= (!all_status_ok);
class_node_found = 0;
all_status_ok = 1;
exit_code |= (!all_status_ok);
class_node_found = 0;
all_status_ok = 1;
exit_code |= (!all_status_ok);
class_node_found = 0;
class_node_found = 0;
return (exit_code);
}
/*ARGSUSED*/
static int
{
char val[PICL_PROPNAMELEN_MAX];
char *names[PARENT_NAMES];
char *base_units[PICL_PROPNAMELEN_MAX];
char *loc;
int i;
char *prop;
double display_val;
if (class_node_found == 0) {
class_node_found = 1;
return (PICL_WALK_TERMINATE);
}
if (!prop) {
all_status_ok = 0;
} else {
sizeof (val));
if (err == PICL_SUCCESS) {
}
}
}
if (sensor_status != SENSOR_DISABLED &&
sensor_status != SENSOR_UNKNOWN) {
sizeof (current_val)) != PICL_SUCCESS) {
} else {
if ((lo_poweroff != INVALID_THRESHOLD &&
current_val <= lo_poweroff) ||
(hi_poweroff != INVALID_THRESHOLD &&
current_val >= hi_poweroff)) {
} else if ((lo_shutdown != INVALID_THRESHOLD &&
current_val <= lo_shutdown) ||
(hi_shutdown != INVALID_THRESHOLD &&
current_val >= hi_shutdown)) {
} else if ((lo_warning != INVALID_THRESHOLD &&
current_val <= lo_warning) ||
(hi_warning != INVALID_THRESHOLD &&
current_val >= hi_warning)) {
} else {
}
}
}
if (syserrlog == 0) {
all_status_ok = 0;
return (PICL_WALK_TERMINATE);
}
if (sensor_status == SENSOR_OK) {
return (PICL_WALK_CONTINUE);
}
}
/*
* If we're here then prtdiag was invoked with "-v" or we have
* a sensor that is beyond a threshold, so give them a book to
* read instead of the Cliff Notes.
*/
sizeof (parenth));
if (err != PICL_SUCCESS) {
log_printf("\n");
return (PICL_WALK_CONTINUE);
}
/* gather up the path name for the sensor */
for (i = 0; i < PARENT_NAMES; i++) {
NULL) {
while (--i > -1)
}
}
}
i = 0;
if (loc != 0) {
while (err == PICL_SUCCESS) {
if (parenth == phyplatformh)
break;
names[i++], PICL_PROPNAMELEN_MAX);
if (err != PICL_SUCCESS) {
i--;
break;
}
if (i == PARENT_NAMES)
break;
}
loc[0] = '\0';
if (--i > -1) {
}
while (--i > -1) {
}
for (i = 0; i < PARENT_NAMES; i++)
} else {
}
sizeof (val));
if (err == PICL_SUCCESS)
/*
* Get the exponent if present, and do a little math so that
* if we need to we can print a normalized value for the
* sensor reading.
*/
exponent = 0;
if (exponent == 0)
display_val = (double)current_val;
else {
display_val = (double)current_val *
/*
* Sometimes ILOM will scale a sensor reading but
* there will be nothing to the right of the decimal
* once that value is normalized. Setting the
* exponent to zero will prevent the printf below
* from printing extraneous zeros. Otherwise a
* negative exponent is used to set the precision
* for the printf.
*/
exponent = 0;
}
base_units, sizeof (base_units));
if (err != PICL_SUCCESS)
base_units[0] = '\0';
switch (sensor_status) {
case SENSOR_FAILED:
break;
case SENSOR_WARN:
break;
case SENSOR_DISABLED:
break;
case SENSOR_OK:
break;
default:
break;
}
log_printf("\n");
return (PICL_WALK_CONTINUE);
}
/*ARGSUSED*/
static int
{
char current_val[PICL_PROPNAMELEN_MAX];
char expected_val[PICL_PROPNAMELEN_MAX];
char label[PICL_PROPNAMELEN_MAX];
char *names[PARENT_NAMES];
char *loc;
int i = 0;
if (class_node_found == 0) {
class_node_found = 1;
return (PICL_WALK_TERMINATE);
}
if (!prop) {
all_status_ok = 0;
} else {
sizeof (current_val));
if (err == PICL_SUCCESS) {
}
}
}
if (sensor_status != SENSOR_DISABLED &&
sensor_status != SENSOR_UNKNOWN) {
sizeof (current_val)) != PICL_SUCCESS) {
sizeof (current_val));
} else {
&expected_val, sizeof (expected_val)) !=
PICL_SUCCESS) {
} else {
sizeof (current_val)) == 0) {
} else {
}
}
}
}
if (syserrlog == 0) {
all_status_ok = 0;
return (PICL_WALK_TERMINATE);
}
if (sensor_status == SENSOR_OK) {
return (PICL_WALK_CONTINUE);
}
}
/*
* If we're here then prtdiag was invoked with "-v" or we have
* a sensor that is beyond a threshold, so give them a book to
* read instead of the Cliff Notes.
*/
sizeof (parenth));
if (err != PICL_SUCCESS) {
log_printf("\n");
return (PICL_WALK_CONTINUE);
}
for (i = 0; i < PARENT_NAMES; i++) {
NULL) {
while (--i > -1)
}
}
}
i = 0;
if (loc) {
while (err == PICL_SUCCESS) {
if (parenth == phyplatformh)
break;
names[i++], PICL_PROPNAMELEN_MAX);
if (err != PICL_SUCCESS) {
i--;
break;
}
if (i == PARENT_NAMES)
break;
}
loc[0] = '\0';
if (--i > -1) {
}
while (--i > -1) {
}
for (i = 0; i < PARENT_NAMES; i++)
} else {
}
sizeof (label));
if (err != PICL_SUCCESS)
log_printf("\n");
return (PICL_WALK_CONTINUE);
}
static void
{
char *fmt = "%-34s %-18s %-10s\n";
/*
* If there isn't any fan sensor node, return now.
*/
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_RPM_SENSOR, (void *)PICL_PROP_SPEED,
if (!class_node_found)
return;
log_printf("Fan sensors:\n");
if (syserrlog == 0) {
(void) picl_walk_tree_by_class(phyplatformh,
if (all_status_ok) {
log_printf("All fan sensors are OK.\n");
return;
}
}
log_printf("-------------------------------------------------"
"---------------\n");
log_printf("-------------------------------------------------"
"---------------\n");
}
static void
{
char *fmt = "%-34s %-18s %-10s\n";
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_RPM_INDICATOR, (void *)PICL_PROP_CONDITION,
if (!class_node_found)
return;
log_printf("\nFan indicators:\n");
if (syserrlog == 0) {
(void) picl_walk_tree_by_class(phyplatformh,
(void *)PICL_PROP_CONDITION,
if (all_status_ok) {
log_printf("All fan indicators are OK.\n");
return;
}
}
log_printf("-------------------------------------------------"
"---------------\n");
log_printf("-------------------------------------------------"
"---------------\n");
}
static void
{
char *fmt = "%-34s %-18s %-10s\n";
(void) picl_walk_tree_by_class(phyplatformh,
(void *)PICL_PROP_TEMPERATURE,
if (!class_node_found)
return;
log_printf("\nTemperature sensors:\n");
if (syserrlog == 0) {
(void) picl_walk_tree_by_class(phyplatformh,
if (all_status_ok) {
log_printf("All temperature sensors are OK.\n");
return;
}
}
log_printf("-------------------------------------------------"
"---------------\n");
log_printf("-------------------------------------------------"
"---------------\n");
(void) picl_walk_tree_by_class(phyplatformh,
}
static void
{
char *fmt = "%-34s %-18s %-8s\n";
(void) picl_walk_tree_by_class(phyplatformh,
if (!class_node_found)
return;
log_printf("\nTemperature indicators:\n");
if (syserrlog == 0) {
(void) picl_walk_tree_by_class(phyplatformh,
(void *)PICL_PROP_CONDITION,
if (all_status_ok) {
log_printf("All temperature indicators are OK.\n");
return;
}
}
log_printf("-------------------------------------------------"
"---------------\n");
log_printf("-------------------------------------------------"
"---------------\n");
(void) picl_walk_tree_by_class(phyplatformh,
(void *)PICL_PROP_CONDITION,
}
static void
{
char *fmt = "%-34s %-18s %-10s\n";
(void *)PICL_PROP_CURRENT, sun4v_env_print_sensor_callback);
if (!class_node_found)
return;
log_printf("\nCurrent sensors:\n");
if (syserrlog == 0) {
(void) picl_walk_tree_by_class(phyplatformh,
if (all_status_ok) {
log_printf("All current sensors are OK.\n");
return;
}
}
log_printf("-------------------------------------------------"
"---------------\n");
log_printf("-------------------------------------------------"
"---------------\n");
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_CURRENT_SENSOR, (void *)PICL_PROP_CURRENT,
}
static void
{
char *fmt = "%-34s %-18s %-8s\n";
(void) picl_walk_tree_by_class(phyplatformh,
(void *)PICL_PROP_CONDITION,
if (!class_node_found)
return;
log_printf("\nCurrent indicators:\n");
if (syserrlog == 0) {
(void) picl_walk_tree_by_class(phyplatformh,
if (all_status_ok) {
log_printf("All current indicators are OK.\n");
return;
}
}
log_printf("-------------------------------------------------"
"---------------\n");
log_printf("-------------------------------------------------"
"---------------\n");
(void) picl_walk_tree_by_class(phyplatformh,
(void *)PICL_PROP_CONDITION,
}
static void
{
char *fmt = "%-34s %-18s %-10s\n";
(void) picl_walk_tree_by_class(phyplatformh,
if (!class_node_found)
return;
log_printf("\nVoltage sensors:\n");
if (syserrlog == 0) {
(void) picl_walk_tree_by_class(phyplatformh,
if (all_status_ok) {
log_printf("All voltage sensors are OK.\n");
return;
}
}
log_printf("-------------------------------------------------"
"---------------\n");
log_printf("-------------------------------------------------"
"---------------\n");
(void) picl_walk_tree_by_class(phyplatformh,
(void *)PICL_PROP_VOLTAGE,
}
static void
{
char *fmt = "%-34s %-18s %-8s\n";
(void) picl_walk_tree_by_class(phyplatformh,
(void *)PICL_PROP_CONDITION,
if (!class_node_found)
return;
log_printf("\nVoltage indicators:\n");
if (syserrlog == 0) {
(void) picl_walk_tree_by_class(phyplatformh,
if (all_status_ok) {
log_printf("All voltage indicators are OK.\n");
return;
}
}
log_printf("-------------------------------------------------"
"---------------\n");
log_printf("-------------------------------------------------"
"---------------\n");
(void) picl_walk_tree_by_class(phyplatformh,
(void *)PICL_PROP_CONDITION,
}
static void
{
char *fmt = "%-34s %-18s %-8s\n";
if (syserrlog == 0)
return;
if (!class_node_found)
return;
log_printf("\nLEDs:\n");
log_printf("-------------------------------------------------"
"---------------\n");
log_printf("-------------------------------------------------"
"---------------\n");
}
/*ARGSUSED*/
static int
{
char label[PICL_PROPNAMELEN_MAX];
char status[PICL_PROPNAMELEN_MAX];
char *names[PARENT_NAMES];
char *loc;
int i;
if (!class_node_found) {
class_node_found = 1;
return (PICL_WALK_TERMINATE);
}
if (err != PICL_SUCCESS)
return (PICL_WALK_CONTINUE);
sizeof (label));
if (err != PICL_SUCCESS)
return (PICL_WALK_CONTINUE);
if (err != PICL_SUCCESS)
return (PICL_WALK_CONTINUE);
if (syserrlog == 0) {
if (all_status_ok) {
all_status_ok = 0;
return (PICL_WALK_TERMINATE);
}
} else
return (PICL_WALK_CONTINUE);
}
if (is_fru_absent(nodeh))
sizeof (parenth));
if (err != PICL_SUCCESS) {
log_printf("\n");
return (PICL_WALK_CONTINUE);
}
return (PICL_WALK_TERMINATE);
for (i = 0; i < PARENT_NAMES; i++)
while (--i > -1)
return (PICL_WALK_TERMINATE);
}
i = 0;
while (err == PICL_SUCCESS) {
if (parenth == phyplatformh)
break;
names[i++], PICL_PROPNAMELEN_MAX);
if (err != PICL_SUCCESS) {
i--;
break;
}
if (i == PARENT_NAMES)
break;
}
loc[0] = '\0';
if (--i > -1) {
}
while (--i > -1) {
}
for (i = 0; i < PARENT_NAMES; i++)
log_printf("\n");
return (PICL_WALK_CONTINUE);
}
static void
{
char *fmt = "%-34s %-9s %-8s\n";
if (!class_node_found)
return;
log_printf("\n");
log_printf("============================");
log_printf(" FRU Status ");
log_printf("============================");
log_printf("\n");
if (syserrlog == 0) {
(void) picl_walk_tree_by_class(phyplatformh,
if (all_status_ok) {
log_printf("All FRUs are enabled.\n");
return;
}
}
log_printf("------------------------------------------------------\n");
}
/* Check the children of the FRU node for a presence indicator */
static int
{
char class [PICL_CLASSNAMELEN_MAX];
char condition [PICL_PROPNAMELEN_MAX];
sizeof (picl_nodehdl_t));
while (err == PICL_SUCCESS) {
if (err == PICL_SUCCESS &&
sizeof (condition));
if (err == PICL_SUCCESS) {
return (1);
} else {
return (0);
}
}
}
&nodeh, sizeof (picl_nodehdl_t));
}
return (0);
}
/*ARGSUSED*/
static int
{
char rev[PICL_PROPNAMELEN_MAX];
if (!class_node_found) {
class_node_found = 1;
return (PICL_WALK_TERMINATE);
}
sizeof (rev));
if (err != PICL_SUCCESS)
return (PICL_WALK_CONTINUE);
return (PICL_WALK_CONTINUE);
log_printf("\n");
return (PICL_WALK_CONTINUE);
}
static void
{
if (syserrlog == 0)
return;
if (!class_node_found)
return;
log_printf("\n");
log_printf("============================");
log_printf(" FW Version ");
log_printf("============================");
log_printf("\n");
log_printf("Version\n");
log_printf("-------------------------------------------------"
"-----------\n");
}
static void
{
if (syserrlog == 0)
return;
if (!class_node_found)
return;
log_printf("\n");
log_printf("======================");
log_printf(" System PROM revisions ");
log_printf("=======================");
log_printf("\n");
log_printf("Version\n");
log_printf("-------------------------------------------------"
"-----------\n");
}
/*
* display the OBP and POST prom revisions (if present)
*/
/* ARGSUSED */
static int
{
char *prom_version = NULL;
char *obp_version = NULL;
int err;
if (!class_node_found) {
class_node_found = 1;
return (PICL_WALK_TERMINATE);
}
if (err == PICL_PROPNOTFOUND)
return (PICL_WALK_TERMINATE);
else if (err != PICL_SUCCESS)
return (err);
/*
* If it's a table prop, the first element is OBP revision
* The second one is POST revision.
* If it's a charstring prop, the value will be only OBP revision
*/
if (prom_version == NULL)
return (PICL_FAILURE);
if (err != PICL_SUCCESS)
return (err);
}
return (PICL_WALK_TERMINATE);
if (err != PICL_SUCCESS)
return (err);
if (err == PICL_SUCCESS) {
/* get first row */
if (err != PICL_SUCCESS)
return (err);
if (prom_version == NULL)
return (PICL_FAILURE);
if (err != PICL_SUCCESS)
return (err);
/* get second row */
if (err == PICL_SUCCESS) {
if (err != PICL_SUCCESS)
return (err);
if (obp_version == NULL)
return (PICL_FAILURE);
if (err != PICL_SUCCESS)
return (err);
}
}
return (PICL_WALK_TERMINATE);
}
static void
{
char val[PICL_PROPNAMELEN_MAX];
return;
log_printf("\n");
log_printf("Chassis Serial Number");
log_printf("\n");
log_printf("---------------------\n");
if (err == PICL_SUCCESS)
log_printf("\n");
}