/*
* 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
*/
/*
*/
#include <assert.h>
#include <alloca.h>
#include <string.h>
#include <strings.h>
#include <limits.h>
#include <fm/topo_mod.h>
#include <libdevinfo.h>
#include <hostbridge.h>
#include <pcibus.h>
#include <did.h>
#include <did_props.h>
const char *, const char *, const char *);
const char *, const char *, const char *);
const char *, const char *, const char *);
const char *, const char *, const char *);
const char *, const char *, const char *);
const char *, const char *, const char *);
const char *, const char *, const char *);
const char *, const char *, const char *);
const char *, const char *, const char *);
const char *, const char *, const char *);
const char *, const char *, const char *);
const char *, const char *, const char *);
/*
* Arrays of "property translation routines" to set the properties a
* given type of topology node should have.
*
* Note that the label_set translation *MUST COME BEFORE* the FRU
* translation. For the near term we're setting the FRU fmri to
* be a legacy-hc style FMRI based on the label, so the label needs
* to have been set before we do the FRU translation.
*
*/
1
}; /* Request to create protocol will be ignored by libtopo */
{ "serd_io_device_nonfatal_btlp_n", &io_pgroup,
"serd_io_device_nonfatal_btlp_n", maybe_di_uint_to_dec_str },
{ "serd_io_device_nonfatal_btlp_t", &io_pgroup,
"serd_io_device_nonfatal_btlp_t", maybe_di_chars_copy },
{ "serd_io_device_nonfatal_bdllp_n", &io_pgroup,
"serd_io_device_nonfatal_bdllp_n", maybe_di_uint_to_dec_str },
{ "serd_io_device_nonfatal_bdllp_t", &io_pgroup,
"serd_io_device_nonfatal_bdllp_t", maybe_di_chars_copy },
{ "serd_io_device_nonfatal_re_n", &io_pgroup,
"serd_io_device_nonfatal_re_n", maybe_di_uint_to_dec_str },
{ "serd_io_device_nonfatal_re_t", &io_pgroup,
"serd_io_device_nonfatal_re_t", maybe_di_chars_copy },
{ "serd_io_device_nonfatal_rto_n", &io_pgroup,
"serd_io_device_nonfatal_rto_n", maybe_di_uint_to_dec_str },
{ "serd_io_device_nonfatal_rto_t", &io_pgroup,
"serd_io_device_nonfatal_rto_t", maybe_di_chars_copy },
{ "serd_io_device_nonfatal_rnr_n", &io_pgroup,
"serd_io_device_nonfatal_rnr_n", maybe_di_uint_to_dec_str },
{ "serd_io_device_nonfatal_rnr_t", &io_pgroup,
"serd_io_pciex_corrlink-bus_rnr_t", maybe_di_chars_copy },
{ "serd_io_pciex_corrlink-bus_btlp_n", &io_pgroup,
"serd_io_pciex_corrlink-bus_btlp_n", maybe_di_uint_to_dec_str },
{ "serd_io_pciex_corrlink-bus_btlp_t", &io_pgroup,
"serd_io_pciex_corrlink-bus_btlp_t", maybe_di_chars_copy },
{ "serd_io_pciex_corrlink-bus_bdllp_n", &io_pgroup,
"serd_io_pciex_corrlink-bus_bdllp_n", maybe_di_uint_to_dec_str },
{ "serd_io_pciex_corrlink-bus_bdllp_t", &io_pgroup,
"serd_io_pciex_corrlink-bus_bdllp_t", maybe_di_chars_copy },
{ "serd_io_pciex_corrlink-bus_re_n", &io_pgroup,
"serd_io_pciex_corrlink-bus_re_n", maybe_di_uint_to_dec_str },
{ "serd_io_pciex_corrlink-bus_re_t", &io_pgroup,
"serd_io_pciex_corrlink-bus_re_t", maybe_di_chars_copy },
{ "serd_io_pciex_corrlink-bus_rto_n", &io_pgroup,
"serd_io_pciex_corrlink-bus_rto_n", maybe_di_uint_to_dec_str },
{ "serd_io_pciex_corrlink-bus_rto_t", &io_pgroup,
"serd_io_pciex_corrlink-bus_rto_t", maybe_di_chars_copy },
{ "serd_io_pciex_corrlink-bus_rnr_n", &io_pgroup,
"serd_io_pciex_corrlink-bus_rnr_n", maybe_di_uint_to_dec_str },
{ "serd_io_pciex_corrlink-bus_rnr_t", &io_pgroup,
"serd_io_pciex_corrlink-bus_rnr_t", maybe_di_chars_copy },
};
};
};
/*
* These props need to be put at the end of table. x86pi has its
* own way to set them.
*/
};
/*
* These props need to be put at the end of table. x86pi has its
* own way to set them.
*/
};
};
/*
* These props need to be put at the end of table. x86pi has its
* own way to set them.
*/
};
/*
* If this devinfo node came originally from OBP data, we'll have prom
* properties associated with the node where we can find properties of
* interest. We ignore anything after the the first four bytes of the
* property, and interpet those first four bytes as our unsigned
* integer. If we don't find the property or it's not large enough,
* 'val' will remained unchanged and we'll return -1. Otherwise 'val'
* gets updated with the property value and we return 0.
*/
static int
{
return (-1);
continue;
return (0);
}
}
return (-1);
}
/*
* If this devinfo node was added by the PCI hotplug framework it
* doesn't have the PROM properties, but hopefully has the properties
* we're looking for attached directly to the devinfo node. We only
* care about the first four bytes of the property, which we read as
* our unsigned integer. The remaining bytes are ignored. If we
* don't find the property we're looking for, or can't get its value,
* 'val' remains unchanged and we return -1. Otherwise 'val' gets the
* property value and we return 0.
*/
static int
{
continue;
return (0);
}
}
return (-1);
}
int
{
return (-1);
return (0);
}
int
{
return (-1);
*sz = -1;
continue;
break;
}
}
if (*sz < 0) {
if (*sz < 0)
continue;
break;
}
}
}
if (*sz < 0)
return (-1);
return (0);
}
/*
* fix_dev_prop -- sometimes di_devfs_path() doesn't tell the whole
* story, leaving off the device and function number. Chances are if
* devfs doesn't put these on then we'll never see this device as an
* error detector called out in an ereport. Unfortunately, there are
* races and we sometimes do get ereports from devices that devfs
* decides aren't there. For example, the error injector card seems
* to bounce in and out of existence according to devfs. We tack on
* the missing dev and fn here so that the DEV property used to look
* up the topology node is correct.
*/
static char *
{
char *lastslash;
char *newpath;
int need;
/*
* We only care about the last component of the dev path. If
* we don't find a slash, something is weird.
*/
/*
* If an @ sign is present in the last component, the
* di_devfs_path() result had the device,fn unit-address.
* In that case there's nothing we need do.
*/
return (path);
if (fnno == 0)
else
need++;
return (NULL);
}
if (fnno == 0)
else
return (newpath);
}
/*
* dev_for_hostbridge() -- For hostbridges we truncate the devfs path
* after the first element in the bus address.
*/
static char *
{
char *lastslash;
char *newpath;
char *comma;
int plen;
/*
* We only care about the last component of the dev path. If
* we don't find a slash, something is weird.
*/
/*
* Find the comma in the last component component@x,y, and
* truncate the comma and any following number.
*/
*comma = '\0';
return (NULL);
}
*comma = ',';
return (newpath);
}
/*ARGSUSED*/
static int
{
int d, e, f;
/*
* If this topology node represents a function of device,
* set the ASRU to a dev scheme FMRI based on the value of
* di_devfs_path(). If that path is NULL, set the ASRU to
* be the resource describing this topology node. If this
* isn't a function, inherit any ASRU from the parent.
*/
/*
* Dup the path, dev_path_fix() may replace it and
* dev_path_fix() wouldn't know to use
* di_devfs_path_free()
*/
}
"dev:///%s fmri creation failed.\n", fpath);
return (-1);
}
} else {
TOPO_PROP_RESOURCE, &fmri, &e) < 0)
return (topo_mod_seterrno(mp, e));
}
return (topo_mod_seterrno(mp, e));
}
return (0);
}
return (0);
}
/*
* Set the FRU property to the hc fmri of this tnode
*/
int
{
int err, e;
}
if (e < 0)
return (0);
}
tnode_t *
{
}
return (pnode);
}
static int
{
int err = 0;
return (-1);
return (-1);
return (-1);
return (0);
}
static int
{
int err = 0;
return (-1);
return (-1);
return (-1);
return (0);
}
/*ARGSUSED*/
static int
{
char *nm;
int e = 0, err = 0;
/*
* If this is a PCIEX_BUS and its parent is a PCIEX_ROOT,
* check for a CPUBOARD predecessor. If found, inherit its
* parent's FRU. Otherwise, continue with FRU set.
*/
return (0);
}
/*
* If this topology node represents something other than an
* ioboard or a device that implements a slot, inherit the
* parent's FRU value. If there is no label, inherit our
* parent's FRU value. Otherwise, munge up an fmri based on
* the label.
*/
return (0);
}
/*
* If ioboard, set fru fmri to hc fmri
*/
return (e);
}
if (topo_method_invoke(tn,
}
} else
return (0);
}
/*ARGSUSED*/
static int
{
char *label;
int err;
/*
* If this is a PCIEX_BUS and its parent is a PCIEX_ROOT,
* check for a CPUBOARD predecessor. If found, inherit its
* parent's Label. Otherwise, continue with label set.
*/
return (0);
}
0) {
}
if (topo_method_invoke(tn,
}
}
}
return (0);
}
/*ARGSUSED*/
static int
{
int err;
int e = 0;
switch (excap & PCIE_PCIECAP_DEV_TYPE_MASK) {
break;
case PCIE_PCIECAP_DEV_TYPE_UP:
break;
break;
break;
break;
break;
}
if (e != 0)
return (0);
}
/*ARGSUSED*/
static int
{
char *dnpath;
int d, f;
int err, e;
}
return (-1);
}
/* The DEV path is modified for hostbridges */
} else {
}
return (-1);
e = topo_prop_set_string(tn,
if (e != 0)
return (0);
}
/*ARGSUSED*/
static int
{
char *dnm;
int err;
return (0);
if (topo_prop_set_string(tn,
return (0);
}
/*ARGSUSED*/
static int
{
char *dnm;
int err;
return (0);
return (0); /* driver maybe detached, return success */
&err) < 0) {
}
return (0);
}
/*ARGSUSED*/
static int
{
char *tmpbuf;
int err, e;
return (0);
e = topo_prop_set_string(tn,
if (e != 0)
return (0);
}
static int
{
int e;
if (topo_prop_set_string(tn,
return (topo_mod_seterrno(mp, e));
return (0);
}
static int
{
uint_t v;
return (0);
}
static int
{
int e;
if (topo_prop_set_string(tn,
return (topo_mod_seterrno(mp, e));
return (0);
}
static int
{
uint_t v;
return (0);
}
static int
const char *tpnm)
{
int err, e;
return (0);
/*LINTED*/
if (e != 0)
return (0);
}
/*ARGSUSED*/
static int
const char *tpnm)
{
int bdf;
int e;
return (0);
if (topo_prop_set_string(tn,
return (0);
}
int
{
int i, r, e;
for (i = 0; i < txnum; i++) {
/*
* Ensure the property group has been created.
*/
< 0) {
if (e != ETOPO_PROP_DEFD)
return (topo_mod_seterrno(mp, e));
}
}
"Setting property %s in group %s.\n",
if (r != 0) {
return (-1);
}
}
return (0);
}