xref: /onnv-gate/usr/src/lib/libprtdiag_psr/sparc/opl/common/opl_picl.c (revision 11285:0fa6a178fb93)
13418Ssubhan /*
23418Ssubhan  * CDDL HEADER START
33418Ssubhan  *
43418Ssubhan  * The contents of this file are subject to the terms of the
53418Ssubhan  * Common Development and Distribution License (the "License").
63418Ssubhan  * You may not use this file except in compliance with the License.
73418Ssubhan  *
83418Ssubhan  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93418Ssubhan  * or http://www.opensolaris.org/os/licensing.
103418Ssubhan  * See the License for the specific language governing permissions
113418Ssubhan  * and limitations under the License.
123418Ssubhan  *
133418Ssubhan  * When distributing Covered Code, include this CDDL HEADER in each
143418Ssubhan  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153418Ssubhan  * If applicable, add the following below this CDDL HEADER, with the
163418Ssubhan  * fields enclosed by brackets "[]" replaced with your own identifying
173418Ssubhan  * information: Portions Copyright [yyyy] [name of copyright owner]
183418Ssubhan  *
193418Ssubhan  * CDDL HEADER END
203418Ssubhan  */
213418Ssubhan /*
22*11285SMichael.Bergknoff@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
233418Ssubhan  * Use is subject to license terms.
243418Ssubhan  *
253418Ssubhan  * Opl platform specific PICL functions.
263418Ssubhan  *
273418Ssubhan  * 	called when :
283418Ssubhan  *	machine_type == MTYPE_OPL
293418Ssubhan  */
303418Ssubhan 
313418Ssubhan #include <stdio.h>
323418Ssubhan #include <stdlib.h>
333418Ssubhan #include <unistd.h>
343418Ssubhan #include <kstat.h>
353418Ssubhan #include <fcntl.h>
363418Ssubhan #include <string.h>
373418Ssubhan #include <assert.h>
383418Ssubhan #include <libintl.h>
393418Ssubhan #include <note.h>
403418Ssubhan #include <dlfcn.h>
413418Ssubhan #include <errno.h>
423418Ssubhan #include <sys/systeminfo.h>
433418Ssubhan #include <sys/openpromio.h>
443418Ssubhan #include <sys/sysmacros.h>
453418Ssubhan #include <picl.h>
463418Ssubhan #include "picldefs.h"
473418Ssubhan #include <pdevinfo.h>
483418Ssubhan #include <display.h>
493418Ssubhan #include <libprtdiag.h>
503418Ssubhan #include <alloca.h>
513418Ssubhan #include "opl_picl.h"
523418Ssubhan #include <sys/pci.h>
533418Ssubhan #include <sys/pci_tools.h>
543418Ssubhan #include <sys/types.h>
553418Ssubhan 
563418Ssubhan #if !defined(TEXT_DOMAIN)
573418Ssubhan #define	TEXT_DOMAIN	"SYS_TEST"
583418Ssubhan #endif
593418Ssubhan 
603418Ssubhan static picl_errno_t do_walk(picl_nodehdl_t rooth, const char *classname,
613418Ssubhan     void *c_args, picl_errno_t (*callback_fn)(picl_nodehdl_t hdl, void *args));
623418Ssubhan static int opl_get_node_by_name(picl_nodehdl_t rooth, char *name,
633418Ssubhan     picl_nodehdl_t *nodeh);
643418Ssubhan static picl_errno_t get_lane_width(char *device_path, int bus_no, int func_no,
653418Ssubhan     int dev_no, int *actual, int *maximum, uint32_t *speed_max,
663418Ssubhan     uint32_t *speed_at, int *type);
673418Ssubhan static int	opl_display_pci(int syserrlog, picl_nodehdl_t plafh);
683418Ssubhan static picl_errno_t opl_pci_callback(picl_nodehdl_t pcih, void *args);
693418Ssubhan static int opl_get_first_compatible_value(picl_nodehdl_t nodeh,
703418Ssubhan     char **outbuf);
713418Ssubhan static int picldiag_get_clock_freq(picl_nodehdl_t modh,
72*11285SMichael.Bergknoff@Sun.COM     uint32_t *freq, uint32_t *freq_max);
733418Ssubhan static uint64_t picldiag_get_uint_propval(picl_nodehdl_t modh,
743418Ssubhan     char *prop_name, int *ret);
753418Ssubhan static uint32_t	read_long(int fd, int bus, int dev, int func,
763418Ssubhan     int offset, int *ret);
773418Ssubhan static uint8_t read_byte(int fd, int bus, int dev, int func, int offset,
783418Ssubhan     int *ret);
793418Ssubhan static uint16_t read_word(int fd, int bus, int dev, int func, int offset,
803418Ssubhan     int *ret);
813418Ssubhan 
823418Ssubhan /*
833418Ssubhan  * Collect I/O nodes information.
843418Ssubhan  */
853418Ssubhan /* ARGSUSED */
863418Ssubhan static picl_errno_t
opl_pci_callback(picl_nodehdl_t pcih,void * args)873418Ssubhan opl_pci_callback(picl_nodehdl_t pcih, void *args)
883418Ssubhan {
893418Ssubhan 	picl_errno_t	err = PICL_SUCCESS;
903418Ssubhan 	picl_nodehdl_t	nodeh;
913418Ssubhan 	picl_prophdl_t  proph;
923418Ssubhan 	picl_propinfo_t pinfo;
933418Ssubhan 	char		path[MAXSTRLEN];
943418Ssubhan 	char		parent_path[MAXSTRLEN];
953418Ssubhan 	static char	root_path[MAXSTRLEN];
963418Ssubhan 	char		piclclass[PICL_CLASSNAMELEN_MAX];
973418Ssubhan 	char		name[MAXSTRLEN];
983418Ssubhan 	char		model[MAXSTRLEN];
993418Ssubhan 	char		*compatible;
1003418Ssubhan 	char		binding_name[MAXSTRLEN];
1013418Ssubhan 	struct io_card	pci_card;
1023418Ssubhan 	char		status[6] = "N/A";
1033418Ssubhan 	int		portid = PROP_INVALID;
1043418Ssubhan 	int		*reg_val;
1053418Ssubhan 	int		board = PROP_INVALID;
1063418Ssubhan 	static int	saved_board = PROP_INVALID;
1073418Ssubhan 	static int	saved_portid = PROP_INVALID;
1083418Ssubhan 	int 		actual = PROP_INVALID, maximum = PROP_INVALID;
1093418Ssubhan 	int 		bus_type;
1103418Ssubhan 	int 		rev_id = PROP_INVALID, dev_id = PROP_INVALID;
1113418Ssubhan 	int		ven_id = PROP_INVALID;
1123418Ssubhan 	size_t		prop_size;
1133418Ssubhan 
1143418Ssubhan 	(void) memset(&pci_card, 0, sizeof (pci_card));
1153418Ssubhan 
1163418Ssubhan 	err = picl_get_propval_by_name(pcih, PICL_PROP_CLASSNAME,
1174397Sschwartz 	    piclclass, sizeof (piclclass));
1183418Ssubhan 
1193418Ssubhan 	if (err !=  PICL_SUCCESS)
1203418Ssubhan 		/* Do not proceed to parse this branch */
1213418Ssubhan 		return (err);
1223418Ssubhan 
1233418Ssubhan 	if (!IS_PCI(piclclass))
1243418Ssubhan 		/* Do not parse non-pci nodes */
1253418Ssubhan 		return (PICL_INVALIDARG);
1263418Ssubhan 
1273418Ssubhan 	err = picl_get_propval_by_name(pcih, PICL_PROP_DEVFS_PATH, parent_path,
1283418Ssubhan 	    sizeof (parent_path));
1293418Ssubhan 	if (err != PICL_SUCCESS)
1303418Ssubhan 		/* Do not proceed to parse this branch */
1313418Ssubhan 		return (err);
1323418Ssubhan 	err = picl_get_propval_by_name(pcih, OBP_PROP_BOARD_NUM, &board,
1334397Sschwartz 	    sizeof (board));
1343418Ssubhan 
1353418Ssubhan 	if (err == PICL_NORESPONSE)
1363418Ssubhan 		/* Do not proceed to parse this branch */
1373418Ssubhan 		return (err);
1383418Ssubhan 	else if (err != PICL_PROPNOTFOUND) {
1393418Ssubhan 		saved_board = board;
1403418Ssubhan 		/* Save board node's pathname */
1413418Ssubhan 		prop_size = sizeof (parent_path) + 1;
1423418Ssubhan 		if (prop_size > MAXSTRLEN)
1433418Ssubhan 			prop_size = MAXSTRLEN;
1443418Ssubhan 		(void) strlcpy(root_path, parent_path, prop_size);
1453418Ssubhan 	}
1463418Ssubhan 
1473418Ssubhan 	err = picl_get_propval_by_name
1484397Sschwartz 	    (pcih, OBP_PROP_PORTID, &portid, sizeof (portid));
1493418Ssubhan 
1503418Ssubhan 	if (err != PICL_PROPNOTFOUND)
1513418Ssubhan 		saved_portid = portid;
1523418Ssubhan 
1533418Ssubhan 	/* Walk through the children */
1543418Ssubhan 
1553418Ssubhan 	err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
1563418Ssubhan 	    sizeof (picl_nodehdl_t));
1573418Ssubhan 
1583418Ssubhan 	while (err == PICL_SUCCESS) {
1593418Ssubhan 		uint32_t	freq_max = 0, freq_at = 0;
1603418Ssubhan 
1613418Ssubhan 		err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
1623418Ssubhan 		    piclclass, sizeof (piclclass));
1633418Ssubhan 		if (err !=  PICL_SUCCESS)
1643418Ssubhan 			/* Do not proceed to parse this node */
1653418Ssubhan 			return (err);
1663418Ssubhan 
1673418Ssubhan 		if (IS_EBUS(piclclass)) {
1683418Ssubhan 			err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
1694397Sschwartz 			    &nodeh, sizeof (picl_nodehdl_t));
1703418Ssubhan 			continue;
1713418Ssubhan 		}
1723418Ssubhan 
1733418Ssubhan 		err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH,
1743418Ssubhan 		    path, sizeof (path));
1753418Ssubhan 		if (err != PICL_SUCCESS) {
1763418Ssubhan 			/* Do not proceed to parse this node */
1773418Ssubhan 			return (err);
1783418Ssubhan 		}
1793418Ssubhan 
1803418Ssubhan 		prop_size = sizeof (path) + 1;
1813418Ssubhan 		if (prop_size > MAXSTRLEN)
1823418Ssubhan 			prop_size = MAXSTRLEN;
1833418Ssubhan 		(void) strlcpy(pci_card.notes, path, prop_size);
1843418Ssubhan 
1853418Ssubhan 		pci_card.board = saved_board;
1863418Ssubhan 		pci_card.schizo_portid = saved_portid;
1873418Ssubhan 
1883418Ssubhan 		/*
1893418Ssubhan 		 * Get bus#, dev# and func# for this card from 'reg' property.
1903418Ssubhan 		 */
1913418Ssubhan 
1923418Ssubhan 		err = picl_get_propinfo_by_name
1934397Sschwartz 		    (nodeh, OBP_PROP_REG, &pinfo, &proph);
1943418Ssubhan 		if (err == PICL_SUCCESS) {
1953418Ssubhan 			/* All of the array of bytes of "reg" have to be read */
1963418Ssubhan 			reg_val = malloc(pinfo.size);
1973418Ssubhan 			if (reg_val == NULL)
1983418Ssubhan 				return (PICL_FAILURE);
1993418Ssubhan 
2003418Ssubhan 
2013418Ssubhan 			err = picl_get_propval_by_name
2023418Ssubhan 			    (nodeh, OBP_PROP_REG, reg_val, pinfo.size);
2033418Ssubhan 
2043418Ssubhan 			if (err != PICL_SUCCESS) {
2053418Ssubhan 				free(reg_val);
2063418Ssubhan 				/* Do not proceed to parse this node */
2073418Ssubhan 				return (err);
2083418Ssubhan 			}
2093418Ssubhan 
2103418Ssubhan 			if (reg_val[0] != 0) {
2113418Ssubhan 				pci_card.dev_no =
2124397Sschwartz 				    (((reg_val[0]) & PCI_DEV_MASK) >> 11);
2133418Ssubhan 				pci_card.func_no =
2144397Sschwartz 				    (((reg_val[0]) & PCI_FUNC_MASK) >> 8);
2153418Ssubhan 				pci_card.slot =
2164397Sschwartz 				    (((reg_val[0]) & PCI_BUS_MASK) >> 16);
2173418Ssubhan 			} else
2183418Ssubhan 				free(reg_val);
2193418Ssubhan 		}
2203418Ssubhan 
2214397Sschwartz 		err = get_lane_width(root_path, pci_card.slot, pci_card.dev_no,
2224397Sschwartz 		    pci_card.func_no, &actual, &maximum, &freq_max, &freq_at,
2234397Sschwartz 		    &bus_type);
2243418Ssubhan 
2253418Ssubhan 		if (err != PICL_SUCCESS) {
2266344Smb158278 			/*
2276344Smb158278 			 * get_lane_width will fail when run as non-root.
2286344Smb158278 			 * Set bus_type to PCI_UNKN so that bus frequency,
2296344Smb158278 			 * bus type and lane width will print as "--" or UNKN.
2306344Smb158278 			 */
2316344Smb158278 			bus_type = PCI_UNKN;
2323418Ssubhan 		}
2333418Ssubhan 
2343418Ssubhan 
2353418Ssubhan 		err = picl_get_propval_by_name
2363418Ssubhan 		    (nodeh, PICL_PROP_NAME, name, sizeof (name));
2373418Ssubhan 		if (err != PICL_SUCCESS)
2383418Ssubhan 			(void) strcpy(name, "");
2393418Ssubhan 
2403418Ssubhan 		/*
2413418Ssubhan 		 * Get the name of this card. If binding_name is found,
2423418Ssubhan 		 * name will be <nodename>-<binding_name>
2433418Ssubhan 		 */
2443418Ssubhan 
2453418Ssubhan 		err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME,
2463418Ssubhan 		    binding_name, sizeof (binding_name));
2473418Ssubhan 		if (err == PICL_PROPNOTFOUND) {
2483418Ssubhan 			/*
2493418Ssubhan 			 * if compatible prop is found, name will be
2503418Ssubhan 			 * <nodename>-<compatible>
2513418Ssubhan 			 */
2523418Ssubhan 			err = opl_get_first_compatible_value(nodeh,
2533418Ssubhan 			    &compatible);
2543418Ssubhan 			if (err == PICL_SUCCESS) {
2553418Ssubhan 				(void) strlcat(name, "-", MAXSTRLEN);
2563418Ssubhan 				(void) strlcat(name, compatible, MAXSTRLEN);
2573418Ssubhan 				free(compatible);
2583418Ssubhan 			}
2593418Ssubhan 		} else if (err != PICL_SUCCESS) {
2603418Ssubhan 			/* No binding-name or compatible */
2613418Ssubhan 			(void) strcpy(binding_name, "N/A");
2623418Ssubhan 		} else if (strcmp(name, binding_name) != 0) {
2633418Ssubhan 			(void) strlcat(name, "-", MAXSTRLEN);
2643418Ssubhan 			(void) strlcat(name, binding_name, MAXSTRLEN);
2653418Ssubhan 		}
2663418Ssubhan 
2673418Ssubhan 
2683418Ssubhan 		prop_size = sizeof (name) + 1;
2693418Ssubhan 		if (prop_size > MAXSTRLEN)
2703418Ssubhan 			prop_size =  MAXSTRLEN;
2713418Ssubhan 		(void) strlcpy(pci_card.name, name, prop_size);
2723418Ssubhan 
2733418Ssubhan 		/* Get the status of the card */
2743418Ssubhan 		err = picl_get_propval_by_name
2753418Ssubhan 		    (nodeh, PICL_PROP_STATUS, status, sizeof (status));
2763418Ssubhan 
2773418Ssubhan 
2783418Ssubhan 		/* Get the model of this card */
2793418Ssubhan 
2803418Ssubhan 		err = picl_get_propval_by_name
2813418Ssubhan 		    (nodeh, OBP_PROP_MODEL, model, sizeof (model));
2823418Ssubhan 		prop_size = sizeof (model) + 1;
2833418Ssubhan 		if (prop_size > MAXSTRLEN)
2843418Ssubhan 			prop_size =  MAXSTRLEN;
2853418Ssubhan 		if (err != PICL_SUCCESS)
2863418Ssubhan 			(void) strcpy(model, "N/A");
2873418Ssubhan 		(void) strlcpy(pci_card.model, model, prop_size);
2883418Ssubhan 
2893418Ssubhan 		if (bus_type == PCI)
2904397Sschwartz 			(void) strlcpy(pci_card.bus_type,
2914397Sschwartz 			    "PCI", sizeof (pci_card.bus_type));
2923418Ssubhan 		else if (bus_type == PCIX)
2934397Sschwartz 			(void) strlcpy(pci_card.bus_type,
2944397Sschwartz 			    "PCIx", sizeof (pci_card.bus_type));
2953418Ssubhan 		else if (bus_type == PCIE)
2964397Sschwartz 			(void) strlcpy(pci_card.bus_type,
2974397Sschwartz 			    "PCIe", sizeof (pci_card.bus_type));
2983418Ssubhan 		else
2994397Sschwartz 			(void) strlcpy(pci_card.bus_type,
3004397Sschwartz 			    "UNKN", sizeof (pci_card.bus_type));
3013418Ssubhan 
3023418Ssubhan 		/* Get revision id */
3033418Ssubhan 		err = picl_get_propval_by_name
3044397Sschwartz 		    (nodeh, OBP_PROP_REVISION_ID, &rev_id, sizeof (rev_id));
3053418Ssubhan 
3063418Ssubhan 		/* Get device id */
3073418Ssubhan 		err = picl_get_propval_by_name
3084397Sschwartz 		    (nodeh, OBP_PROP_DEVICE_ID, &dev_id, sizeof (dev_id));
3093418Ssubhan 
3103418Ssubhan 		/* Get vendor id */
3113418Ssubhan 		err = picl_get_propval_by_name
3124397Sschwartz 		    (nodeh, OBP_PROP_VENDOR_ID, &ven_id, sizeof (ven_id));
3133418Ssubhan 
3143418Ssubhan 		/*
3153418Ssubhan 		 * prtdiag -v prints all devices
3163418Ssubhan 		 */
3173418Ssubhan 
3183418Ssubhan 		/* Print board number */
3193418Ssubhan 		log_printf("%02d  ", pci_card.board);
3203418Ssubhan 		/* Print IO Type */
3213418Ssubhan 		log_printf("%-5.5s ", pci_card.bus_type);
3223418Ssubhan 
3233418Ssubhan 		log_printf("%-3d  ", pci_card.schizo_portid);
3243418Ssubhan 		log_printf("%4x, %4x, %4x     ", rev_id, dev_id, ven_id);
3253418Ssubhan 
3264397Sschwartz 		log_printf("%3d, %2d, %2d",
3274397Sschwartz 		    pci_card.slot, pci_card.dev_no, pci_card.func_no);
3283418Ssubhan 
3293418Ssubhan 		/* Print status */
3303418Ssubhan 		log_printf("  %-5.5s ", status);
3313418Ssubhan 
3323418Ssubhan 		/* Print Lane widths, Max/Sup Freq, Speed */
3333418Ssubhan 		if (bus_type == PCIE) {
3343418Ssubhan 			PRINT_FMT(actual, maximum);
3353418Ssubhan 		} else if (bus_type == PCIX) {
3363418Ssubhan 			PRINT_FREQ_FMT(freq_at, freq_max);
3373418Ssubhan 		} else if (bus_type == PCI) {
338*11285SMichael.Bergknoff@Sun.COM 			err = picldiag_get_clock_freq(nodeh, &freq_at,
339*11285SMichael.Bergknoff@Sun.COM 			    &freq_max);
3403418Ssubhan 			PRINT_FREQ_FMT(freq_at, freq_max);
3413418Ssubhan 		} else
3423418Ssubhan 			log_printf(" -- , --   ");
3433418Ssubhan 
3443418Ssubhan 		/* Print Card Name */
3453418Ssubhan 		log_printf("%-30.30s", pci_card.name);
3463418Ssubhan 
3473418Ssubhan 		/* Print Card Model */
3483418Ssubhan 		log_printf(" %-20.20s", pci_card.model);
3493418Ssubhan 
3503418Ssubhan 		log_printf("\n");
3513418Ssubhan 
3523418Ssubhan 		log_printf("%4s%-100.100s", " ", pci_card.notes);
3533418Ssubhan 		log_printf("\n");
3543418Ssubhan 		log_printf("\n");
3553418Ssubhan 
3563418Ssubhan 
3573418Ssubhan 		err = picl_get_propval_by_name
3583418Ssubhan 		    (nodeh, PICL_PROP_PEER, &nodeh, sizeof (picl_nodehdl_t));
3593418Ssubhan 
3603418Ssubhan 	}
3613418Ssubhan 
3623418Ssubhan 	return (PICL_WALK_CONTINUE);
3633418Ssubhan }
3643418Ssubhan 
3653418Ssubhan /*
3663418Ssubhan  * opl_display_pci
3673418Ssubhan  * Display all the PCI IO cards on this board.
3683418Ssubhan  */
3693418Ssubhan static int
opl_display_pci(int syserrlog,picl_nodehdl_t plafh)3703418Ssubhan opl_display_pci(int syserrlog, picl_nodehdl_t plafh)
3713418Ssubhan {
3723418Ssubhan 	picl_errno_t err;
3733418Ssubhan 	char	*fmt = "%-3s %-5s %-4s %-20s %-11s %-5s %-11s %-30s %-20s";
3743418Ssubhan 	char 	*fmt2 = "%-16s";
3753418Ssubhan 	static int banner = FALSE; /* Have we printed the column headings? */
3763418Ssubhan 
3773418Ssubhan 	if (banner == FALSE) {
3783418Ssubhan 		log_printf("\n", 0);
3793418Ssubhan 		log_printf("=========================", 0);
3803418Ssubhan 		log_printf(dgettext(TEXT_DOMAIN, " IO Devices "), 0);
3813418Ssubhan 		log_printf("=========================", 0);
3823418Ssubhan 		log_printf("\n", 0);
3833418Ssubhan 		log_printf("\n", 0);
3843418Ssubhan 		log_printf(fmt, "", "IO", "", "", "", "", "Lane/Frq",
3854397Sschwartz 		    "", "", 0);
3863418Ssubhan 		log_printf("\n", 0);
3873418Ssubhan 
3883418Ssubhan 		log_printf(fmt, "LSB", "Type", "LPID", "  RvID,DvID,VnID",
3894397Sschwartz 		    "  BDF", "State", "Act,  Max", "Name", "Model", 0);
3903418Ssubhan 
3913418Ssubhan 		log_printf("\n");
3923418Ssubhan 
3934397Sschwartz 		log_printf(fmt,
3944397Sschwartz 		    "---", "-----", "----", "  ------------------",
3954397Sschwartz 		    "  ---------", "-----", "-----------",
3964397Sschwartz 		    "------------------------------",
3974397Sschwartz 		    "--------------------", 0);
3983418Ssubhan 		log_printf("\n");
3993418Ssubhan 		log_printf(fmt2, "    Logical Path");
4003418Ssubhan 		log_printf("\n");
4013418Ssubhan 		log_printf(fmt2, "    ------------");
4023418Ssubhan 		log_printf("\n");
4033418Ssubhan 		banner = TRUE;
4043418Ssubhan 	}
4053418Ssubhan 
4063418Ssubhan 	err = do_walk(plafh, PICL_CLASS_PCI, PICL_CLASS_PCI, opl_pci_callback);
4073418Ssubhan 	return (err);
4083418Ssubhan }
4093418Ssubhan 
4103418Ssubhan 
4113418Ssubhan /*
4123418Ssubhan  * return the first compatible value
4133418Ssubhan  */
4143418Ssubhan static int
opl_get_first_compatible_value(picl_nodehdl_t nodeh,char ** outbuf)4153418Ssubhan opl_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf)
4163418Ssubhan {
4173418Ssubhan 	picl_errno_t	err;
4183418Ssubhan 	picl_prophdl_t	proph;
4193418Ssubhan 	picl_propinfo_t	pinfo;
4203418Ssubhan 	picl_prophdl_t	tblh;
4213418Ssubhan 	picl_prophdl_t	rowproph;
4223418Ssubhan 	char		*pval;
4233418Ssubhan 
4243418Ssubhan 	err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE,
4253418Ssubhan 	    &pinfo, &proph);
4263418Ssubhan 	if (err != PICL_SUCCESS)
4274397Sschwartz 		return (err);
4283418Ssubhan 
4293418Ssubhan 	if (pinfo.type == PICL_PTYPE_CHARSTRING) {
4303418Ssubhan 		pval = malloc(pinfo.size);
4313418Ssubhan 		if (pval == NULL)
4323418Ssubhan 			return (PICL_FAILURE);
4333418Ssubhan 		err = picl_get_propval(proph, pval, pinfo.size);
4343418Ssubhan 		if (err != PICL_SUCCESS) {
4353418Ssubhan 			free(pval);
4363418Ssubhan 			return (err);
4373418Ssubhan 		}
4383418Ssubhan 		*outbuf = pval;
4393418Ssubhan 		return (PICL_SUCCESS);
4403418Ssubhan 	}
4413418Ssubhan 
4423418Ssubhan 	if (pinfo.type != PICL_PTYPE_TABLE)
4433418Ssubhan 		return (PICL_FAILURE);
4443418Ssubhan 
4453418Ssubhan 	/* get first string from table */
4463418Ssubhan 	err = picl_get_propval(proph, &tblh, pinfo.size);
4473418Ssubhan 	if (err != PICL_SUCCESS)
4483418Ssubhan 		return (err);
4493418Ssubhan 
4503418Ssubhan 	err = picl_get_next_by_row(tblh, &rowproph);
4513418Ssubhan 	if (err != PICL_SUCCESS)
4523418Ssubhan 		return (err);
4533418Ssubhan 
4543418Ssubhan 	err = picl_get_propinfo(rowproph, &pinfo);
4553418Ssubhan 	if (err != PICL_SUCCESS)
4564397Sschwartz 		return (err);
4573418Ssubhan 
4583418Ssubhan 	pval = malloc(pinfo.size);
4593418Ssubhan 	if (pval == NULL)
4603418Ssubhan 		return (PICL_FAILURE);
4613418Ssubhan 
4623418Ssubhan 	err = picl_get_propval(rowproph, pval, pinfo.size);
4633418Ssubhan 	if (err != PICL_SUCCESS) {
4643418Ssubhan 		free(pval);
4653418Ssubhan 		return (err);
4663418Ssubhan 	}
4673418Ssubhan 
4683418Ssubhan 	*outbuf = pval;
4693418Ssubhan 	return (PICL_SUCCESS);
4703418Ssubhan }
4713418Ssubhan 
4723418Ssubhan int
do_piclinfo(int syserrlog)4733418Ssubhan do_piclinfo(int syserrlog)
4743418Ssubhan {
4753418Ssubhan 	picl_nodehdl_t rooth;		/* root PICL node for IO display */
4763418Ssubhan 	picl_nodehdl_t plafh;		/* Platform PICL node for IO display */
4773418Ssubhan 
4783418Ssubhan 	picl_errno_t err;
4793418Ssubhan 
4803418Ssubhan 	err = picl_initialize();
4813418Ssubhan 	if (err != PICL_SUCCESS) {
4823418Ssubhan 		(void) log_printf("picl_initialize failed: %s\n",
4834397Sschwartz 		    picl_strerror(err));
4843418Ssubhan 		return (err);
4853418Ssubhan 	}
4863418Ssubhan 
4873418Ssubhan 
4883418Ssubhan 	err = picl_get_root(&rooth);
4893418Ssubhan 	if (err != PICL_SUCCESS) {
4903418Ssubhan 		(void) log_printf("Getting root node failed: %s\n",
4914397Sschwartz 		    picl_strerror(err));
4923418Ssubhan 		return (err);
4933418Ssubhan 	}
4943418Ssubhan 
4953418Ssubhan 	err = opl_get_node_by_name(rooth, PICL_NODE_PLATFORM, &plafh);
4963418Ssubhan 
4973418Ssubhan 	if (err != PICL_SUCCESS) {
4983418Ssubhan 		(void) log_printf("Getting nodes by name failed: %s\n",
4994397Sschwartz 		    picl_strerror(err));
5003418Ssubhan 		return (err);
5013418Ssubhan 	}
5023418Ssubhan 
5033418Ssubhan 	err = opl_display_pci(syserrlog, plafh);
5043418Ssubhan 
5053418Ssubhan 	(void) picl_shutdown();
5063418Ssubhan 
5073418Ssubhan 	return (err);
5083418Ssubhan }
5093418Ssubhan 
5103418Ssubhan /*
5113418Ssubhan  * search children to get the node by the nodename
5123418Ssubhan  */
5133418Ssubhan static int
opl_get_node_by_name(picl_nodehdl_t rooth,char * name,picl_nodehdl_t * nodeh)5143418Ssubhan opl_get_node_by_name(picl_nodehdl_t rooth, char *name,
5153418Ssubhan     picl_nodehdl_t *nodeh)
5163418Ssubhan {
5173418Ssubhan 	picl_nodehdl_t	childh;
5183418Ssubhan 	int		err;
5193418Ssubhan 	char		*nodename;
5203418Ssubhan 
5213418Ssubhan 	nodename = alloca(strlen(name) + 1);
5223418Ssubhan 	if (nodename == NULL)
5233418Ssubhan 		return (PICL_FAILURE);
5243418Ssubhan 
5253418Ssubhan 	err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &childh,
5264397Sschwartz 	    sizeof (picl_nodehdl_t));
5273418Ssubhan 
5283418Ssubhan 	while (err == PICL_SUCCESS) {
5293418Ssubhan 		err = picl_get_propval_by_name(childh, PICL_PROP_NAME,
5304397Sschwartz 		    nodename, (strlen(name) + 1));
5313418Ssubhan 		if (err != PICL_SUCCESS) {
5323418Ssubhan 			err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
5334397Sschwartz 			    &childh, sizeof (picl_nodehdl_t));
5343418Ssubhan 			continue;
5353418Ssubhan 		}
5363418Ssubhan 
5373418Ssubhan 		if (strcmp(nodename, name) == 0) {
5383418Ssubhan 			*nodeh = childh;
5393418Ssubhan 			return (PICL_SUCCESS);
5403418Ssubhan 		}
5413418Ssubhan 
5423418Ssubhan 		err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
5434397Sschwartz 		    &childh, sizeof (picl_nodehdl_t));
5443418Ssubhan 	}
5453418Ssubhan 
5463418Ssubhan 	return (err);
5473418Ssubhan }
5483418Ssubhan 
5493418Ssubhan static int
open_root_complex(char * root_complex)5503418Ssubhan open_root_complex(char *root_complex)
5513418Ssubhan {
5523418Ssubhan 	char *path;
5533418Ssubhan 	static char device_str[] = {"/devices"};
5543418Ssubhan 	static char devctl_str[] = {":reg"};
5553418Ssubhan 	int fd;
5563418Ssubhan 
5573418Ssubhan 	path = malloc(
5583418Ssubhan 	    strlen(root_complex) + sizeof (device_str) + sizeof (devctl_str));
5593418Ssubhan 	if (path == NULL)
5603418Ssubhan 		return (PICL_FAILURE);
5613418Ssubhan 	(void) strcpy(path, device_str);
5623418Ssubhan 	(void) strcat(path, root_complex);
5633418Ssubhan 	(void) strcat(path, devctl_str);
5643418Ssubhan 
5653418Ssubhan 	if ((fd = open(path, O_RDWR)) == -1) {
5663418Ssubhan 		return (-1);
5673418Ssubhan 	}
5683418Ssubhan 	return (fd);
5693418Ssubhan }
5703418Ssubhan 
5713418Ssubhan static uint32_t
read_long(int fd,int bus,int dev,int func,int offset,int * ret)5723418Ssubhan read_long(int fd, int bus, int dev, int func, int offset, int *ret)
5733418Ssubhan {
5743418Ssubhan 	int rval;
5753418Ssubhan 	pcitool_reg_t prg;
5763418Ssubhan 
5774397Sschwartz 	prg.user_version = PCITOOL_VERSION;
5783418Ssubhan 	prg.barnum = 0;
5793418Ssubhan 	prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 +
5803418Ssubhan 	    PCITOOL_ACC_ATTR_ENDN_LTL;
5813418Ssubhan 	prg.bus_no = bus;
5823418Ssubhan 	prg.dev_no = dev;
5833418Ssubhan 	prg.func_no = func;
5843418Ssubhan 	prg.offset = offset;
5853418Ssubhan 	rval = ioctl(fd, PCITOOL_DEVICE_GET_REG, &prg);
5863418Ssubhan 	if (rval != 0) {
5874397Sschwartz 		log_printf("DEV_GET failed %d %s\n", rval, strerror(errno));
5884397Sschwartz 		log_printf("%d.%d.%d offset 0x%x\n", bus, dev, func, offset);
5893418Ssubhan 	}
5903418Ssubhan 	*ret = rval;
5913418Ssubhan 	return ((uint32_t)prg.data);
5923418Ssubhan }
5933418Ssubhan 
5943418Ssubhan static uint16_t
read_word(int fd,int bus,int dev,int func,int offset,int * ret)5953418Ssubhan read_word(int fd, int bus, int dev, int func, int offset, int *ret)
5963418Ssubhan {
5973418Ssubhan 	int rval;
5983418Ssubhan 	pcitool_reg_t prg;
5993418Ssubhan 
6004397Sschwartz 	prg.user_version = PCITOOL_VERSION;
6013418Ssubhan 	prg.barnum = 0;
6023418Ssubhan 	prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_2 +
6033418Ssubhan 	    PCITOOL_ACC_ATTR_ENDN_LTL;
6043418Ssubhan 	prg.bus_no = bus;
6053418Ssubhan 	prg.dev_no = dev;
6063418Ssubhan 	prg.func_no = func;
6073418Ssubhan 	prg.offset = offset;
6083418Ssubhan 	rval = ioctl(fd, PCITOOL_DEVICE_GET_REG, &prg);
6093418Ssubhan 	if (rval != 0) {
6104397Sschwartz 		log_printf("DEV_GET failed %d %s\n", rval, strerror(errno));
6114397Sschwartz 		log_printf("%d.%d.%d offset 0x%x\n", bus, dev, func, offset);
6123418Ssubhan 	}
6133418Ssubhan 	*ret = rval;
6143418Ssubhan 	return ((uint16_t)prg.data);
6153418Ssubhan }
6163418Ssubhan 
6173418Ssubhan static uint8_t
read_byte(int fd,int bus,int dev,int func,int offset,int * ret)6183418Ssubhan read_byte(int fd, int bus, int dev, int func, int offset, int *ret)
6193418Ssubhan {
6203418Ssubhan 	int rval;
6213418Ssubhan 	pcitool_reg_t prg;
6223418Ssubhan 
6234397Sschwartz 	prg.user_version = PCITOOL_VERSION;
6243418Ssubhan 	prg.barnum = 0;
6253418Ssubhan 	prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_1 +
6263418Ssubhan 	    PCITOOL_ACC_ATTR_ENDN_LTL;
6273418Ssubhan 	prg.bus_no = bus;
6283418Ssubhan 	prg.dev_no = dev;
6293418Ssubhan 	prg.func_no = func;
6303418Ssubhan 	prg.offset = offset;
6313418Ssubhan 	rval = ioctl(fd, PCITOOL_DEVICE_GET_REG, &prg);
6323418Ssubhan 	if (rval != 0) {
6334397Sschwartz 		log_printf("DEV_GET failed %d %s\n", rval, strerror(errno));
6344397Sschwartz 		log_printf("%d.%d.%d offset 0x%x\n", bus, dev, func, offset);
6353418Ssubhan 	}
6363418Ssubhan 	*ret = rval;
6373418Ssubhan 	return ((uint8_t)prg.data);
6383418Ssubhan }
6393418Ssubhan 
6403418Ssubhan 
6413418Ssubhan static picl_errno_t
get_lane_width(char * device_path,int bus,int dev,int func,int * actual,int * maximum,uint32_t * speed_max,uint32_t * speed_at,int * type)6423418Ssubhan get_lane_width
6433418Ssubhan 	(char *device_path, int bus, int dev, int func, int *actual,
6443418Ssubhan 	int *maximum, uint32_t *speed_max, uint32_t *speed_at, int *type)
6453418Ssubhan {
6463418Ssubhan 	uint_t cap_ptr, cap_reg, link_status, link_cap, capid;
6473418Ssubhan 	int fd, ret;
6483418Ssubhan 
6493418Ssubhan 	if (device_path == NULL)
6503418Ssubhan 		return (PICL_FAILURE);
6513418Ssubhan 
6523418Ssubhan 	fd = open_root_complex(device_path);
6533418Ssubhan 	if (fd == -1)
6543418Ssubhan 		return (PICL_FAILURE);
6553418Ssubhan 
6563418Ssubhan 	/*
6573418Ssubhan 	 * Link Capabilities and Link Status registers are in the
6583418Ssubhan 	 * PCI-E capabilities register.  They are at offset
6593418Ssubhan 	 * 0xc and 0x12 respectively. They are documented in section
6603418Ssubhan 	 * 7.8 of the PCI Express Base Specification. The address of
6613418Ssubhan 	 * that structure is not fixed, it's kind of a linked list.
6623418Ssubhan 	 * The Capabilities Pointer reg (8 bits) is always at 0x34.
6633418Ssubhan 	 * It contains a pointer to the first capabilities structure.
6643418Ssubhan 	 * For each capability structure, the first 8 bits is the capability
6653418Ssubhan 	 * ID. The next 8 bits is the pointer to the next structure.
6663418Ssubhan 	 * If the Next Cap register is zero, it's the end of the list.
6673418Ssubhan 	 * The capability ID for the PCI-E strucutre is 0x10.  The idea
6683418Ssubhan 	 * is to follow the links until you find a Cap ID of 0x10, then
6693418Ssubhan 	 * read the registers at 0xc and 0x12 from there.
6703418Ssubhan 	 * If there's no Cap ID 0x10, then it's not a PCI-E device.
6713418Ssubhan 	 */
6723418Ssubhan 
6733418Ssubhan 	cap_ptr = read_byte(fd, bus, dev, func, PCI_CONF_CAP_PTR, &ret);
6743418Ssubhan 	if (ret != 0) {
6753418Ssubhan 		/* ioctl failure */
6765511Sanbui 		close(fd);
6773418Ssubhan 		return (PICL_FAILURE);
6783418Ssubhan 	}
6793418Ssubhan 	cap_reg = read_word(fd, bus, dev, func, cap_ptr, &ret);
6803418Ssubhan 	if (ret != 0) {
6813418Ssubhan 		/* ioctl failure */
6825511Sanbui 		close(fd);
6833418Ssubhan 		return (PICL_FAILURE);
6843418Ssubhan 	}
6856848Smb158278 	*type = PCI;
6863418Ssubhan 	capid = cap_reg & PCI_CAP_MASK;
6873418Ssubhan 	while (cap_ptr != 0) {
6883418Ssubhan 
6893418Ssubhan 		if (capid == PCI_CAP_ID_PCI_E) {
6903418Ssubhan 			link_cap = read_long(fd, bus, dev, func, cap_ptr +
6913418Ssubhan 			    PCIE_LINKCAP, &ret);
6923418Ssubhan 			if (ret != 0) {
6935511Sanbui 				close(fd);
6943418Ssubhan 				return (PICL_FAILURE);
6953418Ssubhan 			}
6964397Sschwartz 			link_status = read_word(fd, bus, dev, func,
6974397Sschwartz 			    cap_ptr + PCIE_LINKSTS, &ret);
6983418Ssubhan 			if (ret != 0) {
6995511Sanbui 				close(fd);
7003418Ssubhan 				return (PICL_FAILURE);
7013418Ssubhan 			}
7023418Ssubhan 			*actual = ((link_status >> PCI_LINK_SHIFT) &
7034397Sschwartz 			    PCI_LINK_MASK);
7043418Ssubhan 			*maximum = ((link_cap >> PCI_LINK_SHIFT) &
7054397Sschwartz 			    PCI_LINK_MASK);
7063418Ssubhan 			*type = PCIE;
7076848Smb158278 		} else if (capid == PCI_CAP_ID_PCIX) {
7083418Ssubhan 			uint32_t pcix_status;
7093418Ssubhan 			uint8_t hdr_type;
7103418Ssubhan 			int max_speed = PCI_FREQ_66;
7113418Ssubhan 
7123418Ssubhan 			hdr_type = read_byte
7134397Sschwartz 			    (fd, bus, dev, func, PCI_CONF_HEADER, &ret);
7143418Ssubhan 			if (ret != 0) {
7153418Ssubhan 				/* ioctl failure */
7165511Sanbui 				close(fd);
7173418Ssubhan 				return (PICL_FAILURE);
7183418Ssubhan 			}
7196848Smb158278 			*type = PCIX;
7203418Ssubhan 			if ((hdr_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
7213418Ssubhan 				/* This is a PCI-X bridge */
7223418Ssubhan 				uint16_t sec_status, mode;
7233418Ssubhan 				sec_status = read_word(fd, bus, dev, func,
7244397Sschwartz 				    cap_ptr + PCI_PCIX_SEC_STATUS, &ret);
7253418Ssubhan 				if (ret != 0) {
7263418Ssubhan 					/* ioctl failure */
7275511Sanbui 					close(fd);
7283418Ssubhan 					return (PICL_FAILURE);
7293418Ssubhan 				}
7303418Ssubhan 				if (sec_status & PCI_SEC_133)
7313418Ssubhan 					max_speed = PCI_FREQ_133;
7323418Ssubhan 				if (sec_status & PCI_SEC_266)
7333418Ssubhan 					max_speed = PCI_FREQ_266;
7343418Ssubhan 				if (sec_status & PCI_SEC_533)
7353418Ssubhan 					max_speed = PCI_FREQ_533;
7363418Ssubhan 				*speed_max = max_speed;
7374397Sschwartz 				mode = (sec_status >> PCI_CLASS_BRIDGE) &
7384397Sschwartz 				    PCI_BRIDGE_MC;
7393418Ssubhan 				if (mode) {
7403418Ssubhan 					int speed;
7413418Ssubhan 					if (mode == PCI_MODE_66)
7423418Ssubhan 						speed = PCI_FREQ_66;
7433418Ssubhan 					else if (mode == PCI_MODE_100)
7443418Ssubhan 						speed = PCI_FREQ_100;
7453418Ssubhan 					else if (mode == PCI_MODE_133)
7463418Ssubhan 						speed = PCI_FREQ_133;
7473418Ssubhan 					*speed_at = speed;
7483418Ssubhan 				}
7493418Ssubhan 
7503418Ssubhan 			} else {  /* Leaf device */
7513418Ssubhan 				pcix_status = read_long(fd, bus, dev, func,
7523418Ssubhan 				    cap_ptr + PCI_PCIX_STATUS, &ret);
7533418Ssubhan 				if (ret != 0) {
7543418Ssubhan 					/* ioctl failure */
7555511Sanbui 					close(fd);
7563418Ssubhan 					return (PICL_FAILURE);
7573418Ssubhan 				}
7583418Ssubhan 				if (pcix_status &
7594397Sschwartz 				    (PCI_LEAF_ULONG << PCI_SHIFT_133))
7603418Ssubhan 					max_speed = PCI_FREQ_133;
7613418Ssubhan 				if (pcix_status &
7624397Sschwartz 				    (PCI_LEAF_ULONG << PCI_SHIFT_266))
7633418Ssubhan 					max_speed = PCI_FREQ_266;
7643418Ssubhan 				if (pcix_status &
7654397Sschwartz 				    (PCI_LEAF_ULONG << PCI_SHIFT_533))
7663418Ssubhan 					max_speed = PCI_FREQ_533;
7673418Ssubhan 				*speed_max = max_speed;
7683418Ssubhan 			}
7693418Ssubhan 		}
7703418Ssubhan 		cap_ptr = (cap_reg >> PCI_REG_FUNC_SHIFT);
7713418Ssubhan 		cap_reg = read_word(fd, bus, dev, func, cap_ptr, &ret);
7723418Ssubhan 		if (ret != 0) {
7733418Ssubhan 			/* ioctl failure */
7745511Sanbui 			close(fd);
7753418Ssubhan 			return (PICL_FAILURE);
7763418Ssubhan 		}
7773418Ssubhan 		capid = cap_reg & PCI_CAP_MASK;
7783418Ssubhan 	}
7793418Ssubhan 
7805511Sanbui 	if (close(fd) == -1) {
7815511Sanbui 		return (PICL_FAILURE);
7825511Sanbui 	}
7835511Sanbui 
7843418Ssubhan 	return (PICL_SUCCESS);
7853418Ssubhan }
7863418Ssubhan 
787*11285SMichael.Bergknoff@Sun.COM static int
is_66mhz_capable(picl_nodehdl_t nodeh)788*11285SMichael.Bergknoff@Sun.COM is_66mhz_capable(picl_nodehdl_t nodeh)
789*11285SMichael.Bergknoff@Sun.COM {
790*11285SMichael.Bergknoff@Sun.COM 	picl_errno_t	err;
791*11285SMichael.Bergknoff@Sun.COM 	picl_prophdl_t	proph;
792*11285SMichael.Bergknoff@Sun.COM 	picl_propinfo_t	pinfo;
793*11285SMichael.Bergknoff@Sun.COM 
794*11285SMichael.Bergknoff@Sun.COM 	err = picl_get_propinfo_by_name(nodeh, OBP_PROP_66MHZ_CAPABLE,
795*11285SMichael.Bergknoff@Sun.COM 	    &pinfo, &proph);
796*11285SMichael.Bergknoff@Sun.COM 	if (err == PICL_SUCCESS)
797*11285SMichael.Bergknoff@Sun.COM 		return (1);
798*11285SMichael.Bergknoff@Sun.COM 	return (0);
799*11285SMichael.Bergknoff@Sun.COM }
800*11285SMichael.Bergknoff@Sun.COM 
8013418Ssubhan /*
8023418Ssubhan  * get the clock frequency
8033418Ssubhan  */
8043418Ssubhan static int
picldiag_get_clock_freq(picl_nodehdl_t modh,uint32_t * freq,uint32_t * freq_max)805*11285SMichael.Bergknoff@Sun.COM picldiag_get_clock_freq(picl_nodehdl_t modh, uint32_t *freq, uint32_t *freq_max)
8063418Ssubhan {
8073418Ssubhan 	int		err;
8083418Ssubhan 	uint64_t	clk_freq;
8093418Ssubhan 
810*11285SMichael.Bergknoff@Sun.COM 	*freq_max = PCI_FREQ_33;
811*11285SMichael.Bergknoff@Sun.COM 	if (is_66mhz_capable(modh))
812*11285SMichael.Bergknoff@Sun.COM 		*freq_max = PCI_FREQ_66;
8133418Ssubhan 	clk_freq = picldiag_get_uint_propval(modh, OBP_PROP_CLOCK_FREQ, &err);
8143418Ssubhan 	if (err != PICL_SUCCESS)
8153418Ssubhan 		return (err);
8163418Ssubhan 
8173418Ssubhan 	*freq = ROUND_TO_MHZ(clk_freq);
8183418Ssubhan 
8193418Ssubhan 	return (PICL_SUCCESS);
8203418Ssubhan }
8213418Ssubhan 
8223418Ssubhan static uint64_t
picldiag_get_uint_propval(picl_nodehdl_t modh,char * prop_name,int * ret)8233418Ssubhan picldiag_get_uint_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
8243418Ssubhan {
8253418Ssubhan 	int		err;
8263418Ssubhan 	picl_prophdl_t	proph;
8273418Ssubhan 	picl_propinfo_t pinfo;
8283418Ssubhan 	uint8_t		uint8v;
8293418Ssubhan 	uint16_t	uint16v;
8303418Ssubhan 	uint32_t	uint32v;
8313418Ssubhan 	uint64_t	uint64v;
8323418Ssubhan 
8333418Ssubhan 	err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
8343418Ssubhan 	if (err != PICL_SUCCESS) {
8353418Ssubhan 		*ret = err;
8363418Ssubhan 		return (0);
8373418Ssubhan 	}
8383418Ssubhan 
8393418Ssubhan 	/*
8403418Ssubhan 	 * If it is not an int or uint prop, return failure
8413418Ssubhan 	 */
8423418Ssubhan 	if ((pinfo.type != PICL_PTYPE_INT) &&
8434397Sschwartz 	    (pinfo.type != PICL_PTYPE_UNSIGNED_INT)) {
8443418Ssubhan 		*ret = PICL_FAILURE;
8453418Ssubhan 		return (0);
8463418Ssubhan 	}
8473418Ssubhan 
8483418Ssubhan 
8493418Ssubhan 	/* uint prop */
8503418Ssubhan 
8513418Ssubhan 	switch (pinfo.size) {
8523418Ssubhan 	case sizeof (uint8_t):
8533418Ssubhan 		err = picl_get_propval(proph, &uint8v, sizeof (uint8v));
8543418Ssubhan 		*ret = err;
8553418Ssubhan 		return (uint8v);
8563418Ssubhan 	case sizeof (uint16_t):
8573418Ssubhan 		err = picl_get_propval(proph, &uint16v, sizeof (uint16v));
8583418Ssubhan 		*ret = err;
8593418Ssubhan 		return (uint16v);
8603418Ssubhan 	case sizeof (uint32_t):
8613418Ssubhan 		err = picl_get_propval(proph, &uint32v, sizeof (uint32v));
8623418Ssubhan 		*ret = err;
8633418Ssubhan 		return (uint32v);
8643418Ssubhan 	case sizeof (uint64_t):
8653418Ssubhan 		err = picl_get_propval(proph, &uint64v, sizeof (uint64v));
8663418Ssubhan 		*ret = err;
8673418Ssubhan 		return (uint64v);
8683418Ssubhan 	default:	/* not supported size */
8693418Ssubhan 		*ret = PICL_FAILURE;
8703418Ssubhan 		return (0);
8713418Ssubhan 	}
8723418Ssubhan }
8733418Ssubhan 
8743418Ssubhan /*
8753418Ssubhan  * recursively visit all nodes
8763418Ssubhan  */
8773418Ssubhan static picl_errno_t
do_walk(picl_nodehdl_t rooth,const char * classname,void * c_args,picl_errno_t (* callback_fn)(picl_nodehdl_t hdl,void * args))8783418Ssubhan do_walk(picl_nodehdl_t rooth, const char *classname,
8793418Ssubhan     void *c_args, picl_errno_t (*callback_fn)(picl_nodehdl_t hdl, void *args))
8803418Ssubhan {
8813418Ssubhan 	picl_errno_t	err;
8823418Ssubhan 	picl_nodehdl_t  chdh;
8833418Ssubhan 	char		classval[PICL_CLASSNAMELEN_MAX];
8843418Ssubhan 
8853418Ssubhan 	err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh,
8864397Sschwartz 	    sizeof (chdh));
8873418Ssubhan 	while (err == PICL_SUCCESS) {
8883418Ssubhan 		err = picl_get_propval_by_name(chdh, PICL_PROP_NAME,
8894397Sschwartz 		    classval, sizeof (classval));
8903418Ssubhan 		if (err != PICL_SUCCESS)
8913418Ssubhan 			return (err);
8923418Ssubhan 
8933418Ssubhan 		err = callback_fn(chdh, c_args);
8943418Ssubhan 
8953418Ssubhan 		if ((err = do_walk(chdh, classname, c_args, callback_fn)) !=
8964397Sschwartz 		    PICL_WALK_CONTINUE)
8973418Ssubhan 			return (err);
8983418Ssubhan 
8993418Ssubhan 		err = picl_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh,
9004397Sschwartz 		    sizeof (chdh));
9013418Ssubhan 	}
9023418Ssubhan 	if (err == PICL_PROPNOTFOUND)   /* end of a branch */
9033418Ssubhan 		return (PICL_WALK_CONTINUE);
9043418Ssubhan 	return (err);
9053418Ssubhan }
9065394Sjimand 
9075394Sjimand int
get_proc_mode(void)9085394Sjimand get_proc_mode(void)
9095394Sjimand {
9105394Sjimand 	picl_nodehdl_t nodeh;
9115394Sjimand 	picl_prophdl_t  proph;
9125394Sjimand 	picl_errno_t err;
9135394Sjimand 
9145394Sjimand 	err = picl_initialize();
9155394Sjimand 	if (err != PICL_SUCCESS) {
9165394Sjimand 		(void) log_printf("picl_initialize failed: %s\n",
9175394Sjimand 		    picl_strerror(err));
9185394Sjimand 		return (err);
9195394Sjimand 	}
9205394Sjimand 
9215394Sjimand 	err = picl_get_node_by_path("/platform",  &nodeh);
9225394Sjimand 	if (err != PICL_SUCCESS) {
9235394Sjimand 		(void) log_printf("Getting plat node failed: %s\n",
9245394Sjimand 		    picl_strerror(err));
9255394Sjimand 		return (err);
9265394Sjimand 	}
9275394Sjimand 
9285394Sjimand 	err = picl_get_prop_by_name(nodeh, "SPARC64-VII-mode",  &proph);
9295394Sjimand 	if (err != PICL_SUCCESS) {
9305394Sjimand 		/* Do not display error message */
9315394Sjimand 		return (err);
9325394Sjimand 	}
9335394Sjimand 
9345394Sjimand 	(void) picl_shutdown();
9355394Sjimand 
9365394Sjimand 	return (err);
9375394Sjimand }
938