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) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A/*
2N/A * The routines in this file are what's needed to create a bay topo node.
2N/A */
2N/A
2N/A#include <strings.h>
2N/A#include <devid.h>
2N/A#include <inttypes.h>
2N/A#include <fm/topo_mod.h>
2N/A#include <fm/topo_list.h>
2N/A#include <sys/fm/protocol.h>
2N/A#include <sys/utsname.h>
2N/A#include <sys/systeminfo.h>
2N/A#include <bay_impl.h>
2N/A
2N/Astatic const topo_pgroup_info_t sys_pgroup = {
2N/A TOPO_PGROUP_SYSTEM,
2N/A TOPO_STABILITY_PRIVATE,
2N/A TOPO_STABILITY_PRIVATE,
2N/A 1
2N/A};
2N/A
2N/Astatic const topo_pgroup_info_t 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/*
2N/A * Set the label.
2N/A */
2N/Aint
2N/Abay_set_label(topo_mod_t *mod, bay_t *bp, tnode_t *tn)
2N/A{
2N/A int rv;
2N/A int err;
2N/A
2N/A if (mod == NULL) {
2N/A return (-1);
2N/A }
2N/A
2N/A rv = topo_node_label_set(tn, bp->label, &err);
2N/A if (rv != 0) {
2N/A (void) topo_mod_seterrno(mod, err);
2N/A topo_mod_dprintf(mod,
2N/A "failed to set label (%s) for %s:%d: (%s)\n",
2N/A bp->label == NULL ? "NULL" : bp->label,
2N/A bp->hba_nm, bp->phy, topo_strerror(err));
2N/A }
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/A/*
2N/A * Create the authority pgroup and inherit info from the parent.
2N/A */
2N/Aint
2N/Abay_set_auth(topo_mod_t *mod, tnode_t *pnode, tnode_t *tn)
2N/A{
2N/A int rv;
2N/A int err;
2N/A nvlist_t *auth;
2N/A char *f = "bay_set_auth";
2N/A
2N/A if (mod == NULL || pnode == NULL || tn == NULL) {
2N/A return (-1);
2N/A }
2N/A
2N/A if ((topo_pgroup_create(tn, &auth_pgroup, &err) != 0) &&
2N/A (err != ETOPO_PROP_DEFD)) {
2N/A /* not existing and failed to create */
2N/A (void) topo_mod_seterrno(mod, err);
2N/A return (-1);
2N/A }
2N/A
2N/A /* get auth list from parent */
2N/A auth = topo_mod_auth(mod, pnode);
2N/A
2N/A /*
2N/A * Set the authority data.
2N/A *
2N/A * Continue even if some authority information is not available
2N/A * to enumerate as much as possible.
2N/A */
2N/A rv = topo_node_set_auth_chassis(mod, auth, tn);
2N/A if (rv != 0) {
2N/A topo_mod_dprintf(mod, "%s: failed to set chassis authority "
2N/A "for bay node\n", f);
2N/A }
2N/A
2N/A nvlist_free(auth);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Create the system pgoup and inherit the info from the parent.
2N/A */
2N/Aint
2N/Abay_set_system(topo_mod_t *mod, tnode_t *tn)
2N/A{
2N/A int rv;
2N/A int err;
2N/A struct utsname uts;
2N/A char isa[MAXNAMELEN];
2N/A
2N/A if (mod == NULL || tn == NULL) {
2N/A topo_mod_dprintf(mod, "bay_set_system: NULL args.\n");
2N/A return (-1);
2N/A }
2N/A
2N/A rv = topo_pgroup_create(tn, &sys_pgroup, &err);
2N/A if (rv != 0 && err != ETOPO_PROP_DEFD) {
2N/A /* not existing and failed to create */
2N/A (void) topo_mod_seterrno(mod, err);
2N/A topo_mod_dprintf(mod,
2N/A "bay_set_system: failed to create system pgroup: %s.\n",
2N/A topo_strerror(err));
2N/A return (-1);
2N/A }
2N/A
2N/A rv = topo_prop_inherit(tn, TOPO_PGROUP_SYSTEM, TOPO_PROP_ISA, &err);
2N/A if (rv != 0 && err != ETOPO_PROP_DEFD) {
2N/A isa[0] = '\0';
2N/A rv = sysinfo(SI_ARCHITECTURE, isa, sizeof (isa));
2N/A if (rv == -1) {
2N/A topo_mod_dprintf(mod,
2N/A "bay_set_system: failed to get ISA: %d\n", errno);
2N/A }
2N/A
2N/A if (strnlen(isa, MAXNAMELEN) > 0) {
2N/A rv = topo_prop_set_string(tn, TOPO_PGROUP_SYSTEM,
2N/A TOPO_PROP_ISA, TOPO_PROP_IMMUTABLE, isa, &err);
2N/A if (rv != 0) {
2N/A /* failed to inherit or create prop */
2N/A (void) topo_mod_seterrno(mod, err);
2N/A topo_mod_dprintf(mod,
2N/A "bay_set_system: failed to set isa "
2N/A "system property: %s\n",
2N/A topo_strerror(err));
2N/A }
2N/A }
2N/A }
2N/A
2N/A rv = topo_prop_inherit(tn, TOPO_PGROUP_SYSTEM, TOPO_PROP_MACHINE,
2N/A &err);
2N/A if (rv != 0 && err != ETOPO_PROP_DEFD) {
2N/A rv = uname(&uts);
2N/A if (rv == -1) {
2N/A (void) topo_mod_seterrno(mod, errno);
2N/A topo_mod_dprintf(mod,
2N/A "bay_set_system: failed to get uname: %d\n",
2N/A errno);
2N/A }
2N/A
2N/A if (strnlen(uts.machine, sizeof (uts.machine)) > 0) {
2N/A rv = topo_prop_set_string(tn, TOPO_PGROUP_SYSTEM,
2N/A TOPO_PROP_MACHINE, TOPO_PROP_IMMUTABLE,
2N/A uts.machine, &err);
2N/A if (rv != 0) {
2N/A /* failed to inherit or create prop */
2N/A (void) topo_mod_seterrno(mod, err);
2N/A topo_mod_dprintf(mod,
2N/A "bay_set_system: failed to set "
2N/A "system machine property: %s\n",
2N/A topo_strerror(err));
2N/A }
2N/A }
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Create bay topo node.
2N/A */
2N/Aint
2N/Abay_create_tnode(topo_mod_t *mod, tnode_t *pnode, tnode_t **tnode, bay_t *bayp)
2N/A{
2N/A int rv = 0;
2N/A nvlist_t *fmri = NULL;
2N/A nvlist_t *auth = NULL;
2N/A topo_instance_t instance = bayp->inst;
2N/A
2N/A char *f = "bay_create_tnode";
2N/A
2N/A topo_mod_dprintf(mod, "%s: parent node (%s) instance(%d)\n",
2N/A f, topo_node_name(pnode), instance);
2N/A
2N/A /* create FMRI */
2N/A auth = topo_mod_auth(mod, pnode);
2N/A
2N/A fmri = topo_mod_hcfmri(mod,
2N/A cmp_str(topo_node_name(pnode), "hc") ? NULL : pnode,
2N/A FM_HC_SCHEME_VERSION, BAY, instance, NULL, auth, NULL, NULL, NULL);
2N/A if (fmri == NULL) {
2N/A topo_mod_dprintf(mod, "%s: failed to create fmri: %s\n",
2N/A f, topo_strerror(topo_mod_errno(mod)));
2N/A rv = -1;
2N/A goto out;
2N/A }
2N/A
2N/A /* bind the node to the parent */
2N/A *tnode = topo_node_bind(mod, pnode, BAY, instance, fmri);
2N/A if (*tnode == NULL) {
2N/A topo_mod_dprintf(mod, "%s: failed to bind node: %s\n",
2N/A f, topo_strerror(topo_mod_errno(mod)));
2N/A rv = -1;
2N/A goto out;
2N/A }
2N/A
2N/A /* set the label (bay_set_label) */
2N/A rv = bay_set_label(mod, bayp, *tnode);
2N/A if (rv != 0) {
2N/A /* report the error and drive on */
2N/A topo_mod_dprintf(mod,
2N/A "%s: failed to set label for %s:%d: (%s)\n",
2N/A f, bayp->hba_nm, bayp->phy,
2N/A topo_strerror(topo_mod_errno(mod)));
2N/A }
2N/A
2N/A /* set authority info (bay_set_auth) */
2N/A rv = bay_set_auth(mod, pnode, *tnode);
2N/A if (rv != 0) {
2N/A /* report the error and drive on */
2N/A topo_mod_dprintf(mod,
2N/A "%s: failed to set auth for %s:%d: (%s)\n",
2N/A f, bayp->hba_nm, bayp->phy,
2N/A topo_strerror(topo_mod_errno(mod)));
2N/A }
2N/A
2N/A /* don't set system info if under an external chassis */
2N/A if (cmp_str(topo_node_name(pnode), EXTERNALCHASSIS))
2N/A goto out;
2N/A
2N/A /* set the system info (bay_set_system) */
2N/A rv = bay_set_system(mod, *tnode);
2N/A if (rv != 0) {
2N/A /* report the error and drive on */
2N/A topo_mod_dprintf(mod,
2N/A "%s: failed to set system for %s:%d: (%s)\n",
2N/A f, bayp->hba_nm, bayp->phy,
2N/A topo_strerror(topo_mod_errno(mod)));
2N/A }
2N/Aout:
2N/A if (auth != NULL) {
2N/A nvlist_free(auth);
2N/A }
2N/A if (fmri != NULL) {
2N/A nvlist_free(fmri);
2N/A }
2N/A return (rv);
2N/A}