13d808a52Ssubhan /*
23d808a52Ssubhan * CDDL HEADER START
33d808a52Ssubhan *
43d808a52Ssubhan * The contents of this file are subject to the terms of the
53d808a52Ssubhan * Common Development and Distribution License (the "License").
63d808a52Ssubhan * You may not use this file except in compliance with the License.
73d808a52Ssubhan *
83d808a52Ssubhan * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93d808a52Ssubhan * or http://www.opensolaris.org/os/licensing.
103d808a52Ssubhan * See the License for the specific language governing permissions
113d808a52Ssubhan * and limitations under the License.
123d808a52Ssubhan *
133d808a52Ssubhan * When distributing Covered Code, include this CDDL HEADER in each
143d808a52Ssubhan * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153d808a52Ssubhan * If applicable, add the following below this CDDL HEADER, with the
163d808a52Ssubhan * fields enclosed by brackets "[]" replaced with your own identifying
173d808a52Ssubhan * information: Portions Copyright [yyyy] [name of copyright owner]
183d808a52Ssubhan *
193d808a52Ssubhan * CDDL HEADER END
203d808a52Ssubhan */
213d808a52Ssubhan /*
22*abe610a3SMichael Bergknoff * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
233d808a52Ssubhan * Use is subject to license terms.
243d808a52Ssubhan *
253d808a52Ssubhan * Opl platform specific PICL functions.
263d808a52Ssubhan *
273d808a52Ssubhan * called when :
283d808a52Ssubhan * machine_type == MTYPE_OPL
293d808a52Ssubhan */
303d808a52Ssubhan
313d808a52Ssubhan #include <stdio.h>
323d808a52Ssubhan #include <stdlib.h>
333d808a52Ssubhan #include <unistd.h>
343d808a52Ssubhan #include <kstat.h>
353d808a52Ssubhan #include <fcntl.h>
363d808a52Ssubhan #include <string.h>
373d808a52Ssubhan #include <assert.h>
383d808a52Ssubhan #include <libintl.h>
393d808a52Ssubhan #include <note.h>
403d808a52Ssubhan #include <dlfcn.h>
413d808a52Ssubhan #include <errno.h>
423d808a52Ssubhan #include <sys/systeminfo.h>
433d808a52Ssubhan #include <sys/openpromio.h>
443d808a52Ssubhan #include <sys/sysmacros.h>
453d808a52Ssubhan #include <picl.h>
463d808a52Ssubhan #include "picldefs.h"
473d808a52Ssubhan #include <pdevinfo.h>
483d808a52Ssubhan #include <display.h>
493d808a52Ssubhan #include <libprtdiag.h>
503d808a52Ssubhan #include <alloca.h>
513d808a52Ssubhan #include "opl_picl.h"
523d808a52Ssubhan #include <sys/pci.h>
533d808a52Ssubhan #include <sys/pci_tools.h>
543d808a52Ssubhan #include <sys/types.h>
553d808a52Ssubhan
563d808a52Ssubhan #if !defined(TEXT_DOMAIN)
573d808a52Ssubhan #define TEXT_DOMAIN "SYS_TEST"
583d808a52Ssubhan #endif
593d808a52Ssubhan
603d808a52Ssubhan static picl_errno_t do_walk(picl_nodehdl_t rooth, const char *classname,
613d808a52Ssubhan void *c_args, picl_errno_t (*callback_fn)(picl_nodehdl_t hdl, void *args));
623d808a52Ssubhan static int opl_get_node_by_name(picl_nodehdl_t rooth, char *name,
633d808a52Ssubhan picl_nodehdl_t *nodeh);
643d808a52Ssubhan static picl_errno_t get_lane_width(char *device_path, int bus_no, int func_no,
653d808a52Ssubhan int dev_no, int *actual, int *maximum, uint32_t *speed_max,
663d808a52Ssubhan uint32_t *speed_at, int *type);
673d808a52Ssubhan static int opl_display_pci(int syserrlog, picl_nodehdl_t plafh);
683d808a52Ssubhan static picl_errno_t opl_pci_callback(picl_nodehdl_t pcih, void *args);
693d808a52Ssubhan static int opl_get_first_compatible_value(picl_nodehdl_t nodeh,
703d808a52Ssubhan char **outbuf);
713d808a52Ssubhan static int picldiag_get_clock_freq(picl_nodehdl_t modh,
72*abe610a3SMichael Bergknoff uint32_t *freq, uint32_t *freq_max);
733d808a52Ssubhan static uint64_t picldiag_get_uint_propval(picl_nodehdl_t modh,
743d808a52Ssubhan char *prop_name, int *ret);
753d808a52Ssubhan static uint32_t read_long(int fd, int bus, int dev, int func,
763d808a52Ssubhan int offset, int *ret);
773d808a52Ssubhan static uint8_t read_byte(int fd, int bus, int dev, int func, int offset,
783d808a52Ssubhan int *ret);
793d808a52Ssubhan static uint16_t read_word(int fd, int bus, int dev, int func, int offset,
803d808a52Ssubhan int *ret);
813d808a52Ssubhan
823d808a52Ssubhan /*
833d808a52Ssubhan * Collect I/O nodes information.
843d808a52Ssubhan */
853d808a52Ssubhan /* ARGSUSED */
863d808a52Ssubhan static picl_errno_t
opl_pci_callback(picl_nodehdl_t pcih,void * args)873d808a52Ssubhan opl_pci_callback(picl_nodehdl_t pcih, void *args)
883d808a52Ssubhan {
893d808a52Ssubhan picl_errno_t err = PICL_SUCCESS;
903d808a52Ssubhan picl_nodehdl_t nodeh;
913d808a52Ssubhan picl_prophdl_t proph;
923d808a52Ssubhan picl_propinfo_t pinfo;
933d808a52Ssubhan char path[MAXSTRLEN];
943d808a52Ssubhan char parent_path[MAXSTRLEN];
953d808a52Ssubhan static char root_path[MAXSTRLEN];
963d808a52Ssubhan char piclclass[PICL_CLASSNAMELEN_MAX];
973d808a52Ssubhan char name[MAXSTRLEN];
983d808a52Ssubhan char model[MAXSTRLEN];
993d808a52Ssubhan char *compatible;
1003d808a52Ssubhan char binding_name[MAXSTRLEN];
1013d808a52Ssubhan struct io_card pci_card;
1023d808a52Ssubhan char status[6] = "N/A";
1033d808a52Ssubhan int portid = PROP_INVALID;
1043d808a52Ssubhan int *reg_val;
1053d808a52Ssubhan int board = PROP_INVALID;
1063d808a52Ssubhan static int saved_board = PROP_INVALID;
1073d808a52Ssubhan static int saved_portid = PROP_INVALID;
1083d808a52Ssubhan int actual = PROP_INVALID, maximum = PROP_INVALID;
1093d808a52Ssubhan int bus_type;
1103d808a52Ssubhan int rev_id = PROP_INVALID, dev_id = PROP_INVALID;
1113d808a52Ssubhan int ven_id = PROP_INVALID;
1123d808a52Ssubhan size_t prop_size;
1133d808a52Ssubhan
1143d808a52Ssubhan (void) memset(&pci_card, 0, sizeof (pci_card));
1153d808a52Ssubhan
1163d808a52Ssubhan err = picl_get_propval_by_name(pcih, PICL_PROP_CLASSNAME,
1172917a9c9Sschwartz piclclass, sizeof (piclclass));
1183d808a52Ssubhan
1193d808a52Ssubhan if (err != PICL_SUCCESS)
1203d808a52Ssubhan /* Do not proceed to parse this branch */
1213d808a52Ssubhan return (err);
1223d808a52Ssubhan
1233d808a52Ssubhan if (!IS_PCI(piclclass))
1243d808a52Ssubhan /* Do not parse non-pci nodes */
1253d808a52Ssubhan return (PICL_INVALIDARG);
1263d808a52Ssubhan
1273d808a52Ssubhan err = picl_get_propval_by_name(pcih, PICL_PROP_DEVFS_PATH, parent_path,
1283d808a52Ssubhan sizeof (parent_path));
1293d808a52Ssubhan if (err != PICL_SUCCESS)
1303d808a52Ssubhan /* Do not proceed to parse this branch */
1313d808a52Ssubhan return (err);
1323d808a52Ssubhan err = picl_get_propval_by_name(pcih, OBP_PROP_BOARD_NUM, &board,
1332917a9c9Sschwartz sizeof (board));
1343d808a52Ssubhan
1353d808a52Ssubhan if (err == PICL_NORESPONSE)
1363d808a52Ssubhan /* Do not proceed to parse this branch */
1373d808a52Ssubhan return (err);
1383d808a52Ssubhan else if (err != PICL_PROPNOTFOUND) {
1393d808a52Ssubhan saved_board = board;
1403d808a52Ssubhan /* Save board node's pathname */
1413d808a52Ssubhan prop_size = sizeof (parent_path) + 1;
1423d808a52Ssubhan if (prop_size > MAXSTRLEN)
1433d808a52Ssubhan prop_size = MAXSTRLEN;
1443d808a52Ssubhan (void) strlcpy(root_path, parent_path, prop_size);
1453d808a52Ssubhan }
1463d808a52Ssubhan
1473d808a52Ssubhan err = picl_get_propval_by_name
1482917a9c9Sschwartz (pcih, OBP_PROP_PORTID, &portid, sizeof (portid));
1493d808a52Ssubhan
1503d808a52Ssubhan if (err != PICL_PROPNOTFOUND)
1513d808a52Ssubhan saved_portid = portid;
1523d808a52Ssubhan
1533d808a52Ssubhan /* Walk through the children */
1543d808a52Ssubhan
1553d808a52Ssubhan err = picl_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
1563d808a52Ssubhan sizeof (picl_nodehdl_t));
1573d808a52Ssubhan
1583d808a52Ssubhan while (err == PICL_SUCCESS) {
1593d808a52Ssubhan uint32_t freq_max = 0, freq_at = 0;
1603d808a52Ssubhan
1613d808a52Ssubhan err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
1623d808a52Ssubhan piclclass, sizeof (piclclass));
1633d808a52Ssubhan if (err != PICL_SUCCESS)
1643d808a52Ssubhan /* Do not proceed to parse this node */
1653d808a52Ssubhan return (err);
1663d808a52Ssubhan
1673d808a52Ssubhan if (IS_EBUS(piclclass)) {
1683d808a52Ssubhan err = picl_get_propval_by_name(nodeh, PICL_PROP_PEER,
1692917a9c9Sschwartz &nodeh, sizeof (picl_nodehdl_t));
1703d808a52Ssubhan continue;
1713d808a52Ssubhan }
1723d808a52Ssubhan
1733d808a52Ssubhan err = picl_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH,
1743d808a52Ssubhan path, sizeof (path));
1753d808a52Ssubhan if (err != PICL_SUCCESS) {
1763d808a52Ssubhan /* Do not proceed to parse this node */
1773d808a52Ssubhan return (err);
1783d808a52Ssubhan }
1793d808a52Ssubhan
1803d808a52Ssubhan prop_size = sizeof (path) + 1;
1813d808a52Ssubhan if (prop_size > MAXSTRLEN)
1823d808a52Ssubhan prop_size = MAXSTRLEN;
1833d808a52Ssubhan (void) strlcpy(pci_card.notes, path, prop_size);
1843d808a52Ssubhan
1853d808a52Ssubhan pci_card.board = saved_board;
1863d808a52Ssubhan pci_card.schizo_portid = saved_portid;
1873d808a52Ssubhan
1883d808a52Ssubhan /*
1893d808a52Ssubhan * Get bus#, dev# and func# for this card from 'reg' property.
1903d808a52Ssubhan */
1913d808a52Ssubhan
1923d808a52Ssubhan err = picl_get_propinfo_by_name
1932917a9c9Sschwartz (nodeh, OBP_PROP_REG, &pinfo, &proph);
1943d808a52Ssubhan if (err == PICL_SUCCESS) {
1953d808a52Ssubhan /* All of the array of bytes of "reg" have to be read */
1963d808a52Ssubhan reg_val = malloc(pinfo.size);
1973d808a52Ssubhan if (reg_val == NULL)
1983d808a52Ssubhan return (PICL_FAILURE);
1993d808a52Ssubhan
2003d808a52Ssubhan
2013d808a52Ssubhan err = picl_get_propval_by_name
2023d808a52Ssubhan (nodeh, OBP_PROP_REG, reg_val, pinfo.size);
2033d808a52Ssubhan
2043d808a52Ssubhan if (err != PICL_SUCCESS) {
2053d808a52Ssubhan free(reg_val);
2063d808a52Ssubhan /* Do not proceed to parse this node */
2073d808a52Ssubhan return (err);
2083d808a52Ssubhan }
2093d808a52Ssubhan
2103d808a52Ssubhan if (reg_val[0] != 0) {
2113d808a52Ssubhan pci_card.dev_no =
2122917a9c9Sschwartz (((reg_val[0]) & PCI_DEV_MASK) >> 11);
2133d808a52Ssubhan pci_card.func_no =
2142917a9c9Sschwartz (((reg_val[0]) & PCI_FUNC_MASK) >> 8);
2153d808a52Ssubhan pci_card.slot =
2162917a9c9Sschwartz (((reg_val[0]) & PCI_BUS_MASK) >> 16);
2173d808a52Ssubhan } else
2183d808a52Ssubhan free(reg_val);
2193d808a52Ssubhan }
2203d808a52Ssubhan
2212917a9c9Sschwartz err = get_lane_width(root_path, pci_card.slot, pci_card.dev_no,
2222917a9c9Sschwartz pci_card.func_no, &actual, &maximum, &freq_max, &freq_at,
2232917a9c9Sschwartz &bus_type);
2243d808a52Ssubhan
2253d808a52Ssubhan if (err != PICL_SUCCESS) {
226a7480016Smb /*
227a7480016Smb * get_lane_width will fail when run as non-root.
228a7480016Smb * Set bus_type to PCI_UNKN so that bus frequency,
229a7480016Smb * bus type and lane width will print as "--" or UNKN.
230a7480016Smb */
231a7480016Smb bus_type = PCI_UNKN;
2323d808a52Ssubhan }
2333d808a52Ssubhan
2343d808a52Ssubhan
2353d808a52Ssubhan err = picl_get_propval_by_name
2363d808a52Ssubhan (nodeh, PICL_PROP_NAME, name, sizeof (name));
2373d808a52Ssubhan if (err != PICL_SUCCESS)
2383d808a52Ssubhan (void) strcpy(name, "");
2393d808a52Ssubhan
2403d808a52Ssubhan /*
2413d808a52Ssubhan * Get the name of this card. If binding_name is found,
2423d808a52Ssubhan * name will be <nodename>-<binding_name>
2433d808a52Ssubhan */
2443d808a52Ssubhan
2453d808a52Ssubhan err = picl_get_propval_by_name(nodeh, PICL_PROP_BINDING_NAME,
2463d808a52Ssubhan binding_name, sizeof (binding_name));
2473d808a52Ssubhan if (err == PICL_PROPNOTFOUND) {
2483d808a52Ssubhan /*
2493d808a52Ssubhan * if compatible prop is found, name will be
2503d808a52Ssubhan * <nodename>-<compatible>
2513d808a52Ssubhan */
2523d808a52Ssubhan err = opl_get_first_compatible_value(nodeh,
2533d808a52Ssubhan &compatible);
2543d808a52Ssubhan if (err == PICL_SUCCESS) {
2553d808a52Ssubhan (void) strlcat(name, "-", MAXSTRLEN);
2563d808a52Ssubhan (void) strlcat(name, compatible, MAXSTRLEN);
2573d808a52Ssubhan free(compatible);
2583d808a52Ssubhan }
2593d808a52Ssubhan } else if (err != PICL_SUCCESS) {
2603d808a52Ssubhan /* No binding-name or compatible */
2613d808a52Ssubhan (void) strcpy(binding_name, "N/A");
2623d808a52Ssubhan } else if (strcmp(name, binding_name) != 0) {
2633d808a52Ssubhan (void) strlcat(name, "-", MAXSTRLEN);
2643d808a52Ssubhan (void) strlcat(name, binding_name, MAXSTRLEN);
2653d808a52Ssubhan }
2663d808a52Ssubhan
2673d808a52Ssubhan
2683d808a52Ssubhan prop_size = sizeof (name) + 1;
2693d808a52Ssubhan if (prop_size > MAXSTRLEN)
2703d808a52Ssubhan prop_size = MAXSTRLEN;
2713d808a52Ssubhan (void) strlcpy(pci_card.name, name, prop_size);
2723d808a52Ssubhan
2733d808a52Ssubhan /* Get the status of the card */
2743d808a52Ssubhan err = picl_get_propval_by_name
2753d808a52Ssubhan (nodeh, PICL_PROP_STATUS, status, sizeof (status));
2763d808a52Ssubhan
2773d808a52Ssubhan
2783d808a52Ssubhan /* Get the model of this card */
2793d808a52Ssubhan
2803d808a52Ssubhan err = picl_get_propval_by_name
2813d808a52Ssubhan (nodeh, OBP_PROP_MODEL, model, sizeof (model));
2823d808a52Ssubhan prop_size = sizeof (model) + 1;
2833d808a52Ssubhan if (prop_size > MAXSTRLEN)
2843d808a52Ssubhan prop_size = MAXSTRLEN;
2853d808a52Ssubhan if (err != PICL_SUCCESS)
2863d808a52Ssubhan (void) strcpy(model, "N/A");
2873d808a52Ssubhan (void) strlcpy(pci_card.model, model, prop_size);
2883d808a52Ssubhan
2893d808a52Ssubhan if (bus_type == PCI)
2902917a9c9Sschwartz (void) strlcpy(pci_card.bus_type,
2912917a9c9Sschwartz "PCI", sizeof (pci_card.bus_type));
2923d808a52Ssubhan else if (bus_type == PCIX)
2932917a9c9Sschwartz (void) strlcpy(pci_card.bus_type,
2942917a9c9Sschwartz "PCIx", sizeof (pci_card.bus_type));
2953d808a52Ssubhan else if (bus_type == PCIE)
2962917a9c9Sschwartz (void) strlcpy(pci_card.bus_type,
2972917a9c9Sschwartz "PCIe", sizeof (pci_card.bus_type));
2983d808a52Ssubhan else
2992917a9c9Sschwartz (void) strlcpy(pci_card.bus_type,
3002917a9c9Sschwartz "UNKN", sizeof (pci_card.bus_type));
3013d808a52Ssubhan
3023d808a52Ssubhan /* Get revision id */
3033d808a52Ssubhan err = picl_get_propval_by_name
3042917a9c9Sschwartz (nodeh, OBP_PROP_REVISION_ID, &rev_id, sizeof (rev_id));
3053d808a52Ssubhan
3063d808a52Ssubhan /* Get device id */
3073d808a52Ssubhan err = picl_get_propval_by_name
3082917a9c9Sschwartz (nodeh, OBP_PROP_DEVICE_ID, &dev_id, sizeof (dev_id));
3093d808a52Ssubhan
3103d808a52Ssubhan /* Get vendor id */
3113d808a52Ssubhan err = picl_get_propval_by_name
3122917a9c9Sschwartz (nodeh, OBP_PROP_VENDOR_ID, &ven_id, sizeof (ven_id));
3133d808a52Ssubhan
3143d808a52Ssubhan /*
3153d808a52Ssubhan * prtdiag -v prints all devices
3163d808a52Ssubhan */
3173d808a52Ssubhan
3183d808a52Ssubhan /* Print board number */
3193d808a52Ssubhan log_printf("%02d ", pci_card.board);
3203d808a52Ssubhan /* Print IO Type */
3213d808a52Ssubhan log_printf("%-5.5s ", pci_card.bus_type);
3223d808a52Ssubhan
3233d808a52Ssubhan log_printf("%-3d ", pci_card.schizo_portid);
3243d808a52Ssubhan log_printf("%4x, %4x, %4x ", rev_id, dev_id, ven_id);
3253d808a52Ssubhan
3262917a9c9Sschwartz log_printf("%3d, %2d, %2d",
3272917a9c9Sschwartz pci_card.slot, pci_card.dev_no, pci_card.func_no);
3283d808a52Ssubhan
3293d808a52Ssubhan /* Print status */
3303d808a52Ssubhan log_printf(" %-5.5s ", status);
3313d808a52Ssubhan
3323d808a52Ssubhan /* Print Lane widths, Max/Sup Freq, Speed */
3333d808a52Ssubhan if (bus_type == PCIE) {
3343d808a52Ssubhan PRINT_FMT(actual, maximum);
3353d808a52Ssubhan } else if (bus_type == PCIX) {
3363d808a52Ssubhan PRINT_FREQ_FMT(freq_at, freq_max);
3373d808a52Ssubhan } else if (bus_type == PCI) {
338*abe610a3SMichael Bergknoff err = picldiag_get_clock_freq(nodeh, &freq_at,
339*abe610a3SMichael Bergknoff &freq_max);
3403d808a52Ssubhan PRINT_FREQ_FMT(freq_at, freq_max);
3413d808a52Ssubhan } else
3423d808a52Ssubhan log_printf(" -- , -- ");
3433d808a52Ssubhan
3443d808a52Ssubhan /* Print Card Name */
3453d808a52Ssubhan log_printf("%-30.30s", pci_card.name);
3463d808a52Ssubhan
3473d808a52Ssubhan /* Print Card Model */
3483d808a52Ssubhan log_printf(" %-20.20s", pci_card.model);
3493d808a52Ssubhan
3503d808a52Ssubhan log_printf("\n");
3513d808a52Ssubhan
3523d808a52Ssubhan log_printf("%4s%-100.100s", " ", pci_card.notes);
3533d808a52Ssubhan log_printf("\n");
3543d808a52Ssubhan log_printf("\n");
3553d808a52Ssubhan
3563d808a52Ssubhan
3573d808a52Ssubhan err = picl_get_propval_by_name
3583d808a52Ssubhan (nodeh, PICL_PROP_PEER, &nodeh, sizeof (picl_nodehdl_t));
3593d808a52Ssubhan
3603d808a52Ssubhan }
3613d808a52Ssubhan
3623d808a52Ssubhan return (PICL_WALK_CONTINUE);
3633d808a52Ssubhan }
3643d808a52Ssubhan
3653d808a52Ssubhan /*
3663d808a52Ssubhan * opl_display_pci
3673d808a52Ssubhan * Display all the PCI IO cards on this board.
3683d808a52Ssubhan */
3693d808a52Ssubhan static int
opl_display_pci(int syserrlog,picl_nodehdl_t plafh)3703d808a52Ssubhan opl_display_pci(int syserrlog, picl_nodehdl_t plafh)
3713d808a52Ssubhan {
3723d808a52Ssubhan picl_errno_t err;
3733d808a52Ssubhan char *fmt = "%-3s %-5s %-4s %-20s %-11s %-5s %-11s %-30s %-20s";
3743d808a52Ssubhan char *fmt2 = "%-16s";
3753d808a52Ssubhan static int banner = FALSE; /* Have we printed the column headings? */
3763d808a52Ssubhan
3773d808a52Ssubhan if (banner == FALSE) {
3783d808a52Ssubhan log_printf("\n", 0);
3793d808a52Ssubhan log_printf("=========================", 0);
3803d808a52Ssubhan log_printf(dgettext(TEXT_DOMAIN, " IO Devices "), 0);
3813d808a52Ssubhan log_printf("=========================", 0);
3823d808a52Ssubhan log_printf("\n", 0);
3833d808a52Ssubhan log_printf("\n", 0);
3843d808a52Ssubhan log_printf(fmt, "", "IO", "", "", "", "", "Lane/Frq",
3852917a9c9Sschwartz "", "", 0);
3863d808a52Ssubhan log_printf("\n", 0);
3873d808a52Ssubhan
3883d808a52Ssubhan log_printf(fmt, "LSB", "Type", "LPID", " RvID,DvID,VnID",
3892917a9c9Sschwartz " BDF", "State", "Act, Max", "Name", "Model", 0);
3903d808a52Ssubhan
3913d808a52Ssubhan log_printf("\n");
3923d808a52Ssubhan
3932917a9c9Sschwartz log_printf(fmt,
3942917a9c9Sschwartz "---", "-----", "----", " ------------------",
3952917a9c9Sschwartz " ---------", "-----", "-----------",
3962917a9c9Sschwartz "------------------------------",
3972917a9c9Sschwartz "--------------------", 0);
3983d808a52Ssubhan log_printf("\n");
3993d808a52Ssubhan log_printf(fmt2, " Logical Path");
4003d808a52Ssubhan log_printf("\n");
4013d808a52Ssubhan log_printf(fmt2, " ------------");
4023d808a52Ssubhan log_printf("\n");
4033d808a52Ssubhan banner = TRUE;
4043d808a52Ssubhan }
4053d808a52Ssubhan
4063d808a52Ssubhan err = do_walk(plafh, PICL_CLASS_PCI, PICL_CLASS_PCI, opl_pci_callback);
4073d808a52Ssubhan return (err);
4083d808a52Ssubhan }
4093d808a52Ssubhan
4103d808a52Ssubhan
4113d808a52Ssubhan /*
4123d808a52Ssubhan * return the first compatible value
4133d808a52Ssubhan */
4143d808a52Ssubhan static int
opl_get_first_compatible_value(picl_nodehdl_t nodeh,char ** outbuf)4153d808a52Ssubhan opl_get_first_compatible_value(picl_nodehdl_t nodeh, char **outbuf)
4163d808a52Ssubhan {
4173d808a52Ssubhan picl_errno_t err;
4183d808a52Ssubhan picl_prophdl_t proph;
4193d808a52Ssubhan picl_propinfo_t pinfo;
4203d808a52Ssubhan picl_prophdl_t tblh;
4213d808a52Ssubhan picl_prophdl_t rowproph;
4223d808a52Ssubhan char *pval;
4233d808a52Ssubhan
4243d808a52Ssubhan err = picl_get_propinfo_by_name(nodeh, OBP_PROP_COMPATIBLE,
4253d808a52Ssubhan &pinfo, &proph);
4263d808a52Ssubhan if (err != PICL_SUCCESS)
4272917a9c9Sschwartz return (err);
4283d808a52Ssubhan
4293d808a52Ssubhan if (pinfo.type == PICL_PTYPE_CHARSTRING) {
4303d808a52Ssubhan pval = malloc(pinfo.size);
4313d808a52Ssubhan if (pval == NULL)
4323d808a52Ssubhan return (PICL_FAILURE);
4333d808a52Ssubhan err = picl_get_propval(proph, pval, pinfo.size);
4343d808a52Ssubhan if (err != PICL_SUCCESS) {
4353d808a52Ssubhan free(pval);
4363d808a52Ssubhan return (err);
4373d808a52Ssubhan }
4383d808a52Ssubhan *outbuf = pval;
4393d808a52Ssubhan return (PICL_SUCCESS);
4403d808a52Ssubhan }
4413d808a52Ssubhan
4423d808a52Ssubhan if (pinfo.type != PICL_PTYPE_TABLE)
4433d808a52Ssubhan return (PICL_FAILURE);
4443d808a52Ssubhan
4453d808a52Ssubhan /* get first string from table */
4463d808a52Ssubhan err = picl_get_propval(proph, &tblh, pinfo.size);
4473d808a52Ssubhan if (err != PICL_SUCCESS)
4483d808a52Ssubhan return (err);
4493d808a52Ssubhan
4503d808a52Ssubhan err = picl_get_next_by_row(tblh, &rowproph);
4513d808a52Ssubhan if (err != PICL_SUCCESS)
4523d808a52Ssubhan return (err);
4533d808a52Ssubhan
4543d808a52Ssubhan err = picl_get_propinfo(rowproph, &pinfo);
4553d808a52Ssubhan if (err != PICL_SUCCESS)
4562917a9c9Sschwartz return (err);
4573d808a52Ssubhan
4583d808a52Ssubhan pval = malloc(pinfo.size);
4593d808a52Ssubhan if (pval == NULL)
4603d808a52Ssubhan return (PICL_FAILURE);
4613d808a52Ssubhan
4623d808a52Ssubhan err = picl_get_propval(rowproph, pval, pinfo.size);
4633d808a52Ssubhan if (err != PICL_SUCCESS) {
4643d808a52Ssubhan free(pval);
4653d808a52Ssubhan return (err);
4663d808a52Ssubhan }
4673d808a52Ssubhan
4683d808a52Ssubhan *outbuf = pval;
4693d808a52Ssubhan return (PICL_SUCCESS);
4703d808a52Ssubhan }
4713d808a52Ssubhan
4723d808a52Ssubhan int
do_piclinfo(int syserrlog)4733d808a52Ssubhan do_piclinfo(int syserrlog)
4743d808a52Ssubhan {
4753d808a52Ssubhan picl_nodehdl_t rooth; /* root PICL node for IO display */
4763d808a52Ssubhan picl_nodehdl_t plafh; /* Platform PICL node for IO display */
4773d808a52Ssubhan
4783d808a52Ssubhan picl_errno_t err;
4793d808a52Ssubhan
4803d808a52Ssubhan err = picl_initialize();
4813d808a52Ssubhan if (err != PICL_SUCCESS) {
4823d808a52Ssubhan (void) log_printf("picl_initialize failed: %s\n",
4832917a9c9Sschwartz picl_strerror(err));
4843d808a52Ssubhan return (err);
4853d808a52Ssubhan }
4863d808a52Ssubhan
4873d808a52Ssubhan
4883d808a52Ssubhan err = picl_get_root(&rooth);
4893d808a52Ssubhan if (err != PICL_SUCCESS) {
4903d808a52Ssubhan (void) log_printf("Getting root node failed: %s\n",
4912917a9c9Sschwartz picl_strerror(err));
4923d808a52Ssubhan return (err);
4933d808a52Ssubhan }
4943d808a52Ssubhan
4953d808a52Ssubhan err = opl_get_node_by_name(rooth, PICL_NODE_PLATFORM, &plafh);
4963d808a52Ssubhan
4973d808a52Ssubhan if (err != PICL_SUCCESS) {
4983d808a52Ssubhan (void) log_printf("Getting nodes by name failed: %s\n",
4992917a9c9Sschwartz picl_strerror(err));
5003d808a52Ssubhan return (err);
5013d808a52Ssubhan }
5023d808a52Ssubhan
5033d808a52Ssubhan err = opl_display_pci(syserrlog, plafh);
5043d808a52Ssubhan
5053d808a52Ssubhan (void) picl_shutdown();
5063d808a52Ssubhan
5073d808a52Ssubhan return (err);
5083d808a52Ssubhan }
5093d808a52Ssubhan
5103d808a52Ssubhan /*
5113d808a52Ssubhan * search children to get the node by the nodename
5123d808a52Ssubhan */
5133d808a52Ssubhan static int
opl_get_node_by_name(picl_nodehdl_t rooth,char * name,picl_nodehdl_t * nodeh)5143d808a52Ssubhan opl_get_node_by_name(picl_nodehdl_t rooth, char *name,
5153d808a52Ssubhan picl_nodehdl_t *nodeh)
5163d808a52Ssubhan {
5173d808a52Ssubhan picl_nodehdl_t childh;
5183d808a52Ssubhan int err;
5193d808a52Ssubhan char *nodename;
5203d808a52Ssubhan
5213d808a52Ssubhan nodename = alloca(strlen(name) + 1);
5223d808a52Ssubhan if (nodename == NULL)
5233d808a52Ssubhan return (PICL_FAILURE);
5243d808a52Ssubhan
5253d808a52Ssubhan err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &childh,
5262917a9c9Sschwartz sizeof (picl_nodehdl_t));
5273d808a52Ssubhan
5283d808a52Ssubhan while (err == PICL_SUCCESS) {
5293d808a52Ssubhan err = picl_get_propval_by_name(childh, PICL_PROP_NAME,
5302917a9c9Sschwartz nodename, (strlen(name) + 1));
5313d808a52Ssubhan if (err != PICL_SUCCESS) {
5323d808a52Ssubhan err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
5332917a9c9Sschwartz &childh, sizeof (picl_nodehdl_t));
5343d808a52Ssubhan continue;
5353d808a52Ssubhan }
5363d808a52Ssubhan
5373d808a52Ssubhan if (strcmp(nodename, name) == 0) {
5383d808a52Ssubhan *nodeh = childh;
5393d808a52Ssubhan return (PICL_SUCCESS);
5403d808a52Ssubhan }
5413d808a52Ssubhan
5423d808a52Ssubhan err = picl_get_propval_by_name(childh, PICL_PROP_PEER,
5432917a9c9Sschwartz &childh, sizeof (picl_nodehdl_t));
5443d808a52Ssubhan }
5453d808a52Ssubhan
5463d808a52Ssubhan return (err);
5473d808a52Ssubhan }
5483d808a52Ssubhan
5493d808a52Ssubhan static int
open_root_complex(char * root_complex)5503d808a52Ssubhan open_root_complex(char *root_complex)
5513d808a52Ssubhan {
5523d808a52Ssubhan char *path;
5533d808a52Ssubhan static char device_str[] = {"/devices"};
5543d808a52Ssubhan static char devctl_str[] = {":reg"};
5553d808a52Ssubhan int fd;
5563d808a52Ssubhan
5573d808a52Ssubhan path = malloc(
5583d808a52Ssubhan strlen(root_complex) + sizeof (device_str) + sizeof (devctl_str));
5593d808a52Ssubhan if (path == NULL)
5603d808a52Ssubhan return (PICL_FAILURE);
5613d808a52Ssubhan (void) strcpy(path, device_str);
5623d808a52Ssubhan (void) strcat(path, root_complex);
5633d808a52Ssubhan (void) strcat(path, devctl_str);
5643d808a52Ssubhan
5653d808a52Ssubhan if ((fd = open(path, O_RDWR)) == -1) {
5663d808a52Ssubhan return (-1);
5673d808a52Ssubhan }
5683d808a52Ssubhan return (fd);
5693d808a52Ssubhan }
5703d808a52Ssubhan
5713d808a52Ssubhan static uint32_t
read_long(int fd,int bus,int dev,int func,int offset,int * ret)5723d808a52Ssubhan read_long(int fd, int bus, int dev, int func, int offset, int *ret)
5733d808a52Ssubhan {
5743d808a52Ssubhan int rval;
5753d808a52Ssubhan pcitool_reg_t prg;
5763d808a52Ssubhan
5772917a9c9Sschwartz prg.user_version = PCITOOL_VERSION;
5783d808a52Ssubhan prg.barnum = 0;
5793d808a52Ssubhan prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 +
5803d808a52Ssubhan PCITOOL_ACC_ATTR_ENDN_LTL;
5813d808a52Ssubhan prg.bus_no = bus;
5823d808a52Ssubhan prg.dev_no = dev;
5833d808a52Ssubhan prg.func_no = func;
5843d808a52Ssubhan prg.offset = offset;
5853d808a52Ssubhan rval = ioctl(fd, PCITOOL_DEVICE_GET_REG, &prg);
5863d808a52Ssubhan if (rval != 0) {
5872917a9c9Sschwartz log_printf("DEV_GET failed %d %s\n", rval, strerror(errno));
5882917a9c9Sschwartz log_printf("%d.%d.%d offset 0x%x\n", bus, dev, func, offset);
5893d808a52Ssubhan }
5903d808a52Ssubhan *ret = rval;
5913d808a52Ssubhan return ((uint32_t)prg.data);
5923d808a52Ssubhan }
5933d808a52Ssubhan
5943d808a52Ssubhan static uint16_t
read_word(int fd,int bus,int dev,int func,int offset,int * ret)5953d808a52Ssubhan read_word(int fd, int bus, int dev, int func, int offset, int *ret)
5963d808a52Ssubhan {
5973d808a52Ssubhan int rval;
5983d808a52Ssubhan pcitool_reg_t prg;
5993d808a52Ssubhan
6002917a9c9Sschwartz prg.user_version = PCITOOL_VERSION;
6013d808a52Ssubhan prg.barnum = 0;
6023d808a52Ssubhan prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_2 +
6033d808a52Ssubhan PCITOOL_ACC_ATTR_ENDN_LTL;
6043d808a52Ssubhan prg.bus_no = bus;
6053d808a52Ssubhan prg.dev_no = dev;
6063d808a52Ssubhan prg.func_no = func;
6073d808a52Ssubhan prg.offset = offset;
6083d808a52Ssubhan rval = ioctl(fd, PCITOOL_DEVICE_GET_REG, &prg);
6093d808a52Ssubhan if (rval != 0) {
6102917a9c9Sschwartz log_printf("DEV_GET failed %d %s\n", rval, strerror(errno));
6112917a9c9Sschwartz log_printf("%d.%d.%d offset 0x%x\n", bus, dev, func, offset);
6123d808a52Ssubhan }
6133d808a52Ssubhan *ret = rval;
6143d808a52Ssubhan return ((uint16_t)prg.data);
6153d808a52Ssubhan }
6163d808a52Ssubhan
6173d808a52Ssubhan static uint8_t
read_byte(int fd,int bus,int dev,int func,int offset,int * ret)6183d808a52Ssubhan read_byte(int fd, int bus, int dev, int func, int offset, int *ret)
6193d808a52Ssubhan {
6203d808a52Ssubhan int rval;
6213d808a52Ssubhan pcitool_reg_t prg;
6223d808a52Ssubhan
6232917a9c9Sschwartz prg.user_version = PCITOOL_VERSION;
6243d808a52Ssubhan prg.barnum = 0;
6253d808a52Ssubhan prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_1 +
6263d808a52Ssubhan PCITOOL_ACC_ATTR_ENDN_LTL;
6273d808a52Ssubhan prg.bus_no = bus;
6283d808a52Ssubhan prg.dev_no = dev;
6293d808a52Ssubhan prg.func_no = func;
6303d808a52Ssubhan prg.offset = offset;
6313d808a52Ssubhan rval = ioctl(fd, PCITOOL_DEVICE_GET_REG, &prg);
6323d808a52Ssubhan if (rval != 0) {
6332917a9c9Sschwartz log_printf("DEV_GET failed %d %s\n", rval, strerror(errno));
6342917a9c9Sschwartz log_printf("%d.%d.%d offset 0x%x\n", bus, dev, func, offset);
6353d808a52Ssubhan }
6363d808a52Ssubhan *ret = rval;
6373d808a52Ssubhan return ((uint8_t)prg.data);
6383d808a52Ssubhan }
6393d808a52Ssubhan
6403d808a52Ssubhan
6413d808a52Ssubhan 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)6423d808a52Ssubhan get_lane_width
6433d808a52Ssubhan (char *device_path, int bus, int dev, int func, int *actual,
6443d808a52Ssubhan int *maximum, uint32_t *speed_max, uint32_t *speed_at, int *type)
6453d808a52Ssubhan {
6463d808a52Ssubhan uint_t cap_ptr, cap_reg, link_status, link_cap, capid;
6473d808a52Ssubhan int fd, ret;
6483d808a52Ssubhan
6493d808a52Ssubhan if (device_path == NULL)
6503d808a52Ssubhan return (PICL_FAILURE);
6513d808a52Ssubhan
6523d808a52Ssubhan fd = open_root_complex(device_path);
6533d808a52Ssubhan if (fd == -1)
6543d808a52Ssubhan return (PICL_FAILURE);
6553d808a52Ssubhan
6563d808a52Ssubhan /*
6573d808a52Ssubhan * Link Capabilities and Link Status registers are in the
6583d808a52Ssubhan * PCI-E capabilities register. They are at offset
6593d808a52Ssubhan * 0xc and 0x12 respectively. They are documented in section
6603d808a52Ssubhan * 7.8 of the PCI Express Base Specification. The address of
6613d808a52Ssubhan * that structure is not fixed, it's kind of a linked list.
6623d808a52Ssubhan * The Capabilities Pointer reg (8 bits) is always at 0x34.
6633d808a52Ssubhan * It contains a pointer to the first capabilities structure.
6643d808a52Ssubhan * For each capability structure, the first 8 bits is the capability
6653d808a52Ssubhan * ID. The next 8 bits is the pointer to the next structure.
6663d808a52Ssubhan * If the Next Cap register is zero, it's the end of the list.
6673d808a52Ssubhan * The capability ID for the PCI-E strucutre is 0x10. The idea
6683d808a52Ssubhan * is to follow the links until you find a Cap ID of 0x10, then
6693d808a52Ssubhan * read the registers at 0xc and 0x12 from there.
6703d808a52Ssubhan * If there's no Cap ID 0x10, then it's not a PCI-E device.
6713d808a52Ssubhan */
6723d808a52Ssubhan
6733d808a52Ssubhan cap_ptr = read_byte(fd, bus, dev, func, PCI_CONF_CAP_PTR, &ret);
6743d808a52Ssubhan if (ret != 0) {
6753d808a52Ssubhan /* ioctl failure */
6767561ff47Sanbui close(fd);
6773d808a52Ssubhan return (PICL_FAILURE);
6783d808a52Ssubhan }
6793d808a52Ssubhan cap_reg = read_word(fd, bus, dev, func, cap_ptr, &ret);
6803d808a52Ssubhan if (ret != 0) {
6813d808a52Ssubhan /* ioctl failure */
6827561ff47Sanbui close(fd);
6833d808a52Ssubhan return (PICL_FAILURE);
6843d808a52Ssubhan }
6854c963d50Smb *type = PCI;
6863d808a52Ssubhan capid = cap_reg & PCI_CAP_MASK;
6873d808a52Ssubhan while (cap_ptr != 0) {
6883d808a52Ssubhan
6893d808a52Ssubhan if (capid == PCI_CAP_ID_PCI_E) {
6903d808a52Ssubhan link_cap = read_long(fd, bus, dev, func, cap_ptr +
6913d808a52Ssubhan PCIE_LINKCAP, &ret);
6923d808a52Ssubhan if (ret != 0) {
6937561ff47Sanbui close(fd);
6943d808a52Ssubhan return (PICL_FAILURE);
6953d808a52Ssubhan }
6962917a9c9Sschwartz link_status = read_word(fd, bus, dev, func,
6972917a9c9Sschwartz cap_ptr + PCIE_LINKSTS, &ret);
6983d808a52Ssubhan if (ret != 0) {
6997561ff47Sanbui close(fd);
7003d808a52Ssubhan return (PICL_FAILURE);
7013d808a52Ssubhan }
7023d808a52Ssubhan *actual = ((link_status >> PCI_LINK_SHIFT) &
7032917a9c9Sschwartz PCI_LINK_MASK);
7043d808a52Ssubhan *maximum = ((link_cap >> PCI_LINK_SHIFT) &
7052917a9c9Sschwartz PCI_LINK_MASK);
7063d808a52Ssubhan *type = PCIE;
7074c963d50Smb } else if (capid == PCI_CAP_ID_PCIX) {
7083d808a52Ssubhan uint32_t pcix_status;
7093d808a52Ssubhan uint8_t hdr_type;
7103d808a52Ssubhan int max_speed = PCI_FREQ_66;
7113d808a52Ssubhan
7123d808a52Ssubhan hdr_type = read_byte
7132917a9c9Sschwartz (fd, bus, dev, func, PCI_CONF_HEADER, &ret);
7143d808a52Ssubhan if (ret != 0) {
7153d808a52Ssubhan /* ioctl failure */
7167561ff47Sanbui close(fd);
7173d808a52Ssubhan return (PICL_FAILURE);
7183d808a52Ssubhan }
7194c963d50Smb *type = PCIX;
7203d808a52Ssubhan if ((hdr_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
7213d808a52Ssubhan /* This is a PCI-X bridge */
7223d808a52Ssubhan uint16_t sec_status, mode;
7233d808a52Ssubhan sec_status = read_word(fd, bus, dev, func,
7242917a9c9Sschwartz cap_ptr + PCI_PCIX_SEC_STATUS, &ret);
7253d808a52Ssubhan if (ret != 0) {
7263d808a52Ssubhan /* ioctl failure */
7277561ff47Sanbui close(fd);
7283d808a52Ssubhan return (PICL_FAILURE);
7293d808a52Ssubhan }
7303d808a52Ssubhan if (sec_status & PCI_SEC_133)
7313d808a52Ssubhan max_speed = PCI_FREQ_133;
7323d808a52Ssubhan if (sec_status & PCI_SEC_266)
7333d808a52Ssubhan max_speed = PCI_FREQ_266;
7343d808a52Ssubhan if (sec_status & PCI_SEC_533)
7353d808a52Ssubhan max_speed = PCI_FREQ_533;
7363d808a52Ssubhan *speed_max = max_speed;
7372917a9c9Sschwartz mode = (sec_status >> PCI_CLASS_BRIDGE) &
7382917a9c9Sschwartz PCI_BRIDGE_MC;
7393d808a52Ssubhan if (mode) {
7403d808a52Ssubhan int speed;
7413d808a52Ssubhan if (mode == PCI_MODE_66)
7423d808a52Ssubhan speed = PCI_FREQ_66;
7433d808a52Ssubhan else if (mode == PCI_MODE_100)
7443d808a52Ssubhan speed = PCI_FREQ_100;
7453d808a52Ssubhan else if (mode == PCI_MODE_133)
7463d808a52Ssubhan speed = PCI_FREQ_133;
7473d808a52Ssubhan *speed_at = speed;
7483d808a52Ssubhan }
7493d808a52Ssubhan
7503d808a52Ssubhan } else { /* Leaf device */
7513d808a52Ssubhan pcix_status = read_long(fd, bus, dev, func,
7523d808a52Ssubhan cap_ptr + PCI_PCIX_STATUS, &ret);
7533d808a52Ssubhan if (ret != 0) {
7543d808a52Ssubhan /* ioctl failure */
7557561ff47Sanbui close(fd);
7563d808a52Ssubhan return (PICL_FAILURE);
7573d808a52Ssubhan }
7583d808a52Ssubhan if (pcix_status &
7592917a9c9Sschwartz (PCI_LEAF_ULONG << PCI_SHIFT_133))
7603d808a52Ssubhan max_speed = PCI_FREQ_133;
7613d808a52Ssubhan if (pcix_status &
7622917a9c9Sschwartz (PCI_LEAF_ULONG << PCI_SHIFT_266))
7633d808a52Ssubhan max_speed = PCI_FREQ_266;
7643d808a52Ssubhan if (pcix_status &
7652917a9c9Sschwartz (PCI_LEAF_ULONG << PCI_SHIFT_533))
7663d808a52Ssubhan max_speed = PCI_FREQ_533;
7673d808a52Ssubhan *speed_max = max_speed;
7683d808a52Ssubhan }
7693d808a52Ssubhan }
7703d808a52Ssubhan cap_ptr = (cap_reg >> PCI_REG_FUNC_SHIFT);
7713d808a52Ssubhan cap_reg = read_word(fd, bus, dev, func, cap_ptr, &ret);
7723d808a52Ssubhan if (ret != 0) {
7733d808a52Ssubhan /* ioctl failure */
7747561ff47Sanbui close(fd);
7753d808a52Ssubhan return (PICL_FAILURE);
7763d808a52Ssubhan }
7773d808a52Ssubhan capid = cap_reg & PCI_CAP_MASK;
7783d808a52Ssubhan }
7793d808a52Ssubhan
7807561ff47Sanbui if (close(fd) == -1) {
7817561ff47Sanbui return (PICL_FAILURE);
7827561ff47Sanbui }
7837561ff47Sanbui
7843d808a52Ssubhan return (PICL_SUCCESS);
7853d808a52Ssubhan }
7863d808a52Ssubhan
787*abe610a3SMichael Bergknoff static int
is_66mhz_capable(picl_nodehdl_t nodeh)788*abe610a3SMichael Bergknoff is_66mhz_capable(picl_nodehdl_t nodeh)
789*abe610a3SMichael Bergknoff {
790*abe610a3SMichael Bergknoff picl_errno_t err;
791*abe610a3SMichael Bergknoff picl_prophdl_t proph;
792*abe610a3SMichael Bergknoff picl_propinfo_t pinfo;
793*abe610a3SMichael Bergknoff
794*abe610a3SMichael Bergknoff err = picl_get_propinfo_by_name(nodeh, OBP_PROP_66MHZ_CAPABLE,
795*abe610a3SMichael Bergknoff &pinfo, &proph);
796*abe610a3SMichael Bergknoff if (err == PICL_SUCCESS)
797*abe610a3SMichael Bergknoff return (1);
798*abe610a3SMichael Bergknoff return (0);
799*abe610a3SMichael Bergknoff }
800*abe610a3SMichael Bergknoff
8013d808a52Ssubhan /*
8023d808a52Ssubhan * get the clock frequency
8033d808a52Ssubhan */
8043d808a52Ssubhan static int
picldiag_get_clock_freq(picl_nodehdl_t modh,uint32_t * freq,uint32_t * freq_max)805*abe610a3SMichael Bergknoff picldiag_get_clock_freq(picl_nodehdl_t modh, uint32_t *freq, uint32_t *freq_max)
8063d808a52Ssubhan {
8073d808a52Ssubhan int err;
8083d808a52Ssubhan uint64_t clk_freq;
8093d808a52Ssubhan
810*abe610a3SMichael Bergknoff *freq_max = PCI_FREQ_33;
811*abe610a3SMichael Bergknoff if (is_66mhz_capable(modh))
812*abe610a3SMichael Bergknoff *freq_max = PCI_FREQ_66;
8133d808a52Ssubhan clk_freq = picldiag_get_uint_propval(modh, OBP_PROP_CLOCK_FREQ, &err);
8143d808a52Ssubhan if (err != PICL_SUCCESS)
8153d808a52Ssubhan return (err);
8163d808a52Ssubhan
8173d808a52Ssubhan *freq = ROUND_TO_MHZ(clk_freq);
8183d808a52Ssubhan
8193d808a52Ssubhan return (PICL_SUCCESS);
8203d808a52Ssubhan }
8213d808a52Ssubhan
8223d808a52Ssubhan static uint64_t
picldiag_get_uint_propval(picl_nodehdl_t modh,char * prop_name,int * ret)8233d808a52Ssubhan picldiag_get_uint_propval(picl_nodehdl_t modh, char *prop_name, int *ret)
8243d808a52Ssubhan {
8253d808a52Ssubhan int err;
8263d808a52Ssubhan picl_prophdl_t proph;
8273d808a52Ssubhan picl_propinfo_t pinfo;
8283d808a52Ssubhan uint8_t uint8v;
8293d808a52Ssubhan uint16_t uint16v;
8303d808a52Ssubhan uint32_t uint32v;
8313d808a52Ssubhan uint64_t uint64v;
8323d808a52Ssubhan
8333d808a52Ssubhan err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph);
8343d808a52Ssubhan if (err != PICL_SUCCESS) {
8353d808a52Ssubhan *ret = err;
8363d808a52Ssubhan return (0);
8373d808a52Ssubhan }
8383d808a52Ssubhan
8393d808a52Ssubhan /*
8403d808a52Ssubhan * If it is not an int or uint prop, return failure
8413d808a52Ssubhan */
8423d808a52Ssubhan if ((pinfo.type != PICL_PTYPE_INT) &&
8432917a9c9Sschwartz (pinfo.type != PICL_PTYPE_UNSIGNED_INT)) {
8443d808a52Ssubhan *ret = PICL_FAILURE;
8453d808a52Ssubhan return (0);
8463d808a52Ssubhan }
8473d808a52Ssubhan
8483d808a52Ssubhan
8493d808a52Ssubhan /* uint prop */
8503d808a52Ssubhan
8513d808a52Ssubhan switch (pinfo.size) {
8523d808a52Ssubhan case sizeof (uint8_t):
8533d808a52Ssubhan err = picl_get_propval(proph, &uint8v, sizeof (uint8v));
8543d808a52Ssubhan *ret = err;
8553d808a52Ssubhan return (uint8v);
8563d808a52Ssubhan case sizeof (uint16_t):
8573d808a52Ssubhan err = picl_get_propval(proph, &uint16v, sizeof (uint16v));
8583d808a52Ssubhan *ret = err;
8593d808a52Ssubhan return (uint16v);
8603d808a52Ssubhan case sizeof (uint32_t):
8613d808a52Ssubhan err = picl_get_propval(proph, &uint32v, sizeof (uint32v));
8623d808a52Ssubhan *ret = err;
8633d808a52Ssubhan return (uint32v);
8643d808a52Ssubhan case sizeof (uint64_t):
8653d808a52Ssubhan err = picl_get_propval(proph, &uint64v, sizeof (uint64v));
8663d808a52Ssubhan *ret = err;
8673d808a52Ssubhan return (uint64v);
8683d808a52Ssubhan default: /* not supported size */
8693d808a52Ssubhan *ret = PICL_FAILURE;
8703d808a52Ssubhan return (0);
8713d808a52Ssubhan }
8723d808a52Ssubhan }
8733d808a52Ssubhan
8743d808a52Ssubhan /*
8753d808a52Ssubhan * recursively visit all nodes
8763d808a52Ssubhan */
8773d808a52Ssubhan 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))8783d808a52Ssubhan do_walk(picl_nodehdl_t rooth, const char *classname,
8793d808a52Ssubhan void *c_args, picl_errno_t (*callback_fn)(picl_nodehdl_t hdl, void *args))
8803d808a52Ssubhan {
8813d808a52Ssubhan picl_errno_t err;
8823d808a52Ssubhan picl_nodehdl_t chdh;
8833d808a52Ssubhan char classval[PICL_CLASSNAMELEN_MAX];
8843d808a52Ssubhan
8853d808a52Ssubhan err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh,
8862917a9c9Sschwartz sizeof (chdh));
8873d808a52Ssubhan while (err == PICL_SUCCESS) {
8883d808a52Ssubhan err = picl_get_propval_by_name(chdh, PICL_PROP_NAME,
8892917a9c9Sschwartz classval, sizeof (classval));
8903d808a52Ssubhan if (err != PICL_SUCCESS)
8913d808a52Ssubhan return (err);
8923d808a52Ssubhan
8933d808a52Ssubhan err = callback_fn(chdh, c_args);
8943d808a52Ssubhan
8953d808a52Ssubhan if ((err = do_walk(chdh, classname, c_args, callback_fn)) !=
8962917a9c9Sschwartz PICL_WALK_CONTINUE)
8973d808a52Ssubhan return (err);
8983d808a52Ssubhan
8993d808a52Ssubhan err = picl_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh,
9002917a9c9Sschwartz sizeof (chdh));
9013d808a52Ssubhan }
9023d808a52Ssubhan if (err == PICL_PROPNOTFOUND) /* end of a branch */
9033d808a52Ssubhan return (PICL_WALK_CONTINUE);
9043d808a52Ssubhan return (err);
9053d808a52Ssubhan }
9061ba18ff1Sjimand
9071ba18ff1Sjimand int
get_proc_mode(void)9081ba18ff1Sjimand get_proc_mode(void)
9091ba18ff1Sjimand {
9101ba18ff1Sjimand picl_nodehdl_t nodeh;
9111ba18ff1Sjimand picl_prophdl_t proph;
9121ba18ff1Sjimand picl_errno_t err;
9131ba18ff1Sjimand
9141ba18ff1Sjimand err = picl_initialize();
9151ba18ff1Sjimand if (err != PICL_SUCCESS) {
9161ba18ff1Sjimand (void) log_printf("picl_initialize failed: %s\n",
9171ba18ff1Sjimand picl_strerror(err));
9181ba18ff1Sjimand return (err);
9191ba18ff1Sjimand }
9201ba18ff1Sjimand
9211ba18ff1Sjimand err = picl_get_node_by_path("/platform", &nodeh);
9221ba18ff1Sjimand if (err != PICL_SUCCESS) {
9231ba18ff1Sjimand (void) log_printf("Getting plat node failed: %s\n",
9241ba18ff1Sjimand picl_strerror(err));
9251ba18ff1Sjimand return (err);
9261ba18ff1Sjimand }
9271ba18ff1Sjimand
9281ba18ff1Sjimand err = picl_get_prop_by_name(nodeh, "SPARC64-VII-mode", &proph);
9291ba18ff1Sjimand if (err != PICL_SUCCESS) {
9301ba18ff1Sjimand /* Do not display error message */
9311ba18ff1Sjimand return (err);
9321ba18ff1Sjimand }
9331ba18ff1Sjimand
9341ba18ff1Sjimand (void) picl_shutdown();
9351ba18ff1Sjimand
9361ba18ff1Sjimand return (err);
9371ba18ff1Sjimand }
938