/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Opl platform specific PICL functions.
*
* called when :
* machine_type == MTYPE_OPL
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <kstat.h>
#include <fcntl.h>
#include <string.h>
#include <assert.h>
#include <libintl.h>
#include <note.h>
#include <dlfcn.h>
#include <errno.h>
#include <sys/systeminfo.h>
#include <sys/openpromio.h>
#include <sys/sysmacros.h>
#include <picl.h>
#include "picldefs.h"
#include <pdevinfo.h>
#include <display.h>
#include <libprtdiag.h>
#include <alloca.h>
#include "opl_picl.h"
#include <sys/pci_tools.h>
#if !defined(TEXT_DOMAIN)
#endif
char **outbuf);
int *ret);
int *ret);
/*
* Collect I/O nodes information.
*/
/* ARGSUSED */
static picl_errno_t
{
char *compatible;
int *reg_val;
int bus_type;
if (err != PICL_SUCCESS)
/* Do not proceed to parse this branch */
return (err);
/* Do not parse non-pci nodes */
return (PICL_INVALIDARG);
sizeof (parent_path));
if (err != PICL_SUCCESS)
/* Do not proceed to parse this branch */
return (err);
sizeof (board));
if (err == PICL_NORESPONSE)
/* Do not proceed to parse this branch */
return (err);
else if (err != PICL_PROPNOTFOUND) {
saved_board = board;
/* Save board node's pathname */
}
if (err != PICL_PROPNOTFOUND)
/* Walk through the children */
sizeof (picl_nodehdl_t));
while (err == PICL_SUCCESS) {
if (err != PICL_SUCCESS)
/* Do not proceed to parse this node */
return (err);
&nodeh, sizeof (picl_nodehdl_t));
continue;
}
if (err != PICL_SUCCESS) {
/* Do not proceed to parse this node */
return (err);
}
/*
* Get bus#, dev# and func# for this card from 'reg' property.
*/
if (err == PICL_SUCCESS) {
/* All of the array of bytes of "reg" have to be read */
return (PICL_FAILURE);
if (err != PICL_SUCCESS) {
/* Do not proceed to parse this node */
return (err);
}
if (reg_val[0] != 0) {
} else
}
&bus_type);
if (err != PICL_SUCCESS) {
/*
* get_lane_width will fail when run as non-root.
* Set bus_type to PCI_UNKN so that bus frequency,
* bus type and lane width will print as "--" or UNKN.
*/
}
if (err != PICL_SUCCESS)
/*
* Get the name of this card. If binding_name is found,
* name will be <nodename>-<binding_name>
*/
binding_name, sizeof (binding_name));
if (err == PICL_PROPNOTFOUND) {
/*
* if compatible prop is found, name will be
* <nodename>-<compatible>
*/
&compatible);
if (err == PICL_SUCCESS) {
}
} else if (err != PICL_SUCCESS) {
/* No binding-name or compatible */
}
/* Get the status of the card */
/* Get the model of this card */
if (err != PICL_SUCCESS)
else
/* Get revision id */
/* Get device id */
/* Get vendor id */
/*
* prtdiag -v prints all devices
*/
/* Print board number */
/* Print IO Type */
log_printf("%3d, %2d, %2d",
/* Print status */
&freq_max);
} else
log_printf(" -- , -- ");
/* Print Card Name */
/* Print Card Model */
log_printf("\n");
log_printf("\n");
log_printf("\n");
}
return (PICL_WALK_CONTINUE);
}
/*
* opl_display_pci
* Display all the PCI IO cards on this board.
*/
static int
{
log_printf("\n", 0);
log_printf("=========================", 0);
log_printf("=========================", 0);
log_printf("\n", 0);
log_printf("\n", 0);
"", "", 0);
log_printf("\n", 0);
" BDF", "State", "Act, Max", "Name", "Model", 0);
log_printf("\n");
"---", "-----", "----", " ------------------",
" ---------", "-----", "-----------",
"------------------------------",
"--------------------", 0);
log_printf("\n");
log_printf("\n");
log_printf("\n");
}
return (err);
}
/*
* return the first compatible value
*/
static int
{
char *pval;
if (err != PICL_SUCCESS)
return (err);
return (PICL_FAILURE);
if (err != PICL_SUCCESS) {
return (err);
}
return (PICL_SUCCESS);
}
return (PICL_FAILURE);
/* get first string from table */
if (err != PICL_SUCCESS)
return (err);
if (err != PICL_SUCCESS)
return (err);
if (err != PICL_SUCCESS)
return (err);
return (PICL_FAILURE);
if (err != PICL_SUCCESS) {
return (err);
}
return (PICL_SUCCESS);
}
int
{
err = picl_initialize();
if (err != PICL_SUCCESS) {
(void) log_printf("picl_initialize failed: %s\n",
picl_strerror(err));
return (err);
}
if (err != PICL_SUCCESS) {
(void) log_printf("Getting root node failed: %s\n",
picl_strerror(err));
return (err);
}
if (err != PICL_SUCCESS) {
(void) log_printf("Getting nodes by name failed: %s\n",
picl_strerror(err));
return (err);
}
(void) picl_shutdown();
return (err);
}
/*
* search children to get the node by the nodename
*/
static int
{
int err;
char *nodename;
return (PICL_FAILURE);
sizeof (picl_nodehdl_t));
while (err == PICL_SUCCESS) {
if (err != PICL_SUCCESS) {
&childh, sizeof (picl_nodehdl_t));
continue;
}
return (PICL_SUCCESS);
}
&childh, sizeof (picl_nodehdl_t));
}
return (err);
}
static int
{
char *path;
int fd;
return (PICL_FAILURE);
return (-1);
}
return (fd);
}
static uint32_t
{
int rval;
if (rval != 0) {
}
}
static uint16_t
{
int rval;
if (rval != 0) {
}
}
static uint8_t
{
int rval;
if (rval != 0) {
}
}
static picl_errno_t
{
if (device_path == NULL)
return (PICL_FAILURE);
if (fd == -1)
return (PICL_FAILURE);
/*
* Link Capabilities and Link Status registers are in the
* PCI-E capabilities register. They are at offset
* 0xc and 0x12 respectively. They are documented in section
* 7.8 of the PCI Express Base Specification. The address of
* that structure is not fixed, it's kind of a linked list.
* The Capabilities Pointer reg (8 bits) is always at 0x34.
* It contains a pointer to the first capabilities structure.
* For each capability structure, the first 8 bits is the capability
* ID. The next 8 bits is the pointer to the next structure.
* If the Next Cap register is zero, it's the end of the list.
* The capability ID for the PCI-E strucutre is 0x10. The idea
* is to follow the links until you find a Cap ID of 0x10, then
* read the registers at 0xc and 0x12 from there.
* If there's no Cap ID 0x10, then it's not a PCI-E device.
*/
if (ret != 0) {
/* ioctl failure */
return (PICL_FAILURE);
}
if (ret != 0) {
/* ioctl failure */
return (PICL_FAILURE);
}
while (cap_ptr != 0) {
if (capid == PCI_CAP_ID_PCI_E) {
PCIE_LINKCAP, &ret);
if (ret != 0) {
return (PICL_FAILURE);
}
if (ret != 0) {
return (PICL_FAILURE);
}
} else if (capid == PCI_CAP_ID_PCIX) {
if (ret != 0) {
/* ioctl failure */
return (PICL_FAILURE);
}
/* This is a PCI-X bridge */
if (ret != 0) {
/* ioctl failure */
return (PICL_FAILURE);
}
if (sec_status & PCI_SEC_133)
if (sec_status & PCI_SEC_266)
if (sec_status & PCI_SEC_533)
if (mode) {
int speed;
if (mode == PCI_MODE_66)
speed = PCI_FREQ_66;
else if (mode == PCI_MODE_100)
else if (mode == PCI_MODE_133)
}
} else { /* Leaf device */
if (ret != 0) {
/* ioctl failure */
return (PICL_FAILURE);
}
if (pcix_status &
(PCI_LEAF_ULONG << PCI_SHIFT_133))
if (pcix_status &
(PCI_LEAF_ULONG << PCI_SHIFT_266))
if (pcix_status &
(PCI_LEAF_ULONG << PCI_SHIFT_533))
}
}
if (ret != 0) {
/* ioctl failure */
return (PICL_FAILURE);
}
}
return (PICL_FAILURE);
}
return (PICL_SUCCESS);
}
static int
{
if (err == PICL_SUCCESS)
return (1);
return (0);
}
/*
* get the clock frequency
*/
static int
{
int err;
*freq_max = PCI_FREQ_33;
if (is_66mhz_capable(modh))
*freq_max = PCI_FREQ_66;
if (err != PICL_SUCCESS)
return (err);
return (PICL_SUCCESS);
}
static uint64_t
{
int err;
if (err != PICL_SUCCESS) {
return (0);
}
/*
* If it is not an int or uint prop, return failure
*/
*ret = PICL_FAILURE;
return (0);
}
/* uint prop */
case sizeof (uint8_t):
return (uint8v);
case sizeof (uint16_t):
return (uint16v);
case sizeof (uint32_t):
return (uint32v);
case sizeof (uint64_t):
return (uint64v);
default: /* not supported size */
*ret = PICL_FAILURE;
return (0);
}
}
/*
* recursively visit all nodes
*/
static picl_errno_t
{
sizeof (chdh));
while (err == PICL_SUCCESS) {
if (err != PICL_SUCCESS)
return (err);
return (err);
sizeof (chdh));
}
return (PICL_WALK_CONTINUE);
return (err);
}
int
get_proc_mode(void)
{
err = picl_initialize();
if (err != PICL_SUCCESS) {
(void) log_printf("picl_initialize failed: %s\n",
picl_strerror(err));
return (err);
}
if (err != PICL_SUCCESS) {
(void) log_printf("Getting plat node failed: %s\n",
picl_strerror(err));
return (err);
}
if (err != PICL_SUCCESS) {
/* Do not display error message */
return (err);
}
(void) picl_shutdown();
return (err);
}