2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <string.h>
2N/A#include <fm/topo_mod.h>
2N/A#include <fm/topo_hc.h>
2N/A#include <sys/fm/protocol.h>
2N/A/*
2N/A * xfp.c
2N/A * sun4v specific xfp enumerators
2N/A */
2N/A
2N/A#ifdef __cplusplus
2N/Aextern "C" {
2N/A#endif
2N/A
2N/A#define XFP_VERSION TOPO_VERSION
2N/A
2N/Astatic int xfp_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
2N/A topo_instance_t, void *, void *);
2N/A
2N/Astatic const topo_modops_t xfp_ops =
2N/A { xfp_enum, NULL };
2N/A
2N/Aconst topo_modinfo_t xfp_info =
2N/A {XFP, FM_FMRI_SCHEME_HC, XFP_VERSION, &xfp_ops};
2N/A
2N/Astatic const topo_pgroup_info_t xfp_auth_pgroup = {
2N/A FM_FMRI_AUTHORITY,
2N/A TOPO_STABILITY_PRIVATE,
2N/A TOPO_STABILITY_PRIVATE,
2N/A 1
2N/A};
2N/A
2N/A/*ARGSUSED*/
2N/Aint
2N/A_topo_init(topo_mod_t *mod, topo_version_t version)
2N/A{
2N/A /*
2N/A * Turn on module debugging output
2N/A */
2N/A if (getenv("TOPOXFPDBG") != NULL)
2N/A topo_mod_setdebug(mod);
2N/A topo_mod_dprintf(mod, "initializing xfp enumerator\n");
2N/A
2N/A if (topo_mod_register(mod, &xfp_info, TOPO_VERSION) < 0) {
2N/A topo_mod_dprintf(mod, "xfp registration failed: %s\n",
2N/A topo_mod_errmsg(mod));
2N/A return (-1); /* mod errno already set */
2N/A }
2N/A topo_mod_dprintf(mod, "xfp enum initd\n");
2N/A return (0);
2N/A}
2N/A
2N/Avoid
2N/A_topo_fini(topo_mod_t *mod)
2N/A{
2N/A topo_mod_unregister(mod);
2N/A}
2N/A
2N/Astatic tnode_t *
2N/Axfp_tnode_create(topo_mod_t *mod, tnode_t *parent,
2N/A const char *name, topo_instance_t i, void *priv)
2N/A{
2N/A int err;
2N/A nvlist_t *fmri;
2N/A tnode_t *ntn;
2N/A nvlist_t *auth = topo_mod_auth(mod, parent);
2N/A
2N/A fmri = topo_mod_hcfmri(mod, parent, FM_HC_SCHEME_VERSION, name, i,
2N/A NULL, auth, NULL, NULL, NULL);
2N/A nvlist_free(auth);
2N/A
2N/A if (fmri == NULL) {
2N/A topo_mod_dprintf(mod,
2N/A "Unable to make nvlist for %s bind: %s.\n",
2N/A name, topo_mod_errmsg(mod));
2N/A return (NULL);
2N/A }
2N/A
2N/A ntn = topo_node_bind(mod, parent, name, i, fmri);
2N/A nvlist_free(fmri);
2N/A if (ntn == NULL) {
2N/A topo_mod_dprintf(mod,
2N/A "topo_node_bind (%s%d/%s%d) failed: %s\n",
2N/A topo_node_name(parent), topo_node_instance(parent),
2N/A name, i,
2N/A topo_strerror(topo_mod_errno(mod)));
2N/A return (NULL);
2N/A }
2N/A
2N/A topo_node_setspecific(ntn, priv);
2N/A if (topo_pgroup_create(ntn, &xfp_auth_pgroup, &err) == 0) {
2N/A /* chassis */
2N/A (void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
2N/A FM_FMRI_AUTH_V1_CHASSIS_MFG, &err);
2N/A (void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
2N/A FM_FMRI_AUTH_V1_CHASSIS_NM, &err);
2N/A (void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
2N/A FM_FMRI_AUTH_V1_CHASSIS_PN, &err);
2N/A (void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
2N/A FM_FMRI_AUTH_V1_CHASSIS_SN, &err);
2N/A (void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
2N/A FM_FMRI_AUTH_V1_CHASSIS_ALIAS, &err);
2N/A }
2N/A return (ntn);
2N/A}
2N/Astatic int
2N/Axfp_fru_set(topo_mod_t *mp, tnode_t *tn)
2N/A{
2N/A nvlist_t *fmri;
2N/A int err, e;
2N/A
2N/A if (topo_node_resource(tn, &fmri, &err) < 0 ||
2N/A fmri == NULL) {
2N/A topo_mod_dprintf(mp, "FRU_fmri_set error: %s\n",
2N/A topo_strerror(topo_mod_errno(mp)));
2N/A return (topo_mod_seterrno(mp, err));
2N/A }
2N/A e = topo_node_fru_set(tn, fmri, 0, &err);
2N/A nvlist_free(fmri);
2N/A if (e < 0)
2N/A return (topo_mod_seterrno(mp, err));
2N/A return (0);
2N/A}
2N/Astatic int
2N/Axfp_label_set(topo_mod_t *mod, tnode_t *parent, tnode_t *node,
2N/A topo_instance_t n)
2N/A{
2N/A char *label = NULL;
2N/A char *plabel = NULL;
2N/A const char *xfplabel = "/XFP";
2N/A int err, len;
2N/A
2N/A if (topo_node_label(parent, &plabel, &err) != 0 ||
2N/A plabel == NULL) {
2N/A return (-1);
2N/A }
2N/A
2N/A len = strlen(plabel) + strlen(xfplabel) + 2;
2N/A label = topo_mod_alloc(mod, len);
2N/A (void) snprintf(label, len, "%s%s%d", plabel, xfplabel, n);
2N/A topo_mod_strfree(mod, plabel);
2N/A
2N/A if (label != NULL) {
2N/A if (topo_prop_set_string(node, TOPO_PGROUP_PROTOCOL,
2N/A TOPO_PROP_LABEL, TOPO_PROP_IMMUTABLE, label,
2N/A &err) != 0) {
2N/A topo_mod_strfree(mod, label);
2N/A return (topo_mod_seterrno(mod, err));
2N/A }
2N/A }
2N/A topo_mod_free(mod, label, len);
2N/A return (0);
2N/A}
2N/A/*ARGSUSED*/
2N/Astatic tnode_t *
2N/Axfp_declare(tnode_t *parent, const char *name, topo_instance_t i,
2N/A void *priv, topo_mod_t *mod)
2N/A{
2N/A tnode_t *ntn;
2N/A nvlist_t *fmri = NULL;
2N/A int e;
2N/A
2N/A if ((ntn = xfp_tnode_create(mod, parent, name, i, NULL)) == NULL) {
2N/A topo_mod_dprintf(mod, "%s ntn = NULL\n", name);
2N/A return (NULL);
2N/A }
2N/A
2N/A (void) xfp_fru_set(mod, ntn);
2N/A
2N/A (void) xfp_label_set(mod, parent, ntn, i);
2N/A /* set ASRU to resource fmri */
2N/A if (topo_prop_get_fmri(ntn, TOPO_PGROUP_PROTOCOL,
2N/A TOPO_PROP_RESOURCE, &fmri, &e) == 0)
2N/A (void) topo_node_asru_set(ntn, fmri, 0, &e);
2N/A nvlist_free(fmri);
2N/A
2N/A return (ntn);
2N/A}
2N/A
2N/A/*ARGSUSED*/
2N/Astatic int
2N/Axfp_enum(topo_mod_t *mod, tnode_t *rnode, const char *name,
2N/A topo_instance_t min, topo_instance_t max, void *notused, void *data)
2N/A{
2N/A if (strcmp(name, XFP) != 0) {
2N/A topo_mod_dprintf(mod,
2N/A "Currently only know how to enumerate %s components.\n",
2N/A XFP);
2N/A return (0);
2N/A }
2N/A if (xfp_declare(rnode, name, min, data, mod) == NULL)
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}