/*
* 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
*/
/*
*/
#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"
#include <sys/pci_tools.h>
#if !defined(TEXT_DOMAIN)
#endif
/*
* Additional OBP properties
*/
/*
* Additional picl classes
*/
#ifndef PICL_CLASS_SUN4V
#endif
#ifndef PICL_PROP_NAC
#endif
if (((arg_1) != PROP_INVALID) && \
((arg_2) != PROP_INVALID)) \
else if ((arg_2) != PROP_INVALID) \
else if ((arg_1) != PROP_INVALID) \
else \
log_printf("--");
if ((arg_1) != 0) \
else \
log_printf("--");
/* PCI BUS types */
/* PCI device defines */
/* PCI frequencies */
/* PCI frequency shift bits */
/* PCI frequency modes */
/* PCI frequency SEC status masks */
/* PCIE Speeds */
extern int sys_clk;
picl_nodehdl_t *);
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 *ret);
int *ret);
static int open_root_complex(char *root_complex);
int
{
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
{
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
{
/*
* 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 i = 0;
while (x != 0) {
count++;
x &= x-1;
}
while (count > 1) {
while (p[i++] != '\0')
;
count--;
}
}
}
int
{
do {
== PICL_SUCCESS) {
== PICL_SUCCESS) {
else
break;
} else
return (err);
} else
return (err);
} while (err == PICL_SUCCESS);
/* get path from root node */
return (err);
}
/*
* add all io devices under pci in io list
*/
/* ARGSUSED */
static int
{
char *compatible;
int bus_type;
int *reg_val;
float fspeed;
/* 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 hierarchy.
* 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);
/*
* Fetch values for current lane and speed properties
*/
if (err == PICL_SUCCESS) {
/* All of the array of bytes of "reg" have to be read */
return (PICL_FAILURE);
if ((err == PICL_SUCCESS) &&
(reg_val[0] != 0)) {
PCI_DEV_MASK) >> 11);
PCI_FUNC_MASK) >> 8);
PCI_BUS_MASK) >> 16);
sizeof (root_path)) == -1) ||
!= PICL_SUCCESS)) {
err = PICL_FAILURE;
}
} else {
err = PICL_FAILURE;
}
}
if (err != PICL_SUCCESS) {
/*
* get_lane_width will fail when run as
* non-root. Set bus_type to PCI_UNKN
* so that bus frequency, bus type and
* lane width will print as "--" or UNKN.
*/
}
/* Print NAC name */
/* Print IO Type */
/* Printf Card Name */
/* Print Card Model */
if (bus_type == PCIE_BUSTYPE) {
} else if (bus_type == PCIX_BUSTYPE) {
} else
log_printf("--");
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
{
/* Have we printed the column headings? */
log_printf("\n");
log_printf("================================");
log_printf(" IO Devices ");
log_printf("================================");
log_printf("\n");
"Speed", 0);
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
{
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
{
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;
sizeof (mirror_mode));
if (err != PICL_SUCCESS)
mirror_mode = 0;
if (!mirror_mode) {
} else {
}
if (err == PICL_SUCCESS)
log_printf("\n");
sizeof (picl_nodehdl_t));
}
return (PICL_WALK_CONTINUE);
}
/*ARGSUSED*/
void
{
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
{
/*
* 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 cpuid;
char *comp_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
{
}
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 *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);
}
} else {
all_status_ok = 0;
}
}
/*
* 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 *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) {
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);
}
} else {
all_status_ok = 0;
}
}
/*
* 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
{
/*
* 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
{
(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
{
(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
{
(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
{
(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
{
(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
{
(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
{
(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
{
if (syserrlog == 0)
return;
if (!class_node_found)
return;
log_printf("\nLEDs:\n");
log_printf("-------------------------------------------------"
"---------------\n");
log_printf("-------------------------------------------------"
"---------------\n");
}
/*ARGSUSED*/
static int
{
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);
} else {
all_status_ok = 0;
}
}
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
{
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
{
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
{
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
{
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
{
return;
log_printf("\n");
log_printf("Chassis Serial Number");
log_printf("\n");
log_printf("---------------------\n");
if (err == PICL_SUCCESS)
log_printf("\n");
}
static int
{
char *path;
+ sizeof (devctl_str);
return (-1);
devctl_str) <= 0) {
return (-1);
}
return (fd);
}
static uint32_t
{
int rval;
if (rval != 0) {
}
}
static uint16_t
{
int rval;
if (rval != 0) {
}
}
static uint8_t
{
int rval;
if (rval != 0) {
}
}
static picl_errno_t
{
if (device_path == NULL)
return (PICL_FAILURE);
if (fd == -1) {
return (PICL_FAILURE);
}
/*
* Link Capabilities and Link Status registers are in the
* PCI-E capabilities register. They are at offset
* 0xc and 0x12 respectively. They are documented in section
* 7.8 of the PCI Express Base Specification. The address of
* that structure is not fixed, it's kind of a linked list.
* The Capabilities Pointer reg (8 bits) is always at 0x34.
* It contains a pointer to the first capabilities structure.
* For each capability structure, the first 8 bits is the capability
* ID. The next 8 bits is the pointer to the next structure.
* If the Next Cap register is zero, it's the end of the list.
* The capability ID for the PCI-E strucutre is 0x10. The idea
* is to follow the links until you find a Cap ID of 0x10, then
* read the registers at 0xc and 0x12 from there.
* If there's no Cap ID 0x10, then it's not a PCI-E device.
*/
if (ret != 0) {
/* ioctl failure */
return (PICL_FAILURE);
}
if (ret != 0) {
/* ioctl failure */
return (PICL_FAILURE);
}
*type = PCI_BUSTYPE;
while (cap_ptr != 0) {
if (capid == PCI_CAP_ID_PCI_E) {
if (ret != 0) {
return (PICL_FAILURE);
}
*cur_speed = ((link_status) &
/* PCIE 3 Speed decoding */
if (*cur_speed == 1)
else if (*cur_speed == 2)
else
*type = PCIE_BUSTYPE;
} else if (capid == PCI_CAP_ID_PCIX) {
if (ret != 0) {
/* ioctl failure */
return (PICL_FAILURE);
}
*type = PCIX_BUSTYPE;
/* This is a PCI-X bridge */
if (ret != 0) {
/* ioctl failure */
return (PICL_FAILURE);
}
if (sec_status & PCI_SEC_133)
if (sec_status & PCI_SEC_266)
if (sec_status & PCI_SEC_533)
if (mode) {
int speed;
if (mode == PCI_MODE_66)
speed = PCI_FREQ_66;
else if (mode == PCI_MODE_100)
else if (mode == PCI_MODE_133)
}
} else { /* Leaf device */
if (ret != 0) {
/* ioctl failure */
return (PICL_FAILURE);
}
if (pcix_status &
(PCI_LEAF_ULONG << PCI_SHIFT_133))
if (pcix_status &
(PCI_LEAF_ULONG << PCI_SHIFT_266))
if (pcix_status &
(PCI_LEAF_ULONG << PCI_SHIFT_533))
}
}
if (ret != 0) {
/* ioctl failure */
return (PICL_FAILURE);
}
}
return (PICL_FAILURE);
}
return (PICL_SUCCESS);
}