display_sun4v.c revision 0d63ce2b32a9e1cc8ed71d4d92536c44d66a530a
/*
* 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
* or http://www.opensolaris.org/os/licensing.
* 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 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <stdlib.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/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/openpromio.h>
#include <libintl.h>
#include <syslog.h>
#include <sys/dkio.h>
#include <sys/systeminfo.h>
#include <picldefs.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 IOBOARD "IOBD"
#define NETWORK "network"
#define PCIE_COMPATIBLE_STR "pciex"
#define PCIX_COMPATIBLE_STR "pci"
#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 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;
extern picl_errno_t sun4v_get_node_by_name(picl_nodehdl_t, char *,
picl_nodehdl_t *);
static picl_nodehdl_t rooth = 0, phyplatformh = 0;
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 void 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 void sun4v_print_fw_rev();
static void sun4v_print_chassis_serial_no();
int
sun4v_display(Sys_tree *tree, Prom_node *root, int log,
picl_nodehdl_t plafh)
{
void *value; /* used for opaque PROM data */
struct mem_total memory_total; /* Total memory in system */
struct grp_info grps; /* Info on all groups in system */
char machine[MAXSTRLEN];
if (sysinfo(SI_MACHINE, machine, sizeof (machine)) == -1)
return (1);
if (strncmp(machine, SUN4V_MACHINE, strlen(SUN4V_MACHINE)) != 0)
return (1);
sys_clk = -1; /* System clock freq. (in MHz) */
/*
* Now display the machine's configuration. We do this if we
* are not logging.
*/
if (!logging) {
struct utsname uts_buf;
/*
* Display system banner
*/
(void) uname(&uts_buf);
log_printf(dgettext(TEXT_DOMAIN, "System Configuration: "
"Sun Microsystems %s %s\n"), uts_buf.machine,
get_prop_val(find_prop(root, "banner-name")), 0);
/* display system clock frequency */
value = get_prop_val(find_prop(root, "clock-frequency"));
if (value != NULL) {
sys_clk = ((*((int *)value)) + 500000) / 1000000;
log_printf(dgettext(TEXT_DOMAIN, "System clock "
"frequency: %d MHz\n"), sys_clk, 0);
}
/* Display the Memory Size */
display_memorysize(tree, NULL, &grps, &memory_total);
/* Display the CPU devices */
sun4v_display_cpu_devices(plafh);
/* Display the Memory configuration */
class_node_found = 0;
sun4v_display_memory_conf(plafh);
/* Display all the IO cards. */
(void) sun4v_display_pci(plafh);
sun4v_display_diaginfo((log || (logging)), root, plafh);
if (picl_get_root(&rooth) != PICL_SUCCESS)
return (1);
if (sun4v_get_node_by_name(rooth, PICL_NODE_PHYSICAL_PLATFORM,
&phyplatformh) != PICL_SUCCESS)
return (1);
if (picl_find_node(phyplatformh, PICL_PROP_CLASSNAME,
PICL_PTYPE_CHARSTRING, (void *)PICL_CLASS_CHASSIS,
strlen(PICL_CLASS_CHASSIS), &chassish) != PICL_SUCCESS)
return (1);
syserrlog = log;
sun4v_disp_env_status();
}
return (0);
}
static void
get_bus_type(picl_nodehdl_t nodeh, struct io_card *card)
{
char *compatible;
(void) strcpy(card->bus_type, "PCIX");
if (sun4v_get_first_compatible_value(nodeh, &compatible)
== PICL_SUCCESS) {
if (strncmp(compatible, PCIE_COMPATIBLE_STR,
strlen(PCIE_COMPATIBLE_STR)) == 0)
(void) strcpy(card->bus_type, "PCIE");
free(compatible);
}
}
static picl_errno_t
get_slot_label(picl_nodehdl_t nodeh, struct io_card *card)
{
char val[PICL_PROPNAMELEN_MAX];
picl_errno_t err;
err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
sizeof (val));
if (err != PICL_SUCCESS)
return (err);
(void) strcpy(card->slot_str, val);
card->slot = -1;
return (PICL_SUCCESS);
}
static void
get_slot_number(picl_nodehdl_t nodeh, struct io_card *card)
{
picl_errno_t err;
picl_prophdl_t proph;
picl_propinfo_t pinfo;
picl_nodehdl_t pnodeh;
uint8_t *pval;
uint32_t dev_mask;
char uaddr[MAXSTRLEN];
int i;
if (get_slot_label(nodeh, card) == PICL_SUCCESS)
return;
err = PICL_SUCCESS;
while (err == PICL_SUCCESS) {
if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &pnodeh,
sizeof (pnodeh)) != PICL_SUCCESS) {
(void) strcpy(card->slot_str, IOBOARD);
card->slot = -1;
return;
}
if (picl_get_propinfo_by_name(pnodeh, OBP_PROP_SLOT_NAMES,
&pinfo, &proph) == PICL_SUCCESS) {
break;
}
nodeh = pnodeh;
}
if (picl_get_propval_by_name(nodeh, PICL_PROP_UNIT_ADDRESS, uaddr,
sizeof (uaddr)) != PICL_SUCCESS) {
(void) strcpy(card->slot_str, IOBOARD);
card->slot = -1;
return;
}
pval = (uint8_t *)malloc(pinfo.size);
if (!pval) {
(void) strcpy(card->slot_str, IOBOARD);
card->slot = -1;
return;
}
if (picl_get_propval(proph, pval, pinfo.size) != PICL_SUCCESS) {
(void) strcpy(card->slot_str, IOBOARD);
card->slot = -1;
free(pval);
return;
}
dev_mask = 0;
for (i = 0; i < sizeof (dev_mask); i++)
dev_mask |= (*(pval+i) << 8*(sizeof (dev_mask)-1-i));
for (i = 0; i < sizeof (uaddr) && uaddr[i] != '\0'; i++) {
if (uaddr[i] == ',') {
uaddr[i] = '\0';
break;
}
}
card->slot = atol(uaddr);
if (((1 << card->slot) & dev_mask) == 0) {
(void) strcpy(card->slot_str, IOBOARD);
card->slot = -1;
} else {
char *p = (char *)(pval+sizeof (dev_mask));
int shift = sizeof (uint32_t)*8-1-card->slot;
uint32_t x = (dev_mask << shift) >> shift;
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--;
}
(void) strcpy(card->slot_str, (char *)(p+i));
}
free(pval);
}
/*
* add all io devices under pci in io list
*/
/* ARGSUSED */
static int
sun4v_pci_callback(picl_nodehdl_t pcih, void *args)
{
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;
picl_errno_t err;
picl_nodehdl_t nodeh;
struct io_card pci_card;
/* Walk through the children */
err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
sizeof (picl_nodehdl_t));
while (err == PICL_SUCCESS) {
err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
class, sizeof (class));
if (err != PICL_SUCCESS)
return (err);
if (args) {
char *val = args;
if (strcmp(class, val) == 0) {
err = picl_get_propval_by_name(nodeh,
PICL_PROP_PEER, &nodeh,
sizeof (picl_nodehdl_t));
continue;
} else if (strcmp(val, PICL_CLASS_PCIEX) == 0 &&
strcmp(class, PICL_CLASS_PCI) == 0) {
err = picl_get_propval_by_name(nodeh,
PICL_PROP_PEER, &nodeh,
sizeof (picl_nodehdl_t));
continue;
} else if (strcmp(val, PICL_CLASS_PCI) == 0 &&
strcmp(class, PICL_CLASS_PCIEX) == 0) {
err = picl_get_propval_by_name(nodeh,
PICL_PROP_PEER, &nodeh,
sizeof (picl_nodehdl_t));
continue;
}
}
err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH,
path, sizeof (path));
if (err != PICL_SUCCESS)
return (err);
(void) strlcpy(pci_card.notes, path, sizeof (pci_card.notes));
get_bus_type(nodeh, &pci_card);
get_slot_number(nodeh, &pci_card);
err = picl_get_propval_by_name(nodeh, PICL_PROP_NAME, name,
sizeof (name));
if (err == PICL_PROPNOTFOUND)
(void) strcpy(name, "");
else if (err != PICL_SUCCESS)
return (err);
err = picl_get_propval_by_name(nodeh, PICL_PROP_STATUS, val,
sizeof (val));
if (err == PICL_PROPNOTFOUND)
(void) strcpy(val, "");
else if (err != PICL_SUCCESS)
return (err);
/* Figure NAC name */
if (pci_card.slot != -1)
(void) snprintf(pci_card.status,
sizeof (pci_card.status),
"%s%d", pci_card.slot_str,
pci_card.slot);
else
(void) snprintf(pci_card.status,
sizeof (pci_card.status),
"%s", pci_card.slot_str);
/*
* Get the name of this card. If binding_name is found,
* name will be <nodename>-<binding_name>.
*/
err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME,
binding_name, sizeof (binding_name));
if (err == PICL_SUCCESS) {
if (strcmp(name, binding_name) != 0) {
(void) strlcat(name, "-", sizeof (name));
(void) strlcat(name, binding_name,
sizeof (name));
}
} else if (err == PICL_PROPNOTFOUND) {
/*
* if compatible prop is not found, name will be
* <nodename>-<compatible>
*/
err = sun4v_get_first_compatible_value(nodeh,
&compatible);
if (err == PICL_SUCCESS) {
(void) strlcat(name, "-", sizeof (name));
(void) strlcat(name, compatible, sizeof (name));
free(compatible);
}
} else
return (err);
(void) strlcpy(pci_card.name, name, sizeof (pci_card.name));
/* Get the model of this card */
err = picl_get_propval_by_name(nodeh, OBP_PROP_MODEL,
model, sizeof (model));
if (err == PICL_PROPNOTFOUND)
(void) strcpy(model, "");
else if (err != PICL_SUCCESS)
return (err);
(void) strlcpy(pci_card.model, model, sizeof (pci_card.model));
/* Print NAC name */
log_printf("%-12s", pci_card.status);
/* Print IO Type */
log_printf("%-6s", pci_card.bus_type);
/* Printf Card Name */
log_printf("%-46s", pci_card.name);
/* Print Card Model */
log_printf("%-8s", pci_card.model);
log_printf("\n");
/* Print Status */
log_printf("%-12s", val);
/* Print IO Type */
log_printf("%-6s", "");
/* Print Parent Path */
log_printf("%-46s", pci_card.notes);
log_printf("\n");
err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
sizeof (picl_nodehdl_t));
}
return (PICL_WALK_CONTINUE);
}
/*
* display_pci
* Display all the PCI IO cards on this board.
*/
void
sun4v_display_pci(picl_nodehdl_t plafh)
{
char *fmt = "%-11s %-5s %-45s %-8s";
/* Have we printed the column headings? */
static int banner = FALSE;
if (banner == FALSE) {
log_printf("\n");
log_printf("============================");
log_printf(" IO Devices ");
log_printf("============================");
log_printf("\n");
log_printf(fmt, "Slot +", "Bus", "Name +", "Model", 0);
log_printf("\n");
log_printf(fmt, "Status", "Type", "Path", "", 0);
log_printf("\n");
log_printf("---------------------------------"
"------------------------------------\n");
banner = TRUE;
}
(void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCIEX,
PICL_CLASS_PCIEX, sun4v_pci_callback);
(void) picl_walk_tree_by_class(plafh, PICL_CLASS_PCI,
PICL_CLASS_PCI, sun4v_pci_callback);
(void) picl_walk_tree_by_class(plafh, PICL_CLASS_SUN4V,
PICL_CLASS_SUN4V, sun4v_pci_callback);
}
/*
* return the first compatible value
*/
static int
sun4v_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf)
{
picl_errno_t err;
picl_prophdl_t proph;
picl_propinfo_t pinfo;
picl_prophdl_t tblh;
picl_prophdl_t rowproph;
char *pval;
err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE,
&pinfo, &proph);
if (err != PICL_SUCCESS)
return (err);
if (pinfo.type == PICL_PTYPE_CHARSTRING) {
pval = malloc(pinfo.size);
if (pval == NULL)
return (PICL_FAILURE);
err = picl_get_propval(proph, pval, pinfo.size);
if (err != PICL_SUCCESS) {
free(pval);
return (err);
}
*outbuf = pval;
return (PICL_SUCCESS);
}
if (pinfo.type != PICL_PTYPE_TABLE)
return (PICL_FAILURE);
/* get first string from table */
err = picl_get_propval(proph, &tblh, pinfo.size);
if (err != PICL_SUCCESS)
return (err);
err = picl_get_next_by_row(tblh, &rowproph);
if (err != PICL_SUCCESS)
return (err);
err = picl_get_propinfo(rowproph, &pinfo);
if (err != PICL_SUCCESS)
return (err);
pval = malloc(pinfo.size);
if (pval == NULL)
return (PICL_FAILURE);
err = picl_get_propval(rowproph, pval, pinfo.size);
if (err != PICL_SUCCESS) {
free(pval);
return (err);
}
*outbuf = pval;
return (PICL_SUCCESS);
}
/*
* print size of a memory segment
*/
static void
print_memory_segment_size(uint64_t size)
{
uint64_t kbyte = 1024;
uint64_t mbyte = kbyte * kbyte;
uint64_t gbyte = kbyte * mbyte;
char buf[MEMORY_SIZE_FIELD];
if (size >= gbyte) {
if (size % gbyte == 0)
(void) snprintf(buf, sizeof (buf), "%d GB",
(int)(size / gbyte));
else
(void) snprintf(buf, sizeof (buf), "%.2f GB",
(float)size / gbyte);
} else if (size >= mbyte) {
if (size % mbyte == 0)
(void) snprintf(buf, sizeof (buf), "%d MB",
(int)(size / mbyte));
else
(void) snprintf(buf, sizeof (buf), "%.2f MB",
(float)size / mbyte);
} else {
if (size % kbyte == 0)
(void) snprintf(buf, sizeof (buf), "%d KB",
(int)(size / kbyte));
else
(void) snprintf(buf, sizeof (buf), "%.2f KB",
(float)size / kbyte);
}
log_printf("%-7s ", buf);
}
/*
* print bank IDs of a memory segment
*/
static void
print_memory_segment_contain(picl_nodehdl_t nodeh)
{
char val[PICL_PROPNAMELEN_MAX];
picl_errno_t err = picl_get_propval_by_name(nodeh,
PICL_PROP_NAC, val, sizeof (val));
if (err != PICL_SUCCESS)
return;
log_printf("%-30s", val);
while ((err = picl_get_propval_by_name(nodeh,
PICL_PROP_PEER, &nodeh,
sizeof (nodeh))) == PICL_SUCCESS) {
err = picl_get_propval_by_name(nodeh,
PICL_PROP_NAC, val, sizeof (val));
if (err == PICL_SUCCESS) {
log_printf("\n");
log_printf("%-30s", val);
}
}
}
/*
* Search node where _class=="memory-segment"
* print "Base Address", "Size", etc
*/
/*ARGSUSED*/
static int
sun4v_memory_conf_callback(picl_nodehdl_t nodeh, void *args)
{
uint64_t base;
uint64_t size;
uint64_t ifactor;
picl_errno_t err = PICL_SUCCESS;
if (class_node_found == 0) {
class_node_found = 1;
return (PICL_WALK_TERMINATE);
}
while (err == PICL_SUCCESS) {
err = picl_get_propval_by_name(nodeh, PICL_PROP_BASEADDRESS,
&base, sizeof (base));
if (err != PICL_SUCCESS)
break;
err = picl_get_propval_by_name(nodeh, PICL_PROP_SIZE,
&size, sizeof (size));
if (err != PICL_SUCCESS)
break;
err = picl_get_propval_by_name(nodeh,
PICL_PROP_INTERLEAVE_FACTOR, &ifactor,
sizeof (ifactor));
if (err != PICL_SUCCESS)
break;
err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
&nodeh, sizeof (nodeh));
if (err != PICL_SUCCESS)
break;
log_printf("%-13llx", base);
print_memory_segment_size(size);
log_printf("%-18d", ifactor);
print_memory_segment_contain(nodeh);
log_printf("\n");
err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
sizeof (picl_nodehdl_t));
}
return (PICL_WALK_CONTINUE);
}
/*ARGSUSED*/
void
sun4v_display_memory_conf(picl_nodehdl_t plafh)
{
char *fmt = "%-12s %-7s %-9s %-20s";
(void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
NULL, sun4v_memory_conf_callback);
if (class_node_found == 0)
return;
log_printf("\n");
log_printf("============================");
log_printf(" Memory Configuration ");
log_printf("============================");
log_printf("\n");
log_printf("Segment Table:\n");
log_printf("-----------------------------------------------\n");
log_printf(fmt, "Base Address", "Size", "Interleave Factor",
"Contains", 0);
log_printf("\n");
log_printf("-----------------------------------------------\n");
(void) picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
NULL, sun4v_memory_conf_callback);
}
void
sun4v_display_cpu_devices(picl_nodehdl_t plafh)
{
char *fmt = "%-12s %-5s %-8s %-19s %-5s";
/*
* Display the table header for CPUs . Then display the CPU
* frequency, cache size, and processor revision of all cpus.
*/
log_printf(dgettext(TEXT_DOMAIN,
"\n"
"========================="
" CPUs "
"==============================================="
"\n"
"\n"));
log_printf(fmt, "", "", "", "CPU", "CPU", 0);
log_printf("\n");
log_printf(fmt, "Location", "CPU", "Freq",
"Implementation", "Mask", 0);
log_printf("\n");
log_printf(fmt, "------------", "-----", "--------",
"-------------------", "-----", 0);
log_printf("\n");
(void) picl_walk_tree_by_class(plafh, "cpu", "cpu", sun4v_display_cpus);
}
/*
* Display the CPUs present on this board.
*/
/*ARGSUSED*/
int
sun4v_display_cpus(picl_nodehdl_t cpuh, void* args)
{
int status;
picl_prophdl_t proph;
picl_prophdl_t tblh;
picl_prophdl_t rowproph;
picl_propinfo_t propinfo;
int *int_value;
uint64_t cpuid, mask_no;
char *comp_value;
char *no_prop_value = " ";
char freq_str[MAXSTRLEN];
char fru_name[MAXSTRLEN];
/*
* Get cpuid property and print it and the NAC name
*/
status = picl_get_propinfo_by_name(cpuh, "cpuid", &propinfo, &proph);
if (status == PICL_SUCCESS) {
status = picl_get_propval(proph, &cpuid, sizeof (cpuid));
if (status != PICL_SUCCESS) {
log_printf("%-13s", no_prop_value);
log_printf("%-6s", no_prop_value);
} else {
(void) snprintf(fru_name, sizeof (fru_name), "%s%d",
CPU_STRAND_NAC, (int)cpuid);
log_printf("%-13s", fru_name);
log_printf("%-6d", (int)cpuid);
}
} else {
log_printf("%-13s", no_prop_value);
log_printf("%-6s", no_prop_value);
}
clock_freq:
status = picl_get_propinfo_by_name(cpuh, "clock-frequency", &propinfo,
&proph);
if (status == PICL_SUCCESS) {
int_value = malloc(propinfo.size);
if (int_value == NULL) {
log_printf("%-9s", no_prop_value);
goto compatible;
}
status = picl_get_propval(proph, int_value, propinfo.size);
if (status != PICL_SUCCESS) {
log_printf("%-9s", no_prop_value);
} else {
/* Running frequency */
(void) snprintf(freq_str, sizeof (freq_str), "%d MHz",
CLK_FREQ_TO_MHZ(*int_value));
log_printf("%-9s", freq_str);
}
free(int_value);
} else
log_printf("%-9s", no_prop_value);
compatible:
status = picl_get_propinfo_by_name(cpuh, "compatible", &propinfo,
&proph);
if (status == PICL_SUCCESS) {
if (propinfo.type == PICL_PTYPE_CHARSTRING) {
/*
* Compatible Property only has 1 value
*/
comp_value = malloc(propinfo.size);
if (comp_value == NULL) {
log_printf("%-20s", no_prop_value, 0);
goto mask;
}
status = picl_get_propval(proph, comp_value,
propinfo.size);
if (status != PICL_SUCCESS)
log_printf("%-20s", no_prop_value, 0);
else
log_printf("%-20s", comp_value, 0);
free(comp_value);
} else if (propinfo.type == PICL_PTYPE_TABLE) {
/*
* Compatible Property has multiple values
*/
status = picl_get_propval(proph, &tblh, propinfo.size);
if (status != PICL_SUCCESS) {
log_printf("%-20s", no_prop_value, 0);
goto mask;
}
status = picl_get_next_by_row(tblh, &rowproph);
if (status != PICL_SUCCESS) {
log_printf("%-20s", no_prop_value, 0);
goto mask;
}
status = picl_get_propinfo(rowproph, &propinfo);
if (status != PICL_SUCCESS) {
log_printf("%-20s", no_prop_value, 0);
goto mask;
}
comp_value = malloc(propinfo.size);
if (comp_value == NULL) {
log_printf("%-20s", no_prop_value, 0);
goto mask;
}
status = picl_get_propval(rowproph, comp_value,
propinfo.size);
if (status != PICL_SUCCESS)
log_printf("%-20s", no_prop_value, 0);
else
log_printf("%-20s", comp_value, 0);
free(comp_value);
}
} else
log_printf("%-20s", no_prop_value, 0);
mask:
status = picl_get_propinfo_by_name(cpuh, "mask#", &propinfo, &proph);
if (status == PICL_SUCCESS) {
status = picl_get_propval(proph, &mask_no, sizeof (mask_no));
if (status != PICL_SUCCESS) {
log_printf("%-9s", no_prop_value);
} else {
log_printf(dgettext(TEXT_DOMAIN, " %2d.%d"),
(mask_no>> 4) & 0xf, mask_no & 0xf);
}
} else
log_printf("%-9s", no_prop_value);
done:
log_printf("\n");
return (PICL_WALK_CONTINUE);
}
void
sun4v_display_diaginfo(int flag, Prom_node *root, picl_nodehdl_t plafh)
{
#ifdef lint
flag = flag;
root = root;
plafh = plafh;
#endif
/*
* This function is intentionally empty
*/
}
void
display_boardnum(int num)
{
log_printf("%2d ", num, 0);
}
static void
sun4v_disp_env_status()
{
if (phyplatformh == 0)
return;
log_printf("\n");
log_printf("============================");
log_printf(" Environmental Status ");
log_printf("============================");
log_printf("\n");
class_node_found = 0;
all_status_ok = 1;
sun4v_env_print_fan_sensors();
class_node_found = 0;
all_status_ok = 1;
sun4v_env_print_fan_indicators();
class_node_found = 0;
all_status_ok = 1;
sun4v_env_print_temp_sensors();
class_node_found = 0;
all_status_ok = 1;
sun4v_env_print_temp_indicators();
class_node_found = 0;
all_status_ok = 1;
sun4v_env_print_current_sensors();
class_node_found = 0;
all_status_ok = 1;
sun4v_env_print_current_indicators();
class_node_found = 0;
all_status_ok = 1;
sun4v_env_print_voltage_sensors();
class_node_found = 0;
all_status_ok = 1;
sun4v_env_print_voltage_indicators();
class_node_found = 0;
sun4v_env_print_LEDs();
class_node_found = 0;
all_status_ok = 1;
sun4v_print_fru_status();
class_node_found = 0;
sun4v_print_fw_rev();
sun4v_print_chassis_serial_no();
}
/*ARGSUSED*/
static int
sun4v_env_print_sensor_callback(picl_nodehdl_t nodeh, void *args)
{
char val[PICL_PROPNAMELEN_MAX];
picl_nodehdl_t parenth;
char *names[PARENT_NAMES];
char *loc;
int i;
char *prop;
picl_errno_t err;
int32_t lo_warning, lo_shutdown;
int32_t hi_warning, hi_shutdown;
int32_t current_val;
if (class_node_found == 0) {
class_node_found = 1;
return (PICL_WALK_TERMINATE);
}
if (syserrlog == 0) {
err = picl_get_propval_by_name(nodeh,
PICL_PROP_OPERATIONAL_STATUS, val,
sizeof (val));
if (err == PICL_SUCCESS) {
if (strcmp(val, "disabled") == 0) {
if (all_status_ok) {
all_status_ok = 0;
return (PICL_WALK_TERMINATE);
}
} else
return (PICL_WALK_CONTINUE);
} else {
all_status_ok = 0;
return (PICL_WALK_TERMINATE);
}
}
err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
sizeof (parenth));
if (err != PICL_SUCCESS) {
log_printf("\n");
return (PICL_WALK_CONTINUE);
}
if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL)
return (PICL_WALK_TERMINATE);
for (i = 0; i < PARENT_NAMES; i++)
if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) {
while (--i > -1)
free(names[i]);
free(loc);
return (PICL_WALK_TERMINATE);
}
i = 0;
while (err == PICL_SUCCESS) {
if (parenth == chassish || parenth == phyplatformh)
break;
err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
names[i++], PICL_PROPNAMELEN_MAX);
if (err != PICL_SUCCESS) {
i--;
break;
}
if (i == PARENT_NAMES)
break;
err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
&parenth, sizeof (parenth));
}
loc[0] = '\0';
if (--i > -1)
loc = strncat(loc, names[i], strlen(names[i]));
while (--i > -1) {
loc = strncat(loc, "/", 1);
loc = strncat(loc, names[i], strlen(names[i]));
}
log_printf("%-12s", loc);
for (i = 0; i < PARENT_NAMES; i++)
free(names[i]);
free(loc);
err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
sizeof (val));
if (err == PICL_SUCCESS)
log_printf("%-15s", val);
prop = (char *)args;
if (!prop) {
log_printf("\n");
return (PICL_WALK_CONTINUE);
}
if (picl_get_propval_by_name(nodeh, prop, &current_val,
sizeof (current_val)) != PICL_SUCCESS) {
log_printf("\n");
return (PICL_WALK_CONTINUE);
}
if (picl_get_propval_by_name(nodeh, PICL_PROP_LOW_WARNING,
&lo_warning, sizeof (lo_warning)) != PICL_SUCCESS)
lo_warning = INVALID_THRESHOLD;
if (picl_get_propval_by_name(nodeh, PICL_PROP_LOW_SHUTDOWN,
&lo_shutdown, sizeof (lo_shutdown)) != PICL_SUCCESS)
lo_shutdown = INVALID_THRESHOLD;
if (picl_get_propval_by_name(nodeh, PICL_PROP_HIGH_WARNING,
&hi_warning, sizeof (hi_warning)) != PICL_SUCCESS)
hi_warning = INVALID_THRESHOLD;
if (picl_get_propval_by_name(nodeh, PICL_PROP_HIGH_SHUTDOWN,
&hi_shutdown, sizeof (hi_shutdown)) != PICL_SUCCESS)
hi_shutdown = INVALID_THRESHOLD;
if ((lo_shutdown != INVALID_THRESHOLD &&
current_val <= lo_shutdown) ||
(hi_shutdown != INVALID_THRESHOLD &&
current_val >= hi_shutdown)) {
log_printf("%-s", "failed (");
log_printf("%-d", current_val);
log_printf("%-s", ")");
} else if ((lo_warning != INVALID_THRESHOLD &&
current_val <= lo_warning) ||
(hi_warning != INVALID_THRESHOLD &&
current_val >= hi_warning)) {
log_printf("%-s", "warning (");
log_printf("%-d", current_val);
log_printf("%-s", ")");
} else
log_printf("%-s", "ok");
log_printf("\n");
return (PICL_WALK_CONTINUE);
}
/*ARGSUSED*/
static int
sun4v_env_print_indicator_callback(picl_nodehdl_t nodeh, void *args)
{
char val[PICL_PROPNAMELEN_MAX];
char status[PICL_PROPNAMELEN_MAX];
picl_nodehdl_t parenth;
char *names[PARENT_NAMES];
char *loc;
int i = 0;
char *prop = (char *)args;
picl_errno_t err = PICL_SUCCESS;
if (class_node_found == 0) {
class_node_found = 1;
return (PICL_WALK_TERMINATE);
}
if (syserrlog == 0) {
err = picl_get_propval_by_name(nodeh,
PICL_PROP_OPERATIONAL_STATUS, status,
sizeof (status));
if (err == PICL_SUCCESS) {
if (strcmp(status, "disabled") == 0) {
if (all_status_ok) {
all_status_ok = 0;
return (PICL_WALK_TERMINATE);
}
} else
return (PICL_WALK_CONTINUE);
} else {
all_status_ok = 0;
return (PICL_WALK_TERMINATE);
}
}
err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
sizeof (parenth));
if (err != PICL_SUCCESS) {
log_printf("\n");
return (PICL_WALK_CONTINUE);
}
if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL)
return (PICL_WALK_TERMINATE);
for (i = 0; i < PARENT_NAMES; i++)
if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) {
while (--i > -1)
free(names[i]);
free(loc);
return (PICL_WALK_TERMINATE);
}
i = 0;
while (err == PICL_SUCCESS) {
if (parenth == chassish || parenth == phyplatformh)
break;
err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
names[i++], PICL_PROPNAMELEN_MAX);
if (err != PICL_SUCCESS) {
i--;
break;
}
if (i == PARENT_NAMES)
break;
err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
&parenth, sizeof (parenth));
}
loc[0] = '\0';
if (--i > -1)
loc = strncat(loc, names[i], strlen(names[i]));
while (--i > -1) {
loc = strncat(loc, "/", 1);
loc = strncat(loc, names[i], strlen(names[i]));
}
log_printf("%-12s", loc);
for (i = 0; i < PARENT_NAMES; i++)
free(names[i]);
free(loc);
err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, val,
sizeof (val));
if (err == PICL_SUCCESS)
log_printf("%-15s", val);
if (syserrlog == 0) {
log_printf("%-8s", status);
return (PICL_WALK_CONTINUE);
}
err = picl_get_propval_by_name(nodeh, prop, val,
sizeof (val));
if (err == PICL_SUCCESS)
log_printf("%-8s", val);
log_printf("\n");
return (PICL_WALK_CONTINUE);
}
static void
sun4v_env_print_fan_sensors()
{
char *fmt = "%-11s %-14s %-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_CLASS_RPM_SENSOR,
sun4v_env_print_sensor_callback);
if (!class_node_found)
return;
log_printf("Fan sensors:\n");
if (syserrlog == 0) {
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_RPM_SENSOR,
NULL, sun4v_env_print_sensor_callback);
if (all_status_ok) {
log_printf("All fan sensors are OK.\n");
return;
}
}
log_printf("---------------------------------\n");
log_printf(fmt, "Location", "Sensor", "Status", 0);
log_printf("---------------------------------\n");
(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_SENSOR,
PICL_PROP_SPEED, sun4v_env_print_sensor_callback);
}
static void
sun4v_env_print_fan_indicators()
{
char *fmt = "%-11s %-14s %-10s\n";
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_RPM_INDICATOR, (void *)PICL_CLASS_RPM_INDICATOR,
sun4v_env_print_indicator_callback);
if (!class_node_found)
return;
log_printf("\nFan indicators:\n");
if (syserrlog == 0) {
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_RPM_INDICATOR,
NULL, sun4v_env_print_indicator_callback);
if (all_status_ok) {
log_printf("All fan indicators are OK.\n");
return;
}
}
log_printf("------------------------------------\n");
log_printf(fmt, "Location", "Sensor", "Condition", 0);
log_printf("------------------------------------\n");
(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_RPM_INDICATOR,
PICL_CLASS_RPM_INDICATOR, sun4v_env_print_indicator_callback);
}
static void
sun4v_env_print_temp_sensors()
{
char *fmt = "%-11s %-14s %-10s\n";
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_TEMPERATURE_SENSOR,
(void *)PICL_PROP_TEMPERATURE,
sun4v_env_print_sensor_callback);
if (!class_node_found)
return;
log_printf("\nTemperature sensors:\n");
if (syserrlog == 0) {
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_TEMPERATURE_SENSOR,
NULL, sun4v_env_print_sensor_callback);
if (all_status_ok) {
log_printf("All temperature sensors are OK.\n");
return;
}
}
log_printf("---------------------------------\n");
log_printf(fmt, "Location", "Sensor", "Status", 0);
log_printf("---------------------------------\n");
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_TEMPERATURE_SENSOR,
(void *)PICL_PROP_TEMPERATURE, sun4v_env_print_sensor_callback);
}
static void
sun4v_env_print_temp_indicators()
{
char *fmt = "%-11s %-14s %-8s\n";
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_TEMPERATURE_INDICATOR, (void *)PICL_PROP_CONDITION,
sun4v_env_print_indicator_callback);
if (!class_node_found)
return;
log_printf("\nTemperature indicators:\n");
if (syserrlog == 0) {
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_TEMPERATURE_INDICATOR, NULL,
sun4v_env_print_indicator_callback);
if (all_status_ok) {
log_printf("All temperature indicators are OK.\n");
return;
}
}
log_printf("------------------------------\n");
log_printf(fmt, "Location", "Indicator", "Condition", 0);
log_printf("------------------------------\n");
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_TEMPERATURE_INDICATOR,
(void *)PICL_PROP_CONDITION,
sun4v_env_print_indicator_callback);
}
static void
sun4v_env_print_current_sensors()
{
char *fmt = "%-11s %-14s %-10s\n";
(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_CURRENT_SENSOR,
(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,
PICL_CLASS_CURRENT_SENSOR,
NULL, sun4v_env_print_sensor_callback);
if (all_status_ok) {
log_printf("All current sensors are OK.\n");
return;
}
}
log_printf("---------------------------------\n");
log_printf(fmt, "Location", "Sensor", "Status", 0);
log_printf("---------------------------------\n");
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_CURRENT_SENSOR, (void *)PICL_PROP_CURRENT,
sun4v_env_print_sensor_callback);
}
static void
sun4v_env_print_current_indicators()
{
char *fmt = "%-11s %-14s %-8s\n";
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_CURRENT_INDICATOR,
(void *)PICL_PROP_CONDITION,
sun4v_env_print_indicator_callback);
if (!class_node_found)
return;
log_printf("\nCurrent indicators:\n");
if (syserrlog == 0) {
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_CURRENT_INDICATOR, NULL,
sun4v_env_print_indicator_callback);
if (all_status_ok) {
log_printf("All current indicators are OK.\n");
return;
}
}
log_printf("------------------------------------\n");
log_printf(fmt, "Location", "Indicator", "Condition", 0);
log_printf("------------------------------------\n");
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_CURRENT_INDICATOR,
(void *)PICL_PROP_CONDITION,
sun4v_env_print_indicator_callback);
}
static void
sun4v_env_print_voltage_sensors()
{
char *fmt = "%-11s %-14s %-10s\n";
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_VOLTAGE_SENSOR,
PICL_PROP_VOLTAGE,
sun4v_env_print_sensor_callback);
if (!class_node_found)
return;
log_printf("\nVoltage sensors:\n");
if (syserrlog == 0) {
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_VOLTAGE_SENSOR,
NULL, sun4v_env_print_sensor_callback);
if (all_status_ok) {
log_printf("All voltage sensors are OK.\n");
return;
}
}
log_printf("---------------------------------\n");
log_printf(fmt, "Location", "Sensor", "Status", 0);
log_printf("---------------------------------\n");
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_VOLTAGE_SENSOR,
(void *)PICL_PROP_VOLTAGE,
sun4v_env_print_sensor_callback);
}
static void
sun4v_env_print_voltage_indicators()
{
char *fmt = "%-11s %-14s %-8s\n";
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_VOLTAGE_INDICATOR,
(void *)PICL_PROP_CONDITION,
sun4v_env_print_indicator_callback);
if (!class_node_found)
return;
log_printf("\nVoltage indicators:\n");
if (syserrlog == 0) {
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_VOLTAGE_INDICATOR, NULL,
sun4v_env_print_indicator_callback);
if (all_status_ok) {
log_printf("All voltage indicators are OK.\n");
return;
}
}
log_printf("------------------------------------\n");
log_printf(fmt, "Location", "Indicator", "Condition", 0);
log_printf("------------------------------------\n");
(void) picl_walk_tree_by_class(phyplatformh,
PICL_CLASS_VOLTAGE_INDICATOR,
(void *)PICL_PROP_CONDITION,
sun4v_env_print_indicator_callback);
}
static void
sun4v_env_print_LEDs()
{
char *fmt = "%-11s %-14s %-8s\n";
if (syserrlog == 0)
return;
(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
(void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
if (!class_node_found)
return;
log_printf("\nLEDs:\n");
log_printf("--------------------------------\n");
log_printf(fmt, "Location", "LED", "State", 0);
log_printf("--------------------------------\n");
(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_LED,
(void *)PICL_PROP_STATE, sun4v_env_print_indicator_callback);
}
/*ARGSUSED*/
static int
sun4v_print_fru_status_callback(picl_nodehdl_t nodeh, void *args)
{
char label[PICL_PROPNAMELEN_MAX];
char status[PICL_PROPNAMELEN_MAX];
picl_errno_t err;
picl_prophdl_t proph;
picl_nodehdl_t parenth;
char *names[PARENT_NAMES];
char *loc;
int i;
if (!class_node_found) {
class_node_found = 1;
return (PICL_WALK_TERMINATE);
}
err = picl_get_prop_by_name(nodeh, PICL_PROP_IS_FRU, &proph);
if (err != PICL_SUCCESS)
return (PICL_WALK_CONTINUE);
err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
sizeof (label));
if (err != PICL_SUCCESS)
return (PICL_WALK_CONTINUE);
err = picl_get_propval_by_name(nodeh, PICL_PROP_OPERATIONAL_STATUS,
status, sizeof (status));
if (err != PICL_SUCCESS)
return (PICL_WALK_CONTINUE);
if (syserrlog == 0) {
if (strcmp(status, "disabled") == 0) {
if (all_status_ok) {
all_status_ok = 0;
return (PICL_WALK_TERMINATE);
}
} else
return (PICL_WALK_CONTINUE);
}
err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, &parenth,
sizeof (parenth));
if (err != PICL_SUCCESS) {
log_printf("\n");
return (PICL_WALK_CONTINUE);
}
if ((loc = (char *)malloc(PICL_PROPNAMELEN_MAX*PARENT_NAMES)) == NULL)
return (PICL_WALK_TERMINATE);
for (i = 0; i < PARENT_NAMES; i++)
if ((names[i] = (char *)malloc(PICL_PROPNAMELEN_MAX)) == NULL) {
while (--i > -1)
free(names[i]);
free(loc);
return (PICL_WALK_TERMINATE);
}
i = 0;
while (err == PICL_SUCCESS) {
if (parenth == chassish || parenth == phyplatformh)
break;
err = picl_get_propval_by_name(parenth, PICL_PROP_NAME,
names[i++], PICL_PROPNAMELEN_MAX);
if (err != PICL_SUCCESS) {
i--;
break;
}
if (i == PARENT_NAMES)
break;
err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
&parenth, sizeof (parenth));
}
loc[0] = '\0';
if (--i > -1)
loc = strncat(loc, names[i], strlen(names[i]));
while (--i > -1) {
loc = strncat(loc, "/", 1);
loc = strncat(loc, names[i], strlen(names[i]));
}
log_printf("%-21s", loc);
for (i = 0; i < PARENT_NAMES; i++)
free(names[i]);
free(loc);
log_printf("%-10s", label);
log_printf("%-9s", status);
log_printf("\n");
return (PICL_WALK_CONTINUE);
}
static void
sun4v_print_fru_status()
{
char *fmt = "%-20s %-9s %-8s\n";
(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
sun4v_print_fru_status_callback);
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,
PICL_CLASS_MODULE, NULL,
sun4v_print_fru_status_callback);
if (all_status_ok) {
log_printf("All FRUs are enabled.\n");
return;
}
}
log_printf(fmt, "Location", "Name", "Status", 0);
log_printf("-------------------------------------\n");
(void) picl_walk_tree_by_class(phyplatformh, PICL_CLASS_MODULE, NULL,
sun4v_print_fru_status_callback);
}
/*ARGSUSED*/
static int
sun4v_print_fw_rev_callback(picl_nodehdl_t nodeh, void *args)
{
char label[PICL_PROPNAMELEN_MAX];
char rev[PICL_PROPNAMELEN_MAX];
picl_errno_t err;
if (!class_node_found) {
class_node_found = 1;
return (PICL_WALK_TERMINATE);
}
err = picl_get_propval_by_name(nodeh, PICL_PROP_LABEL, label,
sizeof (label));
if (err != PICL_SUCCESS)
return (PICL_WALK_CONTINUE);
err = picl_get_propval_by_name(nodeh, PICL_PROP_FW_REVISION, rev,
sizeof (rev));
if (err != PICL_SUCCESS)
return (PICL_WALK_CONTINUE);
if (strlen(rev) == 0)
return (PICL_WALK_CONTINUE);
log_printf("%-21s", label);
log_printf("%-40s", rev);
log_printf("\n");
return (PICL_WALK_CONTINUE);
}
static void
sun4v_print_fw_rev()
{
char *fmt = "%-20s %-10s\n";
if (syserrlog == 0)
return;
(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
sun4v_print_fw_rev_callback);
if (!class_node_found)
return;
log_printf("\n");
log_printf("============================");
log_printf(" FW Version ");
log_printf("============================");
log_printf("\n");
log_printf(fmt, "Name", "Version", 0);
log_printf("----------------------------\n");
(void) picl_walk_tree_by_class(phyplatformh, NULL, NULL,
sun4v_print_fw_rev_callback);
}
static void
sun4v_print_chassis_serial_no()
{
char val[PICL_PROPNAMELEN_MAX];
picl_errno_t err;
if (syserrlog == 0 || chassish == 0)
return;
log_printf("\n");
log_printf("Chassis Serial Number");
log_printf("\n");
log_printf("---------------------\n");
err = picl_get_propval_by_name(chassish, PICL_PROP_SERIAL_NUMBER,
val, sizeof (val));
if (err == PICL_SUCCESS)
log_printf("%s", val);
log_printf("\n");
}