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