103831d35Sstevel /*
203831d35Sstevel * CDDL HEADER START
303831d35Sstevel *
403831d35Sstevel * The contents of this file are subject to the terms of the
503831d35Sstevel * Common Development and Distribution License (the "License").
603831d35Sstevel * You may not use this file except in compliance with the License.
703831d35Sstevel *
803831d35Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
903831d35Sstevel * or http://www.opensolaris.org/os/licensing.
1003831d35Sstevel * See the License for the specific language governing permissions
1103831d35Sstevel * and limitations under the License.
1203831d35Sstevel *
1303831d35Sstevel * When distributing Covered Code, include this CDDL HEADER in each
1403831d35Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1503831d35Sstevel * If applicable, add the following below this CDDL HEADER, with the
1603831d35Sstevel * fields enclosed by brackets "[]" replaced with your own identifying
1703831d35Sstevel * information: Portions Copyright [yyyy] [name of copyright owner]
1803831d35Sstevel *
1903831d35Sstevel * CDDL HEADER END
2003831d35Sstevel */
2103831d35Sstevel
2203831d35Sstevel /*
23*2983dda7SMichael Bergknoff * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
2403831d35Sstevel */
2503831d35Sstevel
2603831d35Sstevel #include <stdio.h>
2703831d35Sstevel #include <stdlib.h>
2803831d35Sstevel #include <string.h>
2903831d35Sstevel #include <alloca.h>
3003831d35Sstevel #include <errno.h>
3103831d35Sstevel #include <libintl.h>
3203831d35Sstevel #include <sys/utsname.h>
3303831d35Sstevel #include <sys/types.h>
3403831d35Sstevel #include <sys/stat.h>
3503831d35Sstevel #include <sys/openpromio.h>
3603831d35Sstevel #include <sys/ddi.h>
3703831d35Sstevel #include <syslog.h>
3803831d35Sstevel #include <fcntl.h>
3903831d35Sstevel #include <dirent.h>
4003831d35Sstevel #include <unistd.h>
4103831d35Sstevel #include <locale.h>
4203831d35Sstevel #include <picl.h>
4303831d35Sstevel #include "pdevinfo.h"
4403831d35Sstevel #include "display.h"
4503831d35Sstevel #include "display_sun4u.h"
4603831d35Sstevel #include "picldefs.h"
4703831d35Sstevel #include "libprtdiag.h"
4803831d35Sstevel
4903831d35Sstevel #if !defined(TEXT_DOMAIN)
5003831d35Sstevel #define TEXT_DOMAIN "SYS_TEST"
5103831d35Sstevel #endif
5203831d35Sstevel
5303831d35Sstevel #define EM_INIT_FAIL dgettext(TEXT_DOMAIN,\
5403831d35Sstevel "picl_initialize failed: %s\n")
5503831d35Sstevel #define EM_GET_ROOT_FAIL dgettext(TEXT_DOMAIN,\
5603831d35Sstevel "Getting root node failed: %s\n")
5703831d35Sstevel #define EM_PRTDIAG_FAIL dgettext(TEXT_DOMAIN, "Prtdiag failed!\n")
5803831d35Sstevel
5903831d35Sstevel #define SIGN_ON_MSG dgettext(TEXT_DOMAIN,\
60*2983dda7SMichael Bergknoff "System Configuration: Oracle Corporation ")
6103831d35Sstevel #define SYSCLK_FREQ_MSG dgettext(TEXT_DOMAIN,\
6203831d35Sstevel "System clock frequency: %d MHZ\n")
6303831d35Sstevel #define SERIAL_NUM_MSG dgettext(TEXT_DOMAIN,\
6403831d35Sstevel "Chassis Serial Number:\n")
6503831d35Sstevel #define MEM_SIZE_MSG dgettext(TEXT_DOMAIN, "Memory size: ")
6603831d35Sstevel #define FFB_DOUBLE_BUF dgettext(TEXT_DOMAIN, "FFB, Double Buffered")
6703831d35Sstevel #define FFB_SINGLE_BUF dgettext(TEXT_DOMAIN, "FFB, Single Buffered")
6803831d35Sstevel
6903831d35Sstevel #define DEFAULT_BOARD_NUM 0
7003831d35Sstevel #define DEFAULT_PORTID 0
7103831d35Sstevel #define CLK_FREQ_66MHZ 66
7203831d35Sstevel #define USB -1
7303831d35Sstevel #define HUB -2
7403831d35Sstevel
7503831d35Sstevel /* bus id */
7603831d35Sstevel #define SBUS_TYPE 0
7703831d35Sstevel #define PCI_TYPE 1
7803831d35Sstevel #define UPA_TYPE 2
7903831d35Sstevel #define PCIEX_TYPE 3
8003831d35Sstevel
8103831d35Sstevel #define UPA_NAME "upa"
8203831d35Sstevel #define PCIEX_NAME "pciex"
8303831d35Sstevel
8403831d35Sstevel /*
8503831d35Sstevel * PICL classes
8603831d35Sstevel */
8703831d35Sstevel #define PICL_CLASS_OPTIONS "options"
8803831d35Sstevel
8903831d35Sstevel /*
9003831d35Sstevel * Property names
9103831d35Sstevel */
9203831d35Sstevel
9303831d35Sstevel #define OBP_PROP_REG "reg"
9403831d35Sstevel #define OBP_PROP_CLOCK_FREQ "clock-frequency"
9503831d35Sstevel #define OBP_PROP_BOARD_NUM "board#"
9603831d35Sstevel #define OBP_PROP_REVISION_ID "revision-id"
9703831d35Sstevel #define OBP_PROP_VERSION_NUM "version#"
9803831d35Sstevel #define OBP_PROP_MODREV_NUM "module-revision#"
99d0e72dffSvenki #define OBP_PROP_FIREREV_NUM "fire-revision#"
10003831d35Sstevel #define OBP_PROP_BOARD_TYPE "board_type"
10103831d35Sstevel #define OBP_PROP_ECACHE_SIZE "ecache-size"
10203831d35Sstevel #define OBP_PROP_IMPLEMENTATION "implementation#"
10303831d35Sstevel #define OBP_PROP_MASK "mask#"
10403831d35Sstevel #define OBP_PROP_COMPATIBLE "compatible"
10503831d35Sstevel #define OBP_PROP_BANNER_NAME "banner-name"
10603831d35Sstevel #define OBP_PROP_MODEL "model"
10703831d35Sstevel #define OBP_PROP_66MHZ_CAPABLE "66mhz-capable"
10803831d35Sstevel #define OBP_PROP_FBC_REG_ID "fbc_reg_id"
10903831d35Sstevel #define OBP_PROP_VERSION "version"
11003831d35Sstevel
11103831d35Sstevel #define PROP_POWERFAIL_TIME "powerfail-time"
11203831d35Sstevel #define PICL_PROP_LOW_WARNING_THRESHOLD "LowWarningThreshold"
11303831d35Sstevel
11403831d35Sstevel #define DEFAULT_LINE_WIDTH 78
11503831d35Sstevel #define HEADING_SYMBOL "="
11603831d35Sstevel
11703831d35Sstevel #define MAX_IWAYS 32
11803831d35Sstevel
11903831d35Sstevel typedef struct bank_list {
12003831d35Sstevel picl_nodehdl_t nodeh;
12103831d35Sstevel uint32_t iway_count;
12203831d35Sstevel uint32_t iway[MAX_IWAYS];
12303831d35Sstevel struct bank_list *next;
12403831d35Sstevel } bank_list_t;
12503831d35Sstevel
12603831d35Sstevel typedef struct {
12703831d35Sstevel uint64_t base;
12803831d35Sstevel uint64_t size;
12903831d35Sstevel int ifactor;
13003831d35Sstevel int bank_count;
13103831d35Sstevel } seg_info_t;
13203831d35Sstevel
13303831d35Sstevel static struct io_card *io_card_list = NULL; /* The head of the IO card list */
13403831d35Sstevel static bank_list_t *mem_banks = NULL;
13503831d35Sstevel static int mem_xfersize;
13603831d35Sstevel static int no_xfer_size = 0;
13703831d35Sstevel
13803831d35Sstevel static char *io_device_table[] = {
13903831d35Sstevel "block",
14003831d35Sstevel "disk",
14103831d35Sstevel "cdrom",
14203831d35Sstevel "floppy",
14303831d35Sstevel "tape",
14403831d35Sstevel "network",
14503831d35Sstevel "display",
14603831d35Sstevel "serial",
14703831d35Sstevel "parallel",
14803831d35Sstevel "scsi",
14903831d35Sstevel "scsi-2",
15003831d35Sstevel "scsi-3",
15103831d35Sstevel "ide",
15203831d35Sstevel "fcal",
15303831d35Sstevel "keyboard",
15403831d35Sstevel "mouse",
15503831d35Sstevel "dma"
15603831d35Sstevel };
15703831d35Sstevel
15803831d35Sstevel #define NIODEVICE sizeof (io_device_table) / sizeof (io_device_table[0])
15903831d35Sstevel
16003831d35Sstevel static char *bus_table[] = {
16103831d35Sstevel "ebus",
16203831d35Sstevel "isa",
16303831d35Sstevel "pmu",
16403831d35Sstevel "pci",
16503831d35Sstevel "pciex"
16603831d35Sstevel };
16703831d35Sstevel
16803831d35Sstevel #define NBUS sizeof (bus_table) / sizeof (bus_table[0])
16903831d35Sstevel
17003831d35Sstevel /* prtdiag exit codes */
17103831d35Sstevel #define PD_SUCCESS 0
17203831d35Sstevel #define PD_SYSTEM_FAILURE 1
17303831d35Sstevel #define PD_INTERNAL_FAILURE 2
17403831d35Sstevel
17503831d35Sstevel /*
17603831d35Sstevel * Use of global assumes do_prominfo only called from main in prtdiag and
17703831d35Sstevel * access does not need to be multi-thread safe.
17803831d35Sstevel */
17903831d35Sstevel static int exit_code = PD_SUCCESS;
18003831d35Sstevel
18103831d35Sstevel /*
18203831d35Sstevel * This function is called from every location where a status value is output.
18303831d35Sstevel * It checks the status arg and sets exit_code if an error is detected.
18403831d35Sstevel * The status is typically returned from a PICL query. A case-insensitive
18503831d35Sstevel * string comparison is done to check for any status that starts with "fail"
18603831d35Sstevel * or "fault".
18703831d35Sstevel */
18803831d35Sstevel static void
set_exit_code(char * status)18903831d35Sstevel set_exit_code(char *status)
19003831d35Sstevel {
19103831d35Sstevel if (status == NULL)
19203831d35Sstevel return;
19303831d35Sstevel
19403831d35Sstevel if (strncasecmp(status, "fail", 4) == 0 ||
19503831d35Sstevel strncasecmp(status, "fault", 5) == 0)
19603831d35Sstevel exit_code = PD_SYSTEM_FAILURE;
19703831d35Sstevel }
19803831d35Sstevel
19903831d35Sstevel /*
20003831d35Sstevel * check if it is an IO deice
20103831d35Sstevel */
20203831d35Sstevel static int
is_io_device(char * device_class)20303831d35Sstevel is_io_device(char *device_class)
20403831d35Sstevel {
20503831d35Sstevel int i;
20603831d35Sstevel
20703831d35Sstevel for (i = 0; i < NIODEVICE; i++) {
208*2983dda7SMichael Bergknoff if (strcmp(device_class, io_device_table[i]) == 0)
209*2983dda7SMichael Bergknoff return (1);
21003831d35Sstevel }
21103831d35Sstevel
21203831d35Sstevel return (0);
21303831d35Sstevel }
21403831d35Sstevel
21503831d35Sstevel /*
21603831d35Sstevel * check if it is a bus
21703831d35Sstevel */
21803831d35Sstevel static int
is_bus(char * device_class)21903831d35Sstevel is_bus(char *device_class)
22003831d35Sstevel {
22103831d35Sstevel int i;
22203831d35Sstevel
22303831d35Sstevel for (i = 0; i < NBUS; i++) {
224*2983dda7SMichael Bergknoff if (strcmp(device_class, bus_table[i]) == 0)
225*2983dda7SMichael Bergknoff return (1);
22603831d35Sstevel }
22703831d35Sstevel
22803831d35Sstevel return (0);
22903831d35Sstevel }
23003831d35Sstevel
23103831d35Sstevel /*
23203831d35Sstevel * search children to get the node by the nodename
23303831d35Sstevel */
23403831d35Sstevel static int
picldiag_get_node_by_name(picl_nodehdl_t rooth,char * name,picl_nodehdl_t * nodeh)23503831d35Sstevel picldiag_get_node_by_name(picl_nodehdl_t rooth, char *name,
23603831d35Sstevel picl_nodehdl_t *nodeh)
23703831d35Sstevel {
23803831d35Sstevel picl_nodehdl_t childh;
23903831d35Sstevel int err;
24003831d35Sstevel char *nodename;
24103831d35Sstevel
24203831d35Sstevel nodename = alloca(strlen(name) + 1);
24303831d35Sstevel if (nodename == NULL)
24403831d35Sstevel return (PICL_FAILURE);
24503831d35Sstevel
24603831d35Sstevel err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &childh,
24703831d35Sstevel sizeof (picl_nodehdl_t));
24803831d35Sstevel
24903831d35Sstevel while (err == PICL_SUCCESS) {
25003831d35Sstevel err = picl_get_propval_by_name(childh, PICL_PROP_NAME,
25103831d35Sstevel nodename, (strlen(name) + 1));
25203831d35Sstevel if (err != PICL_SUCCESS) {
25303831d35Sstevel err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
254*2983dda7SMichael Bergknoff &childh, sizeof (picl_nodehdl_t));
25503831d35Sstevel continue;
25603831d35Sstevel }
25703831d35Sstevel
25803831d35Sstevel if (strcmp(nodename, name) == 0) {
25903831d35Sstevel *nodeh = childh;
26003831d35Sstevel return (PICL_SUCCESS);
26103831d35Sstevel }
26203831d35Sstevel
26303831d35Sstevel err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
26403831d35Sstevel &childh, sizeof (picl_nodehdl_t));
26503831d35Sstevel }
26603831d35Sstevel
26703831d35Sstevel return (err);
26803831d35Sstevel }
26903831d35Sstevel
27003831d35Sstevel /*
27103831d35Sstevel * get the value by the property name of the string prop
27203831d35Sstevel * Caller must free the outbuf
27303831d35Sstevel */
27403831d35Sstevel static int
picldiag_get_string_propval(picl_nodehdl_t modh,char * prop_name,char ** outbuf)27503831d35Sstevel picldiag_get_string_propval(picl_nodehdl_t modh, char *prop_name, char **outbuf)
27603831d35Sstevel {
27703831d35Sstevel int err;
27803831d35Sstevel picl_prophdl_t proph;
27903831d35Sstevel picl_propinfo_t pinfo;
28003831d35Sstevel char *prop_value;
28103831d35Sstevel
28203831d35Sstevel err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
28303831d35Sstevel if (err != PICL_SUCCESS)
28403831d35Sstevel return (err);
28503831d35Sstevel
28603831d35Sstevel /*
28703831d35Sstevel * If it is not a string prop, return NULL
28803831d35Sstevel */
28903831d35Sstevel if (pinfo.type != PICL_PTYPE_CHARSTRING)
290*2983dda7SMichael Bergknoff return (PICL_FAILURE);
29103831d35Sstevel
29203831d35Sstevel prop_value = malloc(pinfo.size);
29303831d35Sstevel if (prop_value == NULL)
29403831d35Sstevel return (PICL_FAILURE);
29503831d35Sstevel
29603831d35Sstevel err = picl_get_propval(proph, prop_value, pinfo.size);
29703831d35Sstevel if (err != PICL_SUCCESS) {
29803831d35Sstevel free(prop_value);
29903831d35Sstevel return (err);
30003831d35Sstevel }
30103831d35Sstevel
30203831d35Sstevel *outbuf = prop_value;
30303831d35Sstevel return (PICL_SUCCESS);
30403831d35Sstevel }
30503831d35Sstevel
30603831d35Sstevel
30703831d35Sstevel /*
30803831d35Sstevel * return the value as a signed integer
30903831d35Sstevel */
31003831d35Sstevel
31103831d35Sstevel static int64_t
picldiag_get_int_propval(picl_nodehdl_t modh,char * prop_name,int * ret)31203831d35Sstevel picldiag_get_int_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
31303831d35Sstevel {
31403831d35Sstevel int err;
31503831d35Sstevel picl_prophdl_t proph;
31603831d35Sstevel picl_propinfo_t pinfo;
31703831d35Sstevel int8_t int8v;
31803831d35Sstevel int16_t int16v;
31903831d35Sstevel int32_t int32v;
32003831d35Sstevel int64_t int64v;
32103831d35Sstevel
32203831d35Sstevel err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
32303831d35Sstevel if (err != PICL_SUCCESS) {
32403831d35Sstevel *ret = err;
32503831d35Sstevel return (0);
32603831d35Sstevel }
32703831d35Sstevel
32803831d35Sstevel /*
32903831d35Sstevel * If it is not an int, uint or byte array prop, return failure
33003831d35Sstevel */
33103831d35Sstevel if ((pinfo.type != PICL_PTYPE_INT) &&
332*2983dda7SMichael Bergknoff (pinfo.type != PICL_PTYPE_UNSIGNED_INT) &&
333*2983dda7SMichael Bergknoff (pinfo.type != PICL_PTYPE_BYTEARRAY)) {
33403831d35Sstevel *ret = PICL_FAILURE;
33503831d35Sstevel return (0);
33603831d35Sstevel }
33703831d35Sstevel
33803831d35Sstevel switch (pinfo.size) {
33903831d35Sstevel case sizeof (int8_t):
34003831d35Sstevel err = picl_get_propval(proph, &int8v, sizeof (int8v));
34103831d35Sstevel *ret = err;
34203831d35Sstevel return (int8v);
34303831d35Sstevel case sizeof (int16_t):
34403831d35Sstevel err = picl_get_propval(proph, &int16v, sizeof (int16v));
34503831d35Sstevel *ret = err;
34603831d35Sstevel return (int16v);
34703831d35Sstevel case sizeof (int32_t):
34803831d35Sstevel err = picl_get_propval(proph, &int32v, sizeof (int32v));
34903831d35Sstevel *ret = err;
35003831d35Sstevel return (int32v);
35103831d35Sstevel case sizeof (int64_t):
35203831d35Sstevel err = picl_get_propval(proph, &int64v, sizeof (int64v));
35303831d35Sstevel *ret = err;
35403831d35Sstevel return (int64v);
35503831d35Sstevel default: /* not supported size */
35603831d35Sstevel *ret = PICL_FAILURE;
35703831d35Sstevel return (0);
35803831d35Sstevel }
35903831d35Sstevel }
36003831d35Sstevel
36103831d35Sstevel /*
36203831d35Sstevel * return the value of the uint prop
36303831d35Sstevel */
36403831d35Sstevel static uint64_t
picldiag_get_uint_propval(picl_nodehdl_t modh,char * prop_name,int * ret)36503831d35Sstevel picldiag_get_uint_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
36603831d35Sstevel {
36703831d35Sstevel int err;
36803831d35Sstevel picl_prophdl_t proph;
36903831d35Sstevel picl_propinfo_t pinfo;
37003831d35Sstevel uint8_t uint8v;
37103831d35Sstevel uint16_t uint16v;
37203831d35Sstevel uint32_t uint32v;
37303831d35Sstevel uint64_t uint64v;
37403831d35Sstevel
37503831d35Sstevel err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
37603831d35Sstevel if (err != PICL_SUCCESS) {
37703831d35Sstevel *ret = err;
37803831d35Sstevel return (0);
37903831d35Sstevel }
38003831d35Sstevel
38103831d35Sstevel /*
38203831d35Sstevel * If it is not an int or uint prop, return failure
38303831d35Sstevel */
38403831d35Sstevel if ((pinfo.type != PICL_PTYPE_INT) &&
385*2983dda7SMichael Bergknoff (pinfo.type != PICL_PTYPE_UNSIGNED_INT)) {
38603831d35Sstevel *ret = PICL_FAILURE;
38703831d35Sstevel return (0);
38803831d35Sstevel }
38903831d35Sstevel
39003831d35Sstevel /* uint prop */
39103831d35Sstevel
39203831d35Sstevel switch (pinfo.size) {
39303831d35Sstevel case sizeof (uint8_t):
39403831d35Sstevel err = picl_get_propval(proph, &uint8v, sizeof (uint8v));
39503831d35Sstevel *ret = err;
39603831d35Sstevel return (uint8v);
39703831d35Sstevel case sizeof (uint16_t):
39803831d35Sstevel err = picl_get_propval(proph, &uint16v, sizeof (uint16v));
39903831d35Sstevel *ret = err;
40003831d35Sstevel return (uint16v);
40103831d35Sstevel case sizeof (uint32_t):
40203831d35Sstevel err = picl_get_propval(proph, &uint32v, sizeof (uint32v));
40303831d35Sstevel *ret = err;
40403831d35Sstevel return (uint32v);
40503831d35Sstevel case sizeof (uint64_t):
40603831d35Sstevel err = picl_get_propval(proph, &uint64v, sizeof (uint64v));
40703831d35Sstevel *ret = err;
40803831d35Sstevel return (uint64v);
40903831d35Sstevel default: /* not supported size */
41003831d35Sstevel *ret = PICL_FAILURE;
41103831d35Sstevel return (0);
41203831d35Sstevel }
41303831d35Sstevel }
41403831d35Sstevel
41503831d35Sstevel /*
41603831d35Sstevel * return the value of the float prop
41703831d35Sstevel */
41803831d35Sstevel static float
picldiag_get_float_propval(picl_nodehdl_t modh,char * prop_name,int * ret)41903831d35Sstevel picldiag_get_float_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
42003831d35Sstevel {
42103831d35Sstevel int err;
42203831d35Sstevel picl_prophdl_t proph;
42303831d35Sstevel picl_propinfo_t pinfo;
42403831d35Sstevel float floatv;
42503831d35Sstevel
42603831d35Sstevel err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
42703831d35Sstevel if (err != PICL_SUCCESS) {
42803831d35Sstevel *ret = err;
42903831d35Sstevel return ((float)0);
43003831d35Sstevel }
43103831d35Sstevel
43203831d35Sstevel /*
43303831d35Sstevel * If it is not a float prop, return failure
43403831d35Sstevel */
43503831d35Sstevel if (pinfo.type != PICL_PTYPE_FLOAT) {
43603831d35Sstevel *ret = PICL_FAILURE;
43703831d35Sstevel return ((float)0);
43803831d35Sstevel }
43903831d35Sstevel
44003831d35Sstevel *ret = picl_get_propval(proph, &floatv, sizeof (floatv));
44103831d35Sstevel return (floatv);
44203831d35Sstevel }
44303831d35Sstevel
44403831d35Sstevel /*
44503831d35Sstevel * get the clock frequency
44603831d35Sstevel */
44703831d35Sstevel static int
picldiag_get_clock_freq(picl_nodehdl_t modh,uint32_t * freq)44803831d35Sstevel picldiag_get_clock_freq(picl_nodehdl_t modh, uint32_t *freq)
44903831d35Sstevel {
45003831d35Sstevel #define ROUND_TO_MHZ(x) (((x) + 500000)/ 1000000)
45103831d35Sstevel int err;
45203831d35Sstevel uint64_t clk_freq;
45303831d35Sstevel
45403831d35Sstevel clk_freq = picldiag_get_uint_propval(modh, OBP_PROP_CLOCK_FREQ, &err);
45503831d35Sstevel if (err != PICL_SUCCESS)
45603831d35Sstevel return (err);
45703831d35Sstevel
45803831d35Sstevel *freq = ROUND_TO_MHZ(clk_freq);
45903831d35Sstevel
46003831d35Sstevel return (PICL_SUCCESS);
46103831d35Sstevel }
46203831d35Sstevel
46303831d35Sstevel /*
46403831d35Sstevel * get the clock frequency from parent
46503831d35Sstevel */
46603831d35Sstevel static int
picldiag_get_clock_from_parent(picl_nodehdl_t nodeh,uint32_t * clk)46703831d35Sstevel picldiag_get_clock_from_parent(picl_nodehdl_t nodeh, uint32_t *clk)
46803831d35Sstevel {
46903831d35Sstevel picl_nodehdl_t parenth;
47003831d35Sstevel int err;
47103831d35Sstevel
47203831d35Sstevel
47303831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
47403831d35Sstevel &parenth, sizeof (parenth));
47503831d35Sstevel
47603831d35Sstevel while (err == PICL_SUCCESS) {
47703831d35Sstevel err = picldiag_get_clock_freq(parenth, clk);
47803831d35Sstevel if (err != PICL_PROPNOTFOUND)
47903831d35Sstevel return (err);
48003831d35Sstevel
48103831d35Sstevel err = picl_get_propval_by_name(parenth, PICL_PROP_PARENT,
48203831d35Sstevel &parenth, sizeof (parenth));
48303831d35Sstevel }
48403831d35Sstevel
48503831d35Sstevel return (err);
48603831d35Sstevel }
48703831d35Sstevel
48803831d35Sstevel /*
48903831d35Sstevel * get _fru_parent prop
49003831d35Sstevel * If not found, then travese superiors (parent nodes) until
49103831d35Sstevel * a _fru_parent property is found.
49203831d35Sstevel * If not found, no fru parent
49303831d35Sstevel */
49403831d35Sstevel static int
picldiag_get_fru_parent(picl_nodehdl_t nodeh,picl_nodehdl_t * fruparenth)49503831d35Sstevel picldiag_get_fru_parent(picl_nodehdl_t nodeh, picl_nodehdl_t *fruparenth)
49603831d35Sstevel {
49703831d35Sstevel picl_nodehdl_t fruh;
49803831d35Sstevel int err;
49903831d35Sstevel
50003831d35Sstevel /* find fru parent */
50103831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_REFPROP_FRU_PARENT,
50203831d35Sstevel &fruh, sizeof (fruh));
50303831d35Sstevel if (err != PICL_SUCCESS)
50403831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_REFPROP_LOC_PARENT,
50503831d35Sstevel &fruh, sizeof (fruh));
50603831d35Sstevel
50703831d35Sstevel while (err == PICL_PROPNOTFOUND) {
50803831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
50903831d35Sstevel &nodeh, sizeof (nodeh));
51003831d35Sstevel if (err != PICL_SUCCESS)
51103831d35Sstevel return (err);
51203831d35Sstevel
51303831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_REFPROP_FRU_PARENT,
51403831d35Sstevel &fruh, sizeof (fruh));
51503831d35Sstevel if (err != PICL_SUCCESS)
51603831d35Sstevel err = picl_get_propval_by_name(nodeh,
51703831d35Sstevel PICL_REFPROP_LOC_PARENT, &fruh, sizeof (fruh));
51803831d35Sstevel }
51903831d35Sstevel
52003831d35Sstevel if (err == PICL_SUCCESS)
52103831d35Sstevel *fruparenth = fruh;
52203831d35Sstevel
52303831d35Sstevel return (err);
52403831d35Sstevel }
52503831d35Sstevel
52603831d35Sstevel /*
52703831d35Sstevel * get label
52803831d35Sstevel *
52903831d35Sstevel * To get the label, use the following algorithm:
53003831d35Sstevel * Lookup "Label" property in the fru node itself. If no
53103831d35Sstevel * Label found, then traverse superiors (parent nodes) until
53203831d35Sstevel * a Label property is found.
53303831d35Sstevel * if not found, then no label
53403831d35Sstevel */
53503831d35Sstevel static int
picldiag_get_label(picl_nodehdl_t nodeh,char ** label)53603831d35Sstevel picldiag_get_label(picl_nodehdl_t nodeh, char **label)
53703831d35Sstevel {
53803831d35Sstevel int err;
53903831d35Sstevel
54003831d35Sstevel err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, label);
54103831d35Sstevel
54203831d35Sstevel while (err == PICL_PROPNOTFOUND) {
54303831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
54403831d35Sstevel &nodeh, sizeof (nodeh));
54503831d35Sstevel if (err != PICL_SUCCESS)
54603831d35Sstevel return (err);
54703831d35Sstevel
54803831d35Sstevel err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL,
54903831d35Sstevel label);
55003831d35Sstevel }
55103831d35Sstevel
55203831d35Sstevel return (err);
55303831d35Sstevel }
55403831d35Sstevel
55503831d35Sstevel /*
55603831d35Sstevel * get combined label
55703831d35Sstevel *
55803831d35Sstevel * like picldiag_get_label, except concatenates the labels of parent locations
55903831d35Sstevel * eg SB0/P3 for processor P3 on system board SB0
56003831d35Sstevel *
56103831d35Sstevel * if caller specifies non-zero label length, label will be cut to specified
56203831d35Sstevel * length.
56303831d35Sstevel * negative length is left justified, non-negative length is right justified
56403831d35Sstevel */
56503831d35Sstevel static int
picldiag_get_combined_label(picl_nodehdl_t nodeh,char ** label,int lablen)56603831d35Sstevel picldiag_get_combined_label(picl_nodehdl_t nodeh, char **label, int lablen)
56703831d35Sstevel {
56803831d35Sstevel int err;
56903831d35Sstevel char *ptr;
57003831d35Sstevel char *ptr1 = NULL;
57103831d35Sstevel char *ptr2;
57203831d35Sstevel int len;
57303831d35Sstevel
57403831d35Sstevel err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, &ptr1);
57503831d35Sstevel if (err != PICL_PROPNOTFOUND && err != PICL_SUCCESS)
57603831d35Sstevel return (err);
57703831d35Sstevel
57803831d35Sstevel for (;;) {
57903831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_PROP_PARENT,
58003831d35Sstevel &nodeh, sizeof (nodeh));
58103831d35Sstevel if (err == PICL_PROPNOTFOUND)
58203831d35Sstevel break;
58303831d35Sstevel if (err != PICL_SUCCESS)
58403831d35Sstevel return (err);
58503831d35Sstevel
58603831d35Sstevel err = picldiag_get_string_propval(nodeh, PICL_PROP_LABEL, &ptr);
58703831d35Sstevel if (err == PICL_SUCCESS) {
58803831d35Sstevel if (ptr1 == NULL) {
58903831d35Sstevel ptr1 = ptr;
59003831d35Sstevel } else {
59103831d35Sstevel ptr2 = malloc(strlen(ptr1) + strlen(ptr) + 2);
59203831d35Sstevel if (ptr2 == NULL)
59303831d35Sstevel return (PICL_FAILURE);
59403831d35Sstevel (void) strcpy(ptr2, ptr);
59503831d35Sstevel (void) strcat(ptr2, "/");
59603831d35Sstevel (void) strcat(ptr2, ptr1);
59703831d35Sstevel (void) free(ptr);
59803831d35Sstevel (void) free(ptr1);
59903831d35Sstevel ptr1 = ptr2;
60003831d35Sstevel }
60103831d35Sstevel } else if (err != PICL_PROPNOTFOUND) {
60203831d35Sstevel return (err);
60303831d35Sstevel }
60403831d35Sstevel }
60503831d35Sstevel
60603831d35Sstevel if (ptr1 == NULL)
60703831d35Sstevel return (PICL_PROPNOTFOUND);
60803831d35Sstevel
60903831d35Sstevel len = strlen(ptr1);
61003831d35Sstevel /* if no string truncation is desired or required */
61103831d35Sstevel if ((lablen == 0) || (len <= abs(lablen))) {
61203831d35Sstevel *label = ptr1;
61303831d35Sstevel return (PICL_SUCCESS);
61403831d35Sstevel }
61503831d35Sstevel
61603831d35Sstevel /* string truncation is required; alloc space for (lablen + \0) */
61703831d35Sstevel ptr = malloc(abs(lablen) + 1);
61803831d35Sstevel if (ptr == 0)
61903831d35Sstevel return (PICL_FAILURE);
62003831d35Sstevel if (lablen > 0) {
62103831d35Sstevel /* right justification; label = "+<string>\0" */
62203831d35Sstevel strcpy(ptr, "+");
62303831d35Sstevel strncat(ptr, ptr1 + len - lablen + 1, lablen + 1);
62403831d35Sstevel } else {
62503831d35Sstevel /* left justification; label = "<string>+\0" */
62603831d35Sstevel strncpy(ptr, ptr1, abs(lablen) - 1);
62703831d35Sstevel strcat(ptr, "+");
62803831d35Sstevel }
62903831d35Sstevel
63003831d35Sstevel *label = ptr;
63103831d35Sstevel return (PICL_SUCCESS);
63203831d35Sstevel }
63303831d35Sstevel
63403831d35Sstevel /*
63503831d35Sstevel * return the first compatible value
63603831d35Sstevel */
63703831d35Sstevel static int
picldiag_get_first_compatible_value(picl_nodehdl_t nodeh,char ** outbuf)63803831d35Sstevel picldiag_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf)
63903831d35Sstevel {
64003831d35Sstevel int err;
64103831d35Sstevel picl_prophdl_t proph;
64203831d35Sstevel picl_propinfo_t pinfo;
64303831d35Sstevel picl_prophdl_t tblh;
64403831d35Sstevel picl_prophdl_t rowproph;
64503831d35Sstevel char *pval;
64603831d35Sstevel
64703831d35Sstevel err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE,
64803831d35Sstevel &pinfo, &proph);
64903831d35Sstevel if (err != PICL_SUCCESS)
650*2983dda7SMichael Bergknoff return (err);
65103831d35Sstevel
65203831d35Sstevel if (pinfo.type == PICL_PTYPE_CHARSTRING) {
65303831d35Sstevel pval = malloc(pinfo.size);
65403831d35Sstevel if (pval == NULL)
65503831d35Sstevel return (PICL_FAILURE);
65603831d35Sstevel err = picl_get_propval(proph, pval, pinfo.size);
65703831d35Sstevel if (err != PICL_SUCCESS) {
65803831d35Sstevel free(pval);
65903831d35Sstevel return (err);
66003831d35Sstevel }
66103831d35Sstevel *outbuf = pval;
66203831d35Sstevel return (PICL_SUCCESS);
66303831d35Sstevel }
66403831d35Sstevel
66503831d35Sstevel if (pinfo.type != PICL_PTYPE_TABLE)
66603831d35Sstevel return (PICL_FAILURE);
66703831d35Sstevel
66803831d35Sstevel /* get first string from table */
66903831d35Sstevel err = picl_get_propval(proph, &tblh, pinfo.size);
67003831d35Sstevel if (err != PICL_SUCCESS)
67103831d35Sstevel return (err);
67203831d35Sstevel
67303831d35Sstevel err = picl_get_next_by_row(tblh, &rowproph);
67403831d35Sstevel if (err != PICL_SUCCESS)
67503831d35Sstevel return (err);
67603831d35Sstevel
67703831d35Sstevel err = picl_get_propinfo(rowproph, &pinfo);
67803831d35Sstevel if (err != PICL_SUCCESS)
679*2983dda7SMichael Bergknoff return (err);
68003831d35Sstevel
68103831d35Sstevel pval = malloc(pinfo.size);
68203831d35Sstevel if (pval == NULL)
68303831d35Sstevel return (PICL_FAILURE);
68403831d35Sstevel
68503831d35Sstevel err = picl_get_propval(rowproph, pval, pinfo.size);
68603831d35Sstevel if (err != PICL_SUCCESS) {
68703831d35Sstevel free(pval);
68803831d35Sstevel return (err);
68903831d35Sstevel }
69003831d35Sstevel
69103831d35Sstevel *outbuf = pval;
69203831d35Sstevel return (PICL_SUCCESS);
69303831d35Sstevel }
69403831d35Sstevel
69503831d35Sstevel /*
69603831d35Sstevel * print the header in the center
69703831d35Sstevel */
69803831d35Sstevel static void
logprintf_header(char * header,size_t line_width)69903831d35Sstevel logprintf_header(char *header, size_t line_width)
70003831d35Sstevel {
70103831d35Sstevel size_t start_pos;
70203831d35Sstevel size_t i;
70303831d35Sstevel
70403831d35Sstevel log_printf("\n");
70503831d35Sstevel start_pos = (line_width - strlen(header) - 2) / 2;
70603831d35Sstevel
70703831d35Sstevel for (i = 0; i < start_pos; i++)
70803831d35Sstevel log_printf("%s", HEADING_SYMBOL);
70903831d35Sstevel
71003831d35Sstevel log_printf(" %s ", header);
71103831d35Sstevel
71203831d35Sstevel for (i = 0; i < start_pos; i++)
71303831d35Sstevel log_printf("%s", HEADING_SYMBOL);
71403831d35Sstevel
71503831d35Sstevel log_printf("\n");
71603831d35Sstevel }
71703831d35Sstevel
71803831d35Sstevel /*
71903831d35Sstevel * print the size
72003831d35Sstevel */
72103831d35Sstevel static void
logprintf_size(uint64_t size)72203831d35Sstevel logprintf_size(uint64_t size)
72303831d35Sstevel {
72403831d35Sstevel #define SIZE_FIELD 11
72503831d35Sstevel
72603831d35Sstevel uint64_t kbyte = 1024;
72703831d35Sstevel uint64_t mbyte = 1024 * 1024;
72803831d35Sstevel uint64_t gbyte = 1024 * 1024 * 1024;
72903831d35Sstevel uint64_t residue;
73003831d35Sstevel char buf[SIZE_FIELD];
73103831d35Sstevel
73203831d35Sstevel if (size >= gbyte) {
73303831d35Sstevel residue = size % gbyte;
73403831d35Sstevel if (residue == 0)
73503831d35Sstevel snprintf(buf, sizeof (buf), "%dGB",
73603831d35Sstevel (int)(size / gbyte));
73703831d35Sstevel else
73803831d35Sstevel snprintf(buf, sizeof (buf), "%.2fGB",
73903831d35Sstevel (float)size / gbyte);
74003831d35Sstevel } else if (size >= mbyte) {
74103831d35Sstevel residue = size % mbyte;
74203831d35Sstevel if (residue == 0)
74303831d35Sstevel snprintf(buf, sizeof (buf), "%dMB",
74403831d35Sstevel (int)(size / mbyte));
74503831d35Sstevel else
74603831d35Sstevel snprintf(buf, sizeof (buf), "%.2fMB",
74703831d35Sstevel (float)size / mbyte);
74803831d35Sstevel } else {
74903831d35Sstevel residue = size % kbyte;
75003831d35Sstevel if (residue == 0)
75103831d35Sstevel snprintf(buf, sizeof (buf), "%dKB",
75203831d35Sstevel (int)(size / kbyte));
75303831d35Sstevel else
75403831d35Sstevel snprintf(buf, sizeof (buf), "%.2fKB",
75503831d35Sstevel (float)size / kbyte);
75603831d35Sstevel }
75703831d35Sstevel
75803831d35Sstevel log_printf("%-10s ", buf);
75903831d35Sstevel }
76003831d35Sstevel
76103831d35Sstevel /*
76203831d35Sstevel * display platform banner
76303831d35Sstevel */
76403831d35Sstevel static int
display_platform_banner(picl_nodehdl_t plafh)76503831d35Sstevel display_platform_banner(picl_nodehdl_t plafh)
76603831d35Sstevel {
76703831d35Sstevel char *platform;
76803831d35Sstevel char *banner_name;
76903831d35Sstevel int err;
77003831d35Sstevel
77103831d35Sstevel /*
77203831d35Sstevel * get PICL_PROP_MACHINE and PICL_PROP_BANNER_NAME
77303831d35Sstevel */
77403831d35Sstevel log_printf(SIGN_ON_MSG);
77503831d35Sstevel err = picldiag_get_string_propval(plafh, PICL_PROP_MACHINE,
77603831d35Sstevel &platform);
77703831d35Sstevel if (err != PICL_SUCCESS)
77803831d35Sstevel return (err);
77903831d35Sstevel log_printf(" %s", platform);
78003831d35Sstevel free(platform);
78103831d35Sstevel
78203831d35Sstevel err = picldiag_get_string_propval(plafh, OBP_PROP_BANNER_NAME,
78303831d35Sstevel &banner_name);
78403831d35Sstevel if (err != PICL_SUCCESS)
78503831d35Sstevel return (err);
78603831d35Sstevel log_printf(" %s", banner_name);
78703831d35Sstevel free(banner_name);
78803831d35Sstevel
78903831d35Sstevel log_printf("\n");
79003831d35Sstevel return (PICL_SUCCESS);
79103831d35Sstevel }
79203831d35Sstevel
79303831d35Sstevel static int
serialnum_callback(picl_nodehdl_t serialh,void * arg)79403831d35Sstevel serialnum_callback(picl_nodehdl_t serialh, void *arg)
79503831d35Sstevel {
79603831d35Sstevel int *countp = arg;
79703831d35Sstevel int err;
79803831d35Sstevel picl_nodehdl_t fruph;
79903831d35Sstevel char *buf;
80003831d35Sstevel
80103831d35Sstevel err = picl_get_propval_by_name(serialh, PICL_REFPROP_FRU_PARENT,
80203831d35Sstevel &fruph, sizeof (fruph));
80303831d35Sstevel if (err == PICL_PROPNOTFOUND) {
80403831d35Sstevel err = picl_get_propval_by_name(serialh,
80503831d35Sstevel PICL_REFPROP_LOC_PARENT, &fruph, sizeof (fruph));
80603831d35Sstevel }
80703831d35Sstevel if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE)
80803831d35Sstevel return (PICL_WALK_CONTINUE);
80903831d35Sstevel if (err != PICL_SUCCESS)
81003831d35Sstevel return (err);
81103831d35Sstevel
81203831d35Sstevel err = picldiag_get_string_propval(serialh,
81303831d35Sstevel PICL_PROP_SERIAL_NUMBER, &buf);
81403831d35Sstevel if (err == PICL_SUCCESS) {
81503831d35Sstevel log_printf("\n");
81603831d35Sstevel log_printf(SERIAL_NUM_MSG);
81703831d35Sstevel log_printf("----------------------\n");
81803831d35Sstevel log_printf("%s\n", buf);
81903831d35Sstevel free(buf);
82003831d35Sstevel return (PICL_WALK_TERMINATE);
82103831d35Sstevel }
82203831d35Sstevel return (err);
82303831d35Sstevel }
82403831d35Sstevel
82503831d35Sstevel /*
82603831d35Sstevel * display the chassis serial number
82703831d35Sstevel */
82803831d35Sstevel static int
display_serial_number(picl_nodehdl_t plafh)82903831d35Sstevel display_serial_number(picl_nodehdl_t plafh)
83003831d35Sstevel {
83103831d35Sstevel int print_header;
83203831d35Sstevel
83303831d35Sstevel picl_walk_tree_by_class(plafh, PICL_CLASS_CHASSIS_SERIAL_NUM,
83403831d35Sstevel &print_header, serialnum_callback);
83503831d35Sstevel return (PICL_SUCCESS);
83603831d35Sstevel }
83703831d35Sstevel
83803831d35Sstevel /*
83903831d35Sstevel * display the clock frequency
84003831d35Sstevel */
84103831d35Sstevel static int
display_system_clock(picl_nodehdl_t plafh)84203831d35Sstevel display_system_clock(picl_nodehdl_t plafh)
84303831d35Sstevel {
84403831d35Sstevel uint32_t system_clk;
84503831d35Sstevel int err;
84603831d35Sstevel
84703831d35Sstevel err = picldiag_get_clock_freq(plafh, &system_clk);
84803831d35Sstevel if (err != PICL_SUCCESS)
84903831d35Sstevel return (err);
85003831d35Sstevel
85103831d35Sstevel log_printf(SYSCLK_FREQ_MSG, system_clk);
85203831d35Sstevel
85303831d35Sstevel return (PICL_SUCCESS);
85403831d35Sstevel }
85503831d35Sstevel
85603831d35Sstevel /*
85703831d35Sstevel * callback function to display the memory size
85803831d35Sstevel */
85903831d35Sstevel /*ARGSUSED*/
86003831d35Sstevel static int
memory_callback(picl_nodehdl_t memh,void * args)86103831d35Sstevel memory_callback(picl_nodehdl_t memh, void *args)
86203831d35Sstevel {
86303831d35Sstevel uint64_t mem_size;
86403831d35Sstevel int err;
86503831d35Sstevel
86603831d35Sstevel log_printf(MEM_SIZE_MSG);
86703831d35Sstevel mem_size = picldiag_get_uint_propval(memh, PICL_PROP_SIZE, &err);
86803831d35Sstevel if (err == PICL_SUCCESS)
86903831d35Sstevel logprintf_size(mem_size);
87003831d35Sstevel log_printf("\n");
87103831d35Sstevel no_xfer_size = 0;
87203831d35Sstevel mem_xfersize = picldiag_get_uint_propval(memh, PICL_PROP_TRANSFER_SIZE,
87303831d35Sstevel &err);
87403831d35Sstevel if (err == PICL_PROPNOTFOUND)
87503831d35Sstevel no_xfer_size = 1;
87603831d35Sstevel return (PICL_WALK_TERMINATE);
87703831d35Sstevel }
87803831d35Sstevel
87903831d35Sstevel /*
88003831d35Sstevel * callback function to print cpu information
88103831d35Sstevel */
88203831d35Sstevel /*ARGSUSED*/
88303831d35Sstevel static int
cpu_callback(picl_nodehdl_t nodeh,void * args)88403831d35Sstevel cpu_callback(picl_nodehdl_t nodeh, void *args)
88503831d35Sstevel {
88603831d35Sstevel int err;
88703831d35Sstevel int id;
88803831d35Sstevel uint64_t uintval;
88903831d35Sstevel uint32_t freq;
89003831d35Sstevel char *impl_name;
89103831d35Sstevel char *status;
89203831d35Sstevel picl_prophdl_t parenth;
89303831d35Sstevel char *label;
89403831d35Sstevel
89503831d35Sstevel /*
89603831d35Sstevel * If no ID is found, return
89703831d35Sstevel */
89803831d35Sstevel id = picldiag_get_uint_propval(nodeh, PICL_PROP_ID, &err);
89903831d35Sstevel if (err == PICL_PROPNOTFOUND)
90003831d35Sstevel return (PICL_WALK_CONTINUE);
90103831d35Sstevel else if (err != PICL_SUCCESS)
90203831d35Sstevel return (err);
90303831d35Sstevel log_printf("%-3d ", id);
90403831d35Sstevel
90503831d35Sstevel /*
90603831d35Sstevel * If no freq is found, return
90703831d35Sstevel */
90803831d35Sstevel err = picldiag_get_clock_freq(nodeh, &freq);
90903831d35Sstevel if (err == PICL_PROPNOTFOUND)
91003831d35Sstevel return (PICL_WALK_CONTINUE);
91103831d35Sstevel else if (err != PICL_SUCCESS)
91203831d35Sstevel return (err);
91303831d35Sstevel log_printf("%4d MHz ", freq);
91403831d35Sstevel
91503831d35Sstevel /* Ecache size */
91603831d35Sstevel uintval = picldiag_get_uint_propval(nodeh, OBP_PROP_ECACHE_SIZE, &err);
91703831d35Sstevel if (err == PICL_PROPNOTFOUND)
91803831d35Sstevel log_printf(" - ");
91903831d35Sstevel else if (err == PICL_SUCCESS)
92003831d35Sstevel logprintf_size(uintval);
92103831d35Sstevel else
92203831d35Sstevel return (err);
92303831d35Sstevel
92403831d35Sstevel /* Implementation */
92503831d35Sstevel impl_name = NULL;
92603831d35Sstevel err = picldiag_get_string_propval(nodeh, PICL_PROP_NAME, &impl_name);
92703831d35Sstevel if (err != PICL_SUCCESS)
92803831d35Sstevel log_printf(" <unknown> ");
92903831d35Sstevel else
93003831d35Sstevel log_printf(" %-22s ", impl_name);
93103831d35Sstevel
93203831d35Sstevel /* CPU Mask */
93303831d35Sstevel uintval = picldiag_get_uint_propval(nodeh, OBP_PROP_MASK, &err);
93403831d35Sstevel if (err == PICL_PROPNOTFOUND)
93503831d35Sstevel log_printf(" - ");
93603831d35Sstevel else if (err == PICL_SUCCESS)
93703831d35Sstevel log_printf("%2lld.%-2lld ", (uintval >> 4) & 0xf,
93803831d35Sstevel uintval & 0xf);
93903831d35Sstevel else
94003831d35Sstevel return (err);
94103831d35Sstevel
94203831d35Sstevel /*
94303831d35Sstevel * Status - if the node has a status property then display that
94403831d35Sstevel * otherwise display the State property
94503831d35Sstevel */
94603831d35Sstevel err = picldiag_get_string_propval(nodeh, PICL_PROP_STATUS, &status);
94703831d35Sstevel if (err == PICL_SUCCESS) {
94803831d35Sstevel log_printf("%-12s", status);
94903831d35Sstevel set_exit_code(status);
95003831d35Sstevel free(status);
95103831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err !=
95203831d35Sstevel PICL_PROPVALUNAVAILABLE && err != PICL_ENDOFLIST) {
95303831d35Sstevel return (err);
95403831d35Sstevel } else {
95503831d35Sstevel err = picldiag_get_string_propval(nodeh,
95603831d35Sstevel PICL_PROP_STATE, &status);
95703831d35Sstevel if (err == PICL_SUCCESS) {
95803831d35Sstevel log_printf("%-12s", status);
95903831d35Sstevel set_exit_code(status);
96003831d35Sstevel free(status);
96103831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err !=
96203831d35Sstevel PICL_PROPVALUNAVAILABLE && err !=
96303831d35Sstevel PICL_ENDOFLIST) {
96403831d35Sstevel return (err);
96503831d35Sstevel } else {
96603831d35Sstevel log_printf("unknown ");
96703831d35Sstevel }
96803831d35Sstevel }
96903831d35Sstevel
97003831d35Sstevel /*
97103831d35Sstevel * Location: use label of fru parent
97203831d35Sstevel */
97303831d35Sstevel err = picldiag_get_fru_parent(nodeh, &parenth);
97403831d35Sstevel if (err == PICL_PROPNOTFOUND) {
97503831d35Sstevel log_printf(" - ");
97603831d35Sstevel } else if (err == PICL_SUCCESS) {
97703831d35Sstevel err = picldiag_get_combined_label(parenth, &label, 12);
97803831d35Sstevel if (err == PICL_PROPNOTFOUND)
97903831d35Sstevel log_printf(" - ");
98003831d35Sstevel else if (err == PICL_SUCCESS) {
98103831d35Sstevel log_printf("%s", label);
98203831d35Sstevel free(label);
98303831d35Sstevel } else
98403831d35Sstevel return (err);
98503831d35Sstevel } else
98603831d35Sstevel return (err);
98703831d35Sstevel
98803831d35Sstevel log_printf("\n");
98903831d35Sstevel return (PICL_WALK_CONTINUE);
99003831d35Sstevel }
99103831d35Sstevel
99203831d35Sstevel /*
99303831d35Sstevel * display cpu information
99403831d35Sstevel */
99503831d35Sstevel static int
display_cpu_info(picl_nodehdl_t plafh)99603831d35Sstevel display_cpu_info(picl_nodehdl_t plafh)
99703831d35Sstevel {
99803831d35Sstevel int err;
99903831d35Sstevel
100003831d35Sstevel /*
100103831d35Sstevel * Display the table header for CPUs . Then display the CPU
100203831d35Sstevel * frequency, cache size, and processor revision on all the boards.
100303831d35Sstevel */
100403831d35Sstevel logprintf_header(dgettext(TEXT_DOMAIN, "CPUs"), DEFAULT_LINE_WIDTH);
100503831d35Sstevel log_printf(" E$ CPU "
1006*2983dda7SMichael Bergknoff "CPU\n");
100703831d35Sstevel log_printf("CPU Freq Size Implementation "
1008*2983dda7SMichael Bergknoff "Mask Status Location\n");
100903831d35Sstevel log_printf("--- -------- ---------- --------------------- "
1010*2983dda7SMichael Bergknoff "----- ------ --------\n");
101103831d35Sstevel
101203831d35Sstevel err = picl_walk_tree_by_class(plafh, PICL_CLASS_CPU, PICL_CLASS_CPU,
101303831d35Sstevel cpu_callback);
101403831d35Sstevel return (err);
101503831d35Sstevel }
101603831d35Sstevel
101703831d35Sstevel /*
101803831d35Sstevel * Inserts an io_card structure into the list.
101903831d35Sstevel */
102003831d35Sstevel static void
add_io_card(uint32_t board,uint32_t bus_id,uint32_t slot,char * label,uint32_t freq,char * name,char * model,char * status,char * devfs_path)102103831d35Sstevel add_io_card(uint32_t board, uint32_t bus_id, uint32_t slot, char *label,
102203831d35Sstevel uint32_t freq, char *name, char *model, char *status, char *devfs_path)
102303831d35Sstevel {
102403831d35Sstevel struct io_card card;
102503831d35Sstevel
102603831d35Sstevel card.display = 1;
102703831d35Sstevel card.board = board;
102803831d35Sstevel switch (bus_id) {
102903831d35Sstevel case SBUS_TYPE:
103003831d35Sstevel strlcpy(card.bus_type, SBUS_NAME, MAXSTRLEN);
103103831d35Sstevel break;
103203831d35Sstevel case PCI_TYPE:
103303831d35Sstevel strlcpy(card.bus_type, PCI_NAME, MAXSTRLEN);
103403831d35Sstevel break;
103503831d35Sstevel case PCIEX_TYPE:
103603831d35Sstevel strlcpy(card.bus_type, PCIEX_NAME, MAXSTRLEN);
103703831d35Sstevel break;
103803831d35Sstevel case UPA_TYPE:
103903831d35Sstevel strlcpy(card.bus_type, UPA_NAME, MAXSTRLEN);
104003831d35Sstevel break;
104103831d35Sstevel default: /* won't reach here */
104203831d35Sstevel strlcpy(card.bus_type, "", MAXSTRLEN);
104303831d35Sstevel break;
104403831d35Sstevel }
104503831d35Sstevel if (label == NULL)
104603831d35Sstevel card.slot = slot;
104703831d35Sstevel else {
104803831d35Sstevel card.slot = PCI_SLOT_IS_STRING;
104903831d35Sstevel (void) strlcpy(card.slot_str, label, MAXSTRLEN);
105003831d35Sstevel }
105103831d35Sstevel card.freq = freq;
105203831d35Sstevel card.status[0] = '\0';
105303831d35Sstevel card.name[0] = '\0';
105403831d35Sstevel card.model[0] = '\0';
105503831d35Sstevel card.notes[0] = '\0';
105603831d35Sstevel if (status != NULL)
105703831d35Sstevel strlcpy(card.status, status, MAXSTRLEN);
105803831d35Sstevel if (name != NULL)
105903831d35Sstevel strlcpy(card.name, name, MAXSTRLEN);
106003831d35Sstevel if (model != NULL)
106103831d35Sstevel strlcpy(card.model, model, MAXSTRLEN);
106203831d35Sstevel if (status != NULL)
106303831d35Sstevel strlcpy(card.status, status, MAXSTRLEN);
106403831d35Sstevel if (devfs_path != NULL)
106503831d35Sstevel strlcpy(card.notes, devfs_path, MAXSTRLEN);
106603831d35Sstevel
106703831d35Sstevel io_card_list = insert_io_card(io_card_list, &card);
106803831d35Sstevel }
106903831d35Sstevel
107003831d35Sstevel static void
append_to_bank_list(bank_list_t * newptr)107103831d35Sstevel append_to_bank_list(bank_list_t *newptr)
107203831d35Sstevel {
107303831d35Sstevel bank_list_t *ptr;
107403831d35Sstevel
107503831d35Sstevel if (mem_banks == NULL) {
107603831d35Sstevel mem_banks = newptr;
107703831d35Sstevel return;
107803831d35Sstevel }
107903831d35Sstevel ptr = mem_banks;
108003831d35Sstevel while (ptr->next != NULL)
108103831d35Sstevel ptr = ptr->next;
108203831d35Sstevel
108303831d35Sstevel ptr->next = newptr;
108403831d35Sstevel }
108503831d35Sstevel
108603831d35Sstevel static void
free_bank_list(void)108703831d35Sstevel free_bank_list(void)
108803831d35Sstevel {
108903831d35Sstevel bank_list_t *ptr;
109003831d35Sstevel bank_list_t *tmp;
109103831d35Sstevel
109203831d35Sstevel for (ptr = mem_banks; ptr != NULL; ptr = tmp) {
109303831d35Sstevel tmp = ptr->next;
109403831d35Sstevel free(ptr);
109503831d35Sstevel }
109603831d35Sstevel mem_banks = NULL;
109703831d35Sstevel }
109803831d35Sstevel
109903831d35Sstevel
110003831d35Sstevel /*
110103831d35Sstevel * print label for memory module
110203831d35Sstevel */
110303831d35Sstevel static int
logprintf_memory_module_label(picl_nodehdl_t moduleh)110403831d35Sstevel logprintf_memory_module_label(picl_nodehdl_t moduleh)
110503831d35Sstevel {
110603831d35Sstevel picl_nodehdl_t fruparenth;
110703831d35Sstevel int err;
110803831d35Sstevel char *label;
110903831d35Sstevel
111003831d35Sstevel err = picldiag_get_fru_parent(moduleh, &fruparenth);
111103831d35Sstevel if (err == PICL_PROPNOTFOUND) {
111203831d35Sstevel log_printf("-");
111303831d35Sstevel return (PICL_SUCCESS);
111403831d35Sstevel } else if (err != PICL_SUCCESS)
111503831d35Sstevel return (err);
111603831d35Sstevel
111703831d35Sstevel err = picldiag_get_combined_label(fruparenth, &label, 30);
111803831d35Sstevel if (err == PICL_PROPNOTFOUND)
111903831d35Sstevel log_printf("-");
112003831d35Sstevel else if (err == PICL_SUCCESS) {
112103831d35Sstevel log_printf("%-15s", label);
112203831d35Sstevel free(label);
112303831d35Sstevel } else
112403831d35Sstevel return (err);
112503831d35Sstevel
112603831d35Sstevel return (PICL_SUCCESS);
112703831d35Sstevel }
112803831d35Sstevel
112903831d35Sstevel /*
113003831d35Sstevel * print the bank id and add the bank handle in the bank list
113103831d35Sstevel * return the head of the bank list
113203831d35Sstevel */
113303831d35Sstevel static int
membank_callback(picl_nodehdl_t bankh,void * args)113403831d35Sstevel membank_callback(picl_nodehdl_t bankh, void *args)
113503831d35Sstevel {
113603831d35Sstevel int err;
113703831d35Sstevel int64_t id;
113803831d35Sstevel uint64_t match;
113903831d35Sstevel uint64_t mask;
114003831d35Sstevel int i;
114103831d35Sstevel bank_list_t *newptr;
114203831d35Sstevel seg_info_t *segp = args;
114303831d35Sstevel
114403831d35Sstevel /*
114503831d35Sstevel * print the bank id in the segment table contains column
114603831d35Sstevel */
114703831d35Sstevel id = picldiag_get_uint_propval(bankh, PICL_PROP_ID, &err);
114803831d35Sstevel if (segp->bank_count > 0)
114903831d35Sstevel log_printf(",");
115003831d35Sstevel if (err == PICL_PROPNOTFOUND)
115103831d35Sstevel log_printf("-");
115203831d35Sstevel else if (err == PICL_SUCCESS)
115303831d35Sstevel log_printf("%-lld", id);
115403831d35Sstevel else
115503831d35Sstevel return (err);
115603831d35Sstevel segp->bank_count++;
115703831d35Sstevel
115803831d35Sstevel /*
115903831d35Sstevel * Save the bank information for later (print_bank_table)
116003831d35Sstevel */
116103831d35Sstevel newptr = malloc(sizeof (*newptr));
116203831d35Sstevel if (newptr == NULL)
116303831d35Sstevel return (PICL_FAILURE);
116403831d35Sstevel
116503831d35Sstevel newptr->nodeh = bankh;
116603831d35Sstevel newptr->iway_count = 0;
116703831d35Sstevel newptr->next = NULL;
116803831d35Sstevel append_to_bank_list(newptr);
116903831d35Sstevel
117003831d35Sstevel /*
117103831d35Sstevel * Compute the way numbers for the bank
117203831d35Sstevel */
117303831d35Sstevel if (no_xfer_size)
117403831d35Sstevel return (PICL_WALK_CONTINUE);
117503831d35Sstevel
117603831d35Sstevel match = picldiag_get_uint_propval(bankh, PICL_PROP_ADDRESSMATCH, &err);
117703831d35Sstevel if (err == PICL_PROPNOTFOUND)
117803831d35Sstevel return (PICL_WALK_CONTINUE);
117903831d35Sstevel else if (err != PICL_SUCCESS)
118003831d35Sstevel return (err);
118103831d35Sstevel
118203831d35Sstevel mask = picldiag_get_uint_propval(bankh, PICL_PROP_ADDRESSMASK, &err);
118303831d35Sstevel if (err == PICL_PROPNOTFOUND)
118403831d35Sstevel return (PICL_WALK_CONTINUE);
118503831d35Sstevel else if (err != PICL_SUCCESS)
118603831d35Sstevel return (err);
118703831d35Sstevel
118803831d35Sstevel i = 0;
118903831d35Sstevel while ((i < segp->ifactor) && (newptr->iway_count < MAX_IWAYS)) {
119003831d35Sstevel if (((segp->base + i * mem_xfersize) & mask) == match)
119103831d35Sstevel newptr->iway[newptr->iway_count++] = i;
119203831d35Sstevel ++i;
119303831d35Sstevel }
119403831d35Sstevel return (PICL_WALK_CONTINUE);
119503831d35Sstevel }
119603831d35Sstevel
119703831d35Sstevel
119803831d35Sstevel /*
119903831d35Sstevel * find the memory bank and add the bank handle in the bank list
120003831d35Sstevel * return the head of the bank list
120103831d35Sstevel */
120203831d35Sstevel static int
logprintf_bankinfo(picl_nodehdl_t segh,seg_info_t * segp)120303831d35Sstevel logprintf_bankinfo(picl_nodehdl_t segh, seg_info_t *segp)
120403831d35Sstevel {
120503831d35Sstevel int err;
120603831d35Sstevel
120703831d35Sstevel log_printf("BankIDs ");
120803831d35Sstevel /*
120903831d35Sstevel * find memory-bank
121003831d35Sstevel */
121103831d35Sstevel segp->bank_count = 0;
121203831d35Sstevel err = picl_walk_tree_by_class(segh, PICL_CLASS_MEMORY_BANK, segp,
121303831d35Sstevel membank_callback);
121403831d35Sstevel log_printf("\n");
121503831d35Sstevel return (err);
121603831d35Sstevel }
121703831d35Sstevel
121803831d35Sstevel /*
121903831d35Sstevel * print the label of memory module or the memory module bank ids
122003831d35Sstevel */
122103831d35Sstevel static int
logprintf_seg_contains_col(picl_nodehdl_t nodeh,seg_info_t * segp)122203831d35Sstevel logprintf_seg_contains_col(picl_nodehdl_t nodeh, seg_info_t *segp)
122303831d35Sstevel {
122403831d35Sstevel picl_nodehdl_t moduleh;
122503831d35Sstevel int err;
122603831d35Sstevel
122703831d35Sstevel /*
122803831d35Sstevel * find memory-module if referenced directly from the memory-segment
122903831d35Sstevel * (ie no memory banks)
123003831d35Sstevel */
123103831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_REFPROP_MEMORY_MODULE,
123203831d35Sstevel &moduleh, sizeof (moduleh));
123303831d35Sstevel if ((err != PICL_SUCCESS) && (err != PICL_PROPNOTFOUND))
123403831d35Sstevel return (err);
123503831d35Sstevel if (err == PICL_SUCCESS) {
123603831d35Sstevel err = logprintf_memory_module_label(moduleh);
123703831d35Sstevel log_printf("\n");
123803831d35Sstevel return (err);
123903831d35Sstevel }
124003831d35Sstevel
124103831d35Sstevel /*
124203831d35Sstevel * memory-module not referenced directly from the memory segment
124303831d35Sstevel * so list memory banks instead
124403831d35Sstevel */
124503831d35Sstevel err = logprintf_bankinfo(nodeh, segp);
124603831d35Sstevel return (err);
124703831d35Sstevel }
124803831d35Sstevel
124903831d35Sstevel /*
125003831d35Sstevel * find all memory modules under the given memory module group
125103831d35Sstevel * and print its label
125203831d35Sstevel */
125303831d35Sstevel static int
logprintf_memory_module_group_info(picl_nodehdl_t memgrph,uint64_t mcid)125403831d35Sstevel logprintf_memory_module_group_info(picl_nodehdl_t memgrph, uint64_t mcid)
125503831d35Sstevel {
125603831d35Sstevel int err;
125703831d35Sstevel int64_t id;
125803831d35Sstevel boolean_t got_status;
125903831d35Sstevel picl_nodehdl_t moduleh;
126003831d35Sstevel char piclclass[PICL_CLASSNAMELEN_MAX];
126103831d35Sstevel picl_nodehdl_t fruparenth;
126203831d35Sstevel char *status;
126303831d35Sstevel
126403831d35Sstevel id = picldiag_get_uint_propval(memgrph, PICL_PROP_ID, &err);
126503831d35Sstevel if (err == PICL_PROPNOTFOUND)
126603831d35Sstevel id = -1;
126703831d35Sstevel else if (err != PICL_SUCCESS)
126803831d35Sstevel return (err);
126903831d35Sstevel
127003831d35Sstevel err = picl_get_propval_by_name(memgrph, PICL_PROP_CHILD, &moduleh,
127103831d35Sstevel sizeof (picl_nodehdl_t));
127203831d35Sstevel
127303831d35Sstevel while (err == PICL_SUCCESS) {
127403831d35Sstevel /* controller id */
127503831d35Sstevel log_printf("%-8lld ", mcid);
127603831d35Sstevel
127703831d35Sstevel /* group id */
127803831d35Sstevel if (id == -1) {
127903831d35Sstevel log_printf("- ");
128003831d35Sstevel } else {
128103831d35Sstevel log_printf("%-8lld ", id);
128203831d35Sstevel }
128303831d35Sstevel
128403831d35Sstevel err = picl_get_propval_by_name(moduleh, PICL_PROP_CLASSNAME,
128503831d35Sstevel piclclass, sizeof (piclclass));
128603831d35Sstevel if (err != PICL_SUCCESS)
128703831d35Sstevel return (err);
128803831d35Sstevel
128903831d35Sstevel if (strcmp(piclclass, PICL_CLASS_MEMORY_MODULE) == 0) {
129003831d35Sstevel err = logprintf_memory_module_label(moduleh);
129103831d35Sstevel if (err != PICL_SUCCESS)
129203831d35Sstevel return (err);
129303831d35Sstevel }
129403831d35Sstevel
129503831d35Sstevel got_status = B_FALSE;
129603831d35Sstevel err = picldiag_get_fru_parent(moduleh, &fruparenth);
129703831d35Sstevel if (err == PICL_SUCCESS) {
129803831d35Sstevel err = picldiag_get_string_propval(fruparenth,
129903831d35Sstevel PICL_PROP_OPERATIONAL_STATUS, &status);
130003831d35Sstevel if (err == PICL_SUCCESS) {
130103831d35Sstevel got_status = B_TRUE;
130203831d35Sstevel } else if (err != PICL_PROPNOTFOUND)
130303831d35Sstevel return (err);
130403831d35Sstevel } else if (err != PICL_PROPNOTFOUND)
130503831d35Sstevel return (err);
130603831d35Sstevel
130703831d35Sstevel if (!got_status) {
130803831d35Sstevel err = picldiag_get_string_propval(moduleh,
130903831d35Sstevel PICL_PROP_STATUS, &status);
131003831d35Sstevel if (err == PICL_SUCCESS)
131103831d35Sstevel got_status = B_TRUE;
131203831d35Sstevel else if (err != PICL_PROPNOTFOUND)
131303831d35Sstevel return (err);
131403831d35Sstevel }
131503831d35Sstevel if (got_status) {
131603831d35Sstevel log_printf("%s", status);
131703831d35Sstevel set_exit_code(status);
131803831d35Sstevel free(status);
131903831d35Sstevel }
132003831d35Sstevel err = picl_get_propval_by_name(moduleh, PICL_PROP_PEER,
132103831d35Sstevel &moduleh, sizeof (picl_nodehdl_t));
132203831d35Sstevel
132303831d35Sstevel log_printf("\n");
132403831d35Sstevel }
132503831d35Sstevel if (err == PICL_PROPNOTFOUND)
132603831d35Sstevel return (PICL_SUCCESS);
132703831d35Sstevel return (err);
132803831d35Sstevel }
132903831d35Sstevel
133003831d35Sstevel /*
133103831d35Sstevel * search children to find memory module group under memory-controller
133203831d35Sstevel */
133303831d35Sstevel static int
find_memory_module_group(picl_nodehdl_t mch,int * print_header)133403831d35Sstevel find_memory_module_group(picl_nodehdl_t mch, int *print_header)
133503831d35Sstevel {
133603831d35Sstevel picl_nodehdl_t memgrph;
133703831d35Sstevel uint64_t mcid;
133803831d35Sstevel int err;
133903831d35Sstevel char piclclass[PICL_CLASSNAMELEN_MAX];
134003831d35Sstevel
134103831d35Sstevel mcid = picldiag_get_uint_propval(mch, OBP_PROP_PORTID, &err);
134203831d35Sstevel if (err == PICL_PROPNOTFOUND)
134303831d35Sstevel mcid = DEFAULT_PORTID;
134403831d35Sstevel else if (err != PICL_SUCCESS)
134503831d35Sstevel return (err);
134603831d35Sstevel
134703831d35Sstevel err = picl_get_propval_by_name(mch, PICL_PROP_CHILD,
134803831d35Sstevel &memgrph, sizeof (picl_nodehdl_t));
134903831d35Sstevel while (err == PICL_SUCCESS) {
135003831d35Sstevel err = picl_get_propval_by_name(memgrph,
135103831d35Sstevel PICL_PROP_CLASSNAME, piclclass, sizeof (piclclass));
135203831d35Sstevel if (err != PICL_SUCCESS)
135303831d35Sstevel return (err);
135403831d35Sstevel
135503831d35Sstevel if (strcmp(piclclass, PICL_CLASS_MEMORY_MODULE_GROUP) == 0) {
135603831d35Sstevel if (*print_header == 1) {
135703831d35Sstevel log_printf(
135803831d35Sstevel dgettext(TEXT_DOMAIN,
1359*2983dda7SMichael Bergknoff "\nMemory Module Groups:\n"));
136003831d35Sstevel log_printf("--------------------------");
136103831d35Sstevel log_printf("------------------------\n");
136203831d35Sstevel log_printf("ControllerID GroupID Labels");
136303831d35Sstevel log_printf(" Status\n");
136403831d35Sstevel log_printf("--------------------------");
136503831d35Sstevel log_printf("------------------------\n");
136603831d35Sstevel *print_header = 0;
136703831d35Sstevel }
136803831d35Sstevel err = logprintf_memory_module_group_info(memgrph, mcid);
136903831d35Sstevel if (err != PICL_SUCCESS)
137003831d35Sstevel return (err);
137103831d35Sstevel }
137203831d35Sstevel
137303831d35Sstevel err = picl_get_propval_by_name(memgrph, PICL_PROP_PEER,
137403831d35Sstevel &memgrph, sizeof (picl_nodehdl_t));
137503831d35Sstevel }
137603831d35Sstevel if (err == PICL_PROPNOTFOUND)
137703831d35Sstevel return (PICL_SUCCESS);
137803831d35Sstevel return (err);
137903831d35Sstevel }
138003831d35Sstevel
138103831d35Sstevel /*
138203831d35Sstevel * print memory module group table per memory-controller
138303831d35Sstevel */
138403831d35Sstevel static int
print_memory_module_group_table(picl_nodehdl_t plafh)138503831d35Sstevel print_memory_module_group_table(picl_nodehdl_t plafh)
138603831d35Sstevel {
138703831d35Sstevel picl_nodehdl_t mch;
138803831d35Sstevel int err;
138903831d35Sstevel char piclclass[PICL_CLASSNAMELEN_MAX];
139003831d35Sstevel int print_header;
139103831d35Sstevel
139203831d35Sstevel print_header = 1;
139303831d35Sstevel
139403831d35Sstevel /*
139503831d35Sstevel * find memory-controller
139603831d35Sstevel */
139703831d35Sstevel err = picl_get_propval_by_name(plafh, PICL_PROP_CHILD, &mch,
139803831d35Sstevel sizeof (picl_nodehdl_t));
139903831d35Sstevel while (err == PICL_SUCCESS) {
140003831d35Sstevel err = picl_get_propval_by_name(mch, PICL_PROP_CLASSNAME,
140103831d35Sstevel piclclass, sizeof (piclclass));
140203831d35Sstevel if (err != PICL_SUCCESS)
140303831d35Sstevel return (err);
140403831d35Sstevel
140503831d35Sstevel if (strcmp(piclclass, PICL_CLASS_MEMORY_CONTROLLER) != 0) {
140603831d35Sstevel err = print_memory_module_group_table(mch);
140703831d35Sstevel if (err != PICL_SUCCESS)
140803831d35Sstevel return (err);
140903831d35Sstevel err = picl_get_propval_by_name(mch, PICL_PROP_PEER,
141003831d35Sstevel &mch, sizeof (picl_nodehdl_t));
141103831d35Sstevel continue;
141203831d35Sstevel }
141303831d35Sstevel
141403831d35Sstevel err = find_memory_module_group(mch, &print_header);
141503831d35Sstevel if (err != PICL_SUCCESS)
141603831d35Sstevel return (err);
141703831d35Sstevel
141803831d35Sstevel err = picl_get_propval_by_name(mch, PICL_PROP_PEER,
141903831d35Sstevel &mch, sizeof (picl_nodehdl_t));
142003831d35Sstevel }
142103831d35Sstevel if (err == PICL_PROPNOTFOUND)
142203831d35Sstevel return (PICL_SUCCESS);
142303831d35Sstevel
142403831d35Sstevel return (err);
142503831d35Sstevel }
142603831d35Sstevel
142703831d35Sstevel /*
142803831d35Sstevel * print bank table
142903831d35Sstevel */
143003831d35Sstevel static int
print_bank_table(void)143103831d35Sstevel print_bank_table(void)
143203831d35Sstevel {
143303831d35Sstevel bank_list_t *ptr;
143403831d35Sstevel picl_nodehdl_t bankh;
143503831d35Sstevel picl_nodehdl_t memgrph;
143603831d35Sstevel picl_nodehdl_t mch;
143703831d35Sstevel int err;
143803831d35Sstevel int32_t i;
143903831d35Sstevel uint64_t size;
144003831d35Sstevel int id;
144103831d35Sstevel
144203831d35Sstevel log_printf(dgettext(TEXT_DOMAIN, "\nBank Table:\n"));
144303831d35Sstevel log_printf("---------------------------------------");
144403831d35Sstevel log_printf("--------------------\n");
144503831d35Sstevel log_printf(dgettext(TEXT_DOMAIN, " Physical Location\n"));
144603831d35Sstevel log_printf(dgettext(TEXT_DOMAIN, "ID ControllerID GroupID "));
144703831d35Sstevel log_printf(dgettext(TEXT_DOMAIN, "Size Interleave Way\n"));
144803831d35Sstevel log_printf("---------------------------------------");
144903831d35Sstevel log_printf("--------------------\n");
145003831d35Sstevel
145103831d35Sstevel for (ptr = mem_banks; ptr != NULL; ptr = ptr->next) {
145203831d35Sstevel bankh = ptr->nodeh;
145303831d35Sstevel id = picldiag_get_uint_propval(bankh, PICL_PROP_ID, &err);
145403831d35Sstevel if (err != PICL_SUCCESS)
145503831d35Sstevel log_printf("%-8s ", "-");
145603831d35Sstevel else
145703831d35Sstevel log_printf("%-8d ", id);
145803831d35Sstevel
145903831d35Sstevel /* find memory-module-group */
146003831d35Sstevel err = picl_get_propval_by_name(bankh,
146103831d35Sstevel PICL_REFPROP_MEMORY_MODULE_GROUP, &memgrph,
146203831d35Sstevel sizeof (memgrph));
146303831d35Sstevel if (err == PICL_PROPNOTFOUND) {
146403831d35Sstevel log_printf("%-8s ", "-");
146503831d35Sstevel log_printf("%-8s ", "-");
146603831d35Sstevel } else if (err != PICL_SUCCESS)
146703831d35Sstevel return (err);
146803831d35Sstevel else {
146903831d35Sstevel /*
147003831d35Sstevel * get controller id
147103831d35Sstevel */
147203831d35Sstevel err = picl_get_propval_by_name(memgrph,
147303831d35Sstevel PICL_PROP_PARENT, &mch, sizeof (picl_nodehdl_t));
147403831d35Sstevel if (err != PICL_SUCCESS)
147503831d35Sstevel return (err);
147603831d35Sstevel
147703831d35Sstevel id = picldiag_get_uint_propval(mch, OBP_PROP_PORTID,
147803831d35Sstevel &err);
147903831d35Sstevel if (err == PICL_PROPNOTFOUND)
148003831d35Sstevel id = DEFAULT_PORTID; /* use default */
148103831d35Sstevel else if (err != PICL_SUCCESS)
148203831d35Sstevel return (err);
148303831d35Sstevel
148403831d35Sstevel log_printf("%-8d ", id);
148503831d35Sstevel
148603831d35Sstevel /* get group id */
148703831d35Sstevel id = picldiag_get_uint_propval(memgrph, PICL_PROP_ID,
148803831d35Sstevel &err);
148903831d35Sstevel if (err == PICL_PROPNOTFOUND)
149003831d35Sstevel log_printf("- ");
149103831d35Sstevel else if (err == PICL_SUCCESS)
149203831d35Sstevel log_printf("%-8d ", id);
149303831d35Sstevel else
149403831d35Sstevel return (err);
149503831d35Sstevel }
149603831d35Sstevel
149703831d35Sstevel size = picldiag_get_uint_propval(bankh, PICL_PROP_SIZE, &err);
149803831d35Sstevel if (err == PICL_PROPNOTFOUND)
149903831d35Sstevel log_printf("- ");
150003831d35Sstevel else if (err == PICL_SUCCESS)
150103831d35Sstevel logprintf_size(size);
150203831d35Sstevel else
150303831d35Sstevel return (err);
150403831d35Sstevel
150503831d35Sstevel log_printf(" ");
150603831d35Sstevel for (i = 0; i < ptr->iway_count; i++) {
150703831d35Sstevel if (i != 0)
150803831d35Sstevel log_printf(",");
150903831d35Sstevel log_printf("%d", ptr->iway[i]);
151003831d35Sstevel }
151103831d35Sstevel
151203831d35Sstevel log_printf("\n");
151303831d35Sstevel }
151403831d35Sstevel return (PICL_SUCCESS);
151503831d35Sstevel }
151603831d35Sstevel
151703831d35Sstevel /*
151803831d35Sstevel * callback function to print segment, add the bank in the list and
151903831d35Sstevel * return the bank list
152003831d35Sstevel */
152103831d35Sstevel /* ARGSUSED */
152203831d35Sstevel static int
memseg_callback(picl_nodehdl_t segh,void * args)152303831d35Sstevel memseg_callback(picl_nodehdl_t segh, void *args)
152403831d35Sstevel {
152503831d35Sstevel seg_info_t seginfo;
152603831d35Sstevel int err;
152703831d35Sstevel
152803831d35Sstevel /* get base address */
152903831d35Sstevel seginfo.base = picldiag_get_uint_propval(segh, PICL_PROP_BASEADDRESS,
153003831d35Sstevel &err);
153103831d35Sstevel if (err == PICL_PROPNOTFOUND) {
153203831d35Sstevel log_printf("-\n");
153303831d35Sstevel return (PICL_WALK_CONTINUE);
153403831d35Sstevel } else if (err == PICL_SUCCESS)
153503831d35Sstevel log_printf("0x%-16llx ", seginfo.base);
153603831d35Sstevel else
153703831d35Sstevel return (err);
153803831d35Sstevel
153903831d35Sstevel /* get size */
154003831d35Sstevel seginfo.size = picldiag_get_uint_propval(segh, PICL_PROP_SIZE, &err);
154103831d35Sstevel if (err == PICL_PROPNOTFOUND) {
154203831d35Sstevel log_printf("-\n");
154303831d35Sstevel return (PICL_WALK_CONTINUE);
154403831d35Sstevel } else if (err == PICL_SUCCESS)
154503831d35Sstevel logprintf_size(seginfo.size);
154603831d35Sstevel else
154703831d35Sstevel return (err);
154803831d35Sstevel
154903831d35Sstevel /* get interleave factor */
155003831d35Sstevel seginfo.ifactor = picldiag_get_uint_propval(segh,
155103831d35Sstevel PICL_PROP_INTERLEAVE_FACTOR, &err);
155203831d35Sstevel
155303831d35Sstevel if (err == PICL_PROPNOTFOUND) {
155403831d35Sstevel log_printf(" -\n");
155503831d35Sstevel return (PICL_WALK_CONTINUE);
155603831d35Sstevel } else if (err == PICL_SUCCESS)
155703831d35Sstevel log_printf(" %-2d ", seginfo.ifactor);
155803831d35Sstevel else
155903831d35Sstevel return (err);
156003831d35Sstevel
156103831d35Sstevel seginfo.bank_count = 0;
156203831d35Sstevel err = logprintf_seg_contains_col(segh, &seginfo);
156303831d35Sstevel if (err != PICL_SUCCESS)
156403831d35Sstevel return (err);
156503831d35Sstevel return (PICL_WALK_CONTINUE);
156603831d35Sstevel }
156703831d35Sstevel
156803831d35Sstevel /*
156903831d35Sstevel * search children to find memory-segment and set up the bank list
157003831d35Sstevel */
157103831d35Sstevel static int
find_segments(picl_nodehdl_t plafh)157203831d35Sstevel find_segments(picl_nodehdl_t plafh)
157303831d35Sstevel {
157403831d35Sstevel int err;
157503831d35Sstevel
157603831d35Sstevel log_printf(dgettext(TEXT_DOMAIN, "Segment Table:\n"));
157703831d35Sstevel log_printf("------------------------------");
157803831d35Sstevel log_printf("-----------------------------------------\n");
157903831d35Sstevel log_printf(dgettext(TEXT_DOMAIN, "Base Address Size "));
158003831d35Sstevel log_printf(dgettext(TEXT_DOMAIN, "Interleave Factor Contains\n"));
158103831d35Sstevel log_printf("------------------------------");
158203831d35Sstevel log_printf("-----------------------------------------\n");
158303831d35Sstevel
158403831d35Sstevel err = picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY_SEGMENT,
158503831d35Sstevel NULL, memseg_callback);
158603831d35Sstevel return (err);
158703831d35Sstevel }
158803831d35Sstevel
158903831d35Sstevel /*
159003831d35Sstevel * display memory configuration
159103831d35Sstevel */
159203831d35Sstevel static int
display_memory_config(picl_nodehdl_t plafh)159303831d35Sstevel display_memory_config(picl_nodehdl_t plafh)
159403831d35Sstevel {
159503831d35Sstevel int err;
159603831d35Sstevel
159703831d35Sstevel logprintf_header(dgettext(TEXT_DOMAIN, "Memory Configuration"),
159803831d35Sstevel DEFAULT_LINE_WIDTH);
159903831d35Sstevel
160003831d35Sstevel mem_banks = NULL;
160103831d35Sstevel err = find_segments(plafh);
160203831d35Sstevel
160303831d35Sstevel if ((err == PICL_SUCCESS) && (mem_banks != NULL))
160403831d35Sstevel print_bank_table();
160503831d35Sstevel
160603831d35Sstevel free_bank_list();
160703831d35Sstevel
160803831d35Sstevel return (print_memory_module_group_table(plafh));
160903831d35Sstevel }
161003831d35Sstevel
161103831d35Sstevel /*
161203831d35Sstevel * print the hub device
161303831d35Sstevel */
161403831d35Sstevel static int
logprintf_hub_devices(picl_nodehdl_t hubh)161503831d35Sstevel logprintf_hub_devices(picl_nodehdl_t hubh)
161603831d35Sstevel {
161703831d35Sstevel char *name;
161803831d35Sstevel int portnum;
161903831d35Sstevel char *labelp;
162003831d35Sstevel picl_nodehdl_t parenth;
162103831d35Sstevel int err;
162203831d35Sstevel
162303831d35Sstevel err = picldiag_get_string_propval(hubh, PICL_PROP_NAME, &name);
162403831d35Sstevel if (err != PICL_SUCCESS)
162503831d35Sstevel return (err);
162603831d35Sstevel log_printf("%-12.12s ", name);
162703831d35Sstevel free(name);
162803831d35Sstevel
162903831d35Sstevel err = picl_get_propval_by_name(hubh, PICL_REFPROP_LOC_PARENT, &parenth,
163003831d35Sstevel sizeof (picl_nodehdl_t));
163103831d35Sstevel
163203831d35Sstevel if (err == PICL_SUCCESS) {
163303831d35Sstevel /* Read the Label */
163403831d35Sstevel err = picldiag_get_label(parenth, &labelp);
163503831d35Sstevel if (err == PICL_SUCCESS) {
163603831d35Sstevel log_printf("%s\n", labelp);
163703831d35Sstevel free(labelp);
163803831d35Sstevel return (PICL_SUCCESS);
163903831d35Sstevel } else if (err != PICL_PROPNOTFOUND) {
164003831d35Sstevel log_printf("\n");
164103831d35Sstevel return (err);
164203831d35Sstevel }
164303831d35Sstevel } else if (err != PICL_PROPNOTFOUND) {
164403831d35Sstevel log_printf("\n");
164503831d35Sstevel return (err);
164603831d35Sstevel }
164703831d35Sstevel
164803831d35Sstevel /* No Label, try the reg */
164903831d35Sstevel err = picl_get_propval_by_name(hubh, OBP_PROP_REG, &portnum,
165003831d35Sstevel sizeof (portnum));
165103831d35Sstevel if (err == PICL_PROPNOTFOUND)
165203831d35Sstevel log_printf(" -\n");
165303831d35Sstevel else if (err != PICL_SUCCESS) {
165403831d35Sstevel log_printf("\n");
165503831d35Sstevel return (err);
165603831d35Sstevel } else
165703831d35Sstevel log_printf("%3d\n", portnum);
165803831d35Sstevel
165903831d35Sstevel return (PICL_SUCCESS);
166003831d35Sstevel }
166103831d35Sstevel
166203831d35Sstevel /*
166303831d35Sstevel * callback functions to display hub devices
166403831d35Sstevel */
166503831d35Sstevel /* ARGSUSED */
166603831d35Sstevel static int
print_usb_devices(picl_nodehdl_t hubh,void * arg)166703831d35Sstevel print_usb_devices(picl_nodehdl_t hubh, void *arg)
166803831d35Sstevel {
166903831d35Sstevel picl_nodehdl_t chdh;
167003831d35Sstevel char *rootname;
167103831d35Sstevel int type = *(int *)arg;
167203831d35Sstevel int hubnum;
167303831d35Sstevel int err;
167403831d35Sstevel
167503831d35Sstevel err = picl_get_propval_by_name(hubh, PICL_PROP_CHILD, &chdh,
167603831d35Sstevel sizeof (picl_nodehdl_t));
167703831d35Sstevel
167803831d35Sstevel /* print header */
167903831d35Sstevel if (err == PICL_SUCCESS) {
168003831d35Sstevel err = picldiag_get_string_propval(hubh, PICL_PROP_NAME,
168103831d35Sstevel &rootname);
168203831d35Sstevel if (err != PICL_SUCCESS)
168303831d35Sstevel return (err);
168403831d35Sstevel
168503831d35Sstevel if (type == USB) {
168603831d35Sstevel log_printf("\n===============================");
168703831d35Sstevel log_printf(dgettext(TEXT_DOMAIN,
168803831d35Sstevel " %s Devices "), rootname);
168903831d35Sstevel } else {
169003831d35Sstevel /* Get its hub number */
169103831d35Sstevel err = picl_get_propval_by_name(hubh,
169203831d35Sstevel OBP_PROP_REG, &hubnum, sizeof (hubnum));
169303831d35Sstevel if ((err != PICL_SUCCESS) &&
169403831d35Sstevel (err != PICL_PROPNOTFOUND)) {
169503831d35Sstevel free(rootname);
169603831d35Sstevel return (err);
169703831d35Sstevel }
169803831d35Sstevel
169903831d35Sstevel log_printf("\n===============================");
170003831d35Sstevel if (err == PICL_SUCCESS)
170103831d35Sstevel log_printf(dgettext(TEXT_DOMAIN,
170203831d35Sstevel " %s#%d Devices "),
170303831d35Sstevel rootname, hubnum);
170403831d35Sstevel else
170503831d35Sstevel log_printf(dgettext(TEXT_DOMAIN,
170603831d35Sstevel " %s Devices "), rootname);
170703831d35Sstevel }
170803831d35Sstevel
170903831d35Sstevel log_printf("===============================\n\n");
171003831d35Sstevel log_printf("Name Port#\n");
171103831d35Sstevel log_printf("------------ -----\n");
171203831d35Sstevel free(rootname);
171303831d35Sstevel
171403831d35Sstevel do {
171503831d35Sstevel logprintf_hub_devices(chdh);
171603831d35Sstevel
171703831d35Sstevel err = picl_get_propval_by_name(chdh, PICL_PROP_PEER,
171803831d35Sstevel &chdh, sizeof (picl_nodehdl_t));
171903831d35Sstevel } while (err == PICL_SUCCESS);
172003831d35Sstevel }
172103831d35Sstevel
172203831d35Sstevel
172303831d35Sstevel if (err == PICL_PROPNOTFOUND)
172403831d35Sstevel return (PICL_WALK_CONTINUE);
172503831d35Sstevel return (err);
172603831d35Sstevel }
172703831d35Sstevel
172803831d35Sstevel /*
172903831d35Sstevel * callback functions to display usb devices
173003831d35Sstevel */
173103831d35Sstevel /* ARGSUSED */
173203831d35Sstevel static int
usb_callback(picl_nodehdl_t usbh,void * args)173303831d35Sstevel usb_callback(picl_nodehdl_t usbh, void *args)
173403831d35Sstevel {
173503831d35Sstevel int err;
173603831d35Sstevel int type;
173703831d35Sstevel
173803831d35Sstevel type = USB;
173903831d35Sstevel err = print_usb_devices(usbh, &type);
174003831d35Sstevel if (err != PICL_WALK_CONTINUE)
174103831d35Sstevel return (err);
174203831d35Sstevel type = HUB;
174303831d35Sstevel err = picl_walk_tree_by_class(usbh, NULL, &type, print_usb_devices);
174403831d35Sstevel if (err == PICL_SUCCESS)
174503831d35Sstevel err = PICL_WALK_CONTINUE;
174603831d35Sstevel return (err);
174703831d35Sstevel }
174803831d35Sstevel
174903831d35Sstevel
175003831d35Sstevel /*
175103831d35Sstevel * find usb devices and print its information
175203831d35Sstevel */
175303831d35Sstevel static int
display_usb_devices(picl_nodehdl_t plafh)175403831d35Sstevel display_usb_devices(picl_nodehdl_t plafh)
175503831d35Sstevel {
175603831d35Sstevel int err;
175703831d35Sstevel
175803831d35Sstevel /*
175903831d35Sstevel * get the usb node
176003831d35Sstevel */
176103831d35Sstevel err = picl_walk_tree_by_class(plafh, PICL_CLASS_USB, NULL,
176203831d35Sstevel usb_callback);
176303831d35Sstevel return (err);
176403831d35Sstevel }
176503831d35Sstevel
176603831d35Sstevel
176703831d35Sstevel
176803831d35Sstevel /*
176903831d35Sstevel * If nodeh is the io device, add it into the io list and return
177003831d35Sstevel * If it is not an io device and it has the subtree, traverse the subtree
177103831d35Sstevel * and add all leaf io devices
177203831d35Sstevel */
177303831d35Sstevel static int
add_io_leaves(picl_nodehdl_t nodeh,char * parentname,uint32_t board,uint32_t bus_id,uint64_t slot,uint32_t freq,char * model,char * status)177403831d35Sstevel add_io_leaves(picl_nodehdl_t nodeh, char *parentname, uint32_t board,
177503831d35Sstevel uint32_t bus_id, uint64_t slot, uint32_t freq, char *model, char *status)
177603831d35Sstevel {
177703831d35Sstevel picl_nodehdl_t childh;
177803831d35Sstevel picl_prophdl_t proph;
177903831d35Sstevel picl_propinfo_t pinfo;
178003831d35Sstevel int err;
178103831d35Sstevel char *nameval;
178203831d35Sstevel char piclclass[PICL_CLASSNAMELEN_MAX];
178303831d35Sstevel char nodename[MAXSTRLEN];
178403831d35Sstevel char name[MAXSTRLEN];
178503831d35Sstevel char *devfs_path;
178603831d35Sstevel char *compatible;
178703831d35Sstevel picl_nodehdl_t fruparenth;
178803831d35Sstevel char *label;
178903831d35Sstevel char binding_name[MAXSTRLEN];
179003831d35Sstevel
179103831d35Sstevel err = picl_get_propinfo_by_name(nodeh, PICL_PROP_NAME, &pinfo,
179203831d35Sstevel &proph);
179303831d35Sstevel if (err != PICL_SUCCESS)
179403831d35Sstevel return (err);
179503831d35Sstevel
179603831d35Sstevel nameval = alloca(pinfo.size);
179703831d35Sstevel if (nameval == NULL)
179803831d35Sstevel return (PICL_FAILURE);
179903831d35Sstevel
180003831d35Sstevel err = picl_get_propval(proph, nameval, pinfo.size);
180103831d35Sstevel if (err != PICL_SUCCESS)
180203831d35Sstevel return (err);
180303831d35Sstevel
180403831d35Sstevel (void) strlcpy(nodename, nameval, MAXSTRLEN);
180503831d35Sstevel
180603831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
180703831d35Sstevel piclclass, sizeof (piclclass));
180803831d35Sstevel if (err != PICL_SUCCESS)
180903831d35Sstevel return (err);
181003831d35Sstevel
181103831d35Sstevel /* if binding_name is found, name will be <nodename>-<binding_name> */
181203831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME,
181303831d35Sstevel binding_name, sizeof (binding_name));
181403831d35Sstevel if (err == PICL_PROPNOTFOUND) {
181503831d35Sstevel /*
181603831d35Sstevel * if compatible prop is found, name will be
181703831d35Sstevel * <nodename>-<compatible>
181803831d35Sstevel */
181903831d35Sstevel err = picldiag_get_first_compatible_value(nodeh, &compatible);
182003831d35Sstevel if (err == PICL_SUCCESS) {
182103831d35Sstevel strlcat(nodename, "-", MAXSTRLEN);
182203831d35Sstevel strlcat(nodename, compatible, MAXSTRLEN);
182303831d35Sstevel free(compatible);
182403831d35Sstevel } else if (err != PICL_PROPNOTFOUND) {
182503831d35Sstevel return (err);
182603831d35Sstevel }
182703831d35Sstevel } else if (err != PICL_SUCCESS) {
182803831d35Sstevel return (err);
182903831d35Sstevel } else if (strcmp(nodename, binding_name) != 0) {
183003831d35Sstevel if (strcmp(nodename, piclclass) == 0) {
183103831d35Sstevel /*
183203831d35Sstevel * nodename same as binding name -
183303831d35Sstevel * no need to display twice
183403831d35Sstevel */
183503831d35Sstevel strlcpy(nodename, binding_name, MAXSTRLEN);
183603831d35Sstevel } else {
183703831d35Sstevel strlcat(nodename, "-", MAXSTRLEN);
183803831d35Sstevel strlcat(nodename, binding_name, MAXSTRLEN);
183903831d35Sstevel }
184003831d35Sstevel }
184103831d35Sstevel
184203831d35Sstevel /*
184303831d35Sstevel * If it is an immediate child under pci/pciex/sbus/upa and not
184403831d35Sstevel * a bus node, add it to the io list.
184503831d35Sstevel * If it is a child under sub-bus and it is in an io
184603831d35Sstevel * device, add it to the io list.
184703831d35Sstevel */
184803831d35Sstevel if (((parentname == NULL) && (!is_bus(piclclass))) ||
184903831d35Sstevel ((parentname != NULL) && (is_io_device(piclclass)))) {
185003831d35Sstevel if (parentname == NULL)
185103831d35Sstevel (void) snprintf(name, MAXSTRLEN, "%s", nodename);
185203831d35Sstevel else
185303831d35Sstevel (void) snprintf(name, MAXSTRLEN, "%s/%s", parentname,
185403831d35Sstevel nodename);
185503831d35Sstevel
185603831d35Sstevel /*
185703831d35Sstevel * append the class if its class is not a generic
185803831d35Sstevel * obp-device class
185903831d35Sstevel */
186003831d35Sstevel if (strcmp(piclclass, PICL_CLASS_OBP_DEVICE))
186103831d35Sstevel (void) snprintf(name, MAXSTRLEN, "%s (%s)", name,
186203831d35Sstevel piclclass);
186303831d35Sstevel
186403831d35Sstevel err = picldiag_get_fru_parent(nodeh, &fruparenth);
186503831d35Sstevel if (err == PICL_PROPNOTFOUND) {
186603831d35Sstevel label = NULL;
186703831d35Sstevel } else if (err != PICL_SUCCESS) {
186803831d35Sstevel return (err);
186903831d35Sstevel } else {
187003831d35Sstevel err = picldiag_get_combined_label(fruparenth, &label,
187103831d35Sstevel 15);
187203831d35Sstevel if (err == PICL_PROPNOTFOUND)
187303831d35Sstevel label = NULL;
187403831d35Sstevel else if (err != PICL_SUCCESS)
187503831d35Sstevel return (err);
187603831d35Sstevel }
187703831d35Sstevel /* devfs-path */
187803831d35Sstevel err = picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH,
187903831d35Sstevel &devfs_path);
188003831d35Sstevel if (err == PICL_PROPNOTFOUND)
188103831d35Sstevel devfs_path = NULL;
188203831d35Sstevel else if (err != PICL_SUCCESS)
188303831d35Sstevel return (err);
188403831d35Sstevel
188503831d35Sstevel add_io_card(board, bus_id, slot, label, freq, name,
188603831d35Sstevel model, status, devfs_path);
188703831d35Sstevel if (label != NULL)
188803831d35Sstevel free(label);
188903831d35Sstevel if (devfs_path != NULL)
189003831d35Sstevel free(devfs_path);
189103831d35Sstevel return (PICL_SUCCESS);
189203831d35Sstevel }
189303831d35Sstevel
189403831d35Sstevel /*
189503831d35Sstevel * If there is any child, Go through each child.
189603831d35Sstevel */
189703831d35Sstevel
189803831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD,
189903831d35Sstevel &childh, sizeof (picl_nodehdl_t));
190003831d35Sstevel
190103831d35Sstevel /* there is a child */
190203831d35Sstevel while (err == PICL_SUCCESS) {
190303831d35Sstevel if (parentname == NULL)
190403831d35Sstevel (void) strlcpy(name, nodename, MAXSTRLEN);
190503831d35Sstevel else
190603831d35Sstevel (void) snprintf(name, MAXSTRLEN, "%s/%s", parentname,
190703831d35Sstevel nodename);
190803831d35Sstevel
190903831d35Sstevel err = add_io_leaves(childh, name, board, bus_id, slot, freq,
191003831d35Sstevel model, status);
191103831d35Sstevel if (err != PICL_SUCCESS)
191203831d35Sstevel return (err);
191303831d35Sstevel /*
191403831d35Sstevel * get next child
191503831d35Sstevel */
191603831d35Sstevel err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
191703831d35Sstevel &childh, sizeof (picl_nodehdl_t));
191803831d35Sstevel }
191903831d35Sstevel
192003831d35Sstevel if (err == PICL_PROPNOTFOUND)
192103831d35Sstevel return (PICL_SUCCESS);
192203831d35Sstevel return (err);
192303831d35Sstevel }
192403831d35Sstevel
192503831d35Sstevel /*
192603831d35Sstevel * callback function to add all io devices under sbus in io list
192703831d35Sstevel */
192803831d35Sstevel /*ARGSUSED*/
192903831d35Sstevel static int
sbus_callback(picl_nodehdl_t sbush,void * args)193003831d35Sstevel sbus_callback(picl_nodehdl_t sbush, void *args)
193103831d35Sstevel {
193203831d35Sstevel picl_nodehdl_t nodeh;
193303831d35Sstevel int err;
193403831d35Sstevel uint32_t boardnum;
193503831d35Sstevel uint32_t bus_id;
193603831d35Sstevel uint32_t slot;
193703831d35Sstevel uint32_t freq;
193803831d35Sstevel char *model;
193903831d35Sstevel char *status;
194003831d35Sstevel
194103831d35Sstevel /* Fill in common infomation */
194203831d35Sstevel bus_id = SBUS_TYPE;
194303831d35Sstevel
194403831d35Sstevel err = picldiag_get_clock_freq(sbush, &freq);
194503831d35Sstevel if (err == PICL_PROPNOTFOUND)
194603831d35Sstevel return (PICL_WALK_CONTINUE);
194703831d35Sstevel else if (err != PICL_SUCCESS)
194803831d35Sstevel return (err);
194903831d35Sstevel /*
195003831d35Sstevel * If no board# is found, set boardnum to 0
195103831d35Sstevel */
195203831d35Sstevel boardnum = picldiag_get_uint_propval(sbush, OBP_PROP_BOARD_NUM, &err);
195303831d35Sstevel if (err == PICL_PROPNOTFOUND)
195403831d35Sstevel boardnum = DEFAULT_BOARD_NUM;
195503831d35Sstevel else if (err != PICL_SUCCESS)
195603831d35Sstevel return (err);
195703831d35Sstevel
195803831d35Sstevel err = picl_get_propval_by_name(sbush, PICL_PROP_CHILD, &nodeh,
195903831d35Sstevel sizeof (picl_nodehdl_t));
196003831d35Sstevel
196103831d35Sstevel while (err == PICL_SUCCESS) {
196203831d35Sstevel slot = picldiag_get_uint_propval(nodeh,
196303831d35Sstevel PICL_PROP_SLOT, &err);
196403831d35Sstevel if (err == PICL_PROPNOTFOUND) {
196503831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
196603831d35Sstevel &nodeh, sizeof (picl_nodehdl_t));
196703831d35Sstevel continue;
196803831d35Sstevel } else if (err != PICL_SUCCESS)
196903831d35Sstevel return (err);
197003831d35Sstevel
197103831d35Sstevel err = picldiag_get_string_propval(nodeh, OBP_PROP_MODEL,
197203831d35Sstevel &model);
197303831d35Sstevel if (err == PICL_PROPNOTFOUND)
197403831d35Sstevel model = NULL;
197503831d35Sstevel else if (err != PICL_SUCCESS)
197603831d35Sstevel return (err);
197703831d35Sstevel
197803831d35Sstevel err = picldiag_get_string_propval(nodeh, PICL_PROP_STATUS,
197903831d35Sstevel &status);
198003831d35Sstevel if (err == PICL_PROPNOTFOUND) {
198103831d35Sstevel status = malloc(5);
198203831d35Sstevel if (status == NULL)
198303831d35Sstevel return (PICL_FAILURE);
198403831d35Sstevel strncpy(status, "okay", 5);
198503831d35Sstevel } else if (err != PICL_SUCCESS)
198603831d35Sstevel return (err);
198703831d35Sstevel
198803831d35Sstevel err = add_io_leaves(nodeh, NULL, boardnum, bus_id, slot, freq,
198903831d35Sstevel model, status);
199003831d35Sstevel if (model != NULL)
199103831d35Sstevel free(model);
199203831d35Sstevel if (status != NULL)
199303831d35Sstevel free(status);
199403831d35Sstevel if (err != PICL_SUCCESS)
199503831d35Sstevel return (err);
199603831d35Sstevel
199703831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
199803831d35Sstevel sizeof (picl_nodehdl_t));
199903831d35Sstevel }
200003831d35Sstevel if (err == PICL_PROPNOTFOUND)
200103831d35Sstevel return (PICL_WALK_CONTINUE);
200203831d35Sstevel return (err);
200303831d35Sstevel }
200403831d35Sstevel
200503831d35Sstevel /*
200603831d35Sstevel * add all io devices under pci/pciex in io list
200703831d35Sstevel */
200803831d35Sstevel /* ARGSUSED */
200903831d35Sstevel static int
pci_pciex_callback(picl_nodehdl_t pcih,void * args)201003831d35Sstevel pci_pciex_callback(picl_nodehdl_t pcih, void *args)
201103831d35Sstevel {
201203831d35Sstevel picl_nodehdl_t nodeh;
201303831d35Sstevel int err;
201403831d35Sstevel char piclclass[PICL_CLASSNAMELEN_MAX];
201503831d35Sstevel uint32_t boardnum;
201603831d35Sstevel uint32_t bus_id;
201703831d35Sstevel uint32_t slot;
201803831d35Sstevel uint32_t freq;
201903831d35Sstevel char *model;
202003831d35Sstevel char *status;
202103831d35Sstevel
202203831d35Sstevel if (strcmp(args, PICL_CLASS_PCIEX) == 0)
202303831d35Sstevel bus_id = PCIEX_TYPE;
202403831d35Sstevel else
202503831d35Sstevel bus_id = PCI_TYPE;
202603831d35Sstevel
202703831d35Sstevel /*
202803831d35Sstevel * Check if it has the freq, if not,
202903831d35Sstevel * If not, use its parent's freq
203003831d35Sstevel * if its parent's freq is not found, return
203103831d35Sstevel */
203203831d35Sstevel err = picldiag_get_clock_freq(pcih, &freq);
203303831d35Sstevel if (err == PICL_PROPNOTFOUND) {
203403831d35Sstevel err = picldiag_get_clock_from_parent(pcih, &freq);
203503831d35Sstevel if (err == PICL_PROPNOTFOUND)
203603831d35Sstevel return (PICL_WALK_CONTINUE);
203703831d35Sstevel else if (err != PICL_SUCCESS)
203803831d35Sstevel return (err);
203903831d35Sstevel } else if (err != PICL_SUCCESS)
204003831d35Sstevel return (err);
204103831d35Sstevel
204203831d35Sstevel /*
204303831d35Sstevel * If no board# is found, set boardnum to 0
204403831d35Sstevel */
204503831d35Sstevel boardnum = picldiag_get_uint_propval(pcih, OBP_PROP_BOARD_NUM, &err);
204603831d35Sstevel if (err == PICL_PROPNOTFOUND)
204703831d35Sstevel boardnum = DEFAULT_BOARD_NUM;
204803831d35Sstevel else if (err != PICL_SUCCESS)
204903831d35Sstevel return (err);
205003831d35Sstevel
205103831d35Sstevel /* Walk through the children */
205203831d35Sstevel
205303831d35Sstevel err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
205403831d35Sstevel sizeof (picl_nodehdl_t));
205503831d35Sstevel while (err == PICL_SUCCESS) {
205603831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
205703831d35Sstevel piclclass, sizeof (piclclass));
205803831d35Sstevel if (err != PICL_SUCCESS)
205903831d35Sstevel return (err);
206003831d35Sstevel
206103831d35Sstevel /*
206203831d35Sstevel * Skip PCIEX, PCI bridge and USB devices because they will be
206303831d35Sstevel * processed later
206403831d35Sstevel */
206503831d35Sstevel if ((strcmp(piclclass, PICL_CLASS_PCI) == 0) ||
206603831d35Sstevel (strcmp(piclclass, PICL_CLASS_PCIEX) == 0) ||
206703831d35Sstevel (strcmp(piclclass, PICL_CLASS_USB) == 0)) {
206803831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
206903831d35Sstevel &nodeh, sizeof (picl_nodehdl_t));
207003831d35Sstevel continue;
207103831d35Sstevel }
207203831d35Sstevel
207303831d35Sstevel /* Get the device id for pci card */
207403831d35Sstevel slot = picldiag_get_uint_propval(nodeh,
207503831d35Sstevel PICL_PROP_DEVICE_ID, &err);
207603831d35Sstevel if (err == PICL_PROPNOTFOUND) {
207703831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
207803831d35Sstevel &nodeh, sizeof (picl_nodehdl_t));
207903831d35Sstevel continue;
208003831d35Sstevel } else if (err != PICL_SUCCESS)
208103831d35Sstevel return (err);
208203831d35Sstevel
208303831d35Sstevel /* Get the model of this card */
208403831d35Sstevel err = picldiag_get_string_propval(nodeh, OBP_PROP_MODEL,
208503831d35Sstevel &model);
208603831d35Sstevel if (err == PICL_PROPNOTFOUND)
208703831d35Sstevel model = NULL;
208803831d35Sstevel else if (err != PICL_SUCCESS)
208903831d35Sstevel return (err);
209003831d35Sstevel
209103831d35Sstevel err = picldiag_get_string_propval(nodeh, PICL_PROP_STATUS,
209203831d35Sstevel &status);
209303831d35Sstevel if (err == PICL_PROPNOTFOUND) {
209403831d35Sstevel status = malloc(5);
209503831d35Sstevel if (status == NULL)
209603831d35Sstevel return (PICL_FAILURE);
209703831d35Sstevel strncpy(status, "okay", 5);
209803831d35Sstevel } else if (err != PICL_SUCCESS)
209903831d35Sstevel return (err);
210003831d35Sstevel
210103831d35Sstevel err = add_io_leaves(nodeh, NULL, boardnum, bus_id, slot,
210203831d35Sstevel freq, model, status);
210303831d35Sstevel
210403831d35Sstevel if (model != NULL)
210503831d35Sstevel free(model);
210603831d35Sstevel
210703831d35Sstevel if (status != NULL)
210803831d35Sstevel free(status);
210903831d35Sstevel
211003831d35Sstevel if (err != PICL_SUCCESS)
211103831d35Sstevel return (err);
211203831d35Sstevel
211303831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
211403831d35Sstevel sizeof (picl_nodehdl_t));
211503831d35Sstevel
211603831d35Sstevel }
211703831d35Sstevel
211803831d35Sstevel if (err == PICL_PROPNOTFOUND)
211903831d35Sstevel return (PICL_WALK_CONTINUE);
212003831d35Sstevel
212103831d35Sstevel return (err);
212203831d35Sstevel }
212303831d35Sstevel
212403831d35Sstevel /*
212503831d35Sstevel * add io devices in io list
212603831d35Sstevel * Its slot number is drived from upa-portid
212703831d35Sstevel */
212803831d35Sstevel static int
add_io_devices(picl_nodehdl_t nodeh)212903831d35Sstevel add_io_devices(picl_nodehdl_t nodeh)
213003831d35Sstevel {
213103831d35Sstevel int err;
213203831d35Sstevel uint64_t board_type;
213303831d35Sstevel char piclclass[PICL_CLASSNAMELEN_MAX];
213403831d35Sstevel char name[MAXSTRLEN];
213503831d35Sstevel char *devfs_path;
213603831d35Sstevel char *nameval;
213703831d35Sstevel uint32_t boardnum;
213803831d35Sstevel uint32_t bus_id;
213903831d35Sstevel uint32_t slot;
214003831d35Sstevel uint32_t freq;
214103831d35Sstevel char *model;
214203831d35Sstevel char *status;
214303831d35Sstevel picl_prophdl_t proph;
214403831d35Sstevel picl_propinfo_t pinfo;
214503831d35Sstevel picl_nodehdl_t fruparenth;
214603831d35Sstevel char *label;
214703831d35Sstevel
214803831d35Sstevel
214903831d35Sstevel bus_id = UPA_TYPE;
215003831d35Sstevel
215103831d35Sstevel /*
215203831d35Sstevel * If clock frequency can't be found from its parent, don't add
215303831d35Sstevel */
215403831d35Sstevel err = picldiag_get_clock_from_parent(nodeh, &freq);
215503831d35Sstevel if (err == PICL_PROPNOTFOUND)
215603831d35Sstevel return (PICL_SUCCESS);
215703831d35Sstevel else if (err != PICL_SUCCESS)
215803831d35Sstevel return (err);
215903831d35Sstevel
216003831d35Sstevel /*
216103831d35Sstevel * If no board# is found, set boardnum to 0
216203831d35Sstevel */
216303831d35Sstevel boardnum = picldiag_get_uint_propval(nodeh, OBP_PROP_BOARD_NUM, &err);
216403831d35Sstevel if (err == PICL_PROPNOTFOUND)
216503831d35Sstevel boardnum = DEFAULT_BOARD_NUM;
216603831d35Sstevel else if (err != PICL_SUCCESS)
216703831d35Sstevel return (err);
216803831d35Sstevel
216903831d35Sstevel /*
217003831d35Sstevel * get upa portid as slot number
217103831d35Sstevel * If upa portid is not found, don't add the card.
217203831d35Sstevel */
217303831d35Sstevel slot = picldiag_get_uint_propval(nodeh, OBP_PROP_UPA_PORTID,
217403831d35Sstevel &err);
217503831d35Sstevel if (err == PICL_PROPNOTFOUND)
217603831d35Sstevel return (PICL_SUCCESS);
217703831d35Sstevel else if (err != PICL_SUCCESS)
217803831d35Sstevel return (err);
217903831d35Sstevel
218003831d35Sstevel /* Get the model of this card */
218103831d35Sstevel err = picldiag_get_string_propval(nodeh, OBP_PROP_MODEL, &model);
218203831d35Sstevel if (err == PICL_PROPNOTFOUND)
218303831d35Sstevel model = NULL;
218403831d35Sstevel else if (err != PICL_SUCCESS)
218503831d35Sstevel return (err);
218603831d35Sstevel
218703831d35Sstevel /*
218803831d35Sstevel * check if it is a ffb device
218903831d35Sstevel * If it's a ffb device, append its board type to name
219003831d35Sstevel * otherwise, use its nodename
219103831d35Sstevel */
219203831d35Sstevel err = picl_get_prop_by_name(nodeh, PICL_PROP_FFB_BOARD_REV, &proph);
219303831d35Sstevel if (err == PICL_PROPNOTFOUND) {
219403831d35Sstevel err = picl_get_propinfo_by_name(nodeh, PICL_PROP_NAME,
219503831d35Sstevel &pinfo, &proph);
219603831d35Sstevel if (err != PICL_SUCCESS)
219703831d35Sstevel return (err);
219803831d35Sstevel
219903831d35Sstevel nameval = alloca(pinfo.size);
220003831d35Sstevel if (nameval == NULL)
220103831d35Sstevel return (PICL_FAILURE);
220203831d35Sstevel
220303831d35Sstevel err = picl_get_propval(proph, nameval, pinfo.size);
220403831d35Sstevel if (err != PICL_SUCCESS)
220503831d35Sstevel return (err);
220603831d35Sstevel
220703831d35Sstevel (void) strlcpy(name, nameval, MAXSTRLEN);
220803831d35Sstevel } else if (err == PICL_SUCCESS) {
220903831d35Sstevel /* Find out if it's single or double buffered */
221003831d35Sstevel board_type = picldiag_get_uint_propval(nodeh,
221103831d35Sstevel OBP_PROP_BOARD_TYPE, &err);
221203831d35Sstevel if (err == PICL_PROPNOTFOUND)
221303831d35Sstevel (void) strlcpy(name, FFB_NAME, sizeof (name));
221403831d35Sstevel if (err == PICL_SUCCESS) {
221503831d35Sstevel if (board_type & FFB_B_BUFF)
221603831d35Sstevel (void) strlcpy(name, FFB_DOUBLE_BUF,
221703831d35Sstevel sizeof (name));
221803831d35Sstevel else
221903831d35Sstevel (void) strlcpy(name, FFB_SINGLE_BUF,
222003831d35Sstevel sizeof (name));
222103831d35Sstevel } else
222203831d35Sstevel return (err);
222303831d35Sstevel } else
222403831d35Sstevel return (err);
222503831d35Sstevel
222603831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
222703831d35Sstevel piclclass, sizeof (piclclass));
222803831d35Sstevel if (err != PICL_SUCCESS)
222903831d35Sstevel return (err);
223003831d35Sstevel
223103831d35Sstevel (void) snprintf(name, sizeof (name), "%s (%s)", name, piclclass);
223203831d35Sstevel
223303831d35Sstevel err = picldiag_get_string_propval(nodeh, PICL_PROP_STATUS, &status);
223403831d35Sstevel if (err == PICL_PROPNOTFOUND) {
223503831d35Sstevel status = malloc(5);
223603831d35Sstevel if (status == NULL)
223703831d35Sstevel return (PICL_FAILURE);
223803831d35Sstevel strncpy(status, "okay", 5);
223903831d35Sstevel } else if (err != PICL_SUCCESS)
224003831d35Sstevel return (err);
224103831d35Sstevel
224203831d35Sstevel err = picldiag_get_fru_parent(nodeh, &fruparenth);
224303831d35Sstevel if (err == PICL_PROPNOTFOUND) {
224403831d35Sstevel label = NULL;
224503831d35Sstevel } else if (err != PICL_SUCCESS) {
224603831d35Sstevel return (err);
224703831d35Sstevel } else {
224803831d35Sstevel err = picldiag_get_combined_label(fruparenth, &label, 15);
224903831d35Sstevel if (err == PICL_PROPNOTFOUND)
225003831d35Sstevel label = NULL;
225103831d35Sstevel else if (err != PICL_SUCCESS)
225203831d35Sstevel return (err);
225303831d35Sstevel }
225403831d35Sstevel /* devfs-path */
225503831d35Sstevel err = picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH,
225603831d35Sstevel &devfs_path);
225703831d35Sstevel if (err == PICL_PROPNOTFOUND)
225803831d35Sstevel devfs_path = NULL;
225903831d35Sstevel else if (err != PICL_SUCCESS)
226003831d35Sstevel return (err);
226103831d35Sstevel
226203831d35Sstevel add_io_card(boardnum, bus_id, slot, label, freq, name, model, status,
226303831d35Sstevel devfs_path);
226403831d35Sstevel if (label != NULL)
226503831d35Sstevel free(label);
226603831d35Sstevel if (model != NULL)
226703831d35Sstevel free(model);
226803831d35Sstevel if (status != NULL)
226903831d35Sstevel free(status);
227003831d35Sstevel if (devfs_path != NULL)
227103831d35Sstevel free(devfs_path);
227203831d35Sstevel
227303831d35Sstevel return (PICL_SUCCESS);
227403831d35Sstevel }
227503831d35Sstevel
227603831d35Sstevel /*
227703831d35Sstevel * loop through all children and add io devices in io list
227803831d35Sstevel */
227903831d35Sstevel static int
process_io_leaves(picl_nodehdl_t rooth)228003831d35Sstevel process_io_leaves(picl_nodehdl_t rooth)
228103831d35Sstevel {
228203831d35Sstevel picl_nodehdl_t nodeh;
228303831d35Sstevel char classval[PICL_CLASSNAMELEN_MAX];
228403831d35Sstevel int err;
228503831d35Sstevel
228603831d35Sstevel err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &nodeh,
228703831d35Sstevel sizeof (picl_nodehdl_t));
228803831d35Sstevel while (err == PICL_SUCCESS) {
228903831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
229003831d35Sstevel classval, sizeof (classval));
229103831d35Sstevel if (err != PICL_SUCCESS)
229203831d35Sstevel return (err);
229303831d35Sstevel
229403831d35Sstevel if (is_io_device(classval))
229503831d35Sstevel err = add_io_devices(nodeh);
229603831d35Sstevel
229703831d35Sstevel if (err != PICL_SUCCESS)
229803831d35Sstevel return (err);
229903831d35Sstevel
230003831d35Sstevel err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
230103831d35Sstevel sizeof (picl_nodehdl_t));
230203831d35Sstevel }
230303831d35Sstevel
230403831d35Sstevel if (err == PICL_PROPNOTFOUND)
230503831d35Sstevel return (PICL_SUCCESS);
230603831d35Sstevel
230703831d35Sstevel return (err);
230803831d35Sstevel }
230903831d35Sstevel
231003831d35Sstevel /*
231103831d35Sstevel * callback function to add all io devices under upa in io list
231203831d35Sstevel */
231303831d35Sstevel /*ARGSUSED*/
231403831d35Sstevel static int
upa_callback(picl_nodehdl_t upah,void * args)231503831d35Sstevel upa_callback(picl_nodehdl_t upah, void *args)
231603831d35Sstevel {
231703831d35Sstevel int err;
231803831d35Sstevel
231903831d35Sstevel err = process_io_leaves(upah);
232003831d35Sstevel
232103831d35Sstevel if (err == PICL_SUCCESS)
232203831d35Sstevel return (PICL_WALK_CONTINUE);
232303831d35Sstevel return (err);
232403831d35Sstevel }
232503831d35Sstevel
232603831d35Sstevel /*
232703831d35Sstevel * display ffb hardware configuration
232803831d35Sstevel */
232903831d35Sstevel /* ARGSUSED */
233003831d35Sstevel static int
ffbconfig_callback(picl_nodehdl_t ffbh,void * arg)233103831d35Sstevel ffbconfig_callback(picl_nodehdl_t ffbh, void *arg)
233203831d35Sstevel {
233303831d35Sstevel int err;
233403831d35Sstevel uint64_t board_rev;
233503831d35Sstevel uint64_t fbc_ver;
233603831d35Sstevel char *dac_ver;
233703831d35Sstevel char *fbram_ver;
233803831d35Sstevel
233903831d35Sstevel /*
234003831d35Sstevel * If it has PICL_PROP_FFB_BOARD_REV, it is a ffb device
234103831d35Sstevel * Otherwise, return.
234203831d35Sstevel */
234303831d35Sstevel board_rev = picldiag_get_uint_propval(ffbh, PICL_PROP_FFB_BOARD_REV,
234403831d35Sstevel &err);
234503831d35Sstevel if (err == PICL_PROPNOTFOUND)
234603831d35Sstevel return (PICL_WALK_CONTINUE);
234703831d35Sstevel else if (err != PICL_SUCCESS)
234803831d35Sstevel return (err);
234903831d35Sstevel
235003831d35Sstevel log_printf("FFB Hardware Configuration:\n");
235103831d35Sstevel log_printf("-----------------------------------\n");
235203831d35Sstevel log_printf("Board rev: %lld\n", board_rev);
235303831d35Sstevel
235403831d35Sstevel fbc_ver = picldiag_get_uint_propval(ffbh, OBP_PROP_FBC_REG_ID,
235503831d35Sstevel &err);
235603831d35Sstevel if (err == PICL_SUCCESS)
235703831d35Sstevel log_printf("FBC version: 0x%llx\n", fbc_ver);
235803831d35Sstevel else if (err != PICL_PROPNOTFOUND)
235903831d35Sstevel return (err);
236003831d35Sstevel
236103831d35Sstevel err = picldiag_get_string_propval(ffbh, PICL_PROP_FFB_DAC_VER,
236203831d35Sstevel &dac_ver);
236303831d35Sstevel if (err == PICL_SUCCESS) {
236403831d35Sstevel log_printf("DAC: %s\n", dac_ver);
236503831d35Sstevel free(dac_ver);
236603831d35Sstevel } else if (err != PICL_PROPNOTFOUND)
236703831d35Sstevel return (err);
236803831d35Sstevel
236903831d35Sstevel err = picldiag_get_string_propval(ffbh, PICL_PROP_FFB_FBRAM_VER,
237003831d35Sstevel &fbram_ver);
237103831d35Sstevel if (err == PICL_SUCCESS) {
237203831d35Sstevel log_printf("3DRAM: %s\n", fbram_ver);
237303831d35Sstevel free(fbram_ver);
237403831d35Sstevel } else if (err != PICL_PROPNOTFOUND)
237503831d35Sstevel return (err);
237603831d35Sstevel
237703831d35Sstevel log_printf("\n");
237803831d35Sstevel return (PICL_WALK_CONTINUE);
237903831d35Sstevel }
238003831d35Sstevel
238103831d35Sstevel /*
238203831d35Sstevel * find all io devices and add them in the io list
238303831d35Sstevel */
238403831d35Sstevel static int
gather_io_cards(picl_nodehdl_t plafh)238503831d35Sstevel gather_io_cards(picl_nodehdl_t plafh)
238603831d35Sstevel {
238703831d35Sstevel int err;
238803831d35Sstevel
238903831d35Sstevel /*
239003831d35Sstevel * look for io devices under the immediate children of platform
239103831d35Sstevel */
239203831d35Sstevel err = process_io_leaves(plafh);
239303831d35Sstevel if (err != PICL_SUCCESS)
239403831d35Sstevel return (err);
239503831d35Sstevel
239603831d35Sstevel err = picl_walk_tree_by_class(plafh, PICL_CLASS_SBUS,
239703831d35Sstevel PICL_CLASS_SBUS, sbus_callback);
239803831d35Sstevel if (err != PICL_SUCCESS)
239903831d35Sstevel return (err);
240003831d35Sstevel
240103831d35Sstevel err = picl_walk_tree_by_class(plafh, PICL_CLASS_PCI,
240203831d35Sstevel PICL_CLASS_PCI, pci_pciex_callback);
240303831d35Sstevel if (err != PICL_SUCCESS)
240403831d35Sstevel return (err);
240503831d35Sstevel
240603831d35Sstevel err = picl_walk_tree_by_class(plafh, PICL_CLASS_PCIEX,
2407*2983dda7SMichael Bergknoff PICL_CLASS_PCIEX, pci_pciex_callback);
240803831d35Sstevel if (err != PICL_SUCCESS)
240903831d35Sstevel return (err);
241003831d35Sstevel
241103831d35Sstevel err = picl_walk_tree_by_class(plafh, PICL_CLASS_UPA,
241203831d35Sstevel PICL_CLASS_UPA, upa_callback);
241303831d35Sstevel
241403831d35Sstevel return (err);
241503831d35Sstevel }
241603831d35Sstevel
241703831d35Sstevel static void
picldiag_display_io_cards(struct io_card * list)241803831d35Sstevel picldiag_display_io_cards(struct io_card *list)
241903831d35Sstevel {
242003831d35Sstevel static int banner = 0; /* Have we printed the column headings? */
242103831d35Sstevel struct io_card *p;
242203831d35Sstevel
242303831d35Sstevel if (list == NULL)
242403831d35Sstevel return;
242503831d35Sstevel
242603831d35Sstevel if (banner == 0) {
242703831d35Sstevel log_printf("Bus Freq Slot + Name +\n", 0);
242803831d35Sstevel log_printf("Type MHz Status Path"
2429*2983dda7SMichael Bergknoff " Model", 0);
243003831d35Sstevel log_printf("\n", 0);
243103831d35Sstevel log_printf("------ ---- ---------- "
2432*2983dda7SMichael Bergknoff "---------------------------- "
2433*2983dda7SMichael Bergknoff "--------------------", 0);
243403831d35Sstevel log_printf("\n", 0);
243503831d35Sstevel banner = 1;
243603831d35Sstevel }
243703831d35Sstevel
243803831d35Sstevel for (p = list; p != NULL; p = p -> next) {
243903831d35Sstevel log_printf("%-6s ", p->bus_type, 0);
244003831d35Sstevel log_printf("%-3d ", p->freq, 0);
244103831d35Sstevel /*
244203831d35Sstevel * We check to see if it's an int or
244303831d35Sstevel * a char string to display for slot.
244403831d35Sstevel */
244503831d35Sstevel if (p->slot == PCI_SLOT_IS_STRING)
244603831d35Sstevel log_printf("%-10s ", p->slot_str, 0);
244703831d35Sstevel else
244803831d35Sstevel log_printf("%-10d ", p->slot, 0);
244903831d35Sstevel
245003831d35Sstevel log_printf("%-28.28s", p->name, 0);
245103831d35Sstevel if (strlen(p->name) > 28)
245203831d35Sstevel log_printf("+ ", 0);
245303831d35Sstevel else
245403831d35Sstevel log_printf(" ", 0);
245503831d35Sstevel log_printf("%-19.19s", p->model, 0);
245603831d35Sstevel if (strlen(p->model) > 19)
245703831d35Sstevel log_printf("+", 0);
245803831d35Sstevel log_printf("\n", 0);
245903831d35Sstevel log_printf(" %-10s ", p->status, 0);
246003831d35Sstevel set_exit_code(p->status);
246103831d35Sstevel if (strlen(p->notes) > 0)
246203831d35Sstevel log_printf("%s", p->notes, 0);
246303831d35Sstevel log_printf("\n\n", 0);
246403831d35Sstevel }
246503831d35Sstevel }
246603831d35Sstevel
246703831d35Sstevel /*
246803831d35Sstevel * display all io devices
246903831d35Sstevel */
247003831d35Sstevel static int
display_io_device_info(picl_nodehdl_t plafh)247103831d35Sstevel display_io_device_info(picl_nodehdl_t plafh)
247203831d35Sstevel {
247303831d35Sstevel int err;
247403831d35Sstevel
247503831d35Sstevel err = gather_io_cards(plafh);
247603831d35Sstevel if (err != PICL_SUCCESS)
247703831d35Sstevel return (err);
247803831d35Sstevel
247903831d35Sstevel logprintf_header(dgettext(TEXT_DOMAIN, "IO Devices"),
248003831d35Sstevel DEFAULT_LINE_WIDTH);
248103831d35Sstevel
248203831d35Sstevel picldiag_display_io_cards(io_card_list);
248303831d35Sstevel
248403831d35Sstevel free_io_cards(io_card_list);
248503831d35Sstevel
248603831d35Sstevel return (PICL_SUCCESS);
248703831d35Sstevel }
248803831d35Sstevel
248903831d35Sstevel /*
249003831d35Sstevel * print fan device information
249103831d35Sstevel */
249203831d35Sstevel static int
logprintf_fan_info(picl_nodehdl_t fanh)249303831d35Sstevel logprintf_fan_info(picl_nodehdl_t fanh)
249403831d35Sstevel {
249503831d35Sstevel int err;
249603831d35Sstevel char *label;
249703831d35Sstevel char *unit;
249803831d35Sstevel int64_t speed;
249903831d35Sstevel int64_t min_speed;
250003831d35Sstevel picl_nodehdl_t fruph;
250103831d35Sstevel
250203831d35Sstevel err = picldiag_get_fru_parent(fanh, &fruph);
250303831d35Sstevel if (err != PICL_SUCCESS)
250403831d35Sstevel return (err);
250503831d35Sstevel
250603831d35Sstevel err = picldiag_get_combined_label(fruph, &label, 20);
250703831d35Sstevel if (err != PICL_SUCCESS)
250803831d35Sstevel return (err);
250903831d35Sstevel
251003831d35Sstevel log_printf("%-20s ", label);
251103831d35Sstevel free(label);
251203831d35Sstevel
251303831d35Sstevel err = picldiag_get_label(fanh, &label);
251403831d35Sstevel if (err == PICL_SUCCESS) {
251503831d35Sstevel log_printf("%-14s ", label);
251603831d35Sstevel free(label);
251703831d35Sstevel } else if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
251803831d35Sstevel log_printf(" - ");
251903831d35Sstevel } else
252003831d35Sstevel return (err);
252103831d35Sstevel
252203831d35Sstevel speed = picldiag_get_uint_propval(fanh, PICL_PROP_FAN_SPEED, &err);
252303831d35Sstevel if (err == PICL_SUCCESS) {
252403831d35Sstevel min_speed = picldiag_get_uint_propval(fanh,
252503831d35Sstevel PICL_PROP_LOW_WARNING_THRESHOLD, &err);
252603831d35Sstevel if (err != PICL_SUCCESS)
252703831d35Sstevel min_speed = 0;
25288326d453Svenki
252903831d35Sstevel if (speed < min_speed) {
253003831d35Sstevel log_printf("failed (%lld", speed);
253103831d35Sstevel err = picldiag_get_string_propval(fanh,
253203831d35Sstevel PICL_PROP_FAN_SPEED_UNIT, &unit);
253303831d35Sstevel if (err == PICL_SUCCESS) {
253403831d35Sstevel log_printf("%s", unit);
253503831d35Sstevel free(unit);
253603831d35Sstevel }
253703831d35Sstevel log_printf(")");
253803831d35Sstevel exit_code = PD_SYSTEM_FAILURE;
253903831d35Sstevel } else {
254003831d35Sstevel log_printf("okay");
254103831d35Sstevel }
254203831d35Sstevel } else {
254303831d35Sstevel err = picldiag_get_string_propval(fanh,
254403831d35Sstevel PICL_PROP_FAN_SPEED_UNIT, &unit);
254503831d35Sstevel if (err == PICL_SUCCESS) {
254603831d35Sstevel log_printf("%-12s ", unit);
254703831d35Sstevel free(unit);
254803831d35Sstevel }
254903831d35Sstevel }
255003831d35Sstevel
255103831d35Sstevel log_printf("\n");
255203831d35Sstevel return (PICL_SUCCESS);
255303831d35Sstevel }
255403831d35Sstevel
255503831d35Sstevel static int
fan_callback(picl_nodehdl_t fanh,void * arg)255603831d35Sstevel fan_callback(picl_nodehdl_t fanh, void *arg)
255703831d35Sstevel {
255803831d35Sstevel int *countp = arg;
255903831d35Sstevel
256003831d35Sstevel if (*countp == 0) {
256103831d35Sstevel log_printf(dgettext(TEXT_DOMAIN, "Fan Status:\n"));
256203831d35Sstevel log_printf("-------------------------------------------\n");
256303831d35Sstevel log_printf("Location Sensor Status\n");
256403831d35Sstevel log_printf("-------------------------------------------\n");
256503831d35Sstevel }
256603831d35Sstevel *countp += 1;
25678326d453Svenki
25688326d453Svenki (void) logprintf_fan_info(fanh);
25698326d453Svenki
25708326d453Svenki return (PICL_WALK_CONTINUE);
257103831d35Sstevel }
257203831d35Sstevel
257303831d35Sstevel /*
257403831d35Sstevel * callback function search children to find fan device and print its speed
257503831d35Sstevel */
257603831d35Sstevel static int
display_fan_speed(picl_nodehdl_t plafh)257703831d35Sstevel display_fan_speed(picl_nodehdl_t plafh)
257803831d35Sstevel {
257903831d35Sstevel int err;
258003831d35Sstevel int print_header;
258103831d35Sstevel
258203831d35Sstevel print_header = 0;
258303831d35Sstevel err = picl_walk_tree_by_class(plafh, PICL_CLASS_FAN,
258403831d35Sstevel &print_header, fan_callback);
258503831d35Sstevel return (err);
258603831d35Sstevel }
258703831d35Sstevel
258803831d35Sstevel /*
258903831d35Sstevel * print temperature sensor information
259003831d35Sstevel */
259103831d35Sstevel static int
logprintf_temp_info(picl_nodehdl_t temph)259203831d35Sstevel logprintf_temp_info(picl_nodehdl_t temph)
259303831d35Sstevel {
259403831d35Sstevel int err;
259503831d35Sstevel char *label;
259603831d35Sstevel int64_t temperature;
259703831d35Sstevel int64_t threshold;
259803831d35Sstevel picl_nodehdl_t fruph;
259903831d35Sstevel char *status = "unknown";
260003831d35Sstevel int got_temp = 0;
260103831d35Sstevel
260203831d35Sstevel err = picldiag_get_fru_parent(temph, &fruph);
260303831d35Sstevel if (err != PICL_SUCCESS)
260403831d35Sstevel return (err);
260503831d35Sstevel
260603831d35Sstevel err = picldiag_get_combined_label(fruph, &label, 14);
260703831d35Sstevel if (err != PICL_SUCCESS)
260803831d35Sstevel return (err);
260903831d35Sstevel
261003831d35Sstevel log_printf("%-14s ", label);
261103831d35Sstevel free(label);
261203831d35Sstevel
261303831d35Sstevel err = picldiag_get_label(temph, &label);
261403831d35Sstevel if (err != PICL_SUCCESS)
261503831d35Sstevel return (err);
261603831d35Sstevel log_printf("%-19s ", label);
261703831d35Sstevel free(label);
261803831d35Sstevel
261903831d35Sstevel temperature = picldiag_get_int_propval(temph, PICL_PROP_TEMPERATURE,
262003831d35Sstevel &err);
262103831d35Sstevel if (err == PICL_SUCCESS) {
262203831d35Sstevel got_temp = 1;
262303831d35Sstevel status = "okay";
262403831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
262503831d35Sstevel return (err);
262603831d35Sstevel }
262703831d35Sstevel
262803831d35Sstevel threshold = picldiag_get_int_propval(temph, PICL_PROP_LOW_WARNING,
262903831d35Sstevel &err);
263003831d35Sstevel if (err == PICL_SUCCESS) {
263103831d35Sstevel if (got_temp && temperature < threshold)
263203831d35Sstevel status = "warning";
263303831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
263403831d35Sstevel return (err);
263503831d35Sstevel }
263603831d35Sstevel
263703831d35Sstevel threshold = picldiag_get_int_propval(temph, PICL_PROP_LOW_SHUTDOWN,
263803831d35Sstevel &err);
263903831d35Sstevel if (err == PICL_SUCCESS) {
264003831d35Sstevel if (got_temp && temperature < threshold)
264103831d35Sstevel status = "failed";
264203831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
264303831d35Sstevel return (err);
264403831d35Sstevel }
264503831d35Sstevel
264603831d35Sstevel threshold = picldiag_get_int_propval(temph, PICL_PROP_HIGH_WARNING,
264703831d35Sstevel &err);
264803831d35Sstevel if (err == PICL_SUCCESS) {
264903831d35Sstevel if (got_temp && temperature > threshold)
265003831d35Sstevel status = "warning";
265103831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
265203831d35Sstevel return (err);
265303831d35Sstevel }
265403831d35Sstevel
265503831d35Sstevel threshold = picldiag_get_int_propval(temph, PICL_PROP_HIGH_SHUTDOWN,
265603831d35Sstevel &err);
265703831d35Sstevel if (err == PICL_SUCCESS) {
265803831d35Sstevel if (got_temp && temperature > threshold)
265903831d35Sstevel status = "failed";
266003831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
266103831d35Sstevel return (err);
266203831d35Sstevel }
266303831d35Sstevel
266403831d35Sstevel err = picldiag_get_string_propval(temph, PICL_PROP_CONDITION, &status);
266503831d35Sstevel if (err == PICL_SUCCESS) {
266603831d35Sstevel log_printf("%s", status);
266703831d35Sstevel set_exit_code(status);
266803831d35Sstevel free(status);
266903831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
267003831d35Sstevel return (err);
267103831d35Sstevel } else {
267203831d35Sstevel log_printf("%s ", status);
267303831d35Sstevel set_exit_code(status);
267403831d35Sstevel if (strcmp(status, "failed") == 0 ||
267503831d35Sstevel strcmp(status, "warning") == 0)
267603831d35Sstevel log_printf("(%.2lldC)", temperature);
267703831d35Sstevel }
267803831d35Sstevel
267903831d35Sstevel log_printf("\n");
268003831d35Sstevel return (PICL_SUCCESS);
268103831d35Sstevel }
268203831d35Sstevel
268303831d35Sstevel static int
temp_callback(picl_nodehdl_t temph,void * arg)268403831d35Sstevel temp_callback(picl_nodehdl_t temph, void *arg)
268503831d35Sstevel {
268603831d35Sstevel int err;
268703831d35Sstevel int *countp = arg;
268803831d35Sstevel
268903831d35Sstevel if (*countp == 0) {
269003831d35Sstevel log_printf("\n");
269103831d35Sstevel log_printf(dgettext(TEXT_DOMAIN, "Temperature sensors:\n"));
269203831d35Sstevel log_printf("-----------------------------------------\n");
269303831d35Sstevel log_printf("Location Sensor Status\n");
269403831d35Sstevel log_printf("-----------------------------------------\n");
269503831d35Sstevel }
269603831d35Sstevel *countp += 1;
269703831d35Sstevel err = logprintf_temp_info(temph);
269803831d35Sstevel if (err == PICL_SUCCESS)
269903831d35Sstevel return (PICL_WALK_CONTINUE);
270003831d35Sstevel return (err);
270103831d35Sstevel }
270203831d35Sstevel
270303831d35Sstevel /*
270403831d35Sstevel * callback function search children to find temp sensors and print the temp
270503831d35Sstevel */
270603831d35Sstevel /* ARGSUSED */
270703831d35Sstevel static int
display_temp(picl_nodehdl_t plafh)270803831d35Sstevel display_temp(picl_nodehdl_t plafh)
270903831d35Sstevel {
271003831d35Sstevel int err;
271103831d35Sstevel int print_header;
271203831d35Sstevel
271303831d35Sstevel print_header = 0;
271403831d35Sstevel err = picl_walk_tree_by_class(plafh, PICL_CLASS_TEMPERATURE_SENSOR,
271503831d35Sstevel &print_header, temp_callback);
271603831d35Sstevel if (err != PICL_SUCCESS)
271703831d35Sstevel return (err);
271803831d35Sstevel err = picl_walk_tree_by_class(plafh, PICL_CLASS_TEMPERATURE_INDICATOR,
271903831d35Sstevel &print_header, temp_callback);
272003831d35Sstevel return (err);
272103831d35Sstevel }
272203831d35Sstevel
272303831d35Sstevel /*
272403831d35Sstevel * print current sensor information
272503831d35Sstevel */
272603831d35Sstevel static int
logprintf_current_info(picl_nodehdl_t currenth)272703831d35Sstevel logprintf_current_info(picl_nodehdl_t currenth)
272803831d35Sstevel {
272903831d35Sstevel int err;
273003831d35Sstevel char *label;
273103831d35Sstevel float current;
273203831d35Sstevel float threshold;
273303831d35Sstevel picl_nodehdl_t fruph;
273403831d35Sstevel char *status = "unknown";
273503831d35Sstevel int got_current = 0;
273603831d35Sstevel
273703831d35Sstevel err = picldiag_get_fru_parent(currenth, &fruph);
273803831d35Sstevel if (err != PICL_SUCCESS)
273903831d35Sstevel return (err);
274003831d35Sstevel
274103831d35Sstevel err = picldiag_get_combined_label(fruph, &label, 20);
274203831d35Sstevel if (err != PICL_SUCCESS)
274303831d35Sstevel return (err);
274403831d35Sstevel
274503831d35Sstevel log_printf("%-20s ", label);
274603831d35Sstevel free(label);
274703831d35Sstevel
274803831d35Sstevel err = picldiag_get_label(currenth, &label);
274903831d35Sstevel if (err != PICL_SUCCESS)
275003831d35Sstevel return (err);
275103831d35Sstevel log_printf("%-10s ", label);
275203831d35Sstevel free(label);
275303831d35Sstevel
275403831d35Sstevel current = picldiag_get_float_propval(currenth, PICL_PROP_CURRENT, &err);
275503831d35Sstevel if (err == PICL_SUCCESS) {
275603831d35Sstevel status = "okay";
275703831d35Sstevel got_current = 1;
275803831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
275903831d35Sstevel return (err);
276003831d35Sstevel }
276103831d35Sstevel
276203831d35Sstevel threshold = picldiag_get_float_propval(currenth, PICL_PROP_LOW_WARNING,
276303831d35Sstevel &err);
276403831d35Sstevel if (err == PICL_SUCCESS) {
276503831d35Sstevel if (got_current && current < threshold)
276603831d35Sstevel status = "warning";
276703831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
276803831d35Sstevel return (err);
276903831d35Sstevel }
277003831d35Sstevel
277103831d35Sstevel threshold = picldiag_get_float_propval(currenth, PICL_PROP_LOW_SHUTDOWN,
277203831d35Sstevel &err);
277303831d35Sstevel if (err == PICL_SUCCESS) {
277403831d35Sstevel if (got_current && current < threshold)
277503831d35Sstevel status = "failed";
277603831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
277703831d35Sstevel return (err);
277803831d35Sstevel }
277903831d35Sstevel
278003831d35Sstevel threshold = picldiag_get_float_propval(currenth, PICL_PROP_HIGH_WARNING,
278103831d35Sstevel &err);
278203831d35Sstevel if (err == PICL_SUCCESS) {
278303831d35Sstevel if (got_current && current > threshold)
278403831d35Sstevel status = "warning";
278503831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
278603831d35Sstevel return (err);
278703831d35Sstevel }
278803831d35Sstevel
278903831d35Sstevel threshold = picldiag_get_float_propval(currenth,
279003831d35Sstevel PICL_PROP_HIGH_SHUTDOWN, &err);
279103831d35Sstevel if (err == PICL_SUCCESS) {
279203831d35Sstevel if (got_current && current > threshold)
279303831d35Sstevel status = "failed";
279403831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
279503831d35Sstevel return (err);
279603831d35Sstevel }
279703831d35Sstevel
279803831d35Sstevel err = picldiag_get_string_propval(currenth,
279903831d35Sstevel PICL_PROP_CONDITION, &status);
280003831d35Sstevel if (err == PICL_SUCCESS) {
280103831d35Sstevel log_printf(" %s", status);
280203831d35Sstevel set_exit_code(status);
280303831d35Sstevel free(status);
280403831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
280503831d35Sstevel return (err);
280603831d35Sstevel } else {
280703831d35Sstevel log_printf("%s ", status);
280803831d35Sstevel set_exit_code(status);
280903831d35Sstevel if (strcmp(status, "failed") == 0 ||
281003831d35Sstevel strcmp(status, "warning") == 0)
281103831d35Sstevel log_printf("(%.2fA)", current);
281203831d35Sstevel }
281303831d35Sstevel
281403831d35Sstevel log_printf("\n");
281503831d35Sstevel return (PICL_SUCCESS);
281603831d35Sstevel }
281703831d35Sstevel
281803831d35Sstevel static int
current_callback(picl_nodehdl_t currh,void * arg)281903831d35Sstevel current_callback(picl_nodehdl_t currh, void *arg)
282003831d35Sstevel {
282103831d35Sstevel int err;
282203831d35Sstevel int *countp = arg;
282303831d35Sstevel
282403831d35Sstevel if (*countp == 0) {
282503831d35Sstevel log_printf("------------------------------------\n");
282603831d35Sstevel log_printf(dgettext(TEXT_DOMAIN, "Current sensors:\n"));
282703831d35Sstevel log_printf("----------------------------------------\n");
282803831d35Sstevel log_printf("Location Sensor Status\n");
282903831d35Sstevel log_printf("----------------------------------------\n");
283003831d35Sstevel }
283103831d35Sstevel *countp += 1;
283203831d35Sstevel err = logprintf_current_info(currh);
283303831d35Sstevel if (err == PICL_SUCCESS)
283403831d35Sstevel return (PICL_WALK_CONTINUE);
283503831d35Sstevel return (err);
283603831d35Sstevel }
283703831d35Sstevel
283803831d35Sstevel /*
283903831d35Sstevel * callback function search children to find curr sensors and print the curr
284003831d35Sstevel */
284103831d35Sstevel /* ARGSUSED */
284203831d35Sstevel static int
display_current(picl_nodehdl_t plafh)284303831d35Sstevel display_current(picl_nodehdl_t plafh)
284403831d35Sstevel {
284503831d35Sstevel int err;
284603831d35Sstevel int print_header;
284703831d35Sstevel
284803831d35Sstevel print_header = 0;
284903831d35Sstevel err = picl_walk_tree_by_class(plafh, PICL_CLASS_CURRENT_SENSOR,
285003831d35Sstevel &print_header, current_callback);
285103831d35Sstevel if (err != PICL_SUCCESS)
285203831d35Sstevel return (err);
285303831d35Sstevel err = picl_walk_tree_by_class(plafh, PICL_CLASS_CURRENT_INDICATOR,
285403831d35Sstevel &print_header, current_callback);
285503831d35Sstevel return (err);
285603831d35Sstevel }
285703831d35Sstevel
285803831d35Sstevel /*
285903831d35Sstevel * print voltage sensor information
286003831d35Sstevel */
286103831d35Sstevel static int
logprintf_voltage_info(picl_nodehdl_t voltageh)286203831d35Sstevel logprintf_voltage_info(picl_nodehdl_t voltageh)
286303831d35Sstevel {
286403831d35Sstevel int err;
286503831d35Sstevel char *label;
286603831d35Sstevel float voltage;
286703831d35Sstevel float threshold;
286803831d35Sstevel picl_nodehdl_t fruph;
286903831d35Sstevel char *status = "unknown";
287003831d35Sstevel int got_voltage = 0;
287103831d35Sstevel
287203831d35Sstevel err = picldiag_get_fru_parent(voltageh, &fruph);
287303831d35Sstevel if (err != PICL_SUCCESS)
287403831d35Sstevel return (err);
287503831d35Sstevel
287603831d35Sstevel err = picldiag_get_combined_label(fruph, &label, 14);
287703831d35Sstevel if (err != PICL_SUCCESS)
287803831d35Sstevel return (err);
287903831d35Sstevel
288003831d35Sstevel log_printf("%-14s ", label);
288103831d35Sstevel free(label);
288203831d35Sstevel
288303831d35Sstevel err = picldiag_get_label(voltageh, &label);
288403831d35Sstevel if (err != PICL_SUCCESS)
288503831d35Sstevel return (err);
288603831d35Sstevel log_printf("%-12s ", label);
288703831d35Sstevel free(label);
288803831d35Sstevel
288903831d35Sstevel voltage = picldiag_get_float_propval(voltageh, PICL_PROP_VOLTAGE, &err);
289003831d35Sstevel if (err == PICL_SUCCESS) {
289103831d35Sstevel status = "okay";
289203831d35Sstevel got_voltage = 1;
289303831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
289403831d35Sstevel return (err);
289503831d35Sstevel }
289603831d35Sstevel
289703831d35Sstevel threshold = picldiag_get_float_propval(voltageh, PICL_PROP_LOW_WARNING,
289803831d35Sstevel &err);
289903831d35Sstevel if (err == PICL_SUCCESS) {
290003831d35Sstevel if (got_voltage && voltage < threshold)
290103831d35Sstevel status = "warning";
290203831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
290303831d35Sstevel return (err);
290403831d35Sstevel }
290503831d35Sstevel
290603831d35Sstevel threshold = picldiag_get_float_propval(voltageh, PICL_PROP_LOW_SHUTDOWN,
290703831d35Sstevel &err);
290803831d35Sstevel if (err == PICL_SUCCESS) {
290903831d35Sstevel if (got_voltage && voltage < threshold)
291003831d35Sstevel status = "failed";
291103831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
291203831d35Sstevel return (err);
291303831d35Sstevel }
291403831d35Sstevel
291503831d35Sstevel threshold = picldiag_get_float_propval(voltageh, PICL_PROP_HIGH_WARNING,
291603831d35Sstevel &err);
291703831d35Sstevel if (err == PICL_SUCCESS) {
291803831d35Sstevel if (got_voltage && voltage > threshold)
291903831d35Sstevel status = "warning";
292003831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
292103831d35Sstevel return (err);
292203831d35Sstevel }
292303831d35Sstevel
292403831d35Sstevel threshold = picldiag_get_float_propval(voltageh,
292503831d35Sstevel PICL_PROP_HIGH_SHUTDOWN, &err);
292603831d35Sstevel if (err == PICL_SUCCESS) {
292703831d35Sstevel if (got_voltage && voltage > threshold)
292803831d35Sstevel status = "failed";
292903831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
293003831d35Sstevel return (err);
293103831d35Sstevel }
293203831d35Sstevel
293303831d35Sstevel err = picldiag_get_string_propval(voltageh,
293403831d35Sstevel PICL_PROP_CONDITION, &status);
293503831d35Sstevel if (err == PICL_SUCCESS) {
293603831d35Sstevel log_printf("%s", status);
293703831d35Sstevel set_exit_code(status);
293803831d35Sstevel free(status);
293903831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
294003831d35Sstevel return (err);
294103831d35Sstevel } else {
294203831d35Sstevel log_printf("%s ", status);
294303831d35Sstevel set_exit_code(status);
294403831d35Sstevel if (strcmp(status, "warning") == 0 ||
294503831d35Sstevel strcmp(status, "failed") == 0)
294603831d35Sstevel log_printf("(%.2fV)", voltage);
294703831d35Sstevel }
294803831d35Sstevel
294903831d35Sstevel log_printf("\n");
295003831d35Sstevel return (PICL_SUCCESS);
295103831d35Sstevel }
295203831d35Sstevel
295303831d35Sstevel static int
voltage_callback(picl_nodehdl_t voltageh,void * arg)295403831d35Sstevel voltage_callback(picl_nodehdl_t voltageh, void *arg)
295503831d35Sstevel {
295603831d35Sstevel int *countp = arg;
295703831d35Sstevel int err;
295803831d35Sstevel
295903831d35Sstevel if (*countp == 0) {
296003831d35Sstevel log_printf("------------------------------------\n");
296103831d35Sstevel log_printf(dgettext(TEXT_DOMAIN, "Voltage sensors:\n"));
296203831d35Sstevel log_printf("-----------------------------------\n");
296303831d35Sstevel log_printf("Location Sensor Status\n");
296403831d35Sstevel log_printf("-----------------------------------\n");
296503831d35Sstevel }
296603831d35Sstevel *countp += 1;
296703831d35Sstevel err = logprintf_voltage_info(voltageh);
296803831d35Sstevel if (err == PICL_SUCCESS)
296903831d35Sstevel return (PICL_WALK_CONTINUE);
297003831d35Sstevel return (err);
297103831d35Sstevel }
297203831d35Sstevel
297303831d35Sstevel /*
297403831d35Sstevel * callback function search children to find voltage sensors and print voltage
297503831d35Sstevel */
297603831d35Sstevel /* ARGSUSED */
297703831d35Sstevel static int
display_voltage(picl_nodehdl_t plafh)297803831d35Sstevel display_voltage(picl_nodehdl_t plafh)
297903831d35Sstevel {
298003831d35Sstevel int err;
298103831d35Sstevel int print_header;
298203831d35Sstevel
298303831d35Sstevel print_header = 0;
298403831d35Sstevel err = picl_walk_tree_by_class(plafh, PICL_CLASS_VOLTAGE_SENSOR,
298503831d35Sstevel &print_header, voltage_callback);
298603831d35Sstevel if (err != PICL_SUCCESS)
298703831d35Sstevel return (err);
298803831d35Sstevel err = picl_walk_tree_by_class(plafh, PICL_CLASS_VOLTAGE_INDICATOR,
298903831d35Sstevel &print_header, voltage_callback);
299003831d35Sstevel return (err);
299103831d35Sstevel }
299203831d35Sstevel
299303831d35Sstevel /*
299403831d35Sstevel * print led device information
299503831d35Sstevel */
299603831d35Sstevel static int
logprintf_led_info(picl_nodehdl_t ledh)299703831d35Sstevel logprintf_led_info(picl_nodehdl_t ledh)
299803831d35Sstevel {
299903831d35Sstevel int err;
300003831d35Sstevel char *label;
300103831d35Sstevel char *state;
300203831d35Sstevel char *color;
300303831d35Sstevel picl_nodehdl_t fruph;
300403831d35Sstevel
300503831d35Sstevel err = picldiag_get_fru_parent(ledh, &fruph);
300603831d35Sstevel if (err != PICL_SUCCESS)
300703831d35Sstevel return (err);
300803831d35Sstevel
300903831d35Sstevel err = picldiag_get_combined_label(fruph, &label, 22);
301003831d35Sstevel if (err != PICL_SUCCESS) {
301103831d35Sstevel log_printf(" - ", label);
301203831d35Sstevel } else {
301303831d35Sstevel log_printf("%-22s ", label);
301403831d35Sstevel free(label);
301503831d35Sstevel }
301603831d35Sstevel
301703831d35Sstevel err = picldiag_get_label(ledh, &label);
301803831d35Sstevel if (err != PICL_SUCCESS)
301903831d35Sstevel return (err);
302003831d35Sstevel log_printf("%-20s ", label);
302103831d35Sstevel free(label);
302203831d35Sstevel
302303831d35Sstevel err = picldiag_get_string_propval(ledh, PICL_PROP_STATE, &state);
302403831d35Sstevel if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
302503831d35Sstevel log_printf(" - ");
302603831d35Sstevel } else if (err != PICL_SUCCESS) {
302703831d35Sstevel return (err);
302803831d35Sstevel } else {
302903831d35Sstevel log_printf("%-10s ", state);
303003831d35Sstevel free(state);
303103831d35Sstevel }
303203831d35Sstevel
303303831d35Sstevel err = picldiag_get_string_propval(ledh, PICL_PROP_COLOR, &color);
303403831d35Sstevel if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
303503831d35Sstevel log_printf("\n");
303603831d35Sstevel } else if (err != PICL_SUCCESS) {
303703831d35Sstevel return (err);
303803831d35Sstevel } else {
303903831d35Sstevel log_printf("%-16s\n", color);
304003831d35Sstevel free(color);
304103831d35Sstevel }
304203831d35Sstevel
304303831d35Sstevel return (PICL_SUCCESS);
304403831d35Sstevel }
304503831d35Sstevel
304603831d35Sstevel static int
led_callback(picl_nodehdl_t ledh,void * arg)304703831d35Sstevel led_callback(picl_nodehdl_t ledh, void *arg)
304803831d35Sstevel {
304903831d35Sstevel int *countp = arg;
305003831d35Sstevel int err;
305103831d35Sstevel
305203831d35Sstevel if (*countp == 0) {
305303831d35Sstevel
305403831d35Sstevel log_printf("--------------------------------------"
305503831d35Sstevel "------------\n");
305603831d35Sstevel log_printf(dgettext(TEXT_DOMAIN, "Led State:\n"));
305703831d35Sstevel log_printf("----------------------------------------"
305803831d35Sstevel "----------------------\n");
305903831d35Sstevel log_printf("Location Led State"
306003831d35Sstevel " Color\n");
306103831d35Sstevel log_printf("----------------------------------------"
306203831d35Sstevel "----------------------\n");
306303831d35Sstevel }
306403831d35Sstevel *countp += 1;
306503831d35Sstevel err = logprintf_led_info(ledh);
306603831d35Sstevel if (err == PICL_SUCCESS)
306703831d35Sstevel return (PICL_WALK_CONTINUE);
306803831d35Sstevel return (err);
306903831d35Sstevel }
307003831d35Sstevel
307103831d35Sstevel /*
307203831d35Sstevel * callback function search children to find led devices and print status
307303831d35Sstevel */
307403831d35Sstevel /* ARGSUSED */
307503831d35Sstevel static int
display_led_status(picl_nodehdl_t plafh)307603831d35Sstevel display_led_status(picl_nodehdl_t plafh)
307703831d35Sstevel {
307803831d35Sstevel int print_header;
307903831d35Sstevel
308003831d35Sstevel print_header = 0;
308103831d35Sstevel picl_walk_tree_by_class(plafh, PICL_CLASS_LED,
308203831d35Sstevel &print_header, led_callback);
308303831d35Sstevel return (PICL_SUCCESS);
308403831d35Sstevel }
308503831d35Sstevel
308603831d35Sstevel /*
308703831d35Sstevel * print keyswitch device information
308803831d35Sstevel */
308903831d35Sstevel static int
logprintf_keyswitch_info(picl_nodehdl_t keyswitchh,picl_nodehdl_t fruph)309003831d35Sstevel logprintf_keyswitch_info(picl_nodehdl_t keyswitchh, picl_nodehdl_t fruph)
309103831d35Sstevel {
309203831d35Sstevel int err;
309303831d35Sstevel char *label;
309403831d35Sstevel char *state;
309503831d35Sstevel
309603831d35Sstevel err = picldiag_get_combined_label(fruph, &label, 10);
309703831d35Sstevel if (err != PICL_SUCCESS) {
309803831d35Sstevel log_printf("%-14s", " -");
309903831d35Sstevel } else {
310003831d35Sstevel log_printf("%-14s ", label);
310103831d35Sstevel free(label);
310203831d35Sstevel }
310303831d35Sstevel
310403831d35Sstevel err = picldiag_get_label(keyswitchh, &label);
310503831d35Sstevel if (err != PICL_SUCCESS)
310603831d35Sstevel return (err);
310703831d35Sstevel log_printf("%-11s ", label);
310803831d35Sstevel free(label);
310903831d35Sstevel
311003831d35Sstevel err = picldiag_get_string_propval(keyswitchh, PICL_PROP_STATE, &state);
311103831d35Sstevel if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE) {
311203831d35Sstevel log_printf(" -\n");
311303831d35Sstevel } else if (err != PICL_SUCCESS) {
311403831d35Sstevel return (err);
311503831d35Sstevel } else {
311603831d35Sstevel log_printf("%s\n", state);
311703831d35Sstevel free(state);
311803831d35Sstevel }
311903831d35Sstevel
312003831d35Sstevel return (PICL_SUCCESS);
312103831d35Sstevel }
312203831d35Sstevel
312303831d35Sstevel static int
keyswitch_callback(picl_nodehdl_t keyswitchh,void * arg)312403831d35Sstevel keyswitch_callback(picl_nodehdl_t keyswitchh, void *arg)
312503831d35Sstevel {
312603831d35Sstevel int *countp = arg;
312703831d35Sstevel int err;
312803831d35Sstevel picl_nodehdl_t fruph;
312903831d35Sstevel
313003831d35Sstevel /*
313103831d35Sstevel * Tamale simulates a key-switch on ENxS. So the presence of a
313203831d35Sstevel * node of class keyswitch is not sufficient. If it has a fru parent
313303831d35Sstevel * or location parent, then believe it.
313403831d35Sstevel */
313503831d35Sstevel err = picl_get_propval_by_name(keyswitchh, PICL_REFPROP_FRU_PARENT,
313603831d35Sstevel &fruph, sizeof (fruph));
313703831d35Sstevel if (err == PICL_PROPNOTFOUND) {
313803831d35Sstevel err = picl_get_propval_by_name(keyswitchh,
313903831d35Sstevel PICL_REFPROP_LOC_PARENT, &fruph, sizeof (fruph));
314003831d35Sstevel }
314103831d35Sstevel if (err == PICL_PROPNOTFOUND || err == PICL_PROPVALUNAVAILABLE)
314203831d35Sstevel return (PICL_WALK_CONTINUE);
314303831d35Sstevel if (err != PICL_SUCCESS)
314403831d35Sstevel return (err);
314503831d35Sstevel
314603831d35Sstevel if (*countp == 0) {
314703831d35Sstevel log_printf("-----------------------------------------\n");
314803831d35Sstevel log_printf(dgettext(TEXT_DOMAIN, "Keyswitch:\n"));
314903831d35Sstevel log_printf("-----------------------------------------\n");
315003831d35Sstevel log_printf(dgettext(TEXT_DOMAIN,
315103831d35Sstevel "Location Keyswitch State\n"));
315203831d35Sstevel log_printf("-----------------------------------------\n");
315303831d35Sstevel }
315403831d35Sstevel *countp += 1;
315503831d35Sstevel err = logprintf_keyswitch_info(keyswitchh, fruph);
315603831d35Sstevel if (err == PICL_SUCCESS)
315703831d35Sstevel return (PICL_WALK_CONTINUE);
315803831d35Sstevel return (err);
315903831d35Sstevel }
316003831d35Sstevel
316103831d35Sstevel /*
316203831d35Sstevel * search children to find keyswitch device(s) and print status
316303831d35Sstevel */
316403831d35Sstevel /* ARGSUSED */
316503831d35Sstevel static int
display_keyswitch(picl_nodehdl_t plafh)316603831d35Sstevel display_keyswitch(picl_nodehdl_t plafh)
316703831d35Sstevel {
316803831d35Sstevel int print_header = 0;
316903831d35Sstevel
317003831d35Sstevel picl_walk_tree_by_class(plafh, PICL_CLASS_KEYSWITCH,
317103831d35Sstevel &print_header, keyswitch_callback);
317203831d35Sstevel return (PICL_SUCCESS);
317303831d35Sstevel }
317403831d35Sstevel
317503831d35Sstevel /*
317603831d35Sstevel * display environment status
317703831d35Sstevel */
317803831d35Sstevel static int
display_envctrl_status(picl_nodehdl_t plafh)317903831d35Sstevel display_envctrl_status(picl_nodehdl_t plafh)
318003831d35Sstevel {
318103831d35Sstevel logprintf_header(dgettext(TEXT_DOMAIN, "Environmental Status"),
318203831d35Sstevel DEFAULT_LINE_WIDTH);
318303831d35Sstevel
318403831d35Sstevel display_fan_speed(plafh);
318503831d35Sstevel display_temp(plafh);
318603831d35Sstevel display_current(plafh);
318703831d35Sstevel display_voltage(plafh);
318803831d35Sstevel display_keyswitch(plafh);
318903831d35Sstevel display_led_status(plafh);
319003831d35Sstevel
319103831d35Sstevel return (PICL_SUCCESS);
319203831d35Sstevel }
319303831d35Sstevel
319403831d35Sstevel /*
319503831d35Sstevel * print fru operational status
319603831d35Sstevel */
319703831d35Sstevel static int
logprintf_fru_oper_status(picl_nodehdl_t fruh,int * countp)319803831d35Sstevel logprintf_fru_oper_status(picl_nodehdl_t fruh, int *countp)
319903831d35Sstevel {
320003831d35Sstevel int err;
320103831d35Sstevel char *label;
320203831d35Sstevel char *status;
320303831d35Sstevel
320403831d35Sstevel err = picldiag_get_combined_label(fruh, &label, 23);
320503831d35Sstevel if (err != PICL_SUCCESS)
320603831d35Sstevel return (PICL_WALK_CONTINUE);
320703831d35Sstevel
320803831d35Sstevel err = picldiag_get_string_propval(fruh,
320903831d35Sstevel PICL_PROP_OPERATIONAL_STATUS, &status);
321003831d35Sstevel if (err == PICL_SUCCESS) {
321103831d35Sstevel if (*countp == 0) {
321203831d35Sstevel logprintf_header(dgettext(TEXT_DOMAIN,
321303831d35Sstevel "FRU Operational Status"),
321403831d35Sstevel DEFAULT_LINE_WIDTH);
321503831d35Sstevel log_printf("---------------------------------\n");
321603831d35Sstevel log_printf(dgettext(TEXT_DOMAIN,
321703831d35Sstevel "Fru Operational Status:\n"));
321803831d35Sstevel log_printf("---------------------------------\n");
321903831d35Sstevel log_printf("Location Status\n");
322003831d35Sstevel log_printf("---------------------------------\n");
322103831d35Sstevel }
322203831d35Sstevel *countp += 1;
322303831d35Sstevel log_printf("%-23s ", label);
322403831d35Sstevel free(label);
322503831d35Sstevel log_printf("%s\n", status);
322603831d35Sstevel set_exit_code(status);
322703831d35Sstevel free(status);
322803831d35Sstevel } else if (err != PICL_PROPNOTFOUND && err != PICL_PROPVALUNAVAILABLE) {
322903831d35Sstevel free(label);
323003831d35Sstevel return (err);
323103831d35Sstevel } else {
323203831d35Sstevel free(label);
323303831d35Sstevel }
323403831d35Sstevel return (PICL_WALK_CONTINUE);
323503831d35Sstevel }
323603831d35Sstevel
323703831d35Sstevel static int
fru_oper_status_callback(picl_nodehdl_t fruh,void * arg)323803831d35Sstevel fru_oper_status_callback(picl_nodehdl_t fruh, void *arg)
323903831d35Sstevel {
324003831d35Sstevel int err;
324103831d35Sstevel
324203831d35Sstevel err = logprintf_fru_oper_status(fruh, (int *)arg);
324303831d35Sstevel return (err);
324403831d35Sstevel }
324503831d35Sstevel
324603831d35Sstevel /*
324703831d35Sstevel * display fru operational status
324803831d35Sstevel */
324903831d35Sstevel static int
display_fru_oper_status(picl_nodehdl_t frutreeh)325003831d35Sstevel display_fru_oper_status(picl_nodehdl_t frutreeh)
325103831d35Sstevel {
325203831d35Sstevel int print_header;
325303831d35Sstevel
325403831d35Sstevel print_header = 0;
325503831d35Sstevel picl_walk_tree_by_class(frutreeh, PICL_CLASS_FRU,
325603831d35Sstevel &print_header, fru_oper_status_callback);
325703831d35Sstevel return (PICL_SUCCESS);
325803831d35Sstevel }
325903831d35Sstevel
326003831d35Sstevel /*
326103831d35Sstevel * check if the node having the version prop
326203831d35Sstevel * If yes, print its nodename and version
326303831d35Sstevel */
326403831d35Sstevel /* ARGSUSED */
326503831d35Sstevel static int
asicrev_callback(picl_nodehdl_t nodeh,void * arg)326603831d35Sstevel asicrev_callback(picl_nodehdl_t nodeh, void *arg)
326703831d35Sstevel {
326803831d35Sstevel uint32_t version;
326903831d35Sstevel char *name;
327003831d35Sstevel char *model;
327103831d35Sstevel char *status;
327203831d35Sstevel int err;
327303831d35Sstevel
327403831d35Sstevel /*
3275d0e72dffSvenki * Fire based platforms use "fire-revision#" or "module-revision#"
3276d0e72dffSvenki * (depending on post/pre Fire 2.0) instead of "version#", so we
3277d0e72dffSvenki * need to check for these if we don't find "version#"
327803831d35Sstevel */
327903831d35Sstevel version = picldiag_get_uint_propval(nodeh, OBP_PROP_VERSION_NUM, &err);
328003831d35Sstevel if (err == PICL_PROPNOTFOUND) {
3281d0e72dffSvenki version = picldiag_get_uint_propval(nodeh, OBP_PROP_FIREREV_NUM,
328203831d35Sstevel &err);
3283d0e72dffSvenki if (err == PICL_PROPNOTFOUND) {
3284d0e72dffSvenki version = picldiag_get_uint_propval(nodeh,
3285d0e72dffSvenki OBP_PROP_MODREV_NUM, &err);
3286d0e72dffSvenki if (err == PICL_PROPNOTFOUND)
3287d0e72dffSvenki return (PICL_WALK_CONTINUE);
3288d0e72dffSvenki }
328903831d35Sstevel }
329003831d35Sstevel if (err != PICL_SUCCESS)
329103831d35Sstevel return (err);
329203831d35Sstevel
329303831d35Sstevel /* devfs-path */
329403831d35Sstevel err = picldiag_get_string_propval(nodeh, PICL_PROP_DEVFS_PATH, &name);
329503831d35Sstevel if (err == PICL_PROPNOTFOUND)
329603831d35Sstevel name = NULL;
329703831d35Sstevel else if (err != PICL_SUCCESS)
329803831d35Sstevel return (err);
329903831d35Sstevel
330003831d35Sstevel /* model */
330103831d35Sstevel err = picldiag_get_string_propval(nodeh, PICL_PROP_BINDING_NAME,
330203831d35Sstevel &model);
330303831d35Sstevel if (err == PICL_PROPNOTFOUND)
330403831d35Sstevel model = NULL;
330503831d35Sstevel else if (err != PICL_SUCCESS)
330603831d35Sstevel return (err);
330703831d35Sstevel
330803831d35Sstevel /* status */
330903831d35Sstevel err = picldiag_get_string_propval(nodeh, PICL_PROP_STATUS, &status);
331003831d35Sstevel if (err == PICL_PROPNOTFOUND)
331103831d35Sstevel status = NULL;
331203831d35Sstevel else if (err != PICL_SUCCESS)
331303831d35Sstevel return (err);
331403831d35Sstevel
331503831d35Sstevel /*
331603831d35Sstevel * Display the data
331703831d35Sstevel */
331803831d35Sstevel
331903831d35Sstevel /* name */
332003831d35Sstevel if (name != NULL) {
332103831d35Sstevel log_printf("%-22s ", name);
332203831d35Sstevel free(name);
332303831d35Sstevel } else
332403831d35Sstevel log_printf("%-22s ", "unknown");
332503831d35Sstevel /* model */
332603831d35Sstevel if (model != NULL) {
332703831d35Sstevel log_printf("%-15s ", model);
332803831d35Sstevel free(model);
332903831d35Sstevel } else
333003831d35Sstevel log_printf("%-15s ", "unknown");
333103831d35Sstevel /* status */
333203831d35Sstevel if (status == NULL)
333303831d35Sstevel log_printf("%-15s ", "okay");
333403831d35Sstevel else {
333503831d35Sstevel log_printf("%-15s ", status);
333603831d35Sstevel set_exit_code(status);
333703831d35Sstevel free(status);
333803831d35Sstevel }
333903831d35Sstevel /* revision */
334003831d35Sstevel log_printf(" %-4d\n", version);
334103831d35Sstevel
334203831d35Sstevel return (PICL_WALK_CONTINUE);
334303831d35Sstevel }
334403831d35Sstevel
334503831d35Sstevel /*
334603831d35Sstevel * traverse the tree to display asic revision id for ebus
334703831d35Sstevel */
334803831d35Sstevel /* ARGSUSED */
334903831d35Sstevel static int
ebus_callback(picl_nodehdl_t ebush,void * arg)335003831d35Sstevel ebus_callback(picl_nodehdl_t ebush, void *arg)
335103831d35Sstevel {
335203831d35Sstevel uint32_t id;
335303831d35Sstevel char *name;
335403831d35Sstevel int err;
335503831d35Sstevel char *model;
335603831d35Sstevel char *status;
335703831d35Sstevel
335803831d35Sstevel id = picldiag_get_uint_propval(ebush, OBP_PROP_REVISION_ID, &err);
335903831d35Sstevel if (err == PICL_PROPNOTFOUND)
336003831d35Sstevel return (PICL_WALK_CONTINUE);
336103831d35Sstevel else if (err != PICL_SUCCESS)
336203831d35Sstevel return (err);
336303831d35Sstevel
336403831d35Sstevel /* devfs-path */
336503831d35Sstevel err = picldiag_get_string_propval(ebush, PICL_PROP_DEVFS_PATH, &name);
336603831d35Sstevel if (err == PICL_PROPNOTFOUND)
336703831d35Sstevel name = NULL;
336803831d35Sstevel else if (err != PICL_SUCCESS)
336903831d35Sstevel return (err);
337003831d35Sstevel
337103831d35Sstevel /* model */
337203831d35Sstevel err = picldiag_get_string_propval(ebush, PICL_PROP_BINDING_NAME,
337303831d35Sstevel &model);
337403831d35Sstevel if (err == PICL_PROPNOTFOUND)
337503831d35Sstevel model = NULL;
337603831d35Sstevel else if (err != PICL_SUCCESS)
337703831d35Sstevel return (err);
337803831d35Sstevel
337903831d35Sstevel /* status */
338003831d35Sstevel err = picldiag_get_string_propval(ebush, PICL_PROP_STATUS, &status);
338103831d35Sstevel if (err == PICL_PROPNOTFOUND)
338203831d35Sstevel status = NULL;
338303831d35Sstevel else if (err != PICL_SUCCESS)
338403831d35Sstevel return (err);
338503831d35Sstevel
338603831d35Sstevel /*
338703831d35Sstevel * Display the data
338803831d35Sstevel */
338903831d35Sstevel
339003831d35Sstevel /* name */
339103831d35Sstevel if (name != NULL) {
339203831d35Sstevel log_printf("%-22s ", name);
339303831d35Sstevel free(name);
339403831d35Sstevel } else
339503831d35Sstevel log_printf("%-22s ", "unknown");
339603831d35Sstevel /* model */
339703831d35Sstevel if (model != NULL) {
339803831d35Sstevel log_printf("%-15s ", model);
339903831d35Sstevel free(model);
340003831d35Sstevel } else
340103831d35Sstevel log_printf("%-15s ", "unknown");
340203831d35Sstevel /* status */
340303831d35Sstevel if (status == NULL)
340403831d35Sstevel log_printf("%-15s ", "okay");
340503831d35Sstevel else {
340603831d35Sstevel log_printf("%-15s ", status);
340703831d35Sstevel set_exit_code(status);
340803831d35Sstevel free(status);
340903831d35Sstevel }
341003831d35Sstevel /* revision */
341103831d35Sstevel log_printf(" %-4d\n", id);
341203831d35Sstevel
341303831d35Sstevel return (PICL_WALK_CONTINUE);
341403831d35Sstevel }
341503831d35Sstevel
341603831d35Sstevel /*
341703831d35Sstevel * display asic revision id
341803831d35Sstevel */
341903831d35Sstevel static int
display_hw_revisions(picl_nodehdl_t plafh)342003831d35Sstevel display_hw_revisions(picl_nodehdl_t plafh)
342103831d35Sstevel {
342203831d35Sstevel int err;
342303831d35Sstevel
342403831d35Sstevel /* Print the header */
342503831d35Sstevel logprintf_header(dgettext(TEXT_DOMAIN, "HW Revisions"),
342603831d35Sstevel DEFAULT_LINE_WIDTH);
342703831d35Sstevel
342803831d35Sstevel log_printf("ASIC Revisions:\n");
342903831d35Sstevel log_printf("-----------------------------");
343003831d35Sstevel log_printf("--------------------------------------\n");
343103831d35Sstevel log_printf("Path Device");
343203831d35Sstevel log_printf(" Status Revision\n");
343303831d35Sstevel log_printf("-----------------------------");
343403831d35Sstevel log_printf("--------------------------------------\n");
343503831d35Sstevel
343603831d35Sstevel err = picl_walk_tree_by_class(plafh, NULL, NULL, asicrev_callback);
343703831d35Sstevel if (err != PICL_SUCCESS)
343803831d35Sstevel return (err);
343903831d35Sstevel
344003831d35Sstevel err = picl_walk_tree_by_class(plafh, PICL_CLASS_EBUS,
344103831d35Sstevel NULL, ebus_callback);
344203831d35Sstevel if (err != PICL_SUCCESS)
344303831d35Sstevel return (err);
344403831d35Sstevel
344503831d35Sstevel log_printf("\n");
344603831d35Sstevel
344703831d35Sstevel err = picl_walk_tree_by_class(plafh, PICL_CLASS_DISPLAY,
344803831d35Sstevel NULL, ffbconfig_callback);
344903831d35Sstevel return (err);
345003831d35Sstevel }
345103831d35Sstevel
345203831d35Sstevel /*
345303831d35Sstevel * find the options node and its powerfail_time prop
345403831d35Sstevel * If found, display the list of latest powerfail.
345503831d35Sstevel */
345603831d35Sstevel /* ARGSUSED */
345703831d35Sstevel static int
options_callback(picl_nodehdl_t nodeh,void * arg)345803831d35Sstevel options_callback(picl_nodehdl_t nodeh, void *arg)
345903831d35Sstevel {
346003831d35Sstevel time_t value;
346103831d35Sstevel char *failtime;
346203831d35Sstevel int err;
346303831d35Sstevel
346403831d35Sstevel err = picldiag_get_string_propval(nodeh, PROP_POWERFAIL_TIME,
346503831d35Sstevel &failtime);
346603831d35Sstevel if (err == PICL_PROPNOTFOUND)
346703831d35Sstevel return (PICL_WALK_TERMINATE);
346803831d35Sstevel else if (err != PICL_SUCCESS)
346903831d35Sstevel return (err);
347003831d35Sstevel
347103831d35Sstevel value = (time_t)atoi(failtime);
347203831d35Sstevel free(failtime);
347303831d35Sstevel if (value == 0)
347403831d35Sstevel return (PICL_WALK_TERMINATE);
347503831d35Sstevel
347603831d35Sstevel log_printf(dgettext(TEXT_DOMAIN, "Most recent AC Power Failure:\n"));
347703831d35Sstevel log_printf("=============================\n");
347803831d35Sstevel log_printf("%s", ctime(&value));
347903831d35Sstevel log_printf("\n");
348003831d35Sstevel return (PICL_WALK_TERMINATE);
348103831d35Sstevel }
348203831d35Sstevel
348303831d35Sstevel /*
348403831d35Sstevel * display the OBP and POST prom revisions
348503831d35Sstevel */
348603831d35Sstevel /* ARGSUSED */
348703831d35Sstevel static int
flashprom_callback(picl_nodehdl_t flashpromh,void * arg)348803831d35Sstevel flashprom_callback(picl_nodehdl_t flashpromh, void *arg)
348903831d35Sstevel {
349003831d35Sstevel picl_prophdl_t proph;
349103831d35Sstevel picl_prophdl_t tblh;
349203831d35Sstevel picl_prophdl_t rowproph;
349303831d35Sstevel picl_propinfo_t pinfo;
349403831d35Sstevel char *prom_version = NULL;
349503831d35Sstevel char *obp_version = NULL;
349603831d35Sstevel int err;
349703831d35Sstevel
349803831d35Sstevel err = picl_get_propinfo_by_name(flashpromh, OBP_PROP_VERSION,
349903831d35Sstevel &pinfo, &proph);
350003831d35Sstevel if (err == PICL_PROPNOTFOUND)
350103831d35Sstevel return (PICL_WALK_TERMINATE);
350203831d35Sstevel else if (err != PICL_SUCCESS)
350303831d35Sstevel return (err);
350403831d35Sstevel
350503831d35Sstevel log_printf(dgettext(TEXT_DOMAIN, "System PROM revisions:\n"));
350603831d35Sstevel log_printf("----------------------\n");
350703831d35Sstevel
350803831d35Sstevel /*
350903831d35Sstevel * If it's a table prop, the first element is OBP revision
351003831d35Sstevel * The second one is POST revision.
351103831d35Sstevel * If it's a charstring prop, the value will be only OBP revision
351203831d35Sstevel */
351303831d35Sstevel if (pinfo.type == PICL_PTYPE_CHARSTRING) {
351403831d35Sstevel prom_version = alloca(pinfo.size);
351503831d35Sstevel if (prom_version == NULL)
351603831d35Sstevel return (PICL_FAILURE);
351703831d35Sstevel err = picl_get_propval(proph, prom_version, pinfo.size);
351803831d35Sstevel if (err != PICL_SUCCESS)
351903831d35Sstevel return (err);
352003831d35Sstevel log_printf("%s\n", prom_version);
352103831d35Sstevel }
352203831d35Sstevel
352303831d35Sstevel if (pinfo.type != PICL_PTYPE_TABLE) /* not supported type */
352403831d35Sstevel return (PICL_WALK_TERMINATE);
352503831d35Sstevel
352603831d35Sstevel err = picl_get_propval(proph, &tblh, pinfo.size);
352703831d35Sstevel if (err != PICL_SUCCESS)
352803831d35Sstevel return (err);
352903831d35Sstevel
353003831d35Sstevel err = picl_get_next_by_row(tblh, &rowproph);
353103831d35Sstevel if (err == PICL_SUCCESS) {
353203831d35Sstevel /* get first row */
353303831d35Sstevel err = picl_get_propinfo(rowproph, &pinfo);
353403831d35Sstevel if (err != PICL_SUCCESS)
3535*2983dda7SMichael Bergknoff return (err);
353603831d35Sstevel
353703831d35Sstevel prom_version = alloca(pinfo.size);
353803831d35Sstevel if (prom_version == NULL)
353903831d35Sstevel return (PICL_FAILURE);
354003831d35Sstevel
354103831d35Sstevel err = picl_get_propval(rowproph, prom_version, pinfo.size);
354203831d35Sstevel if (err != PICL_SUCCESS)
354303831d35Sstevel return (err);
354403831d35Sstevel log_printf("%s\n", prom_version);
354503831d35Sstevel
354603831d35Sstevel /* get second row */
354703831d35Sstevel err = picl_get_next_by_col(rowproph, &rowproph);
354803831d35Sstevel if (err == PICL_SUCCESS) {
354903831d35Sstevel err = picl_get_propinfo(rowproph, &pinfo);
355003831d35Sstevel if (err != PICL_SUCCESS)
355103831d35Sstevel return (err);
355203831d35Sstevel
355303831d35Sstevel obp_version = alloca(pinfo.size);
355403831d35Sstevel if (obp_version == NULL)
355503831d35Sstevel return (PICL_FAILURE);
355603831d35Sstevel err = picl_get_propval(rowproph, obp_version,
355703831d35Sstevel pinfo.size);
355803831d35Sstevel if (err != PICL_SUCCESS)
355903831d35Sstevel return (err);
356003831d35Sstevel log_printf("%s\n", obp_version);
356103831d35Sstevel }
356203831d35Sstevel }
356303831d35Sstevel
356403831d35Sstevel return (PICL_WALK_TERMINATE);
356503831d35Sstevel }
356603831d35Sstevel
356703831d35Sstevel static int
display_system_info(int serrlog,int log_flag,picl_nodehdl_t rooth)356803831d35Sstevel display_system_info(int serrlog, int log_flag, picl_nodehdl_t rooth)
356903831d35Sstevel {
357003831d35Sstevel int err;
357103831d35Sstevel picl_nodehdl_t plafh;
357203831d35Sstevel picl_nodehdl_t frutreeh;
357303831d35Sstevel
357403831d35Sstevel err = picldiag_get_node_by_name(rooth, PICL_NODE_PLATFORM, &plafh);
357503831d35Sstevel if (err != PICL_SUCCESS)
357603831d35Sstevel return (err);
357703831d35Sstevel
357803831d35Sstevel if (!log_flag) {
357903831d35Sstevel err = display_platform_banner(plafh);
358003831d35Sstevel if (err != PICL_SUCCESS)
358103831d35Sstevel return (err);
358203831d35Sstevel
358303831d35Sstevel err = display_system_clock(plafh);
358403831d35Sstevel if (err != PICL_SUCCESS)
358503831d35Sstevel return (err);
358603831d35Sstevel
358703831d35Sstevel err = picl_walk_tree_by_class(plafh, PICL_CLASS_MEMORY,
358803831d35Sstevel PICL_CLASS_MEMORY, memory_callback);
358903831d35Sstevel if (err != PICL_SUCCESS)
359003831d35Sstevel return (err);
359103831d35Sstevel
359203831d35Sstevel err = display_cpu_info(plafh);
359303831d35Sstevel if (err != PICL_SUCCESS)
359403831d35Sstevel return (err);
359503831d35Sstevel
359603831d35Sstevel err = display_io_device_info(plafh);
359703831d35Sstevel if (err != PICL_SUCCESS)
359803831d35Sstevel return (err);
359903831d35Sstevel
360003831d35Sstevel err = display_memory_config(plafh);
360103831d35Sstevel if (err != PICL_SUCCESS)
360203831d35Sstevel return (err);
360303831d35Sstevel
360403831d35Sstevel err = display_usb_devices(plafh);
360503831d35Sstevel if (err != PICL_SUCCESS)
360603831d35Sstevel return (err);
360703831d35Sstevel }
360803831d35Sstevel
360903831d35Sstevel if (serrlog) {
361003831d35Sstevel err = picl_walk_tree_by_class(rooth, PICL_CLASS_OPTIONS,
361103831d35Sstevel NULL, options_callback);
361203831d35Sstevel if (err != PICL_SUCCESS)
361303831d35Sstevel return (err);
361403831d35Sstevel
361503831d35Sstevel err = display_envctrl_status(plafh);
361603831d35Sstevel if (err != PICL_SUCCESS)
361703831d35Sstevel return (err);
361803831d35Sstevel
361903831d35Sstevel err = picldiag_get_node_by_name(rooth, PICL_NODE_FRUTREE,
362003831d35Sstevel &frutreeh);
362103831d35Sstevel if (err != PICL_SUCCESS)
362203831d35Sstevel return (err);
362303831d35Sstevel
362403831d35Sstevel err = display_fru_oper_status(frutreeh);
362503831d35Sstevel if (err != PICL_SUCCESS)
362603831d35Sstevel return (err);
362703831d35Sstevel
362803831d35Sstevel err = display_hw_revisions(plafh);
362903831d35Sstevel if (err != PICL_SUCCESS)
363003831d35Sstevel return (err);
363103831d35Sstevel
363203831d35Sstevel err = picl_walk_tree_by_class(plafh, PICL_CLASS_FLASHPROM,
363303831d35Sstevel NULL, flashprom_callback);
363403831d35Sstevel if (err != PICL_SUCCESS)
363503831d35Sstevel return (err);
363603831d35Sstevel
363703831d35Sstevel err = display_serial_number(plafh);
363803831d35Sstevel if ((err != PICL_SUCCESS) && (err != PICL_PROPNOTFOUND))
363903831d35Sstevel return (err);
364003831d35Sstevel }
364103831d35Sstevel
364203831d35Sstevel return (PICL_SUCCESS);
364303831d35Sstevel }
364403831d35Sstevel
364503831d35Sstevel /*
364603831d35Sstevel * do_prominfo is called from main in prtdiag. It returns PD_SYSTEM_FAILURE if
364703831d35Sstevel * any system failure is detected, PD_INTERNAL_FAILURE for internal errors and
364803831d35Sstevel * PD_SUCCESS otherwise. main uses the return value as the exit code.
364903831d35Sstevel */
365003831d35Sstevel /* ARGSUSED */
365103831d35Sstevel int
do_prominfo(int serrlog,char * pgname,int log_flag,int prt_flag)365203831d35Sstevel do_prominfo(int serrlog, char *pgname, int log_flag, int prt_flag)
365303831d35Sstevel {
365403831d35Sstevel int err;
365503831d35Sstevel char *errstr;
365603831d35Sstevel int done;
365703831d35Sstevel picl_nodehdl_t rooth;
365803831d35Sstevel
365903831d35Sstevel err = picl_initialize();
366003831d35Sstevel if (err != PICL_SUCCESS) {
366103831d35Sstevel fprintf(stderr, EM_INIT_FAIL, picl_strerror(err));
366203831d35Sstevel return (PD_INTERNAL_FAILURE);
366303831d35Sstevel }
366403831d35Sstevel
366503831d35Sstevel do {
366603831d35Sstevel done = 1;
366703831d35Sstevel err = picl_get_root(&rooth);
366803831d35Sstevel if (err != PICL_SUCCESS) {
366903831d35Sstevel fprintf(stderr, EM_GET_ROOT_FAIL, picl_strerror(err));
367003831d35Sstevel return (PD_INTERNAL_FAILURE);
367103831d35Sstevel }
367203831d35Sstevel
367303831d35Sstevel err = display_system_info(serrlog, log_flag, rooth);
367403831d35Sstevel
367503831d35Sstevel if ((err == PICL_STALEHANDLE) || (err == PICL_INVALIDHANDLE))
367603831d35Sstevel done = 0;
367703831d35Sstevel } while (!done);
367803831d35Sstevel
367903831d35Sstevel if (err != PICL_SUCCESS) {
368003831d35Sstevel errstr = picl_strerror(err);
368103831d35Sstevel fprintf(stderr, EM_PRTDIAG_FAIL);
368203831d35Sstevel fprintf(stderr, "%s\n", errstr? errstr : " ");
368303831d35Sstevel exit_code = PD_INTERNAL_FAILURE;
368403831d35Sstevel }
368503831d35Sstevel
368603831d35Sstevel (void) picl_shutdown();
368703831d35Sstevel
368803831d35Sstevel return (exit_code);
368903831d35Sstevel }
3690