diff options
author | robj <none@none> | 2008-07-31 17:35:39 -0700 |
---|---|---|
committer | robj <none@none> | 2008-07-31 17:35:39 -0700 |
commit | 825ba0f20a74fd9c5d0d1ce2c195da2cc88a7f77 (patch) | |
tree | 96f964ef7747dc494f62cde1ea099168464a1dd1 /usr/src/lib | |
parent | 3eceedbb4b7e889e84a21828cc72ca79007828f3 (diff) | |
download | illumos-gate-825ba0f20a74fd9c5d0d1ce2c195da2cc88a7f77.tar.gz |
PSARC 2008/428 Extending libnvpair for type double
PSARC 2008/463 Extending HC FMRI scheme to represent sensors/indicators
6579615 fmtopo -e has lots of memory leaks
6635159 libtopo: extend hc scheme to allow for representing sensors and indicators in the topology
6692392 fmtopo -x doesn't handle property methods properly
6718703 Need to extend libnvpair to support type double
6718712 libtopo: Need to implement facility provider module for IPMI
6722594 libtopo: the topo_prop_set_* interfaces need to learn to play well with propmethods
6727190 libtopo: add support for node properties of type double
6727459 libipmi: need interface to convert raw sensor readings to unit-based values
6727470 libipmi: need convenience routine to convert sensor unit defines to string
6729595 libtopo: add <set> case in fan and psu xml maps for SUN-FIRE-X4600-M2
6732318 fmd: small leak in sysevent modelling code
Diffstat (limited to 'usr/src/lib')
35 files changed, 4228 insertions, 207 deletions
diff --git a/usr/src/lib/fm/topo/libtopo/Makefile.com b/usr/src/lib/fm/topo/libtopo/Makefile.com index e2e2a4e69a..dfc7af6ca0 100644 --- a/usr/src/lib/fm/topo/libtopo/Makefile.com +++ b/usr/src/lib/fm/topo/libtopo/Makefile.com @@ -59,6 +59,7 @@ LIBSRCS = \ topo_snap.c \ topo_string.c \ topo_subr.c \ + topo_tables.c \ topo_tree.c \ topo_xml.c @@ -72,7 +73,7 @@ LIBS = $(DYNLIB) $(LINTLIB) SRCDIR = ../common -CLEANFILES += ../common/topo_error.c +CLEANFILES += $(SRCDIR)/topo_error.c $(SRCDIR)/topo_tables.c CPPFLAGS += -I../common -I/usr/include/libxml2 -I. CFLAGS += $(CCVERBOSE) $(C_BIGPICFLAGS) @@ -113,5 +114,8 @@ pics/%.o: ../$(MACH)/%.c sh ../common/mkerror.sh hdlerrors < ../common/libtopo.h >> $@ sh ../common/mkerror.sh moderrors < ../common/topo_mod.h >> $@ +$(SRCDIR)/topo_tables.c: $(SRCDIR)/mktables.sh $(SRCDIR)/libtopo.h + sh $(SRCDIR)/mktables.sh $(SRCDIR)/libtopo.h > $@ + include ../../../../Makefile.targ include ../../../Makefile.targ diff --git a/usr/src/lib/fm/topo/libtopo/common/hc.c b/usr/src/lib/fm/topo/libtopo/common/hc.c index 79daf9b2b5..bb19967c21 100644 --- a/usr/src/lib/fm/topo/libtopo/common/hc.c +++ b/usr/src/lib/fm/topo/libtopo/common/hc.c @@ -44,6 +44,7 @@ #include <sys/utsname.h> #include <topo_method.h> +#include <topo_module.h> #include <topo_subr.h> #include <topo_prop.h> #include <topo_tree.h> @@ -70,6 +71,8 @@ static int hc_fmri_prop_set(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, nvlist_t **); static int hc_fmri_pgrp_get(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, nvlist_t **); +static int hc_fmri_facility(topo_mod_t *, tnode_t *, topo_version_t, + nvlist_t *, nvlist_t **); static nvlist_t *hc_fmri_create(topo_mod_t *, nvlist_t *, int, const char *, topo_instance_t inst, const nvlist_t *, const char *, const char *, @@ -98,6 +101,9 @@ const topo_method_t hc_methods[] = { { TOPO_METH_PGRP_GET, TOPO_METH_PGRP_GET_DESC, TOPO_METH_PGRP_GET_VERSION, TOPO_STABILITY_INTERNAL, hc_fmri_pgrp_get }, + { TOPO_METH_FACILITY, TOPO_METH_FACILITY_DESC, + TOPO_METH_FACILITY_VERSION, TOPO_STABILITY_INTERNAL, + hc_fmri_facility }, { NULL } }; @@ -325,8 +331,10 @@ fmri_compare(topo_mod_t *mod, nvlist_t *nv1, nvlist_t *nv2) { uint8_t v1, v2; nvlist_t **hcp1, **hcp2; + nvlist_t *f1 = NULL, *f2 = NULL; int err, i; uint_t nhcp1, nhcp2; + char *f1str, *f2str; if (nvlist_lookup_uint8(nv1, FM_VERSION, &v1) != 0 || nvlist_lookup_uint8(nv2, FM_VERSION, &v2) != 0 || @@ -360,7 +368,28 @@ fmri_compare(topo_mod_t *mod, nvlist_t *nv1, nvlist_t *nv2) return (0); } - return (1); + /* + * Finally, check if the FMRI's represent a facility node. If so, then + * verify that the facilty type ("sensor"|"indicator") and facility + * name match. + */ + (void) nvlist_lookup_nvlist(nv1, FM_FMRI_FACILITY, &f1); + (void) nvlist_lookup_nvlist(nv2, FM_FMRI_FACILITY, &f2); + + if (f1 == NULL && f2 == NULL) + return (1); + else if (f1 == NULL || f2 == NULL) + return (0); + + if (nvlist_lookup_string(f1, FM_FMRI_FACILITY_NAME, &f1str) == 0 && + nvlist_lookup_string(f2, FM_FMRI_FACILITY_NAME, &f2str) == 0 && + strcmp(f1str, f2str) == 0 && + nvlist_lookup_string(f1, FM_FMRI_FACILITY_TYPE, &f1str) == 0 && + nvlist_lookup_string(f2, FM_FMRI_FACILITY_TYPE, &f2str) == 0 && + strcmp(f1str, f2str) == 0) { + return (1); + } + return (0); } /*ARGSUSED*/ @@ -400,6 +429,7 @@ fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen) { nvlist_t **hcprs = NULL; nvlist_t *anvl = NULL; + nvlist_t *fnvl; uint8_t version; ssize_t size = 0; uint_t hcnprs; @@ -412,6 +442,7 @@ fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen) char *part = NULL; char *root = NULL; char *rev = NULL; + char *fname = NULL, *ftype = NULL; int more_auth = 0; int err, i; @@ -508,6 +539,22 @@ fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen) topo_fmristr_build(&size, buf, buflen, id, NULL, NULL); } + /* + * If the nvlist represents a facility node, then we append the + * facility type and name to the end of the string representation using + * the format below: + * + * ?<ftype>=<fname> + */ + if (nvlist_lookup_nvlist(nvl, FM_FMRI_FACILITY, &fnvl) == 0) { + if (nvlist_lookup_string(fnvl, FM_FMRI_FACILITY_NAME, + &fname) != 0 || nvlist_lookup_string(fnvl, + FM_FMRI_FACILITY_TYPE, &ftype) != 0) + return (0); + topo_fmristr_build(&size, buf, buflen, "?", NULL, NULL); + topo_fmristr_build(&size, buf, buflen, "=", ftype, fname); + } + return (size); } @@ -707,17 +754,17 @@ make_hc_pairs(topo_mod_t *mod, char *fmri, int *num) return (pa); } -void +int make_hc_auth(topo_mod_t *mod, char *fmri, char **serial, char **part, char **rev, nvlist_t **auth) { char *starti, *startn, *endi, *copy; - char *aname, *aid, *fs; + char *aname = NULL, *aid = NULL, *fs; nvlist_t *na = NULL; size_t len; if ((copy = topo_mod_strdup(mod, fmri + 5)) == NULL) - return; + return (-1); len = strlen(copy); @@ -729,7 +776,7 @@ char **rev, nvlist_t **auth) if (startn == NULL || fs == NULL) { topo_mod_strfree(mod, copy); - return; + return (0); } /* @@ -737,21 +784,21 @@ char **rev, nvlist_t **auth) * first slash */ if (startn > fs) - return; + goto hcabail; do { if (++startn >= copy + len) break; if ((starti = strchr(startn, '=')) == NULL) - break; + goto hcabail; *starti = '\0'; if (++starti > copy + len) - break; + goto hcabail; if ((aname = topo_mod_strdup(mod, startn)) == NULL) - break; + goto hcabail; startn = endi = strchr(starti, ':'); if (endi == NULL) @@ -759,10 +806,8 @@ char **rev, nvlist_t **auth) break; *endi = '\0'; - if ((aid = topo_mod_strdup(mod, starti)) == NULL) { - topo_mod_strfree(mod, aname); - break; - } + if ((aid = topo_mod_strdup(mod, starti)) == NULL) + goto hcabail; /* * Return possible serial, part and revision @@ -786,12 +831,74 @@ char **rev, nvlist_t **auth) } topo_mod_strfree(mod, aname); topo_mod_strfree(mod, aid); + aname = aid = NULL; } while (startn != NULL); *auth = na; topo_mod_free(mod, copy, len + 1); + return (0); + +hcabail: + topo_mod_free(mod, copy, len + 1); + topo_mod_strfree(mod, aname); + topo_mod_strfree(mod, aid); + nvlist_free(na); + return (-1); +} + + +/* + * This function creates an nvlist to represent the facility portion of an + * hc-scheme node, given a string representation of the fmri. This is called by + * hc_fmri_str2nvl. If the string does not contain a facility component + * (e.g. ?<ftype>=<fname>) then it bails early and returns 0. + * + * On failure it returns -1 and sets the topo mod errno + */ +int +make_facility(topo_mod_t *mod, char *str, nvlist_t **nvl) +{ + char *fac, *copy, *fname, *ftype; + nvlist_t *nf = NULL; + size_t len; + + if ((fac = strchr(str, '?')) == NULL) + return (0); + + ++fac; + if ((copy = topo_mod_strdup(mod, fac)) == NULL) + return (topo_mod_seterrno(mod, EMOD_NOMEM)); + + fac = copy; + len = strlen(fac); + + if ((fname = strchr(fac, '=')) == NULL) { + topo_mod_free(mod, copy, len + 1); + return (topo_mod_seterrno(mod, EMOD_FMRI_MALFORM)); + } + + fname[0] = '\0'; + ++fname; + ftype = fac; + + if (topo_mod_nvalloc(mod, &nf, NV_UNIQUE_NAME) != 0) { + topo_mod_free(mod, copy, len + 1); + return (topo_mod_seterrno(mod, EMOD_NOMEM)); + } + + if (nvlist_add_string(nf, FM_FMRI_FACILITY_NAME, fname) != 0 || + nvlist_add_string(nf, FM_FMRI_FACILITY_TYPE, ftype) != 0) { + topo_mod_free(mod, copy, len + 1); + return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); + } + + topo_mod_free(mod, copy, len + 1); + + *nvl = nf; + + return (0); } /*ARGSUSED*/ @@ -802,6 +909,7 @@ hc_fmri_str2nvl(topo_mod_t *mod, tnode_t *node, topo_version_t version, nvlist_t **pa = NULL; nvlist_t *nf = NULL; nvlist_t *auth = NULL; + nvlist_t *fac = NULL; char *str; char *serial = NULL, *part = NULL, *rev = NULL; int npairs; @@ -820,7 +928,9 @@ hc_fmri_str2nvl(topo_mod_t *mod, tnode_t *node, topo_version_t version, if ((pa = make_hc_pairs(mod, str, &npairs)) == NULL) return (topo_mod_seterrno(mod, EMOD_FMRI_MALFORM)); - make_hc_auth(mod, str, &serial, &part, &rev, &auth); + if (make_hc_auth(mod, str, &serial, &part, &rev, &auth) < 0) + goto hcfmbail; + if ((nf = hc_base_fmri_create(mod, auth, part, rev, serial)) == NULL) goto hcfmbail; if ((e = nvlist_add_uint32(nf, FM_FMRI_HC_LIST_SZ, npairs)) == 0) @@ -829,17 +939,26 @@ hc_fmri_str2nvl(topo_mod_t *mod, tnode_t *node, topo_version_t version, topo_mod_dprintf(mod, "construction of new hc nvl failed"); goto hcfmbail; } + + /* + * Clean-up + */ for (i = 0; i < npairs; i++) nvlist_free(pa[i]); topo_mod_free(mod, pa, npairs * sizeof (nvlist_t *)); - if (serial != NULL) - topo_mod_strfree(mod, serial); - if (part != NULL) - topo_mod_strfree(mod, part); - if (rev != NULL) - topo_mod_strfree(mod, rev); + topo_mod_strfree(mod, serial); + topo_mod_strfree(mod, part); + topo_mod_strfree(mod, rev); nvlist_free(auth); + if (make_facility(mod, str, &fac) == -1) + goto hcfmbail; + + if (fac != NULL) { + if (nvlist_add_nvlist(nf, FM_FMRI_FACILITY, fac) != 0) + goto hcfmbail; + } + *out = nf; return (0); @@ -850,13 +969,12 @@ hcfmbail: for (i = 0; i < npairs; i++) nvlist_free(pa[i]); topo_mod_free(mod, pa, npairs * sizeof (nvlist_t *)); - if (serial != NULL) - topo_mod_strfree(mod, serial); - if (part != NULL) - topo_mod_strfree(mod, part); - if (rev != NULL) - topo_mod_strfree(mod, rev); + + topo_mod_strfree(mod, serial); + topo_mod_strfree(mod, part); + topo_mod_strfree(mod, rev); nvlist_free(auth); + nvlist_free(nf); return (topo_mod_seterrno(mod, EMOD_FMRI_MALFORM)); } @@ -1053,6 +1171,7 @@ struct hc_walk { topo_walk_t *hcw_wp; nvlist_t **hcw_list; nvlist_t *hcw_fmri; + nvlist_t *hcw_fac; uint_t hcw_index; uint_t hcw_end; }; @@ -1151,7 +1270,7 @@ hc_walk_sibling(topo_mod_t *mod, tnode_t *node, struct hc_walk *hwp, /* * Generic walker for the hc-scheme topo tree. This function uses the - * hierachical nature of the hc-scheme to step through efficiently through + * hierachical nature of the hc-scheme to efficiently step through * the topo hc tree. Node lookups are done by topo_walk_byid() and * topo_walk_bysibling() at each component level to avoid unnecessary * traversal of the tree. hc_walker() never returns TOPO_WALK_NEXT, so @@ -1164,13 +1283,27 @@ hc_walker(topo_mod_t *mod, tnode_t *node, void *pdata) int i, err; struct hc_walk *hwp = (struct hc_walk *)pdata; char *name, *id; + char *fname, *ftype; topo_instance_t inst; boolean_t match; i = hwp->hcw_index; if (i > hwp->hcw_end) { - (void) topo_mod_seterrno(mod, ETOPO_PROP_NOENT); - return (TOPO_WALK_TERMINATE); + if (hwp->hcw_fac != NULL) { + if ((err = hwp->hcw_cb(mod, node, hwp->hcw_priv)) + != 0) { + (void) topo_mod_seterrno(mod, err); + topo_mod_dprintf(mod, "hc_walker: callback " + "failed: %s\n ", topo_mod_errmsg(mod)); + return (TOPO_WALK_ERR); + } + topo_mod_dprintf(mod, "hc_walker: callback " + "complete: terminate walk\n"); + return (TOPO_WALK_TERMINATE); + } else { + topo_mod_dprintf(mod, "hc_walker: node not found\n"); + return (TOPO_WALK_TERMINATE); + } } err = nvlist_lookup_string(hwp->hcw_list[i], FM_FMRI_HC_NAME, &name); @@ -1198,29 +1331,46 @@ hc_walker(topo_mod_t *mod, tnode_t *node, void *pdata) topo_mod_dprintf(mod, "hc_walker: walking node:%s=%d for hc:" "%s=%d at %d, end at %d \n", topo_node_name(node), topo_node_instance(node), name, inst, i, hwp->hcw_end); + if (i == hwp->hcw_end) { + /* - * We are at the end of the hc-list. Verify that - * the last node contains the name/instance we are looking for. + * We are at the end of the hc-list. Now, check for + * a facility leaf and walk one more time. */ - if (match) { - if ((err = hwp->hcw_cb(mod, node, hwp->hcw_priv)) - != 0) { - (void) topo_mod_seterrno(mod, err); - topo_mod_dprintf(mod, "hc_walker: callback " - "failed: %s\n ", topo_mod_errmsg(mod)); + if (hwp->hcw_fac != NULL) { + err = nvlist_lookup_string(hwp->hcw_fac, + FM_FMRI_FACILITY_NAME, &fname); + err |= nvlist_lookup_string(hwp->hcw_fac, + FM_FMRI_FACILITY_TYPE, &ftype); + if (err != 0) { + (void) topo_mod_seterrno(mod, EMOD_NVL_INVAL); return (TOPO_WALK_ERR); } + hwp->hcw_index++; + topo_mod_dprintf(mod, "hc_walker: walk to facility " + "node:%s=%s\n", fname, ftype); + return (topo_walk_byid(hwp->hcw_wp, fname, 0)); + } + + /* + * Otherwise, this is the node we're looking for. + */ + if ((err = hwp->hcw_cb(mod, node, hwp->hcw_priv)) != 0) { + (void) topo_mod_seterrno(mod, err); topo_mod_dprintf(mod, "hc_walker: callback " - "complete: terminate walk\n"); - return (TOPO_WALK_TERMINATE); + "failed: %s\n ", topo_mod_errmsg(mod)); + return (TOPO_WALK_ERR); } else { - topo_mod_dprintf(mod, "hc_walker: %s=%d\n " - "not found\n", name, inst); + topo_mod_dprintf(mod, "hc_walker: callback " + "complete: terminate walk\n"); return (TOPO_WALK_TERMINATE); } } + /* + * Move on to the next component in the hc-list + */ hwp->hcw_index = ++i; err = nvlist_lookup_string(hwp->hcw_list[i], FM_FMRI_HC_NAME, &name); err |= nvlist_lookup_string(hwp->hcw_list[i], FM_FMRI_HC_ID, &id); @@ -1230,8 +1380,6 @@ hc_walker(topo_mod_t *mod, tnode_t *node, void *pdata) } inst = atoi(id); - topo_mod_dprintf(mod, "hc_walker: walk byid of %s=%d \n", name, - inst); return (topo_walk_byid(hwp->hcw_wp, name, inst)); } @@ -1240,7 +1388,7 @@ static struct hc_walk * hc_walk_init(topo_mod_t *mod, tnode_t *node, nvlist_t *rsrc, topo_mod_walk_cb_t cb, void *pdata) { - int err; + int err, ret; uint_t sz; struct hc_walk *hwp; topo_walk_t *wp; @@ -1252,10 +1400,24 @@ hc_walk_init(topo_mod_t *mod, tnode_t *node, nvlist_t *rsrc, if (nvlist_lookup_nvlist_array(rsrc, FM_FMRI_HC_LIST, &hwp->hcw_list, &sz) != 0) { + topo_mod_dprintf(mod, "hc_walk_init: failed to lookup %s " + "nvlist\n", FM_FMRI_HC_LIST); topo_mod_free(mod, hwp, sizeof (struct hc_walk)); (void) topo_mod_seterrno(mod, EMOD_METHOD_INVAL); return (NULL); } + if ((ret = nvlist_lookup_nvlist(rsrc, FM_FMRI_FACILITY, &hwp->hcw_fac)) + != 0) { + if (ret != ENOENT) { + topo_mod_dprintf(mod, "hc_walk_init: unexpected error " + "looking up %s nvlist", FM_FMRI_FACILITY); + topo_mod_free(mod, hwp, sizeof (struct hc_walk)); + (void) topo_mod_seterrno(mod, EMOD_METHOD_INVAL); + return (NULL); + } else { + hwp->hcw_fac = NULL; + } + } hwp->hcw_fmri = rsrc; hwp->hcw_end = sz - 1; @@ -1264,6 +1426,8 @@ hc_walk_init(topo_mod_t *mod, tnode_t *node, nvlist_t *rsrc, hwp->hcw_cb = cb; if ((wp = topo_mod_walk_init(mod, node, hc_walker, (void *)hwp, &err)) == NULL) { + topo_mod_dprintf(mod, "hc_walk_init: topo_mod_walk_init failed " + "(%s)\n", topo_strerror(err)); topo_mod_free(mod, hwp, sizeof (struct hc_walk)); (void) topo_mod_seterrno(mod, err); return (NULL); @@ -1615,3 +1779,122 @@ hc_fmri_unusable(topo_mod_t *mod, tnode_t *node, topo_version_t version, return (err); } + +struct fac_lookup { + const char *fl_fac_type; + uint32_t fl_fac_subtype; +#ifdef _LP64 + uint64_t fl_callback; + uint64_t fl_callback_args; +#else + uint32_t fl_callback; + uint32_t fl_callback_args; +#endif + nvlist_t *fl_rsrc; + nvlist_t *fl_fac_rsrc; +}; + +static int +hc_fac_get(topo_mod_t *mod, tnode_t *node, void *pdata) +{ + struct fac_lookup *flp = (struct fac_lookup *)pdata; + topo_walk_cb_t cb = (topo_walk_cb_t)flp->fl_callback; + topo_faclist_t faclist, *tmp; + int err, ret = 0; + + /* + * Lookup the specified facility node. Return with an error if we can't + * find it. + */ + if (topo_node_facility(mod->tm_hdl, node, flp->fl_fac_type, + flp->fl_fac_subtype, &faclist, &err) != 0) { + topo_mod_dprintf(mod, "hc_fac_get: topo_node_facility " + "failed\n"); + return (TOPO_WALK_ERR); + } + + /* + * Invoke user's callback for each facility node in the topo list, + * passing in a pointer to the facility node + */ + for (tmp = topo_list_next(&faclist.tf_list); tmp != NULL; + tmp = topo_list_next(tmp)) { + + if ((err = cb(mod->tm_hdl, tmp->tf_node, + (void *)flp->fl_callback_args)) != 0) { + (void) topo_mod_seterrno(mod, err); + topo_mod_dprintf(mod, "hc_fac_get: callback failed: " + "%s\n ", topo_mod_errmsg(mod)); + ret = TOPO_WALK_ERR; + break; + } + } + + while ((tmp = topo_list_next(&faclist.tf_list)) != NULL) { + topo_list_delete(&faclist.tf_list, tmp); + topo_mod_free(mod, tmp, sizeof (topo_faclist_t)); + } + return (ret); +} + +static int +hc_fmri_facility(topo_mod_t *mod, tnode_t *node, topo_version_t version, + nvlist_t *in, nvlist_t **out) +{ + int err = 0; + struct hc_walk *hwp; + struct fac_lookup *flp; + + if (version > TOPO_METH_FACILITY_VERSION) + return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW)); + + if ((flp = topo_mod_alloc(mod, sizeof (struct fac_lookup))) == NULL) + return (topo_mod_seterrno(mod, EMOD_NOMEM)); + + /* + * lookup arguments: hw resource, facility type, facility subtype, + * callback and callback args + */ + err = nvlist_lookup_nvlist(in, TOPO_PROP_RESOURCE, &flp->fl_rsrc); + err |= nvlist_lookup_string(in, FM_FMRI_FACILITY_TYPE, + (char **)&flp->fl_fac_type); + err |= nvlist_lookup_uint32(in, "type", &flp->fl_fac_subtype); +#ifdef _LP64 + err |= nvlist_lookup_uint64(in, "callback", &flp->fl_callback); + err |= nvlist_lookup_uint64(in, "callback-args", + &flp->fl_callback_args); +#else + err |= nvlist_lookup_uint32(in, "callback", &flp->fl_callback); + err |= nvlist_lookup_uint32(in, "callback-args", + &flp->fl_callback_args); +#endif + if (err != 0) { + topo_mod_dprintf(mod, "hc_fmri_facility: failed to construct " + "walker arg nvlist\n"); + topo_mod_free(mod, flp, sizeof (struct fac_lookup)); + return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL)); + } + + flp->fl_fac_rsrc = NULL; + if ((hwp = hc_walk_init(mod, node, flp->fl_rsrc, hc_fac_get, + (void *)flp)) != NULL) { + if (topo_walk_step(hwp->hcw_wp, TOPO_WALK_CHILD) == + TOPO_WALK_ERR) + err = -1; + else + err = 0; + topo_walk_fini(hwp->hcw_wp); + topo_mod_free(mod, hwp, sizeof (struct hc_walk)); + } else { + topo_mod_dprintf(mod, "hc_fmri_facility: failed to initialize " + "hc walker\n"); + err = -1; + } + + if (flp->fl_fac_rsrc != NULL) + *out = flp->fl_fac_rsrc; + + topo_mod_free(mod, flp, sizeof (struct fac_lookup)); + + return (err); +} diff --git a/usr/src/lib/fm/topo/libtopo/common/libtopo.h b/usr/src/lib/fm/topo/libtopo/common/libtopo.h index 3d0d9a6d22..5164508eaa 100644 --- a/usr/src/lib/fm/topo/libtopo/common/libtopo.h +++ b/usr/src/lib/fm/topo/libtopo/common/libtopo.h @@ -44,6 +44,16 @@ typedef struct topo_walk topo_walk_t; typedef int32_t topo_instance_t; typedef uint32_t topo_version_t; +typedef struct topo_list { + struct topo_list *l_prev; + struct topo_list *l_next; +} topo_list_t; + +typedef struct topo_faclist { + topo_list_t tf_list; + tnode_t *tf_node; +} topo_faclist_t; + /* * The following functions, error codes and data structures are private * to libtopo snapshot consumers and enumerator modules. @@ -91,6 +101,8 @@ extern int topo_fmri_fru(topo_hdl_t *, nvlist_t *, nvlist_t **, extern int topo_fmri_label(topo_hdl_t *, nvlist_t *, char **, int *); extern int topo_fmri_serial(topo_hdl_t *, nvlist_t *, char **, int *); extern int topo_fmri_compare(topo_hdl_t *, nvlist_t *, nvlist_t *, int *); +extern int topo_fmri_facility(topo_hdl_t *, nvlist_t *, const char *, + uint32_t, topo_walk_cb_t, void *, int *); /* * Private utility functions for fmd @@ -106,13 +118,30 @@ extern char *topo_node_name(tnode_t *); extern topo_instance_t topo_node_instance(tnode_t *); extern tnode_t *topo_node_parent(tnode_t *); extern void *topo_node_private(tnode_t *); +extern int topo_node_flags(tnode_t *); extern int topo_node_asru(tnode_t *, nvlist_t **, nvlist_t *, int *); extern int topo_node_fru(tnode_t *, nvlist_t **, nvlist_t *, int *); extern int topo_node_resource(tnode_t *, nvlist_t **, int *); extern int topo_node_label(tnode_t *, char **, int *); extern int topo_method_invoke(tnode_t *node, const char *, topo_version_t, nvlist_t *, nvlist_t **, int *); +extern boolean_t topo_method_supported(tnode_t *, const char *, + topo_version_t); +extern int topo_node_facility(topo_hdl_t *, tnode_t *, const char *, + uint32_t, topo_faclist_t *, int *); + +/* + * Node flags: denotes type of node + */ +#define TOPO_NODE_DEFAULT 0 +#define TOPO_NODE_FACILITY 1 +#define TOPO_FAC_TYPE_SENSOR "sensor" +#define TOPO_FAC_TYPE_INDICATOR "indicator" + +/* + * Topo property get functions + */ extern int topo_prop_get_int32(tnode_t *, const char *, const char *, int32_t *, int *); extern int topo_prop_get_uint32(tnode_t *, const char *, const char *, @@ -121,6 +150,8 @@ extern int topo_prop_get_int64(tnode_t *, const char *, const char *, int64_t *, int *); extern int topo_prop_get_uint64(tnode_t *, const char *, const char *, uint64_t *, int *); +extern int topo_prop_get_double(tnode_t *, const char *, const char *, + double *, int *); extern int topo_prop_get_string(tnode_t *, const char *, const char *, char **, int *); extern int topo_prop_get_fmri(tnode_t *, const char *, const char *, @@ -138,6 +169,36 @@ extern int topo_prop_get_string_array(tnode_t *, const char *, const char *, extern int topo_prop_get_fmri_array(tnode_t *, const char *, const char *, nvlist_t ***, uint_t *, int *); +/* + * Topo property set functions + */ +extern int topo_prop_set_int32(tnode_t *, const char *, const char *, int, + int32_t, int *); +extern int topo_prop_set_uint32(tnode_t *, const char *, const char *, int, + uint32_t, int *); +extern int topo_prop_set_int64(tnode_t *, const char *, const char *, + int, int64_t, int *); +extern int topo_prop_set_uint64(tnode_t *, const char *, const char *, + int, uint64_t, int *); +extern int topo_prop_set_double(tnode_t *, const char *, const char *, + int, double, int *); +extern int topo_prop_set_string(tnode_t *, const char *, const char *, + int, const char *, int *); +extern int topo_prop_set_fmri(tnode_t *, const char *, const char *, + int, const nvlist_t *, int *); +extern int topo_prop_set_int32_array(tnode_t *, const char *, const char *, int, + int32_t *, uint_t, int *); +extern int topo_prop_set_uint32_array(tnode_t *, const char *, const char *, + int, uint32_t *, uint_t, int *); +extern int topo_prop_set_int64_array(tnode_t *, const char *, const char *, + int, int64_t *, uint_t, int *); +extern int topo_prop_set_uint64_array(tnode_t *, const char *, const char *, + int, uint64_t *, uint_t, int *); +extern int topo_prop_set_string_array(tnode_t *, const char *, const char *, + int, const char **, uint_t, int *); +extern int topo_prop_set_fmri_array(tnode_t *, const char *, const char *, + int, const nvlist_t **, uint_t, int *); + #define TOPO_PROP_IMMUTABLE 0 #define TOPO_PROP_MUTABLE 1 @@ -150,6 +211,8 @@ extern int topo_prop_get_fmri_array(tnode_t *, const char *, const char *, #define TOPO_PROP_PKG "package" /* software package FMRI */ #define TOPO_PROP_LABEL "label" /* property LABEL */ +#define TOPO_METH_FAC_ENUM "fac_enum" + /* * System property group */ @@ -270,7 +333,8 @@ typedef enum { TOPO_TYPE_INT64_ARRAY, /* array of int64_t */ TOPO_TYPE_UINT64_ARRAY, /* array of uint64_t */ TOPO_TYPE_STRING_ARRAY, /* array of const char* */ - TOPO_TYPE_FMRI_ARRAY /* array of nvlist_t */ + TOPO_TYPE_FMRI_ARRAY, /* array of nvlist_t */ + TOPO_TYPE_DOUBLE /* double */ } topo_type_t; extern nvlist_t *topo_prop_getprops(tnode_t *, int *err); @@ -313,6 +377,590 @@ extern int topo_hdl_nvalloc(topo_hdl_t *, nvlist_t **, uint_t); extern int topo_hdl_nvdup(topo_hdl_t *, nvlist_t *, nvlist_t **); extern char *topo_hdl_strdup(topo_hdl_t *, const char *); +/* + * Interfaces for converting sensor/indicator types, units, states, etc to + * a string + */ +void topo_sensor_type_name(uint32_t type, char *buf, size_t len); +void topo_sensor_units_name(uint8_t type, char *buf, size_t len); +void topo_led_type_name(uint8_t type, char *buf, size_t len); +void topo_led_state_name(uint8_t type, char *buf, size_t len); +void topo_sensor_state_name(uint32_t sensor_type, uint8_t state, char *buf, + size_t len); + +/* + * Defines for standard properties for sensors and indicators + */ +#define TOPO_PGROUP_FACILITY "facility" + +#define TOPO_SENSOR_READING "reading" +#define TOPO_SENSOR_STATE "state" +#define TOPO_SENSOR_CLASS "sensor-class" +#define TOPO_FACILITY_TYPE "type" +#define TOPO_SENSOR_UNITS "units" +#define TOPO_LED_MODE "mode" + +/* + * Sensor Classes + * + * The "sensor-class" property in the "facility" propgroup on + * facility nodes of type "sensor" should be set to one of these + * two values. + * + * Threshold sensors provide an analog sensor reading via the + * "reading" property in the facility propgroup. They will also + * provide one or more discrete states via the "state" property + * in the facility propgroup. + * + * Discrete sensors will not provide an analog reading by will + * provide one or more discrete states via the "state" property + * in the facility propgroup. + */ +#define TOPO_SENSOR_CLASS_THRESHOLD "threshold" +#define TOPO_SENSOR_CLASS_DISCRETE "discrete" + +/* + * Sensor unit types. We're using the unit types and corresponding + * codes described in the IPMI 2.0 spec as a reference as it seems to be a + * reasonably comprehensive list. This also simplifies the IPMI provider code + * since the unit type codes will map exactly to what libtopo uses (so no + * conversion necessary). + */ +typedef enum topo_sensor_unit { + TOPO_SENSOR_UNITS_UNSPECIFIED = 0, + TOPO_SENSOR_UNITS_DEGREES_C, + TOPO_SENSOR_UNITS_DEGREES_F, + TOPO_SENSOR_UNITS_DEGREES_K, + TOPO_SENSOR_UNITS_VOLTS, + TOPO_SENSOR_UNITS_AMPS, + TOPO_SENSOR_UNITS_WATTS, + TOPO_SENSOR_UNITS_JOULES, + TOPO_SENSOR_UNITS_COULOMBS, + TOPO_SENSOR_UNITS_VA, + TOPO_SENSOR_UNITS_NITS, + TOPO_SENSOR_UNITS_LUMEN, + TOPO_SENSOR_UNITS_LUX, + TOPO_SENSOR_UNITS_CANDELA, + TOPO_SENSOR_UNITS_KPA, + TOPO_SENSOR_UNITS_PSI, + + TOPO_SENSOR_UNITS_NEWTON, + TOPO_SENSOR_UNITS_CFM, + TOPO_SENSOR_UNITS_RPM, + TOPO_SENSOR_UNITS_HZ, + TOPO_SENSOR_UNITS_MICROSEC, + TOPO_SENSOR_UNITS_MILLISEC, + TOPO_SENSOR_UNITS_SECS, + TOPO_SENSOR_UNITS_MIN, + TOPO_SENSOR_UNITS_HOUR, + TOPO_SENSOR_UNITS_DAY, + TOPO_SENSOR_UNITS_WEEK, + TOPO_SENSOR_UNITS_MIL, + TOPO_SENSOR_UNITS_INCHES, + TOPO_SENSOR_UNITS_FEET, + TOPO_SENSOR_UNITS_CUB_INCH, + TOPO_SENSOR_UNITS_CUB_FEET, + + TOPO_SENSOR_UNITS_MM, + TOPO_SENSOR_UNITS_CM, + TOPO_SENSOR_UNITS_METERS, + TOPO_SENSOR_UNITS_CUB_CM, + TOPO_SENSOR_UNITS_CUB_METER, + TOPO_SENSOR_UNITS_LITERS, + TOPO_SENSOR_UNITS_FLUID_OUNCE, + TOPO_SENSOR_UNITS_RADIANS, + TOPO_SENSOR_UNITS_STERADIANS, + TOPO_SENSOR_UNITS_REVOLUTIONS, + TOPO_SENSOR_UNITS_CYCLES, + TOPO_SENSOR_UNITS_GRAVITIES, + TOPO_SENSOR_UNITS_OUNCE, + TOPO_SENSOR_UNITS_POUND, + TOPO_SENSOR_UNITS_FOOT_POUND, + TOPO_SENSOR_UNITS_OZ_INCH, + + TOPO_SENSOR_UNITS_GAUSS, + TOPO_SENSOR_UNITS_GILBERTS, + TOPO_SENSOR_UNITS_HENRY, + TOPO_SENSOR_UNITS_MILHENRY, + TOPO_SENSOR_UNITS_FARAD, + TOPO_SENSOR_UNITS_MICROFARAD, + TOPO_SENSOR_UNITS_OHMS, + TOPO_SENSOR_UNITS_SIEMENS, + TOPO_SENSOR_UNITS_MOLE, + TOPO_SENSOR_UNITS_BECQUEREL, + TOPO_SENSOR_UNITS_PPM, + TOPO_SENSOR_UNITS_RESERVED1, + TOPO_SENSOR_UNITS_DECIBELS, + TOPO_SENSOR_UNITS_DBA, + TOPO_SENSOR_UNITS_DBC, + TOPO_SENSOR_UNITS_GRAY, + + TOPO_SENSOR_UNITS_SIEVERT, + TOPO_SENSOR_UNITS_COLOR_TEMP_K, + TOPO_SENSOR_UNITS_BIT, + TOPO_SENSOR_UNITS_KILOBIT, + TOPO_SENSOR_UNITS_MEGABIT, + TOPO_SENSOR_UNITS_GIGABIT, + TOPO_SENSOR_UNITS_BYTE, + TOPO_SENSOR_UNITS_KILOBYTE, + TOPO_SENSOR_UNITS_MEGABYTE, + TOPO_SENSOR_UNITS_GIGABYTE, + TOPO_SENSOR_UNITS_WORD, + TOPO_SENSOR_UNITS_DWORD, + TOPO_SENSOR_UNITS_QWORD, + TOPO_SENSOR_UNITS_MEMLINE, + TOPO_SENSOR_UNITS_HIT, + TOPO_SENSOR_UNITS_MISS, + + TOPO_SENSOR_UNITS_RETRY, + TOPO_SENSOR_UNITS_RESET, + TOPO_SENSOR_UNITS_OVERFLOW, + TOPO_SENSOR_UNITS_UNDERRUN, + TOPO_SENSOR_UNITS_COLLISION, + TOPO_SENSOR_UNITS_PACKETS, + TOPO_SENSOR_UNITS_MESSAGES, + TOPO_SENSOR_UNITS_CHARACTERS, + TOPO_SENSOR_UNITS_ERROR, + TOPO_SENSOR_UNITS_CE, + TOPO_SENSOR_UNITS_UE, + TOPO_SENSOR_UNITS_FATAL_ERROR, + TOPO_SENSOR_UNITS_GRAMS +} topo_sensor_unit_t; + +/* + * Sensor Types amd the associated sensor-type-specific states + * + * These are used to decode the type and state properties in the facility + * propgroup on facility nodes of type sensor. + * + * Again we're basically using the same defines as for IPMI as it's serves + * as a good starting point and simplifies the IPMI provider code. Of course + * other facility providers will need to convert from their native codes + * to the topo code when they set the type and state properties. + */ +#define TOPO_SENSOR_TYPE_RESERVED 0x0000 +#define TOPO_SENSOR_TYPE_TEMP 0x0001 +#define TOPO_SENSOR_TYPE_VOLTAGE 0x0002 +#define TOPO_SENSOR_TYPE_CURRENT 0x0003 +#define TOPO_SENSOR_TYPE_FAN 0x0004 +#define TOPO_SENSOR_TYPE_PHYSICAL 0x0005 + +#define TOPO_SENSOR_STATE_PHYSICAL_GENERAL 0x0001 +#define TOPO_SENSOR_STATE_PHYSICAL_BAY 0x0002 +#define TOPO_SENSOR_STATE_PHYSICAL_CARD 0x0004 +#define TOPO_SENSOR_STATE_PHYSICAL_PROCESSOR 0x0008 +#define TOPO_SENSOR_STATE_PHYSICAL_LAN 0x0010 +#define TOPO_SENSOR_STATE_PHYSICAL_DOCK 0x0020 +#define TOPO_SENSOR_STATE_PHYSICAL_FAN 0x0040 + +#define TOPO_SENSOR_TYPE_PLATFORM 0x0006 + +#define TOPO_SENSOR_STATE_PLATFORM_SECURE 0x0001 +#define TOPO_SENSOR_STATE_PLATFORM_USER_PASS 0x0002 +#define TOPO_SENSOR_STATE_PLATFORM_SETUP_PASS 0x0004 +#define TOPO_SENSOR_STATE_PLATFORM_NETWORK_PASS 0x0008 +#define TOPO_SENSOR_STATE_PLATFORM_OTHER_PASS 0x0010 +#define TOPO_SENSOR_STATE_PLATFORM_OUT_OF_BAND 0x0020 + +#define TOPO_SENSOR_TYPE_PROCESSOR 0x0007 + +#define TOPO_SENSOR_STATE_PROCESSOR_IERR 0x0001 +#define TOPO_SENSOR_STATE_PROCESSOR_THERMAL 0x0002 +#define TOPO_SENSOR_STATE_PROCESSOR_FRB1 0x0004 +#define TOPO_SENSOR_STATE_PROCESSOR_FRB2 0x0008 +#define TOPO_SENSOR_STATE_PROCESSOR_FRB3 0x0010 +#define TOPO_SENSOR_STATE_PROCESSOR_CONFIG 0x0020 +#define TOPO_SENSOR_STATE_PROCESSOR_SMBIOS 0x0040 +#define TOPO_SENSOR_STATE_PROCESSOR_PRESENT 0x0080 +#define TOPO_SENSOR_STATE_PROCESSOR_DISABLED 0x0100 +#define TOPO_SENSOR_STATE_PROCESSOR_TERMINATOR 0x0200 +#define TOPO_SENSOR_STATE_PROCESSOR_THROTTLED 0x0400 + +#define TOPO_SENSOR_TYPE_POWER_SUPPLY 0x0008 + +#define TOPO_SENSOR_STATE_POWER_SUPPLY_PRESENT 0x0001 +#define TOPO_SENSOR_STATE_POWER_SUPPLY_FAILURE 0x0002 +#define TOPO_SENSOR_STATE_POWER_SUPPLY_PREDFAIL 0x0004 +#define TOPO_SENSOR_STATE_POWER_SUPPLY_INPUT_LOST 0x0008 +#define TOPO_SENSOR_STATE_POWER_SUPPLY_INPUT_RANGE 0x0010 +#define TOPO_SENSOR_STATE_POWER_SUPPLY_INPUT_RANGE_PRES 0x0020 +#define TOPO_SENSOR_STATE_POWER_SUPPLY_CONFIG_ERR 0x0040 + +#define TOPO_SENSOR_TYPE_POWER_UNIT 0x0009 + +#define TOPO_SENSOR_STATE_POWER_UNIT_OFF 0x0001 +#define TOPO_SENSOR_STATE_POWER_UNIT_CYCLE 0x0002 +#define TOPO_SENSOR_STATE_POWER_UNIT_240_DOWN 0x0004 +#define TOPO_SENSOR_STATE_POWER_UNIT_INTERLOCK_DOWN 0x0008 +#define TOPO_SENSOR_STATE_POWER_UNIT_AC_LOST 0x0010 +#define TOPO_SENSOR_STATE_POWER_UNIT_SOFT_FAILURE 0x0020 +#define TOPO_SENSOR_STATE_POWER_UNIT_FAIL 0x0040 +#define TOPO_SENSOR_STATE_POWER_UNIT_PREDFAIL 0x0080 + +#define TOPO_SENSOR_TYPE_COOLING 0x000A +#define TOPO_SENSOR_TYPE_OTHER 0x000B + +#define TOPO_SENSOR_TYPE_MEMORY 0x000C + +#define TOPO_SENSOR_STATE_MEMORY_CE 0x0001 +#define TOPO_SENSOR_STATE_MEMORY_UE 0x0002 +#define TOPO_SENSOR_STATE_MEMORY_PARITY 0x0004 +#define TOPO_SENSOR_STATE_MEMORY_SCRUB_FAIL 0x0008 +#define TOPO_SENSOR_STATE_MEMORY_DISABLED 0x0010 +#define TOPO_SENSOR_STATE_MEMORY_CE_LOG_LIMIT 0x0020 +#define TOPO_SENSOR_STATE_MEMORY_PRESENT 0x0040 +#define TOPO_SENSOR_STATE_MEMORY_CONFIG_ERR 0x0080 +#define TOPO_SENSOR_STATE_MEMORY_SPARE 0x0100 +#define TOPO_SENSOR_STATE_MEMORY_THROTTLED 0x0200 +#define TOPO_SENSOR_STATE_MEMORY_OVERTEMP 0x0400 + +#define TOPO_SENSOR_TYPE_BAY 0x000D + +#define TOPO_SENSOR_STATE_BAY_PRESENT 0x0001 +#define TOPO_SENSOR_STATE_BAY_FAULT 0x0002 +#define TOPO_SENSOR_STATE_BAY_PREDFAIL 0x0004 +#define TOPO_SENSOR_STATE_BAY_SPARE 0x0008 +#define TOPO_SENSOR_STATE_BAY_CHECK 0x0010 +#define TOPO_SENSOR_STATE_BAY_CRITICAL 0x0020 +#define TOPO_SENSOR_STATE_BAY_FAILED 0x0040 +#define TOPO_SENSOR_STATE_BAY_REBUILDING 0x0080 +#define TOPO_SENSOR_STATE_BAY_ABORTED 0x0100 + +#define TOPO_SENSOR_TYPE_POST_RESIZE 0x000E + +#define TOPO_SENSOR_TYPE_FIRMWARE 0x000F + +#define TOPO_SENSOR_STATE_FIRMWARE_ERROR 0x0001 +#define TOPO_SENSOR_STATE_FIRMWARE_HANG 0x0002 +#define TOPO_SENSOR_STATE_FIRMWARE_PROGRESS 0x0004 + +#define TOPO_SENSOR_TYPE_EVENT_LOG 0x0010 + +#define TOPO_SENSOR_STATE_EVENT_LOG_CE 0x0001 +#define TOPO_SENSOR_STATE_EVENT_LOG_TYPE 0x0002 +#define TOPO_SENSOR_STATE_EVENT_LOG_RESET 0x0004 +#define TOPO_SENSOR_STATE_EVENT_LOG_ALL 0x0008 +#define TOPO_SENSOR_STATE_EVENT_LOG_FULL 0x0010 +#define TOPO_SENSOR_STATE_EVENT_LOG_ALMOST_FULL 0x0020 + +#define TOPO_SENSOR_TYPE_WATCHDOG1 0x0011 + +#define TOPO_SENSOR_STATE_WATCHDOG_BIOS_RESET 0x0001 +#define TOPO_SENSOR_STATE_WATCHDOG_OS_RESET 0x0002 +#define TOPO_SENSOR_STATE_WATCHDOG_OS_SHUTDOWN 0x0004 +#define TOPO_SENSOR_STATE_WATCHDOG_OS_PWR_DOWN 0x0008 +#define TOPO_SENSOR_STATE_WATCHDOG_OS_PWR_CYCLE 0x0010 +#define TOPO_SENSOR_STATE_WATCHDOG_OS_NMI_DIAG 0x0020 +#define TOPO_SENSOR_STATE_WATCHDOG_EXPIRED 0x0040 +#define TOPO_SENSOR_STATE_WATCHDOG_PRE_TIMEOUT_INT 0x0080 + +#define TOPO_SENSOR_TYPE_SYSTEM 0x0012 + +#define TOPO_SENSOR_STATE_SYSTEM_RECONF 0x0001 +#define TOPO_SENSOR_STATE_SYSTEM_BOOT 0x0002 +#define TOPO_SENSOR_STATE_SYSTEM_UNKNOWN_HW_FAILURE 0x0004 +#define TOPO_SENSOR_STATE_SYSTEM_AUX_LOG_UPDATED 0x0008 +#define TOPO_SENSOR_STATE_SYSTEM_PEF_ACTION 0x0010 +#define TOPO_SENSOR_STATE_SYSTEM_TIMETAMP_CLOCKSYNC 0x0020 + +#define TOPO_SENSOR_TYPE_CRITICAL 0x0013 + +#define TOPO_SENSOR_STATE_CRITICAL_EXT_NMI 0x0001 +#define TOPO_SENSOR_STATE_CRITICAL_BUS_TIMEOUT 0x0002 +#define TOPO_SENSOR_STATE_CRITICAL_IO_NMI 0x0004 +#define TOPO_SENSOR_STATE_CRITICAL_SW_NMI 0x0008 +#define TOPO_SENSOR_STATE_CRITICAL_PCI_PERR 0x0010 +#define TOPO_SENSOR_STATE_CRITICAL_PCI_SERR 0x0020 +#define TOPO_SENSOR_STATE_CRITICAL_EISA_FAILSAFE 0x0040 +#define TOPO_SENSOR_STATE_CRITICAL_BUS_CE 0x0080 +#define TOPO_SENSOR_STATE_CRITICAL_BUS_UE 0x0100 +#define TOPO_SENSOR_STATE_CRITICAL_FATAL_NMI 0x0200 +#define TOPO_SENSOR_STATE_CRITICAL_BUS_FATAL_ERR 0x0400 +#define TOPO_SENSOR_STATE_CRITICAL_BUS_DEGRADED 0x0800 + +#define TOPO_SENSOR_TYPE_BUTTON 0x0014 + +#define TOPO_SENSOR_STATE_BUTTON_PWR 0x0001 +#define TOPO_SENSOR_STATE_BUTTON_SLEEP 0x0002 +#define TOPO_SENSOR_STATE_BUTTON_RESET 0x0004 +#define TOPO_SENSOR_STATE_BUTTON_FRU_LATCH 0x0008 +#define TOPO_SENSOR_STATE_BUTTON_FRU_SERVICE 0x0010 + +#define TOPO_SENSOR_TYPE_MODULE 0x0015 +#define TOPO_SENSOR_TYPE_MICROCONTROLLER 0x0016 +#define TOPO_SENSOR_TYPE_CARD 0x0017 +#define TOPO_SENSOR_TYPE_CHASSIS 0x0018 + +#define TOPO_SENSOR_TYPE_CHIPSET 0x0019 + +#define TOPO_SENSOR_STATE_CHIPSET_PWR_CTL_FAIL 0x0001 + +#define TOPO_SENSOR_TYPE_FRU 0x001A + +#define TOPO_SENSOR_TYPE_CABLE 0x001B + +#define TOPO_SENSOR_STATE_CABLE_CONNECTED 0x0001 +#define TOPO_SENSOR_STATE_CABLE_CONFIG_ERR 0x0002 + +#define TOPO_SENSOR_TYPE_TERMINATOR 0x001C + +#define TOPO_SENSOR_TYPE_BOOT_STATE 0x001D + +#define TOPO_SENSOR_STATE_BOOT_STATE_BIOS_PWR_UP 0x0001 +#define TOPO_SENSOR_STATE_BOOT_STATE_BIOS_HARD_RESET 0x0002 +#define TOPO_SENSOR_STATE_BOOT_STATE_BIOS_WARM_RESET 0x0004 +#define TOPO_SENSOR_STATE_BOOT_STATE_PXE_BOOT 0x0008 +#define TOPO_SENSOR_STATE_BOOT_STATE_DIAG_BOOT 0x0010 +#define TOPO_SENSOR_STATE_BOOT_STATE_OS_HARD_RESET 0x0020 +#define TOPO_SENSOR_STATE_BOOT_STATE_OS_WARM_RESET 0x0040 +#define TOPO_SENSOR_STATE_BOOT_STATE_SYS_RESTART 0x0080 + +#define TOPO_SENSOR_TYPE_BOOT_ERROR 0x001E + +#define TOPO_SENSOR_STATE_BOOT_ERROR_NOMEDIA 0x0001 +#define TOPO_SENSOR_STATE_BOOT_ERROR_NON_BOOTABLE_DISK 0x0002 +#define TOPO_SENSOR_STATE_BOOT_ERROR_NO_PXE_SERVER 0x0004 +#define TOPO_SENSOR_STATE_BOOT_ERROR_INV_BOOT_SECT 0x0008 +#define TOPO_SENSOR_STATE_BOOT_ERROR_USR_SELECT_TIMEOUT 0x0010 + +#define TOPO_SENSOR_TYPE_BOOT_OS 0x001F + +#define TOPO_SENSOR_STATE_BOOT_OS_A_DRV_BOOT_COMPLETE 0x0001 +#define TOPO_SENSOR_STATE_BOOT_OS_C_DRV_BOOT_COMPLETE 0x0002 +#define TOPO_SENSOR_STATE_BOOT_OS_PXE_BOOT_COMPLETE 0x0004 +#define TOPO_SENSOR_STATE_BOOT_OS_DIAG_BOOT_COMPLETE 0x0008 +#define TOPO_SENSOR_STATE_BOOT_OS_CDROM_BOOT_COMPLETE 0x0010 +#define TOPO_SENSOR_STATE_BOOT_OS_ROM_BOOT_COMPLETE 0x0020 +#define TOPO_SENSOR_STATE_BOOT_OS_UNSPEC_BOOT_COMPLETE 0x0040 + +#define TOPO_SENSOR_TYPE_OS_SHUTDOWN 0x0020 + +#define TOPO_SENSOR_STATE_OS_SHUTDOWN_LOADING 0x0001 +#define TOPO_SENSOR_STATE_OS_SHUTDOWN_CRASH 0x0002 +#define TOPO_SENSOR_STATE_OS_STOP_GRACEFUL 0x0004 +#define TOPO_SENSOR_STATE_OS_SHUTDOWN_GRACEFUL 0x0008 +#define TOPO_SENSOR_STATE_OS_SHUTDOWN_PEF 0x0010 +#define TOPO_SENSOR_STATE_OS_SHUTDOWN_BMC 0x0020 + +#define TOPO_SENSOR_TYPE_SLOT 0x0021 + +#define TOPO_SENSOR_STATE_SLOT_FAULT_ASSERTED 0x0001 +#define TOPO_SENSOR_STATE_SLOT_IDENTIFY_ASSERTED 0x0002 +#define TOPO_SENSOR_STATE_SLOT_CONNECTED 0x0004 +#define TOPO_SENSOR_STATE_SLOT_INSTALL_READY 0x0008 +#define TOPO_SENSOR_STATE_SLOT_REMOVE_READY 0x0010 +#define TOPO_SENSOR_STATE_SLOT_PWR_OFF 0x0020 +#define TOPO_SENSOR_STATE_SLOT_REMOVED 0x0040 +#define TOPO_SENSOR_STATE_SLOT_INTERLOCK_ASSERTED 0x0080 +#define TOPO_SENSOR_STATE_SLOT_DISABLED 0x0100 +#define TOPO_SENSOR_STATE_SLOT_SPARE_DEVICE 0x0200 + +#define TOPO_SENSOR_TYPE_ACPI 0x0022 + +#define TOPO_SENSOR_STATE_ACPI_PSTATE_S0_G0 0x0001 +#define TOPO_SENSOR_STATE_ACPI_PSTATE_S1 0x0002 +#define TOPO_SENSOR_STATE_ACPI_PSTATE_S2 0x0004 +#define TOPO_SENSOR_STATE_ACPI_PSTATE_S3 0x0008 +#define TOPO_SENSOR_STATE_ACPI_PSTATE_S4 0x0010 +#define TOPO_SENSOR_STATE_ACPI_PSTATE_S5_G2_SOFT_OFF 0x0020 +#define TOPO_SENSOR_STATE_ACPI_PSTATE_S4_S5_SOFT_OFF 0x0040 +#define TOPO_SENSOR_STATE_ACPI_PSATTE_G3_MECH_OFF 0x0080 +#define TOPO_SENSOR_STATE_ACPI_PSTATE_S1_S2_S3_SLEEP 0x0100 +#define TOPO_SENSOR_STATE_ACPI_PSTATE_G1_SLEEP 0x0200 +#define TOPO_SENSOR_STATE_ACPI_PSTATE_S5_OVERRIDE 0x0400 +#define TOPO_SENSOR_STATE_ACPI_PSTATE_LEGACY_ON 0x0800 +#define TOPO_SENSOR_STATE_ACPI_PSTATE_LEGACY_OFF 0x1000 +#define TOPO_SENSOR_STATE_ACPI_PSTATE_UNKNOWN 0x2000 + +#define TOPO_SENSOR_TYPE_WATCHDOG2 0x0023 + +#define TOPO_SENSOR_STATE_WATCHDOG2_EXPIRED 0x0001 +#define TOPO_SENSOR_STATE_WATCHDOG2_HARD_RESET 0x0002 +#define TOPO_SENSOR_STATE_WATCHDOG2_PWR_DOWN 0x0004 +#define TOPO_SENSOR_STATE_WATCHDOG2_PWR_CYCLE 0x0008 +#define TOPO_SENSOR_STATE_WATCHDOG2_RESERVED1 0x0010 +#define TOPO_SENSOR_STATE_WATCHDOG2_RESERVED2 0x0020 +#define TOPO_SENSOR_STATE_WATCHDOG2_RESERVED3 0x0040 +#define TOPO_SENSOR_STATE_WATCHDOG2_RESERVED4 0x0080 +#define TOPO_SENSOR_STATE_WATCHDOG2_TIMEOUT_INT 0x0100 + +#define TOPO_SENSOR_TYPE_ALERT 0x0024 + +#define TOPO_SENSOR_STATE_ALERT_PLAT_PAGE 0x0001 +#define TOPO_SENSOR_STATE_ALERT_PLAT_LAN_ALERT 0x0002 +#define TOPO_SENSOR_STATE_ALERT_PLAT_EVT_TRAP 0x0004 +#define TOPO_SENSOR_STATE_ALERT_PLAT_SNMP_TRAP 0x0008 + +#define TOPO_SENSOR_TYPE_PRESENCE 0x0025 + +#define TOPO_SENSOR_STATE_PRESENCE_PRESENT 0x0001 +#define TOPO_SENSOR_STATE_PRESENCE_ABSENT 0x0002 +#define TOPO_SENSOR_STATE_PRESENCE_DISABLED 0x0004 + +#define TOPO_SENSOR_TYPE_ASIC 0x0026 + +#define TOPO_SENSOR_TYPE_LAN 0x0027 + +#define TOPO_SENSOR_STATE_LAN_HEARTBEAT_LOST 0x0001 +#define TOPO_SENSOR_STATE_LAN_HEARTBEAT 0x0002 + +#define TOPO_SENSOR_TYPE_HEALTH 0x0028 + +#define TOPO_SENSOR_STATE_HEALTH_SENSOR_ACC_DEGRADED 0x0001 +#define TOPO_SENSOR_STATE_HEALTH_CNTLR_ACC_DEGRADED 0x0002 +#define TOPO_SENSOR_STATE_HEALTH_CNTLR_OFFLINE 0x0004 +#define TOPO_SENSOR_STATE_HEALTH_CNTLR_UNAVAIL 0x0008 +#define TOPO_SENSOR_STATE_HEALTH_SENSOR_FAILURE 0x0010 +#define TOPO_SENSOR_STATE_HEALTH_FRU_FAILURE 0x0020 + +#define TOPO_SENSOR_TYPE_BATTERY 0x0029 + +#define TOPO_SENSOR_STATE_BATTERY_LOW 0x0001 +#define TOPO_SENSOR_STATE_BATTERY_FAILED 0x0002 +#define TOPO_SENSOR_STATE_BATTERY_PRESENCE 0x0004 + +#define TOPO_SENSOR_TYPE_AUDIT 0x002A + +#define TOPO_SENSOR_STATE_AUDIT_SESSION_ACTIVATED 0x0001 +#define TOPO_SENSOR_STATE_AUDIT_SESSION_DEACTIVATED 0x0002 + +#define TOPO_SENSOR_TYPE_VERSION 0x002B + +#define TOPO_SENSOR_STATE_VERSION_HW_CHANGE 0x0001 +#define TOPO_SENSOR_STATE_VERSION_SW_CHANGE 0x0002 +#define TOPO_SENSOR_STATE_VERSION_HW_INCOMPATIBLE 0x0004 +#define TOPO_SENSOR_STATE_VERSION_SW_INCOMPATIBLE 0x0008 +#define TOPO_SENSOR_STATE_VERSION_HW_INVAL 0x0010 +#define TOPO_SENSOR_STATE_VERSION_SW_INVAL 0x0020 +#define TOPO_SENSOR_STATE_VERSION_HW_CHANGE_SUCCESS 0x0040 +#define TOPO_SENSOR_STATE_VERSION_SW_CHANGE_SUCCESS 0x0080 + +#define TOPO_SENSOR_TYPE_FRU_STATE 0x002C + +#define TOPO_SENSOR_STATE_FRU_STATE_NOT_INSTALLED 0x0001 +#define TOPO_SENSOR_STATE_FRU_STATE_INACTIVE 0x0002 +#define TOPO_SENSOR_STATE_FRU_STATE_ACT_REQ 0x0004 +#define TOPO_SENSOR_STATE_FRU_STATE_ACT_INPROGRESS 0x0008 +#define TOPO_SENSOR_STATE_FRU_STATE_ACTIVE 0x0010 +#define TOPO_SENSOR_STATE_FRU_STATE_DEACT_REQ 0x0020 +#define TOPO_SENSOR_STATE_FRU_STATE_DEACT_INPROGRESS 0x0040 +#define TOPO_SENSOR_STATE_FRU_STATE_COMM_LOST 0x0080 + +/* + * We simplify the IPMI sensor type code defines by combining the generic + * and sensor-specific codes into a single range. Because there's overlap + * between the two ranges we offset the generic type codes by 0x0100 + * which allows ample room in the hole for future expansion of the table to + * accomodate either additions to the IPMI spec or to support new sensor types + * for alternate provider modules. + */ +#define TOPO_SENSOR_TYPE_THRESHOLD_STATE 0x0101 + +#define TOPO_SENSOR_THRESH_LOWER_NONCRIT_GOING_LOW 0x0001 +#define TOPO_SENSOR_THRESH_LOWER_NONCRIT_GOING_HIGH 0x0002 +#define TOPO_SENSOR_THRESH_LOWER_CRIT_GOING_LOW 0x0004 +#define TOPO_SENSOR_THRESH_LOWER_CRIT_GOING_HIGH 0x0008 +#define TOPO_SENSOR_THRESH_LOWER_NONREC_GOING_LOW 0x0010 +#define TOPO_SENSOR_THRESH_LOWER_NONREC_GOING_HIGH 0x0020 +#define TOPO_SENSOR_THRESH_UPPER_NONCRIT_GOING_LOW 0x0040 +#define TOPO_SENSOR_THRESH_UPPER_NONCRIT_GOING_HIGH 0x0080 +#define TOPO_SENSOR_THRESH_UPPER_CRIT_GOING_LOW 0x0100 +#define TOPO_SENSOR_THRESH_UPPER_CRIT_GOING_HIGH 0x0200 +#define TOPO_SENSOR_THRESH_UPPER_NONREC_GOING_LOW 0x0400 +#define TOPO_SENSOR_THRESH_UPPER_NONREC_GOING_HIGH 0x0800 + +#define TOPO_SENSOR_TYPE_GENERIC_USAGE 0x0102 + +#define TOPO_SENSOR_STATE_GENERIC_USAGE_IDLE 0x0001 +#define TOPO_SENSOR_STATE_GENERIC_USAGE_ACTIVE 0x0002 +#define TOPO_SENSOR_STATE_GENERIC_USAGE_BUSY 0x0004 + +#define TOPO_SENSOR_TYPE_GENERIC_STATE 0x0103 + +#define TOPO_SENSOR_STATE_GENERIC_STATE_DEASSERTED 0x0001 +#define TOPO_SENSOR_STATE_GENERIC_STATE_ASSERTED 0x0002 + +#define TOPO_SENSOR_TYPE_GENERIC_PREDFAIL 0x0104 + +#define TOPO_SENSOR_STATE_GENERIC_PREDFAIL_DEASSERTED 0x0001 +#define TOPO_SENSOR_STATE_GENERIC_PREDFAIL_ASSERTED 0x0002 + +#define TOPO_SENSOR_TYPE_GENERIC_LIMIT 0x0105 + +#define TOPO_SENSOR_STATE_GENERIC_LIMIT_NOT_EXCEEDED 0x0001 +#define TOPO_SENSOR_STATE_GENERIC_LIMIT_EXCEEDED 0x0002 + +#define TOPO_SENSOR_TYPE_GENERIC_PERFORMANCE 0x0106 + +#define TOPO_SENSOR_STATE_GENERIC_PERFORMANCE_MET 0x0001 +#define TOPO_SENSOR_STATE_GENERIC_PERFORMANCE_LAGS 0x0002 + +#define TOPO_SENSOR_TYPE_SEVERITY 0x0107 + +#define TOPO_SENSOR_STATE_SEVERITY_OK 0x0001 +#define TOPO_SENSOR_STATE_SEVERITY_NONCRIT_GOING_HIGH 0x0002 +#define TOPO_SENSOR_STATE_SEVERITY_CRIT_GOING_HIGH 0x0004 +#define TOPO_SENSOR_STATE_SEVERITY_NONREC_GOING_HIGH 0x0008 +#define TOPO_SENSOR_STATE_SEVERITY_NONCRIT_GOING_LOW 0x0010 +#define TOPO_SENSOR_STATE_SEVERITY_CRIT_GOING_LOW 0x0020 +#define TOPO_SENSOR_STATE_SEVERITY_NONREC_GOING_LOW 0x0020 +#define TOPO_SENSOR_STATE_SEVERITY_MONITOR 0x0040 +#define TOPO_SENSOR_STATE_SEVERITY_INFORMATIONAL 0x0080 + +#define TOPO_SENSOR_TYPE_GENERIC_PRESENCE 0x0108 + +#define TOPO_SENSOR_STATE_GENERIC_PRESENCE_DEASSERTED 0x0001 +#define TOPO_SENSOR_STATE_GENERIC_PRESENCE_ASSERTED 0x0002 + +#define TOPO_SENSOR_TYPE_GENERIC_AVAILABILITY 0x0109 + +#define TOPO_SENSOR_STATE_GENERIC_AVAIL_DEASSERTED 0x0001 +#define TOPO_SENSOR_STATE_GENERIC_AVAIL_ASSERTED 0x0002 + +#define TOPO_SENSOR_TYPE_GENERIC_STATUS 0x010A + +#define TOPO_SENSOR_STATE_GENERIC_STATUS_RUNNING 0x0001 +#define TOPO_SENSOR_STATE_GENERIC_STATUS_IN_TEST 0x0002 +#define TOPO_SENSOR_STATE_GENERIC_STATUS_POWER_OFF 0x0004 +#define TOPO_SENSOR_STATE_GENERIC_STATUS_ONLINE 0x0008 +#define TOPO_SENSOR_STATE_GENERIC_STATUS_OFFLINE 0x0010 +#define TOPO_SENSOR_STATE_GENERIC_STATUS_OFF_DUTY 0x0020 +#define TOPO_SENSOR_STATE_GENERIC_STATUS_DEGRADED 0x0040 +#define TOPO_SENSOR_STATE_GENERIC_STATUS_POWER_SAVE 0x0080 +#define TOPO_SENSOR_STATE_GENERIC_STATUS_INSTALL_ERR 0x0100 + +#define TOPO_SENSOR_TYPE_GENERIC_REDUNDANCY 0x010B + +/* + * ACPI power state + */ +#define TOPO_SENSOR_TYPE_GENERIC_ACPI 0x010C + +#define TOPO_SENSOR_STATE_GENERIC_ACPI_D0 0x0001 +#define TOPO_SENSOR_STATE_GENERIC_ACPI_D1 0x0002 +#define TOPO_SENSOR_STATE_GENERIC_ACPI_D2 0x0004 +#define TOPO_SENSOR_STATE_GENERIC_ACPI_D3 0x0008 + +/* + * Indicator modes and types + */ +typedef enum topo_led_state { + TOPO_LED_STATE_OFF = 0, + TOPO_LED_STATE_ON +} topo_led_state_t; + +/* + * This list is limited to the set of LED's that we're likely to manage through + * FMA. Thus is does not include things like power or activity LED's + */ +typedef enum topo_led_type { + TOPO_LED_TYPE_SERVICE = 0, + TOPO_LED_TYPE_LOCATE, + TOPO_LED_TYPE_OK2RM, + TOPO_LED_TYPE_PRESENT +} topo_led_type_t; + + #ifdef __cplusplus } #endif diff --git a/usr/src/lib/fm/topo/libtopo/common/mapfile-vers b/usr/src/lib/fm/topo/libtopo/common/mapfile-vers index 8e405f2ada..95ac3e2bcd 100644 --- a/usr/src/lib/fm/topo/libtopo/common/mapfile-vers +++ b/usr/src/lib/fm/topo/libtopo/common/mapfile-vers @@ -34,6 +34,7 @@ SUNWprivate { topo_fmri_contains; topo_fmri_create; topo_fmri_expand; + topo_fmri_facility; topo_fmri_fru; topo_fmri_getpgrp; topo_fmri_getprop; @@ -55,10 +56,13 @@ SUNWprivate { topo_hdl_strdup; topo_hdl_strfree; topo_hdl_zalloc; + topo_led_state_name; + topo_led_type_name; topo_list_append; topo_list_delete; topo_method_invoke; topo_method_register; + topo_method_supported; topo_method_unregister; topo_method_unregister_all; topo_mod_alloc; @@ -98,6 +102,9 @@ SUNWprivate { topo_node_asru; topo_node_asru_set; topo_node_bind; + topo_node_facility; + topo_node_facbind; + topo_node_flags; topo_node_fru; topo_node_fru_set; topo_node_getspecific; @@ -121,6 +128,7 @@ SUNWprivate { topo_prop_get_string; topo_prop_get_uint32; topo_prop_get_uint64; + topo_prop_get_double; topo_prop_get_int32_array; topo_prop_get_uint32_array; topo_prop_get_int64_array; @@ -139,6 +147,7 @@ SUNWprivate { topo_prop_set_string; topo_prop_set_uint32; topo_prop_set_uint64; + topo_prop_set_double; topo_prop_set_int32_array; topo_prop_set_uint32_array; topo_prop_set_int64_array; @@ -146,7 +155,11 @@ SUNWprivate { topo_prop_set_string_array; topo_prop_set_fmri_array; topo_prop_setprop; + topo_prop_setmutable; topo_name2stability; + topo_sensor_state_name; + topo_sensor_type_name; + topo_sensor_units_name; topo_stability2name; topo_snap_hold; topo_snap_release; diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_2xml.c b/usr/src/lib/fm/topo/libtopo/common/topo_2xml.c index 0f3e69ae70..c988d7682d 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_2xml.c +++ b/usr/src/lib/fm/topo/libtopo/common/topo_2xml.c @@ -38,7 +38,8 @@ #include <topo_tree.h> #define INT32BUFSZ sizeof (UINT32_MAX) + 1 -#define INT64BUFSZ sizeof (UINT64_MAX) + 1 +/* 2 bytes for "0x" + 16 bytes for the hex value + 1 for sign + null */ +#define INT64BUFSZ 20 #define XML_VERSION "1.0" static int txml_print_range(topo_hdl_t *, FILE *, tnode_t *, int); @@ -103,77 +104,88 @@ end_element(FILE *fp, const char *ename) } static void -txml_print_prop(topo_hdl_t *thp, FILE *fp, topo_propval_t *pv) +txml_print_prop(topo_hdl_t *thp, FILE *fp, tnode_t *node, const char *pgname, + topo_propval_t *pv) { int err; char *fmri = NULL; - char vbuf[INT64BUFSZ], tbuf[10], *pval, *aval; - nvpair_t *nvp; - - nvp = nvlist_next_nvpair(pv->tp_val, NULL); - while (nvp && (strcmp(TOPO_PROP_VAL_VAL, nvpair_name(nvp)) != 0)) - nvp = nvlist_next_nvpair(pv->tp_val, nvp); - - if (nvp == NULL) - return; + char vbuf[INT64BUFSZ], tbuf[32], *pval = NULL, *aval; switch (pv->tp_type) { case TOPO_TYPE_INT32: { int32_t val; - (void) nvpair_value_int32(nvp, &val); - (void) snprintf(vbuf, INT64BUFSZ, "%d", val); - (void) snprintf(tbuf, 10, "%s", Int32); - pval = vbuf; + if (topo_prop_get_int32(node, pgname, pv->tp_name, &val, + &err) == 0) { + (void) snprintf(vbuf, INT64BUFSZ, "%d", val); + (void) snprintf(tbuf, 10, "%s", Int32); + pval = vbuf; + } else + return; break; } case TOPO_TYPE_UINT32: { uint32_t val; - (void) nvpair_value_uint32(nvp, &val); - (void) snprintf(vbuf, INT64BUFSZ, "0x%x", val); - (void) snprintf(tbuf, 10, "%s", UInt32); - pval = vbuf; + if (topo_prop_get_uint32(node, pgname, pv->tp_name, + &val, &err) == 0) { + (void) snprintf(vbuf, INT64BUFSZ, "0x%x", val); + (void) snprintf(tbuf, 10, "%s", UInt32); + pval = vbuf; + } else + return; break; } case TOPO_TYPE_INT64: { int64_t val; - (void) nvpair_value_int64(nvp, &val); - (void) snprintf(vbuf, INT64BUFSZ, "%lld", - (longlong_t)val); - (void) snprintf(tbuf, 10, "%s", Int64); - pval = vbuf; + if (topo_prop_get_int64(node, pgname, pv->tp_name, &val, + &err) == 0) { + (void) snprintf(vbuf, INT64BUFSZ, "0x%llx", + (longlong_t)val); + (void) snprintf(tbuf, 10, "%s", Int64); + pval = vbuf; + } else + return; break; } case TOPO_TYPE_UINT64: { uint64_t val; - (void) nvpair_value_uint64(nvp, &val); - (void) snprintf(vbuf, INT64BUFSZ, "0x%llx", - (u_longlong_t)val); - (void) snprintf(tbuf, 10, "%s", UInt64); - pval = vbuf; + if (topo_prop_get_uint64(node, pgname, pv->tp_name, + &val, &err) == 0) { + (void) snprintf(vbuf, INT64BUFSZ, "0x%llx", + (u_longlong_t)val); + (void) snprintf(tbuf, 10, "%s", UInt64); + pval = vbuf; + } else + return; break; } case TOPO_TYPE_STRING: { - (void) nvpair_value_string(nvp, &pval); - (void) snprintf(tbuf, 10, "%s", String); + if (topo_prop_get_string(node, pgname, pv->tp_name, + &pval, &err) != 0) + return; + (void) snprintf(tbuf, 10, "%s", "string"); break; } case TOPO_TYPE_FMRI: { nvlist_t *val; - (void) nvpair_value_nvlist(nvp, &val); - if (topo_fmri_nvl2str(thp, val, &fmri, &err) == 0) - pval = fmri; - else + if (topo_prop_get_fmri(node, pgname, pv->tp_name, &val, + &err) == 0) { + if (topo_fmri_nvl2str(thp, val, &fmri, &err) + == 0) + pval = fmri; + else + return; + } else return; - (void) snprintf(tbuf, 10, "%s", FMRI); break; } case TOPO_TYPE_UINT32_ARRAY: { uint32_t *val; uint_t nelem, i; - - (void) nvpair_value_uint32_array(nvp, &val, &nelem); + if (topo_prop_get_uint32_array(node, pgname, + pv->tp_name, &val, &nelem, &err) != 0) + return; if (nelem > 0) { aval = calloc((nelem*9-1), sizeof (uchar_t)); @@ -195,11 +207,10 @@ txml_print_prop(topo_hdl_t *thp, FILE *fp, topo_propval_t *pv) if (fmri != NULL) topo_hdl_strfree(thp, fmri); - } static void -txml_print_pgroup(topo_hdl_t *thp, FILE *fp, topo_pgroup_t *pg) +txml_print_pgroup(topo_hdl_t *thp, FILE *fp, tnode_t *node, topo_pgroup_t *pg) { topo_ipgroup_info_t *pip = pg->tpg_info; topo_proplist_t *plp; @@ -213,7 +224,7 @@ txml_print_pgroup(topo_hdl_t *thp, FILE *fp, topo_pgroup_t *pg) namestab, Datastab, datastab, Version, version, NULL); for (plp = topo_list_next(&pg->tpg_pvals); plp != NULL; plp = topo_list_next(plp)) { - txml_print_prop(thp, fp, plp->tp_pval); + txml_print_prop(thp, fp, node, pip->tpi_name, plp->tp_pval); } end_element(fp, Propgrp); } @@ -238,7 +249,7 @@ txml_print_node(topo_hdl_t *thp, FILE *fp, tnode_t *node) begin_element(fp, Node, Instance, inst, Static, True, NULL); for (pg = topo_list_next(&node->tn_pgroups); pg != NULL; pg = topo_list_next(pg)) { - txml_print_pgroup(thp, fp, pg); + txml_print_pgroup(thp, fp, node, pg); } txml_print_dependents(thp, fp, node); end_element(fp, Node); diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_error.h b/usr/src/lib/fm/topo/libtopo/common/topo_error.h index 017a160d1b..829ca707a2 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_error.h +++ b/usr/src/lib/fm/topo/libtopo/common/topo_error.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -64,13 +64,6 @@ typedef enum topo_errno { ETOPO_RTLD_NOMEM, /* memory limit exceeded when opening shared library */ ETOPO_BLTIN_NAME, /* built-in plug-in name not found in definition list */ ETOPO_BLTIN_INIT, /* built-in plug-in does not define init function */ - ETOPO_NODE_INVAL, /* node opertation invalid argument */ - ETOPO_NODE_LINKED, /* node already linked */ - ETOPO_NODE_BOUND, /* node already bound */ - ETOPO_NODE_DUP, /* duplicate node */ - ETOPO_NODE_RANGE, /* invalid instance range */ - ETOPO_NODE_NOENT, /* node not found */ - ETOPO_NODE_FMRI, /* no fmri specified */ ETOPO_VER_OLD, /* plugin compiled using an obsolete topo ABI */ ETOPO_VER_NEW, /* plugin is compiled using a newer topo ABI */ ETOPO_ENUM_PARTIAL, /* partial enumeration completed for client */ @@ -93,6 +86,7 @@ typedef enum topo_errno { ETOPO_PRSR_REGMETH, /* failed to register property method */ ETOPO_WALK_EMPTY, /* empty topology */ ETOPO_WALK_NOTFOUND, /* scheme based topology not found */ + ETOPO_FAC_NOENT, /* no facility node of specified type found */ ETOPO_END /* end of custom errno list (to ease auto-merge) */ } topo_errno_t; diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_fmri.c b/usr/src/lib/fm/topo/libtopo/common/topo_fmri.c index 85fd5d3155..da82e8bc57 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_fmri.c +++ b/usr/src/lib/fm/topo/libtopo/common/topo_fmri.c @@ -690,3 +690,49 @@ topo_fmri_strcmp(topo_hdl_t *thp, const char *a, const char *b) return (strcmp(ea, eb) == 0); } + +int +topo_fmri_facility(topo_hdl_t *thp, nvlist_t *rsrc, const char *fac_type, + uint32_t fac_subtype, topo_walk_cb_t cb, void *cb_args, int *err) +{ + int rv; + nvlist_t *in = NULL, *out; + tnode_t *rnode; + char *scheme; + + if (nvlist_lookup_string(rsrc, FM_FMRI_SCHEME, &scheme) != 0) + return (set_error(thp, ETOPO_FMRI_MALFORM, err, + TOPO_METH_PROP_GET, in)); + + if ((rnode = topo_hdl_root(thp, scheme)) == NULL) + return (set_error(thp, ETOPO_METHOD_NOTSUP, err, + TOPO_METH_PROP_GET, in)); + + if (topo_hdl_nvalloc(thp, &in, NV_UNIQUE_NAME) != 0) + return (set_error(thp, ETOPO_FMRI_NVL, err, + TOPO_METH_PROP_GET, in)); + + rv = nvlist_add_nvlist(in, TOPO_PROP_RESOURCE, rsrc); + rv |= nvlist_add_string(in, FM_FMRI_FACILITY_TYPE, fac_type); + rv |= nvlist_add_uint32(in, "type", fac_subtype); +#ifdef _LP64 + rv |= nvlist_add_uint64(in, "callback", (uint64_t)cb); + rv |= nvlist_add_uint64(in, "callback-args", (uint64_t)cb_args); +#else + rv |= nvlist_add_uint32(in, "callback", (uint32_t)cb); + rv |= nvlist_add_uint32(in, "callback-args", (uint32_t)cb_args); +#endif + if (rv != 0) + return (set_error(thp, ETOPO_FMRI_NVL, err, + TOPO_METH_PROP_GET, in)); + + rv = topo_method_invoke(rnode, TOPO_METH_FACILITY, + TOPO_METH_FACILITY_VERSION, in, &out, err); + + nvlist_free(in); + + if (rv != 0) + return (-1); /* *err is set for us */ + + return (0); +} diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_method.c b/usr/src/lib/fm/topo/libtopo/common/topo_method.c index dc8719646e..32e783e908 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_method.c +++ b/usr/src/lib/fm/topo/libtopo/common/topo_method.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -58,6 +58,29 @@ topo_method_lookup(tnode_t *node, const char *name) return (NULL); } +/* + * Simple API to determine if the specified node supports a given topo method + * (specified by the method name and version). Returns true if supported, false + * otherwise. + */ +boolean_t +topo_method_supported(tnode_t *node, const char *name, topo_version_t vers) +{ + topo_imethod_t *mp; + + topo_node_lock(node); + for (mp = topo_list_next(&node->tn_methods); mp != NULL; + mp = topo_list_next(mp)) { + if ((strcmp(name, mp->tim_name) == 0) && + (vers == mp->tim_version)) { + topo_node_unlock(node); + return (B_TRUE); + } + } + topo_node_unlock(node); + return (B_FALSE); +} + static void topo_method_enter(topo_imethod_t *mp) { diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_method.h b/usr/src/lib/fm/topo/libtopo/common/topo_method.h index 80c9656b67..07abf76230 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_method.h +++ b/usr/src/lib/fm/topo/libtopo/common/topo_method.h @@ -67,6 +67,7 @@ extern int topo_prop_method_version_register(tnode_t *, const char *, #define TOPO_METH_PROP_GET "topo_prop_get" #define TOPO_METH_PGRP_GET "topo_pgrp_get" #define TOPO_METH_PROP_SET "topo_prop_set" +#define TOPO_METH_FACILITY "topo_facility" #define TOPO_METH_FMRI_VERSION 0 #define TOPO_METH_FRU_COMPUTE_VERSION 0 @@ -77,6 +78,7 @@ extern int topo_prop_method_version_register(tnode_t *, const char *, #define TOPO_METH_PROP_GET_VERSION 0 #define TOPO_METH_PGRP_GET_VERSION 0 #define TOPO_METH_PROP_SET_VERSION 0 +#define TOPO_METH_FACILITY_VERSION 0 #define TOPO_METH_ASRU_COMPUTE_DESC "Dynamic ASRU constructor" #define TOPO_METH_FRU_COMPUTE_DESC "Dynamic FRU constructor" @@ -87,6 +89,7 @@ extern int topo_prop_method_version_register(tnode_t *, const char *, #define TOPO_METH_PROP_GET_DESC "get properties for FMRI" #define TOPO_METH_PGRP_GET_DESC "get property group for FMRI" #define TOPO_METH_PROP_SET_DESC "set properties for FMRI" +#define TOPO_METH_FACILITY_DESC "get facility for FMRI" #define TOPO_METH_COMPARE_RET "contains-return" diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_mod.h b/usr/src/lib/fm/topo/libtopo/common/topo_mod.h index 570ce22ab2..4c404ca450 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_mod.h +++ b/usr/src/lib/fm/topo/libtopo/common/topo_mod.h @@ -96,7 +96,8 @@ extern nvlist_t *topo_mod_modfmri(topo_mod_t *, int, const char *); extern nvlist_t *topo_mod_pkgfmri(topo_mod_t *, int, const char *); extern int topo_mod_nvl2str(topo_mod_t *, nvlist_t *, char **); extern int topo_mod_str2nvl(topo_mod_t *, const char *, nvlist_t **); - +extern int topo_prop_setmutable(tnode_t *node, const char *pgname, + const char *pname, int *err); /* * Snapshot walker support */ @@ -127,8 +128,8 @@ extern nvlist_t *topo_mod_auth(topo_mod_t *, tnode_t *); #define TOPO_METH_LABEL_DESC "label constructor" #define TOPO_METH_LABEL_VERSION0 0 #define TOPO_METH_LABEL_VERSION TOPO_METH_LABEL_VERSION0 -#define TOPO_METH_LABEL_ARG_NVL "label-specific" -#define TOPO_METH_LABEL_RET_STR "label-string" +#define TOPO_METH_LABEL_ARG_NVL "label-specific" +#define TOPO_METH_LABEL_RET_STR "label-string" #define TOPO_METH_PRESENT "topo_present" #define TOPO_METH_PRESENT_DESC "presence indicator" @@ -167,6 +168,11 @@ extern nvlist_t *topo_mod_auth(topo_mod_t *, tnode_t *); #define TOPO_METH_DISK_STATUS_VERSION 0 #define TOPO_METH_DISK_STATUS_DESC "Disk status" +#define TOPO_PROP_METH_DESC "Dynamic Property method" + +#define TOPO_METH_IPMI_ENTITY "ipmi_entity" +#define TOPO_METH_FAC_ENUM_DESC "Facility Enumerator" + extern void *topo_mod_alloc(topo_mod_t *, size_t); extern void *topo_mod_zalloc(topo_mod_t *, size_t); extern void topo_mod_free(topo_mod_t *, void *, size_t); @@ -189,6 +195,8 @@ extern int topo_node_range_create(topo_mod_t *, tnode_t *, const char *, extern void topo_node_range_destroy(tnode_t *, const char *); extern tnode_t *topo_node_bind(topo_mod_t *, tnode_t *, const char *, topo_instance_t, nvlist_t *); +extern tnode_t *topo_node_facbind(topo_mod_t *, tnode_t *, const char *, + const char *); extern void topo_node_unbind(tnode_t *); extern void topo_node_setspecific(tnode_t *, void *); extern void *topo_node_getspecific(tnode_t *); @@ -199,33 +207,6 @@ extern int topo_node_label_set(tnode_t *node, char *, int *); #define TOPO_ASRU_COMPUTE 0x0001 /* Compute ASRU dynamically */ #define TOPO_FRU_COMPUTE 0x0002 /* Compute FRU dynamically */ -/* - * Topo property set functions - */ -extern int topo_prop_set_int32(tnode_t *, const char *, const char *, int, - int32_t, int *); -extern int topo_prop_set_uint32(tnode_t *, const char *, const char *, int, - uint32_t, int *); -extern int topo_prop_set_int64(tnode_t *, const char *, const char *, - int, int64_t, int *); -extern int topo_prop_set_uint64(tnode_t *, const char *, const char *, - int, uint64_t, int *); -extern int topo_prop_set_string(tnode_t *, const char *, const char *, - int, const char *, int *); -extern int topo_prop_set_fmri(tnode_t *, const char *, const char *, - int, const nvlist_t *, int *); -extern int topo_prop_set_int32_array(tnode_t *, const char *, const char *, int, - int32_t *, uint_t, int *); -extern int topo_prop_set_uint32_array(tnode_t *, const char *, const char *, - int, uint32_t *, uint_t, int *); -extern int topo_prop_set_int64_array(tnode_t *, const char *, const char *, - int, int64_t *, uint_t, int *); -extern int topo_prop_set_uint64_array(tnode_t *, const char *, const char *, - int, uint64_t *, uint_t, int *); -extern int topo_prop_set_string_array(tnode_t *, const char *, const char *, - int, const char **, uint_t, int *); -extern int topo_prop_set_fmri_array(tnode_t *, const char *, const char *, - int, const nvlist_t **, uint_t, int *); extern int topo_prop_inherit(tnode_t *, const char *, const char *, int *); extern int topo_pgroup_create(tnode_t *, const topo_pgroup_info_t *, int *); @@ -252,6 +233,10 @@ typedef enum topo_mod_errno { EMOD_FMRI_NVL, /* nvlist allocation failure for FMRI */ EMOD_FMRI_VERSION, /* invalid FMRI scheme version */ EMOD_FMRI_MALFORM, /* malformed FMRI */ + EMOD_NODE_BOUND, /* node already bound */ + EMOD_NODE_DUP, /* duplicate node */ + EMOD_NODE_NOENT, /* node not found */ + EMOD_NODE_RANGE, /* invalid node range */ EMOD_VER_ABI, /* registered with invalid ABI version */ EMOD_VER_OLD, /* attempt to load obsolete module */ EMOD_VER_NEW, /* attempt to load a newer module */ diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_node.c b/usr/src/lib/fm/topo/libtopo/common/topo_node.c index 2b0f4e7777..3f12fdd3f5 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_node.c +++ b/usr/src/lib/fm/topo/libtopo/common/topo_node.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -94,6 +94,13 @@ * ----------- * | tnode_t | * ----------- + * + * Facility Nodes + * + * Facility nodes are always leaf nodes in the topology and represent a FMRI + * sensor or indicator facility for the path to which it is connected. + * Facility nodes are bound to the topology with topo_node_facbind() and + * unbound with topo_node_unbind(). */ #include <assert.h> @@ -102,6 +109,7 @@ #include <sys/fm/protocol.h> #include <topo_alloc.h> #include <topo_error.h> +#include <topo_list.h> #include <topo_method.h> #include <topo_subr.h> #include <topo_tree.h> @@ -248,6 +256,12 @@ topo_node_parent(tnode_t *node) return (node->tn_parent); } +int +topo_node_flags(tnode_t *node) +{ + return (node->tn_fflags); +} + void topo_node_setspecific(tnode_t *node, void *data) { @@ -297,24 +311,24 @@ topo_node_range_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nhp = topo_list_next(nhp)) { if (strcmp(nhp->th_name, name) == 0) return (node_create_seterror(mod, pnode, NULL, - ETOPO_NODE_DUP)); + EMOD_NODE_DUP)); } if (min < 0 || max < min) return (node_create_seterror(mod, pnode, NULL, - ETOPO_NODE_INVAL)); + EMOD_NODE_RANGE)); if ((nhp = topo_mod_zalloc(mod, sizeof (topo_nodehash_t))) == NULL) - return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM)); + return (node_create_seterror(mod, pnode, nhp, EMOD_NOMEM)); if ((nhp->th_name = topo_mod_strdup(mod, name)) == NULL) - return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM)); + return (node_create_seterror(mod, pnode, nhp, EMOD_NOMEM)); nhp->th_arrlen = max - min + 1; if ((nhp->th_nodearr = topo_mod_zalloc(mod, nhp->th_arrlen * sizeof (tnode_t *))) == NULL) - return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM)); + return (node_create_seterror(mod, pnode, nhp, EMOD_NOMEM)); nhp->th_range.tr_min = min; nhp->th_range.tr_max = max; @@ -442,12 +456,12 @@ topo_node_bind(topo_mod_t *mod, tnode_t *pnode, const char *name, if (inst > nhp->th_range.tr_max || inst < nhp->th_range.tr_min) return (node_bind_seterror(mod, pnode, NULL, - ETOPO_NODE_INVAL)); + EMOD_NODE_RANGE)); h = topo_node_hash(nhp, inst); if (nhp->th_nodearr[h] != NULL) return (node_bind_seterror(mod, pnode, NULL, - ETOPO_NODE_BOUND)); + EMOD_NODE_BOUND)); else break; @@ -455,10 +469,10 @@ topo_node_bind(topo_mod_t *mod, tnode_t *pnode, const char *name, } if (nhp == NULL) - return (node_bind_seterror(mod, pnode, NULL, ETOPO_NODE_NOENT)); + return (node_bind_seterror(mod, pnode, NULL, EMOD_NODE_NOENT)); if ((node = topo_mod_zalloc(mod, sizeof (tnode_t))) == NULL) - return (node_bind_seterror(mod, pnode, NULL, ETOPO_NOMEM)); + return (node_bind_seterror(mod, pnode, NULL, EMOD_NOMEM)); (void) pthread_mutex_init(&node->tn_lock, NULL); @@ -474,7 +488,7 @@ topo_node_bind(topo_mod_t *mod, tnode_t *pnode, const char *name, topo_mod_hold(mod); if (fmri == NULL) - return (node_bind_seterror(mod, pnode, node, ETOPO_NODE_INVAL)); + return (node_bind_seterror(mod, pnode, node, EMOD_NVL_INVAL)); if (topo_pgroup_create(node, &protocol_pgroup, &err) < 0) return (node_bind_seterror(mod, pnode, node, err)); @@ -492,6 +506,7 @@ topo_node_bind(topo_mod_t *mod, tnode_t *pnode, const char *name, topo_node_hold(node); nhp->th_nodearr[h] = node; ++pnode->tn_refs; + topo_node_unlock(pnode); if (topo_pgroup_create(node, &auth_pgroup, &err) == 0) { @@ -506,6 +521,227 @@ topo_node_bind(topo_mod_t *mod, tnode_t *pnode, const char *name, return (node); } +tnode_t * +topo_node_facbind(topo_mod_t *mod, tnode_t *pnode, const char *name, + const char *type) +{ + int h, err; + tnode_t *node; + topo_nodehash_t *nhp; + topo_instance_t inst = 0; + nvlist_t *pfmri, *fnvl; + + /* + * Create a single entry range for this facility + */ + if (topo_node_range_create(mod, pnode, name, 0, 0) < 0) + return (NULL); /* mod errno set */ + + topo_node_lock(pnode); + for (nhp = topo_list_next(&pnode->tn_children); nhp != NULL; + nhp = topo_list_next(nhp)) { + if (strcmp(nhp->th_name, name) == 0) { + + if (inst > nhp->th_range.tr_max || + inst < nhp->th_range.tr_min) + return (node_bind_seterror(mod, pnode, NULL, + EMOD_NVL_INVAL)); + + h = topo_node_hash(nhp, inst); + if (nhp->th_nodearr[h] != NULL) + return (node_bind_seterror(mod, pnode, NULL, + EMOD_NODE_BOUND)); + else + break; + + } + } + + if (nhp == NULL) + return (node_bind_seterror(mod, pnode, NULL, EMOD_NODE_NOENT)); + + if ((node = topo_mod_zalloc(mod, sizeof (tnode_t))) == NULL) + return (node_bind_seterror(mod, pnode, NULL, EMOD_NOMEM)); + + (void) pthread_mutex_init(&node->tn_lock, NULL); + + node->tn_enum = mod; + node->tn_hdl = mod->tm_hdl; + node->tn_parent = pnode; + node->tn_name = nhp->th_name; + node->tn_instance = inst; + node->tn_phash = nhp; + node->tn_refs = 0; + node->tn_fflags = TOPO_NODE_FACILITY; + + /* Ref count module that bound this node */ + topo_mod_hold(mod); + + if (topo_pgroup_create(node, &protocol_pgroup, &err) < 0) + return (node_bind_seterror(mod, pnode, node, err)); + + if (topo_mod_nvalloc(mod, &fnvl, NV_UNIQUE_NAME) < 0) + return (node_bind_seterror(mod, pnode, node, EMOD_NOMEM)); + if (nvlist_add_string(fnvl, FM_FMRI_FACILITY_NAME, name) != 0 || + nvlist_add_string(fnvl, FM_FMRI_FACILITY_TYPE, type) != 0) { + nvlist_free(fnvl); + return (node_bind_seterror(mod, pnode, node, EMOD_FMRI_NVL)); + } + + if (topo_node_resource(pnode, &pfmri, &err) < 0) { + nvlist_free(fnvl); + return (node_bind_seterror(mod, pnode, node, err)); + } + + if (nvlist_add_nvlist(pfmri, FM_FMRI_FACILITY, fnvl) != 0) { + nvlist_free(fnvl); + nvlist_free(pfmri); + return (node_bind_seterror(mod, pnode, node, EMOD_FMRI_NVL)); + } + + nvlist_free(fnvl); + + if (topo_prop_set_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_RESOURCE, + TOPO_PROP_IMMUTABLE, pfmri, &err) < 0) { + nvlist_free(pfmri); + return (node_bind_seterror(mod, pnode, node, err)); + } + + nvlist_free(pfmri); + + topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC, + "facility node bound %s=%s\n", type, node->tn_name); + + node->tn_state |= TOPO_NODE_BOUND; + + topo_node_hold(node); + nhp->th_nodearr[h] = node; + ++pnode->tn_refs; + + topo_node_unlock(pnode); + + if (topo_pgroup_create(node, &auth_pgroup, &err) == 0) { + (void) topo_prop_inherit(node, FM_FMRI_AUTHORITY, + FM_FMRI_AUTH_PRODUCT, &err); + (void) topo_prop_inherit(node, FM_FMRI_AUTHORITY, + FM_FMRI_AUTH_CHASSIS, &err); + (void) topo_prop_inherit(node, FM_FMRI_AUTHORITY, + FM_FMRI_AUTH_SERVER, &err); + } + + return (node); +} + +int +topo_node_facility(topo_hdl_t *thp, tnode_t *node, const char *fac_type, + uint32_t fac_subtype, topo_faclist_t *faclist, int *errp) +{ + tnode_t *tmp; + nvlist_t *rsrc, *fac, *out; + char *tmp_factype; + uint32_t tmp_facsubtype; + boolean_t list_empty = 1; + topo_faclist_t *fac_ele; + + /* + * Some facility nodes will be statically enumerated in the xml maps. + * Other may be enumerated on-demand. We can check for/handle the + * latter case by looking for a node method for doing facility + * enumeration and invoking it, if found. + * + * If the TOPO_FACILITIES_BOUND flag is set on this node, then we've + * already enumerated the facilties for this node (by a previous call + * to topo_node_facility) so there's no need to invoke the enumeration + * method. + */ + topo_node_lock(node); + if (!(node->tn_state & TOPO_FACILITIES_BOUND) && + topo_method_supported(node, TOPO_METH_FAC_ENUM, 0)) { + + if (topo_method_invoke(node, TOPO_METH_FAC_ENUM, 0, NULL, &out, + errp) != 0) { + topo_dprintf(thp, TOPO_DBG_ERR, + "topo_method_invoke failed (%s) on node %s=%d\n", + topo_strerror(*errp), topo_node_name(node), + topo_node_instance(node)); + topo_node_unlock(node); + return (-1); + } else + node->tn_state |= TOPO_FACILITIES_BOUND; + } + + bzero(faclist, sizeof (topo_faclist_t)); + for (tmp = topo_child_first(node); tmp != NULL; + tmp = topo_child_next(node, tmp)) { + + topo_node_hold(tmp); + /* + * If it's not a facility node, move on + */ + if (topo_node_flags(tmp) != TOPO_NODE_FACILITY) { + topo_node_rele(tmp); + continue; + } + + /* + * Lookup whether the fac type is sensor or indicator and if + * it's not the type we're looking for, move on + */ + if (topo_node_resource(tmp, &rsrc, errp) != 0) { + topo_dprintf(thp, TOPO_DBG_ERR, + "Failed to get resource for node %s=%d (%s)\n", + topo_node_name(node), topo_node_instance(node), + topo_strerror(*errp)); + topo_node_rele(tmp); + topo_node_unlock(node); + return (-1); + } + if ((nvlist_lookup_nvlist(rsrc, "facility", &fac) != 0) || + (nvlist_lookup_string(fac, FM_FMRI_FACILITY_TYPE, + &tmp_factype) != 0)) { + + topo_node_rele(tmp); + topo_node_unlock(node); + return (-1); + } + if (strcmp(fac_type, tmp_factype) != 0) { + topo_node_rele(tmp); + continue; + } + + /* + * Finally, look up the subtype, which is a property in the + * facility propgroup. If it's a match return a pointer to the + * node. Otherwise, move on. + */ + if (topo_prop_get_uint32(tmp, TOPO_PGROUP_FACILITY, + TOPO_FACILITY_TYPE, &tmp_facsubtype, errp) != 0) { + + topo_node_rele(tmp); + topo_node_unlock(node); + return (-1); + } + if (fac_subtype == tmp_facsubtype) { + if ((fac_ele = topo_mod_zalloc(tmp->tn_enum, + sizeof (topo_faclist_t))) == NULL) { + *errp = ETOPO_NOMEM; + return (-1); + } + fac_ele->tf_node = tmp; + topo_list_append(&faclist->tf_list, fac_ele); + list_empty = 0; + } + topo_node_rele(tmp); + } + topo_node_unlock(node); + + if (list_empty) { + *errp = ETOPO_FAC_NOENT; + return (-1); + } + return (0); +} + void topo_node_unbind(tnode_t *node) { @@ -561,7 +797,7 @@ topo_node_walk_init(topo_hdl_t *thp, topo_mod_t *mod, tnode_t *node, topo_node_hold(node); if ((wp = topo_hdl_zalloc(thp, sizeof (topo_walk_t))) == NULL) { - *errp = ETOPO_NOMEM; + *errp = ETOPO_HDL_NOMEM; topo_node_rele(node); return (NULL); } diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_parse.h b/usr/src/lib/fm/topo/libtopo/common/topo_parse.h index 392398886b..f53fae6d90 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_parse.h +++ b/usr/src/lib/fm/topo/libtopo/common/topo_parse.h @@ -95,6 +95,15 @@ typedef struct tf_rdata { tf_edata_t *rd_einfo; /* enumerator information, if any */ struct tf_idata *rd_instances; /* hard instances */ tf_pad_t *rd_pad; /* properties and dependents */ + /* + * true, if this range xml element contains any child xml + * node elements. + * We use this to determine whether or not we should apply + * property map changes to all of the nodes in a given range + * or just a specific node. + * + */ + int contains_node_ele; } tf_rdata_t; /* @@ -135,19 +144,25 @@ typedef struct tf_info { #define Argval "argval" #define Children "children" #define Dependents "dependents" +#define Facility "facility" #define FMRI "fmri" #define Grouping "grouping" #define Immutable "immutable" +#define Indicator "indicator" #define Instance "instance" #define Int32 "int32" #define Int64 "int64" +#define Ipmi "ipmi" +#define Mutable "mutable" #define Name "name" #define Propname "propname" #define Proptype "proptype" +#define Provider "provider" #define Range "range" #define Scheme "scheme" #define Set "set" #define Setlist "setlist" +#define Sensor "sensor" #define Siblings "siblings" #define Static "static" #define String "string" diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_prop.c b/usr/src/lib/fm/topo/libtopo/common/topo_prop.c index 7b9a005c1a..1dbf028d77 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_prop.c +++ b/usr/src/lib/fm/topo/libtopo/common/topo_prop.c @@ -234,6 +234,10 @@ prop_getval(tnode_t *node, const char *pgname, const char *pname, void *val, ret = nvlist_lookup_uint64(pv->tp_val, TOPO_PROP_VAL_VAL, (uint64_t *)val); break; + case TOPO_TYPE_DOUBLE: + ret = nvlist_lookup_double(pv->tp_val, + TOPO_PROP_VAL_VAL, (double *)val); + break; case TOPO_TYPE_STRING: { char *str; @@ -419,6 +423,14 @@ topo_prop_get_uint64(tnode_t *node, const char *pgname, const char *pname, } int +topo_prop_get_double(tnode_t *node, const char *pgname, const char *pname, + double *val, int *err) +{ + return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_DOUBLE, + NULL, err)); +} + +int topo_prop_get_string(tnode_t *node, const char *pgname, const char *pname, char **val, int *err) { @@ -557,7 +569,6 @@ topo_prop_set(tnode_t *node, const char *pgname, const char *pname, int ret; topo_hdl_t *thp = node->tn_hdl; nvlist_t *nvl; - topo_propval_t *pv; if (topo_hdl_nvalloc(thp, &nvl, NV_UNIQUE_NAME) < 0) { *err = ETOPO_PROP_NVL; @@ -583,6 +594,10 @@ topo_prop_set(tnode_t *node, const char *pgname, const char *pname, ret |= nvlist_add_uint64(nvl, TOPO_PROP_VAL_VAL, *(uint64_t *)val); break; + case TOPO_TYPE_DOUBLE: + ret |= nvlist_add_double(nvl, TOPO_PROP_VAL_VAL, + *(double *)val); + break; case TOPO_TYPE_STRING: ret |= nvlist_add_string(nvl, TOPO_PROP_VAL_VAL, (char *)val); @@ -631,16 +646,11 @@ topo_prop_set(tnode_t *node, const char *pgname, const char *pname, } } - topo_node_lock(node); - if ((pv = prop_create(node, pgname, pname, type, flag, err)) == NULL) { + if (topo_prop_setprop(node, pgname, nvl, flag, nvl, err) != 0) { nvlist_free(nvl); - return (-1); /* unlocked and err set */ + return (-1); /* err set */ } - - pv->tp_val = nvl; - - topo_node_unlock(node); - + nvlist_free(nvl); return (ret); } @@ -677,6 +687,14 @@ topo_prop_set_uint64(tnode_t *node, const char *pgname, const char *pname, } int +topo_prop_set_double(tnode_t *node, const char *pgname, const char *pname, + int flag, double val, int *err) +{ + return (topo_prop_set(node, pgname, pname, TOPO_TYPE_DOUBLE, flag, + &val, 1, err)); +} + +int topo_prop_set_string(tnode_t *node, const char *pgname, const char *pname, int flag, const char *val, int *err) { @@ -877,10 +895,18 @@ prop_method_register(tnode_t *node, const char *pgname, const char *pname, * to allow the method to be registered. This is to handle the case * where we specify an prop method in an xml map to override the value * that was set by the enumerator. + * + * By default, propmethod-backed properties are IMMUTABLE. This is done + * to simplify the programming model for modules that implement property + * methods as most propmethods tend to only support get operations. + * Enumerator modules can override this by calling topo_prop_setflags(). + * Propmethods that are registered via XML can be set as mutable via + * the optional "mutable" attribute, which will result in the xml parser + * calling topo_prop_setflags() after registering the propmethod. */ if ((pv = propval_get(pgroup_get(node, pgname), pname)) == NULL) if ((pv = prop_create(node, pgname, pname, ptype, - TOPO_PROP_MUTABLE, err)) == NULL) { + TOPO_PROP_IMMUTABLE, err)) == NULL) { /* node unlocked */ return (register_methoderror(node, pm, err, 0, *err)); } @@ -982,6 +1008,35 @@ topo_prop_method_unregister(tnode_t *node, const char *pgname, topo_node_unlock(node); } +int +topo_prop_setmutable(tnode_t *node, const char *pgname, const char *pname, + int *err) +{ + topo_propval_t *pv = NULL; + + topo_node_lock(node); + if ((pv = propval_get(pgroup_get(node, pgname), pname)) == NULL) { + topo_node_unlock(node); + *err = ETOPO_PROP_NOENT; + return (-1); + } + + /* + * If the property is being inherited then we don't want to allow a + * change from IMMUTABLE to MUTABLE. + */ + if (pv->tp_refs > 1) { + topo_node_unlock(node); + *err = ETOPO_PROP_DEFD; + return (-1); + } + pv->tp_flag = TOPO_PROP_MUTABLE; + + topo_node_unlock(node); + + return (0); +} + static int inherit_seterror(tnode_t *node, int *errp, int err) { diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_subr.c b/usr/src/lib/fm/topo/libtopo/common/topo_subr.c index b15dc170c2..e1c9e6fcc2 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_subr.c +++ b/usr/src/lib/fm/topo/libtopo/common/topo_subr.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -351,3 +351,204 @@ topo_cleanup_auth_str(topo_hdl_t *thp, char *begin) pp = topo_hdl_strdup(thp, buf); return (pp); } + +void +topo_sensor_type_name(uint32_t type, char *buf, size_t len) +{ + topo_name_trans_t *ntp; + + for (ntp = &topo_sensor_type_table[0]; ntp->int_name != NULL; ntp++) { + if (ntp->int_value == type) { + (void) strlcpy(buf, ntp->int_name, len); + return; + } + } + + (void) snprintf(buf, len, "0x%02x", type); +} + +void +topo_sensor_units_name(uint8_t type, char *buf, size_t len) +{ + topo_name_trans_t *ntp; + + for (ntp = &topo_units_type_table[0]; ntp->int_name != NULL; ntp++) { + if (ntp->int_value == type) { + (void) strlcpy(buf, ntp->int_name, len); + return; + } + } + + (void) snprintf(buf, len, "0x%02x", type); +} + +void +topo_led_type_name(uint8_t type, char *buf, size_t len) +{ + topo_name_trans_t *ntp; + + for (ntp = &topo_led_type_table[0]; ntp->int_name != NULL; ntp++) { + if (ntp->int_value == type) { + (void) strlcpy(buf, ntp->int_name, len); + return; + } + } + + (void) snprintf(buf, len, "0x%02x", type); +} + +void +topo_led_state_name(uint8_t type, char *buf, size_t len) +{ + topo_name_trans_t *ntp; + + for (ntp = &topo_led_states_table[0]; ntp->int_name != NULL; ntp++) { + if (ntp->int_value == type) { + (void) strlcpy(buf, ntp->int_name, len); + return; + } + } + + (void) snprintf(buf, len, "0x%02x", type); +} + +void +topo_sensor_state_name(uint32_t sensor_type, uint8_t state, char *buf, +size_t len) +{ + topo_name_trans_t *ntp; + + switch (sensor_type) { + case TOPO_SENSOR_TYPE_PHYSICAL: + ntp = &topo_sensor_states_physical_table[0]; + break; + case TOPO_SENSOR_TYPE_PLATFORM: + ntp = &topo_sensor_states_platform_table[0]; + break; + case TOPO_SENSOR_TYPE_PROCESSOR: + ntp = &topo_sensor_states_processor_table[0]; + break; + case TOPO_SENSOR_TYPE_POWER_SUPPLY: + ntp = &topo_sensor_states_power_supply_table[0]; + break; + case TOPO_SENSOR_TYPE_POWER_UNIT: + ntp = &topo_sensor_states_power_unit_table[0]; + break; + case TOPO_SENSOR_TYPE_MEMORY: + ntp = &topo_sensor_states_memory_table[0]; + break; + case TOPO_SENSOR_TYPE_BAY: + ntp = &topo_sensor_states_bay_table[0]; + break; + case TOPO_SENSOR_TYPE_FIRMWARE: + ntp = &topo_sensor_states_firmware_table[0]; + break; + case TOPO_SENSOR_TYPE_EVENT_LOG: + ntp = &topo_sensor_states_event_log_table[0]; + break; + case TOPO_SENSOR_TYPE_WATCHDOG1: + ntp = &topo_sensor_states_watchdog1_table[0]; + break; + case TOPO_SENSOR_TYPE_SYSTEM: + ntp = &topo_sensor_states_system_table[0]; + break; + case TOPO_SENSOR_TYPE_CRITICAL: + ntp = &topo_sensor_states_critical_table[0]; + break; + case TOPO_SENSOR_TYPE_BUTTON: + ntp = &topo_sensor_states_button_table[0]; + break; + case TOPO_SENSOR_TYPE_CABLE: + ntp = &topo_sensor_states_cable_table[0]; + break; + case TOPO_SENSOR_TYPE_BOOT_STATE: + ntp = &topo_sensor_states_boot_state_table[0]; + break; + case TOPO_SENSOR_TYPE_BOOT_ERROR: + ntp = &topo_sensor_states_boot_error_table[0]; + break; + case TOPO_SENSOR_TYPE_BOOT_OS: + ntp = &topo_sensor_states_boot_os_table[0]; + break; + case TOPO_SENSOR_TYPE_OS_SHUTDOWN: + ntp = &topo_sensor_states_os_table[0]; + break; + case TOPO_SENSOR_TYPE_SLOT: + ntp = &topo_sensor_states_slot_table[0]; + break; + case TOPO_SENSOR_TYPE_ACPI: + ntp = &topo_sensor_states_acpi_table[0]; + break; + case TOPO_SENSOR_TYPE_WATCHDOG2: + ntp = &topo_sensor_states_watchdog2_table[0]; + break; + case TOPO_SENSOR_TYPE_ALERT: + ntp = &topo_sensor_states_alert_table[0]; + break; + case TOPO_SENSOR_TYPE_PRESENCE: + ntp = &topo_sensor_states_presence_table[0]; + break; + case TOPO_SENSOR_TYPE_LAN: + ntp = &topo_sensor_states_lan_table[0]; + break; + case TOPO_SENSOR_TYPE_HEALTH: + ntp = &topo_sensor_states_health_table[0]; + break; + case TOPO_SENSOR_TYPE_BATTERY: + ntp = &topo_sensor_states_battery_table[0]; + break; + case TOPO_SENSOR_TYPE_AUDIT: + ntp = &topo_sensor_states_audit_table[0]; + break; + case TOPO_SENSOR_TYPE_VERSION: + ntp = &topo_sensor_states_version_table[0]; + break; + case TOPO_SENSOR_TYPE_FRU_STATE: + ntp = &topo_sensor_states_fru_state_table[0]; + break; + case TOPO_SENSOR_TYPE_THRESHOLD_STATE: + ntp = &topo_sensor_states_thresh_table[0]; + break; + case TOPO_SENSOR_TYPE_GENERIC_USAGE: + ntp = &topo_sensor_states_generic_usage_table[0]; + break; + case TOPO_SENSOR_TYPE_GENERIC_STATE: + ntp = &topo_sensor_states_generic_state_table[0]; + break; + case TOPO_SENSOR_TYPE_GENERIC_PREDFAIL: + ntp = &topo_sensor_states_generic_predfail_table[0]; + break; + case TOPO_SENSOR_TYPE_GENERIC_LIMIT: + ntp = &topo_sensor_states_generic_limit_table[0]; + break; + case TOPO_SENSOR_TYPE_GENERIC_PERFORMANCE: + ntp = &topo_sensor_states_generic_perf_table[0]; + break; + case TOPO_SENSOR_TYPE_SEVERITY: + ntp = &topo_sensor_states_severity_table[0]; + break; + case TOPO_SENSOR_TYPE_GENERIC_PRESENCE: + ntp = &topo_sensor_states_generic_presence_table[0]; + break; + case TOPO_SENSOR_TYPE_GENERIC_AVAILABILITY: + ntp = &topo_sensor_states_generic_avail_table[0]; + break; + case TOPO_SENSOR_TYPE_GENERIC_STATUS: + ntp = &topo_sensor_states_generic_status_table[0]; + break; + case TOPO_SENSOR_TYPE_GENERIC_ACPI: + ntp = &topo_sensor_states_generic_acpi_pwr_table[0]; + break; + default: + (void) snprintf(buf, len, "0x%02x", state); + return; + } + for (; ntp->int_name != NULL; ntp++) { + if (ntp->int_value == state) { + (void) strlcpy(buf, ntp->int_name, len); + return; + } + } + + (void) snprintf(buf, len, "0x%02x", state); +} diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_subr.h b/usr/src/lib/fm/topo/libtopo/common/topo_subr.h index ec3dc825d9..b4934241d4 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_subr.h +++ b/usr/src/lib/fm/topo/libtopo/common/topo_subr.h @@ -65,6 +65,55 @@ typedef struct topo_debug_mode { #define TOPO_STABSTR_STANDARD "Standard" /* industry standard */ #define TOPO_STABSTR_UNKNOWN "Unknown" /* stability unknown */ +typedef struct topo_name_trans { + uint32_t int_value; + const char *int_name; +} topo_name_trans_t; + +extern topo_name_trans_t topo_sensor_type_table[]; +extern topo_name_trans_t topo_units_type_table[]; +extern topo_name_trans_t topo_led_type_table[]; +extern topo_name_trans_t topo_led_states_table[]; +extern topo_name_trans_t topo_sensor_states_physical_table[]; +extern topo_name_trans_t topo_sensor_states_platform_table[]; +extern topo_name_trans_t topo_sensor_states_processor_table[]; +extern topo_name_trans_t topo_sensor_states_power_supply_table[]; +extern topo_name_trans_t topo_sensor_states_power_unit_table[]; +extern topo_name_trans_t topo_sensor_states_memory_table[]; +extern topo_name_trans_t topo_sensor_states_bay_table[]; +extern topo_name_trans_t topo_sensor_states_firmware_table[]; +extern topo_name_trans_t topo_sensor_states_event_log_table[]; +extern topo_name_trans_t topo_sensor_states_watchdog1_table[]; +extern topo_name_trans_t topo_sensor_states_system_table[]; +extern topo_name_trans_t topo_sensor_states_critical_table[]; +extern topo_name_trans_t topo_sensor_states_button_table[]; +extern topo_name_trans_t topo_sensor_states_cable_table[]; +extern topo_name_trans_t topo_sensor_states_boot_state_table[]; +extern topo_name_trans_t topo_sensor_states_boot_error_table[]; +extern topo_name_trans_t topo_sensor_states_boot_os_table[]; +extern topo_name_trans_t topo_sensor_states_os_table[]; +extern topo_name_trans_t topo_sensor_states_slot_table[]; +extern topo_name_trans_t topo_sensor_states_acpi_table[]; +extern topo_name_trans_t topo_sensor_states_watchdog2_table[]; +extern topo_name_trans_t topo_sensor_states_alert_table[]; +extern topo_name_trans_t topo_sensor_states_presence_table[]; +extern topo_name_trans_t topo_sensor_states_lan_table[]; +extern topo_name_trans_t topo_sensor_states_health_table[]; +extern topo_name_trans_t topo_sensor_states_battery_table[]; +extern topo_name_trans_t topo_sensor_states_audit_table[]; +extern topo_name_trans_t topo_sensor_states_version_table[]; +extern topo_name_trans_t topo_sensor_states_fru_state_table[]; +extern topo_name_trans_t topo_sensor_states_thresh_table[]; +extern topo_name_trans_t topo_sensor_states_generic_usage_table[]; +extern topo_name_trans_t topo_sensor_states_generic_state_table[]; +extern topo_name_trans_t topo_sensor_states_generic_predfail_table[]; +extern topo_name_trans_t topo_sensor_states_generic_limit_table[]; +extern topo_name_trans_t topo_sensor_states_generic_perf_table[]; +extern topo_name_trans_t topo_sensor_states_generic_presence_table[]; +extern topo_name_trans_t topo_sensor_states_severity_table[]; +extern topo_name_trans_t topo_sensor_states_generic_avail_table[]; +extern topo_name_trans_t topo_sensor_states_generic_status_table[]; +extern topo_name_trans_t topo_sensor_states_generic_acpi_pwr_table[]; extern int topo_rw_read_held(pthread_rwlock_t *); extern int topo_rw_write_held(pthread_rwlock_t *); diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_xml.c b/usr/src/lib/fm/topo/libtopo/common/topo_xml.c index 817ce2cc08..eed5132ef4 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_xml.c +++ b/usr/src/lib/fm/topo/libtopo/common/topo_xml.c @@ -23,7 +23,6 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - #pragma ident "%Z%%M% %I% %E% SMI" #include <libxml/parser.h> @@ -50,6 +49,9 @@ static tf_rdata_t *topo_xml_walk(topo_mod_t *, tf_info_t *, xmlNodePtr, tnode_t *); static tf_edata_t *enum_attributes_process(topo_mod_t *, xmlNodePtr); static int enum_run(topo_mod_t *, tf_rdata_t *); +static int fac_enum_run(topo_mod_t *, tnode_t *, const char *); +static int fac_process(topo_mod_t *, xmlNodePtr, tf_rdata_t *, tnode_t *); +static int fac_enum_process(topo_mod_t *, xmlNodePtr, tnode_t *); static int decorate_nodes(topo_mod_t *, tf_rdata_t *, xmlNodePtr, tnode_t *, tf_pad_t **); @@ -103,7 +105,8 @@ xmlattr_to_int(topo_mod_t *mp, xmlChar *str; xmlChar *estr; - topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "attribute to int\n"); + topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xmlattr_to_int(propname=%s)\n", + propname); if ((str = xmlGetProp(n, (xmlChar *)propname)) == NULL) return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR)); *value = strtoull((char *)str, (char **)&estr, 10); @@ -122,7 +125,8 @@ xmlattr_to_fmri(topo_mod_t *mp, { xmlChar *str; - topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "attribute to int\n"); + topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xmlattr_to_fmri(propname=%s)\n", + propname); if ((str = xmlGetProp(xn, (xmlChar *)propname)) == NULL) return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR)); if (topo_mod_str2nvl(mp, (const char *)str, rnvl) < 0) { @@ -176,7 +180,8 @@ const char *name) nvlist_t *fmri; xmlChar *str; - topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xlate_common\n"); + topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "xlate_common (name=%s)\n", + name); switch (ptype) { case TOPO_TYPE_INT32: if (xmlattr_to_int(mp, xn, Value, &ui) < 0) @@ -329,8 +334,8 @@ prop_create(topo_mod_t *mp, char *str; int err, e; - topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "prop_create(gnm = %s, " - "pnm = %s)\n", gnm, pnm); + topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "prop_create(pgrp = %s, " + "prop = %s)\n", gnm, pnm); switch (ptype) { case TOPO_TYPE_INT32: e = nvlist_lookup_int32(pfmri, INV_PVAL, &i32); @@ -404,7 +409,8 @@ props_create(topo_mod_t *mp, int pn; int e; - topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "props_create(gnm = %s)\n", gnm); + topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "props_create(pgrp = %s)\n", + gnm); for (pn = 0; pn < nprops; pn++) { e = nvlist_lookup_string(props[pn], INV_PNAME, &pnm); if (e != 0) { @@ -449,7 +455,8 @@ pgroups_create(topo_mod_t *mp, tf_pad_t *pad, tnode_t *ptn) int pg; int e; - topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pgroups_create\n"); + topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pgroups_create: %s=%d\n", + topo_node_name(ptn), topo_node_instance(ptn)); for (pg = 0; pg < pad->tpad_pgcnt; pg++) { e = nvlist_lookup_string(pad->tpad_pgs[pg], INV_PGRP_NAME, &gnm); @@ -601,14 +608,15 @@ pmeth_record(topo_mod_t *mp, const char *pg_name, xmlNodePtr xn, tnode_t *tn, xmlNodePtr cn; xmlChar *meth_name = NULL, *prop_name = NULL; xmlChar *arg_name = NULL; - uint64_t meth_ver; + uint64_t meth_ver, is_mutable = 0; topo_type_t prop_type; struct propmeth_data meth; - int ret = 0; + int ret = 0, err; topo_type_t ptype; tnode_t *tmp; - topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pmeth_record\n"); + topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pmeth_record: %s=%d " + "(pgrp=%s)\n", topo_node_name(tn), topo_node_instance(tn), pg_name); /* * Get propmethod attribute values @@ -624,6 +632,12 @@ pmeth_record(topo_mod_t *mp, const char *pg_name, xmlNodePtr xn, tnode_t *tn, ret = topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR); goto pmr_done; } + /* + * The "mutable" attribute is optional. If not specified we default to + * false (0) + */ + (void) xmlattr_to_int(mp, xn, Mutable, &is_mutable); + if ((prop_name = xmlGetProp(xn, (xmlChar *)Propname)) == NULL) { topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "propmethod element lacks propname attribute\n"); @@ -702,18 +716,36 @@ pmeth_record(topo_mod_t *mp, const char *pg_name, xmlNodePtr xn, tnode_t *tn, */ if (strcmp(ppgrp_name, Range) == 0) { for (tmp = tn; tmp != NULL; tmp = topo_child_next(NULL, tmp)) { - if (strcmp(rname, topo_node_name(tmp)) == 0) + if (strcmp(rname, topo_node_name(tmp)) == 0) { if (register_method(mp, tmp, &meth) != 0) { ret = topo_mod_seterrno(mp, ETOPO_PRSR_REGMETH); goto pmr_done; } + if (is_mutable) { + if (topo_prop_setmutable(tmp, + meth.pg_name, meth.prop_name, &err) + != 0) { + ret = topo_mod_seterrno(mp, + ETOPO_PRSR_REGMETH); + goto pmr_done; + } + } + } } } else { if (register_method(mp, tn, &meth) != 0) { ret = topo_mod_seterrno(mp, ETOPO_PRSR_REGMETH); goto pmr_done; } + if (is_mutable) { + if (topo_prop_setmutable(tn, meth.pg_name, + meth.prop_name, &err) != 0) { + ret = topo_mod_seterrno(mp, + ETOPO_PRSR_REGMETH); + goto pmr_done; + } + } } pmr_done: @@ -878,8 +910,9 @@ static int pad_process(topo_mod_t *mp, tf_rdata_t *rd, xmlNodePtr pxn, tnode_t *ptn, tf_pad_t **rpad) { - xmlNodePtr cn, gcn, psn, ecn; + xmlNodePtr cn, gcn, psn, ecn, target; xmlNodePtr def_set = NULL; + tnode_t *ct; tf_pad_t *new = *rpad; tf_rdata_t tmp_rd; int pgcnt = 0; @@ -1008,23 +1041,48 @@ pad_process(topo_mod_t *mp, tf_rdata_t *rd, xmlNodePtr pxn, tnode_t *ptn, return (-1); } - if (joined_set) { - /* - * If the property groups are contained within a - * set then they will be one level lower in - * the XML tree. - */ - if (pgroups_record(mp, psn, ptn, rd->rd_name, - new, (const char *)pxn->name) < 0) { - tf_pad_free(mp, new); - return (-1); + /* + * If the property groups are contained within a set + * then they will be one level lower in the XML tree. + */ + if (joined_set) + target = psn; + else + target = pxn; + + /* + * If there is no "node" element under the "range" + * element, then we need to attach the facility node to + * each node in this range. + * + * Otherwise we only attach it to the current node + */ + if (!rd->contains_node_ele) { + for (ct = topo_child_first(rd->rd_pn); + ct != NULL; + ct = topo_child_next(rd->rd_pn, ct)) { + + if (strcmp(topo_node_name(ct), + rd->rd_name) != 0) + continue; + + if (fac_enum_process(mp, target, + ct) < 0) + return (-1); + + if (fac_process(mp, target, rd, ct) < 0) + return (-1); } - } else { - if (pgroups_record(mp, pxn, ptn, rd->rd_name, - new, (const char *)pxn->name) < 0) { - tf_pad_free(mp, new); + } else + if (fac_enum_process(mp, target, ptn) < 0) return (-1); - } + if (fac_process(mp, target, rd, ptn) < 0) + return (-1); + + if (pgroups_record(mp, target, ptn, rd->rd_name, + new, (const char *)pxn->name) < 0) { + tf_pad_free(mp, new); + return (-1); } } *rpad = new; @@ -1043,6 +1101,154 @@ pad_process(topo_mod_t *mp, tf_rdata_t *rd, xmlNodePtr pxn, tnode_t *ptn, static int +fac_enum_process(topo_mod_t *mp, xmlNodePtr pn, tnode_t *ptn) +{ + xmlNodePtr cn; + xmlChar *fprov = NULL; + int rv = 0; + + topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, + "fac_enum_process() called for %s=%d\n", topo_node_name(ptn), + topo_node_instance(ptn)); + + for (cn = pn->xmlChildrenNode; cn != NULL; cn = cn->next) { + + if (xmlStrcmp(cn->name, (xmlChar *)"fac-enum") != 0) + continue; + + if ((fprov = xmlGetProp(cn, (xmlChar *)Provider)) == NULL) + goto fenumdone; + + if (xmlStrcmp(fprov, (xmlChar *)"fac_prov_ipmi") != 0) { + topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, + "Invalid provider specified: %s\n", fprov); + goto fenumdone; + } + + /* + * Invoke enum entry point in fac provider which will cause the + * facility enumeration node method to be registered. + */ + if (fac_enum_run(mp, ptn, (const char *)fprov) != 0) { + topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, + "fac_enum_process: enum entry point failed!\n"); + goto fenumdone; + } + xmlFree(fprov); + } + return (0); +fenumdone: + topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "fac-enum processing failed\n"); + + if (fprov != NULL) + xmlFree(fprov); + + return (rv); +} + + +static int +fac_process(topo_mod_t *mp, xmlNodePtr pn, tf_rdata_t *rd, tnode_t *ptn) +{ + xmlNodePtr cn; + xmlChar *fname = NULL, *ftype = NULL, *provider = NULL; + tnode_t *ntn = NULL; + tf_idata_t *newi; + int err; + topo_pgroup_info_t pgi; + + topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, + "fac_process() called\n"); + + for (cn = pn->xmlChildrenNode; cn != NULL; cn = cn->next) { + + if (xmlStrcmp(cn->name, (xmlChar *)Facility) != 0) + continue; + + topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, + "facility processing\n"); + + if ((fname = xmlGetProp(cn, (xmlChar *)Name)) == NULL) + goto facdone; + + if ((ftype = xmlGetProp(cn, (xmlChar *)Type)) == NULL) + goto facdone; + + if ((provider = xmlGetProp(cn, (xmlChar *)Provider)) == NULL) + goto facdone; + + if (xmlStrcmp(ftype, (xmlChar *)Sensor) != 0 && + xmlStrcmp(ftype, (xmlChar *)Indicator) != 0) + goto facdone; + + if (xmlStrcmp(provider, (xmlChar *)"fac_prov_ipmi") != 0) { + topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "fac_process: " + "Invalid provider attr value: %s\n", provider); + goto facdone; + } + + if ((ntn = topo_node_facbind(mp, ptn, (char *)fname, + (char *)ftype)) == NULL) + goto facdone; + + pgi.tpi_name = TOPO_PGROUP_FACILITY; + pgi.tpi_namestab = TOPO_STABILITY_PRIVATE; + pgi.tpi_datastab = TOPO_STABILITY_PRIVATE; + pgi.tpi_version = 1; + if (topo_pgroup_create(ntn, &pgi, &err) != 0) { + if (err != ETOPO_PROP_DEFD) { + topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, + "pgroups create failure: %s\n", + topo_strerror(err)); + return (-1); + } + } + /* + * Invoke enum entry point in fac_prov_ipmi module, which will + * cause the provider methods to be registered on this node + */ + if (fac_enum_run(mp, ntn, (const char *)provider) != 0) { + topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "fac_process: " + "enum entry point failed for provider %s!\n", + provider); + goto facdone; + } + + if ((newi = tf_idata_new(mp, 0, ntn)) == NULL) + goto facdone; + + if (tf_idata_insert(&rd->rd_instances, newi) < 0) + goto facdone; + + if (pad_process(mp, rd, cn, ntn, &newi->ti_pad) < 0) + goto facdone; + + topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "done with " + "facility %s=%s.\n", ftype, fname); + + xmlFree(ftype); + xmlFree(fname); + xmlFree(provider); + } + + return (0); + +facdone: + topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "facility processing failed\n"); + + if (ftype != NULL) + xmlFree(ftype); + if (fname != NULL) + xmlFree(fname); + if (provider != NULL) + xmlFree(provider); + if (ntn != NULL) + topo_node_unbind(ntn); + + return (0); +} + +static int node_process(topo_mod_t *mp, xmlNodePtr nn, tf_rdata_t *rd) { xmlChar *str; @@ -1056,6 +1262,7 @@ node_process(topo_mod_t *mp, xmlNodePtr nn, tf_rdata_t *rd) topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "node_process %s\n", rd->rd_name); + rd->contains_node_ele = 1; if (xmlattr_to_int(mp, nn, Instance, &ui) < 0) goto nodedone; inst = (topo_instance_t)ui; @@ -1098,6 +1305,8 @@ node_process(topo_mod_t *mp, xmlNodePtr nn, tf_rdata_t *rd) } if (pad_process(mp, rd, nn, ntn, &newi->ti_pad) < 0) goto nodedone; + if (fac_process(mp, nn, rd, ntn) < 0) + goto nodedone; rv = 0; nodedone: topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "done with node %s.\n", @@ -1191,6 +1400,44 @@ enum_run(topo_mod_t *mp, tf_rdata_t *rd) return (e); } +static int +fac_enum_run(topo_mod_t *mp, tnode_t *node, const char *name) +{ + topo_hdl_t *thp = mp->tm_hdl; + topo_mod_t *fmod; + int e = -1; + + topo_dprintf(thp, TOPO_DBG_XML, "fac_enum_run\n"); + /* + * Check if the enumerator module is already loaded. + * Module loading is single-threaded at this point so there's + * no need to worry about the module going away or bumping the + * ref count. + */ + if ((fmod = topo_mod_lookup(thp, name, 0)) == NULL) { + if ((fmod = topo_mod_load(mp, name, TOPO_VERSION)) == NULL) { + topo_dprintf(thp, TOPO_DBG_ERR, + "fac_enum_run: mod_load of %s failed: %s.\n", + name, topo_strerror(topo_mod_errno(mp))); + (void) topo_hdl_seterrno(thp, topo_mod_errno(mp)); + return (e); + } + } + /* + * We're live, so let's enumerate. + */ + topo_dprintf(thp, TOPO_DBG_XML, "fac enumerate request. (%s)\n", name); + e = topo_mod_enumerate(fmod, node, name, name, 0, 0, NULL); + topo_dprintf(thp, TOPO_DBG_XML, "back from enumeration. %d\n", e); + if (e != 0) { + topo_dprintf(thp, TOPO_DBG_ERR, + "Facility provider enumeration failed (%s)\n", + topo_strerror(topo_mod_errno(mp))); + (void) topo_hdl_seterrno(thp, EMOD_PARTIAL_ENUM); + return (topo_mod_seterrno(mp, EMOD_PARTIAL_ENUM)); + } + return (e); +} int decorate_nodes(topo_mod_t *mp, tf_rdata_t *rd, xmlNodePtr pxn, tnode_t *ptn, @@ -1231,9 +1478,10 @@ topo_xml_range_process(topo_mod_t *mp, xmlNodePtr rn, tf_rdata_t *rd) "process %s range beneath %s\n", rd->rd_name, topo_node_name(rd->rd_pn)); + rd->contains_node_ele = 0; e = topo_node_range_create(mp, rd->rd_pn, rd->rd_name, rd->rd_min, rd->rd_max); - if (e != 0 && topo_mod_errno(mp) != ETOPO_NODE_DUP) { + if (e != 0 && topo_mod_errno(mp) != EMOD_NODE_DUP) { topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "Range create failed due to %s.\n", topo_strerror(topo_mod_errno(mp))); @@ -1326,6 +1574,10 @@ topo_xml_range_process(topo_mod_t *mp, xmlNodePtr rn, tf_rdata_t *rd) if (pad_process(mp, rd, rn, ct, &rd->rd_pad) < 0) return (-1); + + if (fac_process(mp, rn, rd, ct) < 0) + return (-1); + ct = topo_child_next(rd->rd_pn, ct); ccnt++; } diff --git a/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4500/Sun-Fire-X4500-hc-topology.xmlgen b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4500/Sun-Fire-X4500-hc-topology.xmlgen index 7f713decdd..8cdccd9883 100644 --- a/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4500/Sun-Fire-X4500-hc-topology.xmlgen +++ b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4500/Sun-Fire-X4500-hc-topology.xmlgen @@ -201,6 +201,103 @@ print OFILE " <!--xml-gen internal storage-->\n"; printf OFILE " <range name='bay' min='0' max='%d'>\n", $sys_supported->{"num_bays"}-1; +# +# Statically define locate indicator +# +print OFILE " <facility name='locate' type='indicator' ". + "provider='fac_prov_ipmi' >\n"; +print OFILE " <propgroup name='facility' version='1' ". + "name-stability='Private' data-stability='Private' >\n"; +print OFILE " <propval name='type' type='uint32' value='1' />\n"; +print OFILE " <propmethod name='ipmi_entity' version='0' ". + "propname='entity_ref' proptype='string' >\n"; +print OFILE " <argval name='format' type='string' ". + "value='hdd%d.ok2rm.led' />\n"; +print OFILE " <argval name='offset' type='uint32' ". + "value='0' />\n"; +print OFILE " <argval name='nparams' type='uint32' ". + "value='1' />\n"; +print OFILE " </propmethod>\n"; +print OFILE " <propmethod name='thumper_locate_mode' ". + "version='0'\n"; +print OFILE " propname='mode' proptype='uint32' ". + "mutable='1' >\n"; +print OFILE " </propmethod>\n"; +print OFILE " </propgroup>\n"; +print OFILE " </facility>\n"; + +# +# Statically define ok2rm indicator +# +print OFILE " <facility name='ok2rm' type='indicator' ". + "provider='fac_prov_ipmi' >\n"; +print OFILE " <propgroup name='facility' version='1' ". + "name-stability='Private' data-stability='Private' >\n"; +print OFILE " <propval name='type' type='uint32' value='2' />\n"; +print OFILE " <propmethod name='ipmi_entity' version='0' ". + "propname='entity_ref' proptype='string' >\n"; +print OFILE " <argval name='format' type='string' ". + "value='hdd%d.state' />\n"; +print OFILE " <argval name='offset' type='uint32' ". + "value='0' />\n"; +print OFILE " <argval name='nparams' type='uint32' ". + "value='1' />\n"; +print OFILE " </propmethod>\n"; +print OFILE " <propmethod name='thumper_indicator_mode' ". + "version='0'\n"; +print OFILE " propname='mode' proptype='uint32' ". + "mutable='1' >\n"; +print OFILE " </propmethod>\n"; +print OFILE " </propgroup>\n"; +print OFILE " </facility>\n"; + +# +# Statically define service indicator +# +print OFILE " <facility name='service' type='indicator' ". + "provider='fac_prov_ipmi' >\n"; +print OFILE " <propgroup name='facility' version='1' ". + "name-stability='Private' data-stability='Private' >\n"; +print OFILE " <propval name='type' type='uint32' value='0' />\n"; +print OFILE " <propmethod name='ipmi_entity' version='0' ". + "propname='entity_ref' proptype='string' >\n"; +print OFILE " <argval name='format' type='string' ". + "value='hdd%d.state' />\n"; +print OFILE " <argval name='offset' type='uint32' ". + "value='0' />\n"; +print OFILE " <argval name='nparams' type='uint32' ". + "value='1' />\n"; +print OFILE " </propmethod>\n"; +print OFILE " <propmethod name='thumper_indicator_mode' ". + "version='0' propname='mode' proptype='uint32' mutable='1' >\n"; +print OFILE " </propmethod>\n"; +print OFILE " </propgroup>\n"; +print OFILE " </facility>\n"; + + +# +# Statically define present indicator +# +print OFILE " <facility name='present' type='indicator' ". + "provider='fac_prov_ipmi' >\n"; +print OFILE " <propgroup name='facility' version='1' ". + "name-stability='Private' data-stability='Private' >\n"; +print OFILE " <propval name='type' type='uint32' value='3' />\n"; +print OFILE " <propmethod name='ipmi_entity' version='0' ". + "propname='entity_ref' proptype='string' >\n"; +print OFILE " <argval name='format' type='string' ". + "value='hdd%d.state' />\n"; +print OFILE " <argval name='offset' type='uint32' ". + "value='0' />\n"; +print OFILE " <argval name='nparams' type='uint32' ". + "value='1' />\n"; +print OFILE " </propmethod>\n"; +print OFILE " <propmethod name='thumper_indicator_mode' ". + "version='0' propname='mode' proptype='uint32' mutable='1' >\n"; +print OFILE " </propmethod>\n"; +print OFILE " </propgroup>\n"; +print OFILE " </facility>\n"; + calc_nodes(0); printf OFILE " <dependents grouping='children'>\n"; diff --git a/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4540/Sun-Fire-X4540-hc-topology.xmlgen b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4540/Sun-Fire-X4540-hc-topology.xmlgen index c8a90be61c..87614d9af4 100644 --- a/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4540/Sun-Fire-X4540-hc-topology.xmlgen +++ b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4540/Sun-Fire-X4540-hc-topology.xmlgen @@ -200,6 +200,102 @@ print OFILE " <!--xml-gen internal storage-->\n"; printf OFILE " <range name='bay' min='0' max='%d'>\n", $sys_supported->{"num_bays"}-1; +# +# Statically define locate indicator +# +print OFILE " <facility name='locate' type='indicator' ". + "provider='fac_prov_ipmi' >\n"; +print OFILE " <propgroup name='facility' version='1' ". + "name-stability='Private' data-stability='Private' >\n"; +print OFILE " <propval name='type' type='uint32' value='1' />\n"; +print OFILE " <propmethod name='ipmi_entity' version='0' ". + "propname='entity_ref' proptype='string' >\n"; +print OFILE " <argval name='format' type='string' ". + "value='hdd%d.ok2rm.led' />\n"; +print OFILE " <argval name='offset' type='uint32' ". + "value='0' />\n"; +print OFILE " <argval name='nparams' type='uint32' ". + "value='1' />\n"; +print OFILE " </propmethod>\n"; +print OFILE " <propmethod name='thumper_locate_mode' ". + "version='0'\n"; +print OFILE " propname='mode' proptype='uint32' ". + "mutable='1' >\n"; +print OFILE " </propmethod>\n"; +print OFILE " </propgroup>\n"; +print OFILE " </facility>\n"; + +# +# Statically define ok2rm indicator +# +print OFILE " <facility name='ok2rm' type='indicator' ". + "provider='fac_prov_ipmi' >\n"; +print OFILE " <propgroup name='facility' version='1' ". + "name-stability='Private' data-stability='Private' >\n"; +print OFILE " <propval name='type' type='uint32' value='2' />\n"; +print OFILE " <propmethod name='ipmi_entity' version='0' ". + "propname='entity_ref' proptype='string' >\n"; +print OFILE " <argval name='format' type='string' ". + "value='hdd%d.state' />\n"; +print OFILE " <argval name='offset' type='uint32' ". + "value='0' />\n"; +print OFILE " <argval name='nparams' type='uint32' ". + "value='1' />\n"; +print OFILE " </propmethod>\n"; +print OFILE " <propmethod name='thumper_indicator_mode' ". + "version='0'\n"; +print OFILE " propname='mode' proptype='uint32' ". + "mutable='1' >\n"; +print OFILE " </propmethod>\n"; +print OFILE " </propgroup>\n"; +print OFILE " </facility>\n"; + +# +# Statically define service indicator +# +print OFILE " <facility name='service' type='indicator' ". + "provider='fac_prov_ipmi' >\n"; +print OFILE " <propgroup name='facility' version='1' ". + "name-stability='Private' data-stability='Private' >\n"; +print OFILE " <propval name='type' type='uint32' value='0' />\n"; +print OFILE " <propmethod name='ipmi_entity' version='0' ". + "propname='entity_ref' proptype='string' >\n"; +print OFILE " <argval name='format' type='string' ". + "value='hdd%d.state' />\n"; +print OFILE " <argval name='offset' type='uint32' ". + "value='0' />\n"; +print OFILE " <argval name='nparams' type='uint32' ". + "value='1' />\n"; +print OFILE " </propmethod>\n"; +print OFILE " <propmethod name='thumper_indicator_mode' ". + "version='0' propname='mode' proptype='uint32' mutable='1' >\n"; +print OFILE " </propmethod>\n"; +print OFILE " </propgroup>\n"; +print OFILE " </facility>\n"; + +# +# Statically define present indicator +# +print OFILE " <facility name='present' type='indicator' ". + "provider='fac_prov_ipmi' >\n"; +print OFILE " <propgroup name='facility' version='1' ". + "name-stability='Private' data-stability='Private' >\n"; +print OFILE " <propval name='type' type='uint32' value='3' />\n"; +print OFILE " <propmethod name='ipmi_entity' version='0' ". + "propname='entity_ref' proptype='string' >\n"; +print OFILE " <argval name='format' type='string' ". + "value='hdd%d.state' />\n"; +print OFILE " <argval name='offset' type='uint32' ". + "value='0' />\n"; +print OFILE " <argval name='nparams' type='uint32' ". + "value='1' />\n"; +print OFILE " </propmethod>\n"; +print OFILE " <propmethod name='thumper_indicator_mode' ". + "version='0' propname='mode' proptype='uint32' mutable='1' >\n"; +print OFILE " </propmethod>\n"; +print OFILE " </propgroup>\n"; +print OFILE " </facility>\n"; + calc_nodes(0); printf OFILE " <dependents grouping='children'>\n"; diff --git a/usr/src/lib/fm/topo/maps/common/topology.dtd.1 b/usr/src/lib/fm/topo/maps/common/topology.dtd.1 index 72077b3a2e..a5d406acc9 100644 --- a/usr/src/lib/fm/topo/maps/common/topology.dtd.1 +++ b/usr/src/lib/fm/topo/maps/common/topology.dtd.1 @@ -125,7 +125,7 @@ --> <!ELEMENT set - ( range*, propgroup* ) > + ( range*, fac-enum?, propgroup*, facility* ) > <!ATTLIST set type ( product ) #REQUIRED @@ -177,6 +177,7 @@ version Version of the method API propname Name of the property to create proptype Type of the property to create + mutable optional: default is false (0) --> <!ELEMENT propmethod @@ -186,7 +187,8 @@ name CDATA #REQUIRED version CDATA #REQUIRED propname CDATA #REQUIRED - proptype CDATA #REQUIRED> + proptype CDATA #REQUIRED + mutable (0|1) "0" > <!-- enum-method @@ -221,7 +223,7 @@ --> <!ELEMENT node - ( propgroup*, dependents*, set*, enum-method* ) > + ( fac-enum?, facility*, propgroup*, set*, enum-method*, dependents? ) > <!ATTLIST node instance CDATA #REQUIRED > @@ -259,7 +261,8 @@ --> <!ELEMENT range - ( enum-method?, propmap?, node*, propgroup*, set*, dependents* ) > + ( enum-method?, propmap?, fac-enum?, facility*, node*, propgroup*, set*, + dependents* ) > <!ATTLIST range name CDATA #REQUIRED @@ -267,6 +270,47 @@ max CDATA #REQUIRED > <!-- + facility + + This element identifies a single facility node instance + + Its attributes are + + name The name of the facility node + + type The type of facility node: either "sensor" or "indicator" + + provider The name of the facility provider module that + implements the methods for this node or range +--> + +<!ELEMENT facility + ( propgroup* ) > + +<!ATTLIST facility + name CDATA #REQUIRED + type (sensor | indicator) #REQUIRED + provider CDATA #REQUIRED > + +<!-- + fac-enum + + This element identifies a facility provider module that + implements a facility enumeration method for the enclosing + node or range. + + Its attributes are + + provider The name of the facility provider module that + implements the facility enumerator method for + the parent node or range +--> + +<!ELEMENT fac-enum EMPTY > + +<!ATTLIST fac-enum provider CDATA #REQUIRED > + +<!-- topology This is the root-level for the scheme-specific topology diff --git a/usr/src/lib/fm/topo/maps/i86pc/chip-hc-topology.xml b/usr/src/lib/fm/topo/maps/i86pc/chip-hc-topology.xml index 95d853b845..21d0da88c0 100644 --- a/usr/src/lib/fm/topo/maps/i86pc/chip-hc-topology.xml +++ b/usr/src/lib/fm/topo/maps/i86pc/chip-hc-topology.xml @@ -31,7 +31,7 @@ <range name='chip' min='0' max='100'> <set type='product' - setlist='Sun-Fire-V20z|Sun-Fire-V40z|W1100z-2100z|Sun-Ultra-20-Workstation|Ultra20-M2|Sun-Ultra-40-M2-Workstation'> + setlist='Sun-Fire(TM)-X2100|W1100z-2100z|Sun-Ultra-20-Workstation|Ultra20-M2|Sun-Ultra-40-M2-Workstation'> <propgroup name='protocol' version='1' name-stability='Private' data-stability='Private' > @@ -48,7 +48,7 @@ </set> <set type='product' - setlist='Sun-Fire(TM)-X2100|Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4200E|Sun-Fire-X4500|X2100-M2|Sun-Fire-X4140|Sun-Fire-X4240|Sun-Fire-X4440'> + setlist='Sun-Fire-V20z|Sun-Fire-V40z'> <propgroup name='protocol' version='1' name-stability='Private' data-stability='Private' > @@ -62,11 +62,143 @@ </propmethod> </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propmethod name='ipmi_entity' version='0' + propname='entity_ref' proptype='string' > + + <argval name='format' type='string' value='cpu%d.vpd' /> + <argval name='offset' type='uint32' value='0' /> + <argval name='nparams' type='uint32' value='1' /> + + </propmethod> + </propgroup> </set> <set type='product' - setlist='Sun-Fire-X4100-M2|Sun-Fire-X4200-M2'> - + setlist='X2100-M2|Sun-Blade-X8440-Server-Module'> + <propgroup name='protocol' version='1' + name-stability='Private' data-stability='Private' > + + <propmethod name='simple_chip_label' version='0' + propname='label' proptype='string' > + + <argval name='format' type='string' value='CPU %d' /> + <argval name='offset' type='uint32' value='0' /> + + </propmethod> + + </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propmethod name='ipmi_entity' version='0' + propname='entity_ref' proptype='string' > + + <argval name='format' type='string' value='p%d.fru' /> + <argval name='offset' type='uint32' value='0' /> + <argval name='nparams' type='uint32' value='1' /> + + </propmethod> + </propgroup> + </set> + + <set type='product' + setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4200E|Sun-Fire-X4140|Sun-Fire-X4240|Sun-Fire-X4440'> + <fac-enum provider='fac_prov_ipmi' /> + <!-- + chip FRU label + --> + <propgroup name='protocol' version='1' + name-stability='Private' data-stability='Private' > + + <propmethod name='simple_chip_label' version='0' + propname='label' proptype='string' > + + <argval name='format' type='string' value='CPU %d' /> + <argval name='offset' type='uint32' value='0' /> + + </propmethod> + + </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propmethod name='ipmi_entity' version='0' + propname='entity_ref' proptype='string' > + + <argval name='format' type='string' value='p%d.fru' /> + <argval name='offset' type='uint32' value='0' /> + <argval name='nparams' type='uint32' value='1' /> + + </propmethod> + </propgroup> + <!-- + chip service LED + --> + <facility name='service' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='type' type='uint32' value='0' /> + <propmethod name='ipmi_entity' version='0' propname='entity_ref' proptype='string' > + <argval name='format' type='string' value='p%d.led' /> + <argval name='offset' type='uint32' value='0' /> + <argval name='nparams' type='uint32' value='1' /> + </propmethod> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1'> + </propmethod> + </propgroup> + </facility> + </set> + <set type='product' setlist='Sun-Fire-X4500'> + <fac-enum provider='fac_prov_ipmi' /> + <!-- + chip FRU label + --> + <propgroup name='protocol' version='1' + name-stability='Private' data-stability='Private' > + + <propmethod name='simple_chip_label' version='0' + propname='label' proptype='string' > + + <argval name='format' type='string' value='CPU %d' /> + <argval name='offset' type='uint32' value='0' /> + + </propmethod> + + </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propmethod name='ipmi_entity' version='0' + propname='entity_ref' proptype='string' > + + <argval name='format' type='string' value='p%d.fru' /> + <argval name='offset' type='uint32' value='0' /> + <argval name='nparams' type='uint32' value='1' /> + + </propmethod> + </propgroup> + <!-- + chip service LED + --> + <facility name='service' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='type' type='uint32' value='0' /> + <propmethod name='ipmi_entity' version='0' propname='entity_ref' proptype='string' > + <argval name='format' type='string' value='p%d.fail.led' /> + <argval name='offset' type='uint32' value='0' /> + <argval name='nparams' type='uint32' value='1' /> + </propmethod> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> + </set> + + <set type='product' setlist='Sun-Fire-X4540'> + <fac-enum provider='fac_prov_ipmi' /> + <!-- + chip FRU label + --> <propgroup name='protocol' version='1' name-stability='Private' data-stability='Private' > @@ -74,16 +206,91 @@ propname='label' proptype='string' > <argval name='format' type='string' value='CPU %d' /> + <argval name='offset' type='uint32' value='0' /> + + </propmethod> + + </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propmethod name='ipmi_entity' version='0' + propname='entity_ref' proptype='string' > + + <argval name='format' type='string' value='p%d.fru' /> + <argval name='offset' type='uint32' value='0' /> + <argval name='nparams' type='uint32' value='1' /> + + </propmethod> + </propgroup> + <!-- + chip service LED + --> + <facility name='service' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='type' type='uint32' value='0' /> + <propmethod name='ipmi_entity' version='0' propname='entity_ref' proptype='string' > + <argval name='format' type='string' value='p%d.led' /> + <argval name='offset' type='uint32' value='0' /> + <argval name='nparams' type='uint32' value='1' /> + </propmethod> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> + </set> + <set type='product' + setlist='Sun-Fire-X4100-M2|Sun-Fire-X4200-M2'> + <fac-enum provider='fac_prov_ipmi' /> + <!-- + chip FRU label + --> + <propgroup name='protocol' version='1' + name-stability='Private' data-stability='Private' > + <propmethod name='simple_chip_label' version='0' + propname='label' proptype='string' > + + <argval name='format' type='string' value='CPU %d' /> <argval name='offset' type='uint32' value='1' /> </propmethod> </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propmethod name='ipmi_entity' version='0' + propname='entity_ref' proptype='string' > + + <argval name='format' type='string' value='p%d.fru' /> + <argval name='offset' type='uint32' value='0' /> + <argval name='nparams' type='uint32' value='1' /> + </propmethod> + </propgroup> + <!-- + chip service LED + --> + <facility name='service' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='type' type='uint32' value='0' /> + <propmethod name='ipmi_entity' version='0' propname='entity_ref' proptype='string' > + <argval name='format' type='string' value='p%d.led' /> + <argval name='offset' type='uint32' value='0' /> + <argval name='nparams' type='uint32' value='1' /> + </propmethod> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> </set> <set type='product' setlist='Sun-Fire-X4600|Sun-Fire-X4600-M2'> + <fac-enum provider='fac_prov_ipmi' /> + <!-- + chip FRU label + --> <propgroup name='protocol' version='1' name-stability='Private' data-stability='Private' > @@ -95,7 +302,34 @@ </propmethod> </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propmethod name='ipmi_entity' version='0' + propname='entity_ref' proptype='string' > + + <argval name='format' type='string' value='p%d.fru' /> + <argval name='offset' type='uint32' value='0' /> + <argval name='nparams' type='uint32' value='1' /> + </propmethod> + </propgroup> + <!-- + chip service LED + --> + <facility name='service' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='type' type='uint32' value='0' /> + <propmethod name='ipmi_entity' version='0' propname='entity_ref' proptype='string' > + <argval name='format' type='string' value='p%d.led' /> + <argval name='offset' type='uint32' value='0' /> + <argval name='nparams' type='uint32' value='1' /> + </propmethod> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> + </set> <set type='product' setlist='Sun-Blade-X8420-Server-Module|Sun-Blade-X8440-Server-Module|SUN-BLADE-X8440-SERVER-MODULE'> @@ -212,8 +446,9 @@ </propgroup> </set> - <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4200E|Sun-Fire-X4500'> + <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4200E'> + <fac-enum provider='fac_prov_ipmi' /> <propgroup name='protocol' version='1' name-stability='Private' data-stability='Private' > @@ -238,12 +473,88 @@ <argval name='offset' type='uint32' value='0' /> </propmethod> + </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + + <propmethod name='dimm_ipmi_entity' version='0' + propname='entity_ref' proptype='string' > + + <argval name='format' type='string' + value='p%d.d%d.fru' /> + <argval name='offset' type='uint32' value='0' /> + </propmethod> </propgroup> + <facility name='service' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='type' type='uint32' value='0' /> + <propmethod name='dimm_ipmi_entity' version='0' propname='entity_ref' proptype='string' > + <argval name='format' type='string' value='p%d.d%d.led' /> + <argval name='offset' type='uint32' value='0' /> + </propmethod> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> + </set> + <set type='product' setlist='Sun-Fire-X4500'> + + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='protocol' version='1' + name-stability='Private' + data-stability='Private' > + <propmethod name='simple_dimm_label_mp' version='0' + propname='label' proptype='string' > + + <argval name='format' type='string' + value='CPU %d DIMM %d' /> + <argval name='offset' type='uint32' value='0' /> + <argval name='order' type='string' + value='forward' /> + <argval name='dimms_per_chip' type='uint32' + value='4' /> + + </propmethod> + <propmethod name='get_dimm_serial' version='0' + propname='serial' proptype='string' > + + <argval name='format' type='string' + value='p%d.d%d.fru' /> + <argval name='offset' type='uint32' value='0' /> + + </propmethod> + </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + + <propmethod name='dimm_ipmi_entity' version='0' + propname='entity_ref' proptype='string' > + + <argval name='format' type='string' + value='p%d.d%d.fru' /> + <argval name='offset' type='uint32' value='0' /> + + </propmethod> + </propgroup> + <facility name='service' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='type' type='uint32' value='0' /> + <propmethod name='dimm_ipmi_entity' version='0' propname='entity_ref' proptype='string' > + <argval name='format' type='string' value='p%d.d%d.fail.led' /> + <argval name='offset' type='uint32' value='0' /> + </propmethod> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> </set> <set type='product' setlist='Sun-Fire-X4100-M2|Sun-Fire-X4200-M2'> + <fac-enum provider='fac_prov_ipmi' /> <propgroup name='protocol' version='1' name-stability='Private' data-stability='Private' > @@ -265,10 +576,37 @@ </propmethod> </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + + <propmethod name='dimm_ipmi_entity' version='0' + propname='entity_ref' proptype='string' > + + <argval name='format' type='string' + value='p%d.d%d.fru' /> + <argval name='offset' type='uint32' value='0' /> + </propmethod> + </propgroup> + <!-- + DIMM service LED + --> + <facility name='service' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='type' type='uint32' value='0' /> + <propmethod name='dimm_ipmi_entity' version='0' propname='entity_ref' proptype='string' > + <argval name='format' type='string' value='p%d.d%d.led' /> + <argval name='offset' type='uint32' value='0' /> + </propmethod> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> </set> <set type='product' setlist='Sun-Fire-X4600|Sun-Fire-X4600-M2'> + <fac-enum provider='fac_prov_ipmi' /> <propgroup name='protocol' version='1' name-stability='Private' data-stability='Private' > @@ -291,6 +629,33 @@ </propmethod> </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + + <propmethod name='dimm_ipmi_entity' version='0' + propname='entity_ref' proptype='string' > + + <argval name='format' type='string' + value='p%d.d%d.fru' /> + <argval name='offset' type='uint32' value='0' /> + + </propmethod> + </propgroup> + <!-- + DIMM service LED + --> + <facility name='service' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='type' type='uint32' value='0' /> + <propmethod name='dimm_ipmi_entity' version='0' propname='entity_ref' proptype='string' > + <argval name='format' type='string' value='p%d.d%d.led' /> + <argval name='offset' type='uint32' value='0' /> + </propmethod> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> </set> <set type='product' diff --git a/usr/src/lib/fm/topo/maps/i86pc/fan-hc-topology.xmlgen b/usr/src/lib/fm/topo/maps/i86pc/fan-hc-topology.xmlgen index da510918b1..01567b8e6e 100644 --- a/usr/src/lib/fm/topo/maps/i86pc/fan-hc-topology.xmlgen +++ b/usr/src/lib/fm/topo/maps/i86pc/fan-hc-topology.xmlgen @@ -54,9 +54,13 @@ my @platforms = ( count => 2, fru => "self" }, { + fac_enum => 1, + provider => "fac_prov_ipmi", count => 3, label => "FT %d FM %d", entity_ref => "ft%d.fm%d.led", + entity_ref_nparams => 2, + fm_service_indctr => "ft%d.fm%d.led", fru => "self" } ] @@ -72,12 +76,21 @@ my @platforms = ( set => "Sun-Fire-X4500|Sun-Fire-X4540", topology => [ { + fac_enum => 0, + provider => "fac_prov_ipmi", label => "FT %d", count => 5, fru => "self", entity_ref => "ft%d.prsnt", + entity_ref_nparams => 1, + fm_service_indctr => "ft%d.service.led", + fm_ok2rm_indctr => "ft%d.ok2rm.led", }, { + fac_enum => 1, + provider => "fac_prov_ipmi", count => 2, + entity_ref => "ft%d.f%d.speed", + entity_ref_nparams => 2, fru => "parent" } ] @@ -86,8 +99,10 @@ my @platforms = ( # # Fan Module/Fan topology for all G1N/G2N platforms. # - # These systems have 6 fan modules, with each fan module containing 2 fans. - # The FRU's for the individual fans are the containing fan module. + # There are two fan boards, which are FRU's. Each fan board has + # 3 fan modules for a total of 6 fan modules, with each fan module + # containing 2 fans. The FRU's for the individual fans are the + # containing fan module. # # Unfortunately, the IPMI topology on these systems is rather broken, and # all the SDRs that should be separate entities in fact refer to the same @@ -99,19 +114,47 @@ my @platforms = ( topology => [ { count => 2, - label => "FT %d", + label => "FANBD%d", fru => "self" }, { - label => "FT %d FM %d", + fac_enum => 1, + provider => "fac_prov_ipmi", + label => "FANBD%d FM%d", count => 3, fru => "self", entity_present => "fb%d.fm%d.prsnt", + entity_ref => "fb%d.fm%d.prsnt", + entity_ref_nparams => 2, + fm_service_indctr_ => "fb%d.fm%d.led", }, { count => 2, fru => "parent" } ] + }, + + # + # Fan Module/Fan topology for G4F platforms. + # + # These systems have 4 fan assemblies with a single fan per assembly. + # Each fan assembly is a FRU. The fan assemblies have a service LED + # but no other indicators. + # + { + set => "Sun-Fire-X4600-M2", + topology => [ + { + fac_enum => 1, + provider => "fac_prov_ipmi", + count => 4, + label => "FT %d", + fru => "self", + entity_ref => "ft%d.fm0.prsnt", + entity_ref_nparams => 1, + fm_service_indctr => "ft%d.fm0.led" + } + ] } ); @@ -143,6 +186,69 @@ sub process_topology $indent += 2; + # Facility enumerator + if ($level->{fac_enum}) { + printf(OFILE "%*s<fac-enum provider='", + $indent, ""); + printf(OFILE $level->{provider}, @indices); + printf(OFILE "' />\n"); + } + + # Facility nodes for service and ok2rm LED's + if ($level->{fm_service_indctr}) { + printf(OFILE "%*s<facility name='service' type='indicator' ". + "provider='fac_prov_ipmi' >\n", $indent+2, ""); + printf(OFILE "%*s<propgroup name='facility' version='1' ". + "name-stability='Private' data-stability='Private' >\n", + $indent+4, ""); + printf(OFILE "%*s<propval name='type' type='uint32' ". + "value='1' />\n", $indent+6, ""); + printf(OFILE "%*s<propmethod name='ipmi_entity' version='0' ". + "propname='entity_ref' proptype='string' >\n", + $indent+6, ""); + printf(OFILE "%*s<argval name='format' type='string' ". + "value='%s' />\n", $indent+8, "", + $level->{fm_service_indctr}); + printf(OFILE "%*s<argval name='offset' type='uint32' ". + "value='0' />\n", $indent+8, ""); + printf(OFILE "%*s<argval name='nparams' type='uint32' ". + "value='%d' />\n", $indent+8, "", + $level->{entity_ref_nparams}); + printf(OFILE "%*s</propmethod>\n", $indent+6, ""); + printf(OFILE "%*s<propmethod name='ipmi_indicator_mode' ". + "version='0' propname='mode' proptype='uint32' ". + "mutable='1' >\n", $indent+6, ""); + printf(OFILE "%*s</propmethod>\n", $indent+6, ""); + printf(OFILE "%*s</propgroup>\n", $indent+4, ""); + printf(OFILE "%*s</facility>\n", $indent+2, ""); + } + if ($level->{fm_ok2rm_indctr}) { + printf(OFILE "%*s<facility name='ok2rm' type='indicator' ". + "provider='fac_prov_ipmi' >\n", $indent+2, ""); + printf(OFILE "%*s<propgroup name='facility' version='1' ". + "name-stability='Private' data-stability='Private' >\n", + $indent+4, ""); + printf(OFILE "%*s<propval name='type' type='uint32' ". + "value='2' />\n", $indent+6, ""); + printf(OFILE "%*s<propmethod name='ipmi_entity' version='0' ". + "propname='entity_ref' proptype='string' >\n", + $indent+6, ""); + printf(OFILE "%*s<argval name='format' type='string' ". + "value='%s' />\n", $indent+8, "", + $level->{fm_ok2rm_indctr}); + printf(OFILE "%*s<argval name='offset' type='uint32' ". + "value='0' />\n", $indent+8, ""); + printf(OFILE "%*s<argval name='nparams' type='uint32' ". + "value='%d' />\n", $indent+8, "", + $level->{entity_ref_nparams}); + printf(OFILE "%*s</propmethod>\n", $indent+6, ""); + printf(OFILE "%*s<propmethod name='ipmi_indicator_mode' ". + "version='0' propname='mode' proptype='uint32' mutable='1' >\n", + $indent+6, ""); + printf(OFILE "%*s</propmethod>\n", $indent+6, ""); + printf(OFILE "%*s</propgroup>\n", $indent+4, ""); + printf(OFILE "%*s</facility>\n", $indent+2, ""); + } # Protocol properties (label, fmri) printf(OFILE "%*s<propgroup name='protocol' version='1' " . "name-stability='Private' data-stability='Private'>\n", @@ -169,7 +275,7 @@ sub process_topology printf(OFILE "%*s</propgroup>\n", $indent, ""); # - # Entity reference (if any) + # Entity references (if any) # if ($level->{entity_ref} || $level->{entity_present}) { my $name = $level->{entity_ref} ? "entity_ref" : @@ -185,6 +291,13 @@ sub process_topology printf(OFILE "%*s</propgroup>\n", $indent, ""); } + # + # Post-process IPMI enumerator method + # + if ($level->{provider}) { + printf(OFILE "%*s<enum-method name='ipmi' version='1' ". + "/>\n", $indent, ""); + } # # Children (if any) @@ -196,12 +309,6 @@ sub process_topology printf(OFILE "%*s</dependents>\n", $indent, ""); } - # - # Post-process IPMI enumerator method - # - printf(OFILE "%*s<enum-method name='ipmi' version='1' />\n", - $indent, ""); - $indent -= 2; printf(OFILE "%*s</node>\n", $indent, ""); diff --git a/usr/src/lib/fm/topo/maps/i86pc/i86pc-hc-topology.xml b/usr/src/lib/fm/topo/maps/i86pc/i86pc-hc-topology.xml index 0ac7c96747..fdf71f87e0 100644 --- a/usr/src/lib/fm/topo/maps/i86pc/i86pc-hc-topology.xml +++ b/usr/src/lib/fm/topo/maps/i86pc/i86pc-hc-topology.xml @@ -30,10 +30,24 @@ <range name='motherboard' min='0' max='0'> <node instance='0'> - <propgroup name='protocol' version='1' - name-stability='Private' data-stability='Private' > - <propval name='label' type='string' value='MB' /> - </propgroup> + <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4100-M2|Sun-Fire-X4200-M2|Sun-Fire-X4240|Sun-Fire-X4440|Sun-Fire-X4500|Sun-Fire-X4540|Sun-Fire-X4600-M2'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='protocol' version='1' + name-stability='Private' data-stability='Private' > + <propval name='label' type='string' value='MB' /> + </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity_ref' type='string' value='mb.fru' /> + </propgroup> + + </set> + <set type='product' setlist='default'> + <propgroup name='protocol' version='1' + name-stability='Private' data-stability='Private' > + <propval name='label' type='string' value='MB' /> + </propgroup> + </set> </node> <dependents grouping='children'> @@ -50,8 +64,152 @@ <range name='chassis' min='0' max='0'> <node instance='0'> + <set type='product' setlist='Sun-Fire-X4240|Sun-Fire-X4440'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity_ref' type='string' value='sys.intsw' /> + </propgroup> + </set> + <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4100-M2|Sun-Fire-X4200-M2'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity_ref' type='string' value='sys.intsw' /> + </propgroup> + <!-- + chassis locate and service LED's for Galaxy 1/2 + --> + <facility name='fp.locate.led' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='entity_ref' type='string' value='fp.locate.led' /> + <propval name='type' type='uint32' value='1' /> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> + <facility name='bp.locate.led' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='entity_ref' type='string' value='bp.locate.led' /> + <propval name='type' type='uint32' value='1' /> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> + <facility name='fp.alert.led' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='entity_ref' type='string' value='fp.alert.led' /> + <propval name='type' type='uint32' value='0' /> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> + <facility name='bp.alert.led' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='entity_ref' type='string' value='bp.alert.led' /> + <propval name='type' type='uint32' value='0' /> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> + </set> + <set type='product' setlist='Sun-Fire-X4500|Sun-Fire-X4540'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity_ref' type='string' value='sys.intsw' /> + </propgroup> + <!-- + chassis locate and service LED's for X4500/X4540 + --> + <facility name='fp.locate.led' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='entity_ref' type='string' value='fp.locate.led' /> + <propval name='type' type='uint32' value='1' /> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> + <facility name='bp.locate.led' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='entity_ref' type='string' value='bp.locate.led' /> + <propval name='type' type='uint32' value='1' /> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> + <facility name='fp.alert.led' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='entity_ref' type='string' value='fp.alert.led' /> + <propval name='type' type='uint32' value='0' /> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> + <facility name='bp.alert.led' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='entity_ref' type='string' value='bp.alert.led' /> + <propval name='type' type='uint32' value='0' /> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> + <facility name='sys.top_svc.led' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='entity_ref' type='string' value='sys.top_svc.led' /> + <propval name='type' type='uint32' value='0' /> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> + <facility name='sys.rear_svc.led' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='entity_ref' type='string' value='sys.rear_svc.led' /> + <propval name='type' type='uint32' value='0' /> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> + </set> + <set type='product' setlist='Sun-Fire-X4600-M2'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity_ref' type='string' value='sys.intsw' /> + </propgroup> + <!-- + chassis locate and service LED's for X4600M2 + --> + <facility name='sys.locate.led' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='entity_ref' type='string' value='sys.locate.led' /> + <propval name='type' type='uint32' value='1' /> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> + <facility name='sys.alert.led' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='entity_ref' type='string' value='sys.alert.led' /> + <propval name='type' type='uint32' value='0' /> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> + </set> </node> - <dependents grouping='children'> <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4100-M2|Sun-Fire-X4200-M2|Sun-Fire-X4240|Sun-Fire-X4440'> @@ -73,6 +231,16 @@ </range> </set> + <set type='product' setlist='Sun-Fire-X4600-M2'> + <range name='psu' min='0' max='100'> + <enum-method name='ipmi' version='1' /> + <propmap name='psu' /> + </range> + <range name='fan' min='0' max='3'> + <propmap name='fan' /> + </range> + </set> + <set type='product' setlist='default'> <range name='psu' min='0' max='100'> <enum-method name='ipmi' version='1' /> diff --git a/usr/src/lib/fm/topo/maps/i86pc/psu-hc-topology.xml b/usr/src/lib/fm/topo/maps/i86pc/psu-hc-topology.xml index 334b9067b0..ff9361eb84 100644 --- a/usr/src/lib/fm/topo/maps/i86pc/psu-hc-topology.xml +++ b/usr/src/lib/fm/topo/maps/i86pc/psu-hc-topology.xml @@ -36,6 +36,7 @@ <set type='product' setlist='Sun-Fire-X4500|Sun-Fire-X4540'> <range name='psu' min='0' max='100'> <node instance='0'> + <fac-enum provider='fac_prov_ipmi' /> <propgroup name='protocol' version='1' name-stability='Private' data-stability='Private' > <propval name='label' type='string' value='PS0' /> @@ -52,6 +53,7 @@ <enum-method name='ipmi' version='1' /> </node> <node instance='1'> + <fac-enum provider='fac_prov_ipmi' /> <propgroup name='protocol' version='1' name-stability='Private' data-stability='Private' > <propval name='label' type='string' value='PS1' /> @@ -69,8 +71,18 @@ </node> </range> </set> - <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4100-M2|Sun-Fire-X4200-M2|Sun-Fire-X4240|Sun-Fire-X4440'> + <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4100-M2|Sun-Fire-X4200-M2|Sun-Fire-X4240|Sun-Fire-X4440|Sun-Fire-X4600-M2'> <range name='psu' min='0' max='100'> + <fac-enum provider='fac_prov_ipmi' /> + <facility name='sys.psfail.led' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' data-stability='Private' > + <propval name='entity_ref' type='string' value='sys.psfail.led' /> + <propval name='type' type='uint32' value='0' /> + <propmethod name='ipmi_indicator_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> <propgroup name='protocol' version='1' name-stability='Private' data-stability='Private' > @@ -82,6 +94,18 @@ </propmethod> </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + + <propmethod name='ipmi_entity' version='0' + propname='entity_ref' proptype='string' > + + <argval name='format' type='string' value='ps%d.prsnt' /> + <argval name='offset' type='uint32' value='0' /> + <argval name='nparams' type='uint32' value='1' /> + + </propmethod> + </propgroup> </range> </set> </topology> diff --git a/usr/src/lib/fm/topo/modules/common/Makefile b/usr/src/lib/fm/topo/modules/common/Makefile index 5c64690d6f..0b0f965a70 100644 --- a/usr/src/lib/fm/topo/modules/common/Makefile +++ b/usr/src/lib/fm/topo/modules/common/Makefile @@ -27,6 +27,7 @@ SUBDIRS = \ disk \ + fac_prov_ipmi \ ipmi \ ses \ xfp diff --git a/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/Makefile b/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/Makefile new file mode 100644 index 0000000000..9b1907d3ee --- /dev/null +++ b/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/Makefile @@ -0,0 +1,34 @@ +# +# 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 +# or http://www.opensolaris.org/os/licensing. +# 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 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" + +MODULE = fac_prov_ipmi +CLASS = common + +MODULESRCS = fac_prov_ipmi.c + +include ../../Makefile.plugin + +LDLIBS += -lipmi diff --git a/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c b/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c new file mode 100644 index 0000000000..95829d94ec --- /dev/null +++ b/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c @@ -0,0 +1,1095 @@ +/* + * 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 + * or http://www.opensolaris.org/os/licensing. + * 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 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <limits.h> +#include <alloca.h> +#include <errno.h> +#include <libnvpair.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/fm/protocol.h> +#include <fm/libtopo.h> +#include <fm/topo_mod.h> +#include <libipmi.h> + +#define BUFSZ 128 +#define TOPO_PGROUP_IPMI "ipmi" + +#define THUMPER_PRESENT_LED_MASK 0x01 +#define THUMPER_SERVICE_LED_MASK 0x02 +#define THUMPER_OK2RM_LED_MASK 0x08 + +/* + * The largest possible SDR ID length is 2^5+1 + */ +#define MAX_ID_LEN 33 + +#define TOPO_METH_IPMI_READING_VERSION 0 +#define TOPO_METH_IPMI_STATE_VERSION 0 +#define TOPO_METH_IPMI_MODE_VERSION 0 +#define TOPO_METH_THUMPER_LOCATE_VERSION 0 +#define TOPO_METH_THUMPER_MODE_VERSION 0 +#define TOPO_METH_IPMI_ENTITY_VERSION 0 +#define TOPO_METH_DIMM_IPMI_ENTITY_VERSION 0 + +static int fac_prov_ipmi_enum(topo_mod_t *, tnode_t *, const char *, + topo_instance_t, topo_instance_t, void *, void *); + +/* + * IPMI facility provider methods + */ +static int ipmi_sensor_enum(topo_mod_t *, tnode_t *, topo_version_t, + nvlist_t *, nvlist_t **); +static int ipmi_entity(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, + nvlist_t **); +static int dimm_ipmi_entity(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, + nvlist_t **); +static int ipmi_sensor_reading(topo_mod_t *, tnode_t *, topo_version_t, + nvlist_t *, nvlist_t **); +static int ipmi_sensor_state(topo_mod_t *, tnode_t *, topo_version_t, + nvlist_t *, nvlist_t **); +static int ipmi_indicator_mode(topo_mod_t *, tnode_t *, topo_version_t, + nvlist_t *, nvlist_t **); +static int thumper_locate_mode(topo_mod_t *, tnode_t *, topo_version_t, + nvlist_t *, nvlist_t **); +static int thumper_indicator_mode(topo_mod_t *, tnode_t *, topo_version_t, + nvlist_t *, nvlist_t **); + +const topo_modops_t ipmi_ops = { fac_prov_ipmi_enum, NULL }; + +const topo_modinfo_t ipmi_info = + { "IPMI facility provider", FM_FMRI_SCHEME_HC, TOPO_VERSION, + &ipmi_ops }; + +static const topo_method_t ipmi_node_methods[] = { + { TOPO_METH_FAC_ENUM, TOPO_METH_FAC_ENUM_DESC, 0, + TOPO_STABILITY_INTERNAL, ipmi_sensor_enum }, + { TOPO_METH_IPMI_ENTITY, TOPO_PROP_METH_DESC, + TOPO_METH_IPMI_ENTITY_VERSION, + TOPO_STABILITY_INTERNAL, ipmi_entity }, + { "dimm_ipmi_entity", TOPO_PROP_METH_DESC, + TOPO_METH_DIMM_IPMI_ENTITY_VERSION, + TOPO_STABILITY_INTERNAL, dimm_ipmi_entity }, + { NULL } +}; + +static const topo_method_t ipmi_fac_methods[] = { + { "ipmi_sensor_reading", TOPO_PROP_METH_DESC, + TOPO_METH_IPMI_READING_VERSION, + TOPO_STABILITY_INTERNAL, ipmi_sensor_reading }, + { "ipmi_sensor_state", TOPO_PROP_METH_DESC, + TOPO_METH_IPMI_STATE_VERSION, + TOPO_STABILITY_INTERNAL, ipmi_sensor_state }, + { "ipmi_indicator_mode", TOPO_PROP_METH_DESC, + TOPO_METH_IPMI_MODE_VERSION, + TOPO_STABILITY_INTERNAL, ipmi_indicator_mode }, + { "thumper_locate_mode", TOPO_PROP_METH_DESC, + TOPO_METH_THUMPER_LOCATE_VERSION, + TOPO_STABILITY_INTERNAL, thumper_locate_mode }, + { "thumper_indicator_mode", TOPO_PROP_METH_DESC, + TOPO_METH_THUMPER_MODE_VERSION, + TOPO_STABILITY_INTERNAL, thumper_indicator_mode }, + { TOPO_METH_IPMI_ENTITY, TOPO_PROP_METH_DESC, + TOPO_METH_IPMI_ENTITY_VERSION, + TOPO_STABILITY_INTERNAL, ipmi_entity }, + { "dimm_ipmi_entity", TOPO_PROP_METH_DESC, + TOPO_METH_DIMM_IPMI_ENTITY_VERSION, + TOPO_STABILITY_INTERNAL, dimm_ipmi_entity }, + { NULL } +}; + +struct entity_info { + uint32_t ei_id; + uint32_t ei_inst; + topo_mod_t *ei_mod; + tnode_t *ei_node; +}; + +struct sensor_data { + char sd_entity_ref[MAX_ID_LEN]; + uint8_t sd_units; + uint32_t sd_stype; + uint32_t sd_rtype; + char *sd_class; +}; + +/*ARGSUSED*/ +int +_topo_init(topo_mod_t *mod, topo_version_t version) +{ + if (getenv("TOPOFACIPMIDEBUG") != NULL) + topo_mod_setdebug(mod); + + return (topo_mod_register(mod, &ipmi_info, TOPO_VERSION)); +} + +void +_topo_fini(topo_mod_t *mod) +{ + topo_mod_unregister(mod); +} + +static char * +get_fmtstr(topo_mod_t *mod, nvlist_t *in) +{ + char *fmtstr; + nvlist_t *args; + + if (nvlist_lookup_nvlist(in, TOPO_PROP_ARGS, &args) != 0) { + topo_mod_dprintf(mod, "Failed to lookup 'args' list (%s)\n", + strerror(errno)); + (void) topo_mod_seterrno(mod, EMOD_NVL_INVAL); + return (NULL); + } + if (nvlist_lookup_string(args, "format", &fmtstr) != 0) { + topo_mod_dprintf(mod, "Failed to lookup 'format' arg (%s)\n", + strerror(errno)); + (void) topo_mod_seterrno(mod, EMOD_NVL_INVAL); + return (NULL); + } + return (fmtstr); +} + +/*ARGSUSED*/ +static int +ipmi_sensor_state(topo_mod_t *mod, tnode_t *node, topo_version_t vers, + nvlist_t *in, nvlist_t **out) +{ + char *entity_ref; + ipmi_sdr_t *sdr = NULL; + ipmi_sensor_reading_t *reading; + ipmi_handle_t *hdl; + int err; + uint8_t sensor_num; + ipmi_sdr_full_sensor_t *fsensor; + ipmi_sdr_compact_sensor_t *csensor; + nvlist_t *nvl; + + if (vers > TOPO_METH_IPMI_STATE_VERSION) + return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW)); + + if (topo_prop_get_string(node, TOPO_PGROUP_FACILITY, "entity_ref", + &entity_ref, &err) != 0) { + topo_mod_dprintf(mod, "Failed to lookup entity_ref property " + "(%s)", topo_strerror(err)); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + + if ((hdl = topo_mod_ipmi(mod)) == NULL) { + topo_mod_dprintf(mod, "Failed to get IPMI handle\n"); + topo_mod_strfree(mod, entity_ref); + return (-1); + } + + if ((sdr = ipmi_sdr_lookup(hdl, entity_ref)) == NULL) { + topo_mod_dprintf(mod, "Failed to lookup SDR for %s (%s)\n", + entity_ref, ipmi_errmsg(hdl)); + topo_mod_strfree(mod, entity_ref); + return (-1); + } + + switch (sdr->is_type) { + case IPMI_SDR_TYPE_FULL_SENSOR: + fsensor = (ipmi_sdr_full_sensor_t *)sdr->is_record; + sensor_num = fsensor->is_fs_number; + break; + case IPMI_SDR_TYPE_COMPACT_SENSOR: + csensor = (ipmi_sdr_compact_sensor_t *)sdr->is_record; + sensor_num = csensor->is_cs_number; + break; + default: + topo_mod_dprintf(mod, "%s does not refer to a full or " + "compact SDR\n", entity_ref); + topo_mod_strfree(mod, entity_ref); + return (-1); + } + if ((reading = ipmi_get_sensor_reading(hdl, sensor_num)) + == NULL) { + topo_mod_dprintf(mod, "Failed to get sensor reading for sensor " + "%s, sensor_num=%d (%s)\n", entity_ref, sensor_num, + ipmi_errmsg(hdl)); + topo_mod_strfree(mod, entity_ref); + return (-1); + } + topo_mod_strfree(mod, entity_ref); + + if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 || + nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, + TOPO_SENSOR_STATE) != 0 || + nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_UINT32) != 0 || + nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, reading->isr_state) + != 0) { + topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n"); + nvlist_free(nvl); + return (topo_mod_seterrno(mod, EMOD_NOMEM)); + } + *out = nvl; + + return (0); +} + +/*ARGSUSED*/ +static int +ipmi_sensor_reading(topo_mod_t *mod, tnode_t *node, topo_version_t vers, + nvlist_t *in, nvlist_t **out) +{ + char *entity_ref, reading_str[BUFSZ]; + int err = 0; + ipmi_sdr_full_sensor_t *sensor; + ipmi_sensor_reading_t *reading; + double conv_reading; + ipmi_handle_t *hdl; + nvlist_t *nvl; + + if (vers > TOPO_METH_IPMI_READING_VERSION) + return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW)); + + if (topo_prop_get_string(node, TOPO_PGROUP_FACILITY, "entity_ref", + &entity_ref, &err) != 0) { + topo_mod_dprintf(mod, "Failed to lookup entity_ref property " + "(%s)", topo_strerror(err)); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + + if ((hdl = topo_mod_ipmi(mod)) == NULL) { + topo_mod_dprintf(mod, "Failed to get IPMI handle\n"); + topo_mod_strfree(mod, entity_ref); + return (-1); + } + + if ((sensor = ipmi_sdr_lookup_full_sensor(hdl, entity_ref)) + == NULL) { + topo_mod_dprintf(mod, "Failed to lookup SDR for %s (%s)\n", + entity_ref, ipmi_errmsg(hdl)); + topo_mod_strfree(mod, entity_ref); + return (-1); + } + + if ((reading = ipmi_get_sensor_reading(hdl, sensor->is_fs_number)) + == NULL) { + topo_mod_dprintf(mod, "Failed to get sensor reading for sensor " + "%s, sensor_num=%d (%s)\n", entity_ref, + sensor->is_fs_number, ipmi_errmsg(hdl)); + topo_mod_strfree(mod, entity_ref); + return (-1); + } + if (ipmi_sdr_conv_reading(sensor, reading->isr_reading, &conv_reading) + != 0) { + topo_mod_dprintf(mod, "Failed to convert sensor reading for " + "sensor %s (%s)\n", entity_ref, ipmi_errmsg(hdl)); + topo_mod_strfree(mod, entity_ref); + return (-1); + } + topo_mod_strfree(mod, entity_ref); + + (void) snprintf(reading_str, BUFSZ, "%f", conv_reading); + if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 || + nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, + TOPO_SENSOR_READING) != 0 || + nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_DOUBLE) != 0 || + nvlist_add_double(nvl, TOPO_PROP_VAL_VAL, conv_reading) != 0) { + topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n"); + nvlist_free(nvl); + return (topo_mod_seterrno(mod, EMOD_NOMEM)); + } + *out = nvl; + + return (0); +} + +static int +ipmi_indicator_mode(topo_mod_t *mod, tnode_t *node, topo_version_t vers, + nvlist_t *in, nvlist_t **out) +{ + char *entity_ref; + ipmi_sdr_generic_locator_t *gdl = NULL; + ipmi_handle_t *hdl; + int err, ret; + uint8_t ledmode; + uint32_t mode_in; + nvlist_t *pargs, *nvl; + + if (vers > TOPO_METH_IPMI_MODE_VERSION) + return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW)); + + /* + * Get an IPMI handle and then lookup the generic device locator sensor + * data record referenced by the entity_ref prop val + */ + if ((hdl = topo_mod_ipmi(mod)) == NULL) { + topo_mod_dprintf(mod, "Failed to get IPMI handle\n"); + return (-1); + } + + if (topo_prop_get_string(node, TOPO_PGROUP_FACILITY, "entity_ref", + &entity_ref, &err) != 0) { + topo_mod_dprintf(mod, "Failed to lookup entity_ref property " + "(%s)", topo_strerror(err)); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + + if ((gdl = ipmi_sdr_lookup_generic(hdl, entity_ref)) + == NULL) { + topo_mod_dprintf(mod, "Failed to lookup SDR for %s (%s)\n", + entity_ref, ipmi_errmsg(hdl)); + topo_mod_strfree(mod, entity_ref); + return (-1); + } + + /* + * Now look for a private argument list to figure out whether we're + * doing a get or a set operation, and then do it. + */ + if ((nvlist_lookup_nvlist(in, TOPO_PROP_PARGS, &pargs) == 0) && + nvlist_exists(pargs, TOPO_PROP_VAL_VAL)) { + /* + * Set the LED mode + */ + if ((ret = nvlist_lookup_uint32(pargs, TOPO_PROP_VAL_VAL, + &mode_in)) != 0) { + topo_mod_dprintf(mod, "Failed to lookup %s nvpair " + "(%s)\n", TOPO_PROP_VAL_VAL, strerror(ret)); + topo_mod_strfree(mod, entity_ref); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + if (mode_in != TOPO_LED_STATE_OFF && + mode_in != TOPO_LED_STATE_ON) { + topo_mod_dprintf(mod, "Invalid property value: %d\n", + mode_in); + topo_mod_strfree(mod, entity_ref); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + ledmode = (uint8_t)mode_in; + topo_mod_dprintf(mod, "Setting LED mode to %s\n", + ledmode ? "ON" : "OFF"); + if (ipmi_sunoem_led_set(hdl, gdl, ledmode) < 0) { + topo_mod_dprintf(mod, "Failed to set LED mode for %s " + "(%s)\n", entity_ref, ipmi_errmsg(hdl)); + topo_mod_strfree(mod, entity_ref); + return (-1); + } + } else { + /* + * Get the LED mode + */ + topo_mod_dprintf(mod, "Getting LED mode\n"); + if (ipmi_sunoem_led_get(hdl, gdl, &ledmode) < 0) { + topo_mod_dprintf(mod, "Failed to get LED mode for %s " + "(%s)\n", entity_ref, ipmi_errmsg(hdl)); + topo_mod_strfree(mod, entity_ref); + return (-1); + } + } + topo_mod_strfree(mod, entity_ref); + + if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 || + nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, TOPO_LED_MODE) != 0 || + nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_UINT32) != 0 || + nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, ledmode) != 0) { + topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n"); + nvlist_free(nvl); + return (topo_mod_seterrno(mod, EMOD_NOMEM)); + } + *out = nvl; + + return (0); +} + +/* + * On thumper platforms these is no seperate locate LED for the drive bays. + * Therefore we simulate a locate LED by blinking the ok2rm LED. + */ +static int +thumper_locate_mode(topo_mod_t *mod, tnode_t *node, topo_version_t vers, + nvlist_t *in, nvlist_t **out) +{ + char *entity_ref; + ipmi_sdr_generic_locator_t *gdl = NULL; + ipmi_handle_t *hdl; + int err, ret; + uint8_t ledmode; + uint32_t mode_in; + nvlist_t *pargs, *nvl; + + if (vers > TOPO_METH_THUMPER_LOCATE_VERSION) + return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW)); + + /* + * Get an IPMI handle and then lookup the generic device locator sensor + * data record referenced by the entity_ref prop val + */ + if ((hdl = topo_mod_ipmi(mod)) == NULL) { + topo_mod_dprintf(mod, "Failed to get IPMI handle\n"); + return (-1); + } + + if (topo_prop_get_string(node, TOPO_PGROUP_FACILITY, "entity_ref", + &entity_ref, &err) != 0) { + topo_mod_dprintf(mod, "Failed to lookup entity_ref property " + "(%s)", topo_strerror(err)); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + + if ((gdl = ipmi_sdr_lookup_generic(hdl, entity_ref)) + == NULL) { + topo_mod_dprintf(mod, "Failed to lookup SDR for %s (%s)\n", + entity_ref, ipmi_errmsg(hdl)); + topo_mod_strfree(mod, entity_ref); + return (-1); + } + + /* + * Now look for a private argument list to figure out whether we're + * doing a get or a set operation, and then do it. + */ + if ((nvlist_lookup_nvlist(in, TOPO_PROP_PARGS, &pargs) == 0) && + nvlist_exists(pargs, TOPO_PROP_VAL_VAL)) { + /* + * Set the LED mode + */ + if ((ret = nvlist_lookup_uint32(pargs, TOPO_PROP_VAL_VAL, + &mode_in)) != 0) { + topo_mod_dprintf(mod, "Failed to lookup %s nvpair " + "(%s)\n", TOPO_PROP_VAL_VAL, strerror(ret)); + topo_mod_strfree(mod, entity_ref); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + if (mode_in != TOPO_LED_STATE_OFF && + mode_in != TOPO_LED_STATE_ON) { + topo_mod_dprintf(mod, "Invalid property value: %d\n", + mode_in); + topo_mod_strfree(mod, entity_ref); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + if (mode_in == TOPO_LED_STATE_ON) + ledmode = IPMI_SUNOEM_LED_MODE_FAST; + else + ledmode = (uint8_t)mode_in; + if (ipmi_sunoem_led_set(hdl, gdl, ledmode) < 0) { + topo_mod_dprintf(mod, "Failed to set LED mode for %s " + "(%s)\n", entity_ref, ipmi_errmsg(hdl)); + topo_mod_strfree(mod, entity_ref); + return (-1); + } + } else { + /* + * Get the LED mode + */ + if (ipmi_sunoem_led_get(hdl, gdl, &ledmode) < 0) { + topo_mod_dprintf(mod, "Failed to get LED mode for %s " + "(%s)\n", entity_ref, ipmi_errmsg(hdl)); + topo_mod_strfree(mod, entity_ref); + return (-1); + } + } + topo_mod_strfree(mod, entity_ref); + + if (ledmode == IPMI_SUNOEM_LED_MODE_FAST) + ledmode = TOPO_LED_STATE_ON; + else + ledmode = TOPO_LED_STATE_OFF; + + if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 || + nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, TOPO_LED_MODE) != 0 || + nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_UINT32) != 0 || + nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, ledmode) != 0) { + topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n"); + nvlist_free(nvl); + return (topo_mod_seterrno(mod, EMOD_NOMEM)); + } + *out = nvl; + + return (0); +} + + +/* + * This is a method for the "mode" property that is specific for the drive bay + * LED's on thumper platforms. On thumper, the drive bay LED's are manipulated + * by asserting the right state bits in the hdd#.state compact SDR. + */ +static int +thumper_indicator_mode(topo_mod_t *mod, tnode_t *node, topo_version_t vers, + nvlist_t *in, nvlist_t **out) +{ + char *entity_ref; + ipmi_sdr_compact_sensor_t *cs = NULL; + ipmi_handle_t *hdl; + int err, ret; + uint32_t mask, type, ledmode; + nvlist_t *pargs, *nvl; + + if (vers > TOPO_METH_THUMPER_MODE_VERSION) + return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW)); + + /* + * Figure out which sensor state mask to use based on the indicator + * node's type prop val + */ + if (topo_prop_get_uint32(node, TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE, + &type, &err) != 0) { + topo_mod_dprintf(mod, "Failed to lookup %s property " + "(%s)", TOPO_FACILITY_TYPE, topo_strerror(err)); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + switch (type) { + case (TOPO_LED_TYPE_SERVICE): + mask = THUMPER_SERVICE_LED_MASK; + break; + case (TOPO_LED_TYPE_PRESENT): + mask = THUMPER_PRESENT_LED_MASK; + break; + case (TOPO_LED_TYPE_OK2RM): + mask = THUMPER_OK2RM_LED_MASK; + break; + default: + topo_mod_dprintf(mod, "Invalid LED type: 0x%x\n", type); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + + /* + * Get an IPMI handle and then lookup the compact sensor data record + * referenced by the entity_ref prop val + */ + if ((hdl = topo_mod_ipmi(mod)) == NULL) { + topo_mod_dprintf(mod, "Failed to get IPMI handle\n"); + return (-1); + } + + if (topo_prop_get_string(node, TOPO_PGROUP_FACILITY, "entity_ref", + &entity_ref, &err) != 0) { + topo_mod_dprintf(mod, "Failed to lookup entity_ref property " + "(%s)", topo_strerror(err)); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + + if ((cs = ipmi_sdr_lookup_compact_sensor(hdl, entity_ref)) + == NULL) { + topo_mod_dprintf(mod, "Failed to lookup SDR for %s (%s)\n", + entity_ref, ipmi_errmsg(hdl)); + topo_mod_strfree(mod, entity_ref); + return (-1); + } + + /* + * Now lookup the propmethod argument list and figure out whether we're + * doing a get or a set operation, and then do it. + */ + if ((nvlist_lookup_nvlist(in, TOPO_PROP_PARGS, &pargs) == 0) && + nvlist_exists(pargs, TOPO_PROP_VAL_VAL)) { + /* + * Set the LED mode + */ + ipmi_set_sensor_reading_t sr_out; + + if ((ret = nvlist_lookup_uint32(pargs, TOPO_PROP_VAL_VAL, + &ledmode)) != 0) { + topo_mod_dprintf(mod, "Failed to lookup %s nvpair " + "(%s)\n", TOPO_PROP_VAL_VAL, strerror(ret)); + topo_mod_strfree(mod, entity_ref); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + + if (ledmode == TOPO_LED_STATE_OFF) { + sr_out.iss_deassert_state = mask; + sr_out.iss_deassrt_op = IPMI_SENSOR_OP_SET; + } else if (ledmode == TOPO_LED_STATE_ON) { + sr_out.iss_assert_state = mask; + sr_out.iss_assert_op = IPMI_SENSOR_OP_SET; + } else { + topo_mod_dprintf(mod, "Invalid LED mode: %d 0x%x\n", + ledmode); + topo_mod_strfree(mod, entity_ref); + return (-1); + } + sr_out.iss_id = cs->is_cs_number; + topo_mod_dprintf(mod, "Setting LED mode (mask = 0x%x)\n", mask); + if (ipmi_set_sensor_reading(hdl, &sr_out) != 0) { + topo_mod_dprintf(mod, "Failed to set sensor reading " + "for sensor %s (%s)\n", entity_ref, + ipmi_errmsg(hdl)); + topo_mod_strfree(mod, entity_ref); + return (-1); + } + } else { + /* + * Get the LED mode + */ + ipmi_sensor_reading_t *sr_in; + + topo_mod_dprintf(mod, "Getting LED mode\n"); + if ((sr_in = ipmi_get_sensor_reading(hdl, cs->is_cs_number)) + == NULL) { + topo_mod_dprintf(mod, "Failed to get sensor reading " + "for sensor %s (sensor num: %d) (error: %s)\n", + entity_ref, cs->is_cs_number, ipmi_errmsg(hdl)); + topo_mod_strfree(mod, entity_ref); + return (-1); + } + if (sr_in->isr_state & (uint16_t)mask) + ledmode = TOPO_LED_STATE_ON; + else + ledmode = TOPO_LED_STATE_OFF; + } + topo_mod_strfree(mod, entity_ref); + + if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 || + nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, TOPO_LED_MODE) != 0 || + nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_UINT32) != 0 || + nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, ledmode) != 0) { + topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n"); + nvlist_free(nvl); + return (topo_mod_seterrno(mod, EMOD_NOMEM)); + } + *out = nvl; + return (0); +} + +static int +make_sensor_node(topo_mod_t *mod, tnode_t *pnode, struct sensor_data *sd) +{ + int err, ret; + tnode_t *fnode; + char *ftype = "sensor"; + topo_pgroup_info_t pgi; + nvlist_t *arg_nvl = NULL; + + if ((fnode = topo_node_facbind(mod, pnode, sd->sd_entity_ref, + ftype)) == NULL) { + topo_mod_dprintf(mod, "Failed to bind facility node: %s\n", + sd->sd_entity_ref); + /* topo errno set */ + return (-1); + } + + pgi.tpi_name = TOPO_PGROUP_FACILITY; + pgi.tpi_namestab = TOPO_STABILITY_PRIVATE; + pgi.tpi_datastab = TOPO_STABILITY_PRIVATE; + pgi.tpi_version = 1; + if (topo_pgroup_create(fnode, &pgi, &err) != 0) { + if (err != ETOPO_PROP_DEFD) { + topo_mod_dprintf(mod, "pgroups create failure: %s\n", + topo_strerror(err)); + topo_node_unbind(fnode); + return (-1); + } + } + if (topo_method_register(mod, fnode, ipmi_fac_methods) < 0) { + topo_mod_dprintf(mod, "make_fac_node: " + "failed to register facility methods"); + topo_node_unbind(fnode); + return (-1); + } + /* + * For both threshold and discrete sensors we set up a propmethod for + * getting the sensor state and properties to hold the entity ref, + * sensor class and sensor type. + * + * Additionally, for analog sensors we set up a property method for + * getting the converted sensor reading and property for the base + * unit type + */ + if (topo_prop_set_string(fnode, TOPO_PGROUP_FACILITY, "entity_ref", + TOPO_PROP_IMMUTABLE, sd->sd_entity_ref, &err) != 0) { + topo_mod_dprintf(mod, "Failed to set entity_ref property on " + "node: %s=%d (%s)\n", topo_node_name(fnode), + topo_node_instance(fnode), topo_strerror(err)); + return (-1); + } + if (topo_prop_set_string(fnode, TOPO_PGROUP_FACILITY, TOPO_SENSOR_CLASS, + TOPO_PROP_IMMUTABLE, sd->sd_class, &err) != 0) { + topo_mod_dprintf(mod, "Failed to set %s property on node: " + "%s=%d (%s)\n", TOPO_SENSOR_CLASS, topo_node_name(fnode), + topo_node_instance(fnode), topo_strerror(err)); + return (-1); + } + if (topo_prop_set_uint32(fnode, TOPO_PGROUP_FACILITY, + TOPO_FACILITY_TYPE, TOPO_PROP_IMMUTABLE, sd->sd_stype, &err) != 0) { + topo_mod_dprintf(mod, "Failed to set %s property on node: " + "%s=%d (%s)\n", TOPO_FACILITY_TYPE, topo_node_name(fnode), + topo_node_instance(fnode), topo_strerror(err)); + return (-1); + } + if (topo_mod_nvalloc(mod, &arg_nvl, NV_UNIQUE_NAME) < 0) { + topo_node_unbind(fnode); + return (topo_mod_seterrno(mod, EMOD_NOMEM)); + } + + if ((ret = nvlist_add_string(arg_nvl, "ipmi_entity", sd->sd_entity_ref)) + != 0) { + topo_mod_dprintf(mod, "Failed build arg nvlist (%s)\n", + strerror(ret)); + nvlist_free(arg_nvl); + return (-1); + } + + if (topo_prop_method_register(fnode, TOPO_PGROUP_FACILITY, + TOPO_SENSOR_STATE, TOPO_TYPE_UINT32, "ipmi_sensor_state", arg_nvl, + &err) != 0) { + topo_mod_dprintf(mod, "Failed to register %s propmeth on fac " + "node %s (%s)\n", TOPO_SENSOR_STATE, topo_node_name(fnode), + topo_strerror(err)); + nvlist_free(arg_nvl); + return (-1); + } + + if (strcmp(sd->sd_class, TOPO_SENSOR_CLASS_THRESHOLD) == 0) { + if (topo_prop_method_register(fnode, TOPO_PGROUP_FACILITY, + TOPO_SENSOR_READING, TOPO_TYPE_DOUBLE, + "ipmi_sensor_reading", arg_nvl, &err) != 0) { + topo_mod_dprintf(mod, "Failed to register %s propmeth " + "on fac node %s (%s)\n", TOPO_SENSOR_READING, + topo_node_name(fnode), topo_strerror(err)); + nvlist_free(arg_nvl); + return (-1); + } + if (topo_prop_set_uint32(fnode, TOPO_PGROUP_FACILITY, + TOPO_SENSOR_UNITS, TOPO_PROP_IMMUTABLE, sd->sd_units, &err) + != 0) { + topo_mod_dprintf(mod, "Failed to set units property on " + "node: %s (%s)\n", topo_node_name(fnode), + topo_strerror(err)); + nvlist_free(arg_nvl); + return (-1); + } + } + nvlist_free(arg_nvl); + return (0); +} + +/* ARGSUSED */ +static int +sdr_callback(ipmi_handle_t *hdl, const char *id, ipmi_sdr_t *sdr, void *data) +{ + uint8_t sensor_entity, sensor_inst; + int sensor_idlen; + ipmi_sdr_full_sensor_t *f_sensor = NULL; + ipmi_sdr_compact_sensor_t *c_sensor = NULL; + struct sensor_data sd; + struct entity_info *ei = (struct entity_info *)data; + + switch (sdr->is_type) { + case IPMI_SDR_TYPE_FULL_SENSOR: + f_sensor = + (ipmi_sdr_full_sensor_t *)sdr->is_record; + sensor_entity = f_sensor->is_fs_entity_id; + sensor_inst = f_sensor->is_fs_entity_instance; + sensor_idlen = f_sensor->is_fs_idlen; + (void) strncpy(sd.sd_entity_ref, + f_sensor->is_fs_idstring, + f_sensor->is_fs_idlen); + sd.sd_entity_ref[sensor_idlen] = '\0'; + sd.sd_class = TOPO_SENSOR_CLASS_THRESHOLD; + sd.sd_units = f_sensor->is_fs_unit2; + sd.sd_stype = f_sensor->is_fs_type; + sd.sd_rtype = f_sensor->is_fs_reading_type; + break; + case IPMI_SDR_TYPE_COMPACT_SENSOR: + c_sensor = + (ipmi_sdr_compact_sensor_t *)sdr->is_record; + sensor_entity = c_sensor->is_cs_entity_id; + sensor_inst = c_sensor->is_cs_entity_instance; + sensor_idlen = c_sensor->is_cs_idlen; + (void) strncpy(sd.sd_entity_ref, + c_sensor->is_cs_idstring, + sensor_idlen); + sd.sd_entity_ref[sensor_idlen] = '\0'; + sd.sd_class = TOPO_SENSOR_CLASS_DISCRETE; + sd.sd_units = c_sensor->is_cs_unit2; + sd.sd_stype = c_sensor->is_cs_type; + sd.sd_rtype = c_sensor->is_cs_reading_type; + break; + default: + return (0); + } + /* + * We offset the threshold and generic sensor reading types by 0x100 + */ + if (sd.sd_rtype >= 0x1 && sd.sd_rtype <= 0xc) + sd.sd_stype = sd.sd_rtype + 0x100; + + if ((sensor_entity == ei->ei_id) && (sensor_inst == ei->ei_inst)) + if (make_sensor_node(ei->ei_mod, ei->ei_node, &sd) != 0) { + topo_mod_dprintf(ei->ei_mod, "Failed to create sensor " + "node for %s\n", sd.sd_entity_ref); + if (topo_mod_errno(ei->ei_mod) != EMOD_NODE_DUP) + return (-1); + } + return (0); +} + +/* ARGSUSED */ +static int +ipmi_sensor_enum(topo_mod_t *mod, tnode_t *node, topo_version_t vers, + nvlist_t *in, nvlist_t **out) +{ + char *entity_ref; + int err; + struct entity_info ei; + ipmi_sdr_t *ref_sdr; + ipmi_handle_t *hdl; + ipmi_sdr_full_sensor_t *fsensor; + ipmi_sdr_compact_sensor_t *csensor; + ipmi_sdr_fru_locator_t *floc; + ipmi_sdr_generic_locator_t *gloc; + + if ((hdl = topo_mod_ipmi(mod)) == NULL) { + topo_mod_dprintf(mod, "Failed to get IPMI handle\n"); + return (-1); + } + + /* + * Use the entity ref to lookup the SDR, which will have the entity ID + * and instance. + */ + if (topo_prop_get_string(node, TOPO_PGROUP_IPMI, + "entity_ref", &entity_ref, &err) != 0) { + topo_mod_dprintf(mod, "Failed to lookup entity_ref " + "property (%s)\n", topo_strerror(err)); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + + topo_mod_dprintf(mod, "Looking up SDR for %s ...\n", + entity_ref); + if ((ref_sdr = ipmi_sdr_lookup(hdl, entity_ref)) == NULL) { + topo_mod_dprintf(mod, "Failed to lookup SDR (%s)\n", + ipmi_errmsg(hdl)); + topo_mod_strfree(mod, entity_ref); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + topo_mod_strfree(mod, entity_ref); + + switch (ref_sdr->is_type) { + case IPMI_SDR_TYPE_FULL_SENSOR: + fsensor = (ipmi_sdr_full_sensor_t *)ref_sdr->is_record; + ei.ei_id = fsensor->is_fs_entity_id; + ei.ei_inst = fsensor->is_fs_entity_instance; + break; + case IPMI_SDR_TYPE_COMPACT_SENSOR: + csensor + = (ipmi_sdr_compact_sensor_t *)ref_sdr->is_record; + ei.ei_id = csensor->is_cs_entity_id; + ei.ei_inst = csensor->is_cs_entity_instance; + break; + case IPMI_SDR_TYPE_FRU_LOCATOR: + floc = (ipmi_sdr_fru_locator_t *)ref_sdr->is_record; + ei.ei_id = floc->is_fl_entity; + ei.ei_inst = floc->is_fl_instance; + break; + case IPMI_SDR_TYPE_GENERIC_LOCATOR: + gloc = (ipmi_sdr_generic_locator_t *)ref_sdr->is_record; + ei.ei_id = gloc->is_gl_entity; + ei.ei_inst = gloc->is_gl_instance; + break; + default: + topo_mod_dprintf(mod, "Failed to determine entity id " + "and instance\n", ipmi_errmsg(hdl)); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + topo_mod_dprintf(mod, "Entity ID = 0x%x, Entity Instance = 0x%x\n", + ei.ei_id, ei.ei_inst); + + ei.ei_node = node; + ei.ei_mod = mod; + + /* + * Now iterate through all of the full and compact sensor data records + * and create a sensor facility node for each record that matches our + * entity ID and instance + */ + if (ipmi_sdr_iter(hdl, sdr_callback, &ei) != 0) { + topo_mod_dprintf(mod, "ipmi_sdr_iter() failed\n"); + return (-1); + } + return (0); +} + +static int +ipmi_entity(topo_mod_t *mod, tnode_t *node, topo_version_t vers, + nvlist_t *in, nvlist_t **out) +{ + char *fmtstr, buf[BUFSZ]; + tnode_t *refnode; + int ret, inst1, inst2; + uint32_t offset, nparams; + nvlist_t *args, *nvl; + + if (vers > TOPO_METH_IPMI_ENTITY_VERSION) + return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW)); + + if ((ret = nvlist_lookup_nvlist(in, TOPO_PROP_ARGS, &args)) != 0) { + topo_mod_dprintf(mod, "Failed to lookup 'args' list (%s)\n", + strerror(ret)); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + if ((ret = nvlist_lookup_uint32(args, "offset", &offset)) != 0) { + topo_mod_dprintf(mod, "Failed to lookup 'offset' arg (%s)\n", + strerror(ret)); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + if ((ret = nvlist_lookup_uint32(args, "nparams", &nparams)) != 0) { + topo_mod_dprintf(mod, "Failed to lookup 'nparams' arg (%s)\n", + strerror(ret)); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + + if ((fmtstr = get_fmtstr(mod, in)) == NULL) { + topo_mod_dprintf(mod, "Failed to retrieve 'format' arg\n"); + /* topo errno already set */ + return (-1); + } + + if (topo_node_flags(node) & TOPO_NODE_FACILITY) + refnode = topo_node_parent(node); + else + refnode = node; + + switch (nparams) { + case 1: + /* LINTED: E_SEC_PRINTF_VAR_FMT */ + (void) snprintf(buf, BUFSZ, fmtstr, + (topo_node_instance(refnode) + offset)); + break; + case 2: + inst1 = topo_node_instance(topo_node_parent(refnode)) + offset; + inst2 = topo_node_instance(refnode) + offset; + /* LINTED: E_SEC_PRINTF_VAR_FMT */ + (void) snprintf(buf, BUFSZ, fmtstr, inst1, inst2); + break; + default: + topo_mod_dprintf(mod, "Invalid 'nparams' argval (%d)\n", + nparams); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + + if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 || + nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, "entity_ref") != 0 || + nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_STRING) != 0 || + nvlist_add_string(nvl, TOPO_PROP_VAL_VAL, buf) != 0) { + topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n"); + nvlist_free(nvl); + return (topo_mod_seterrno(mod, EMOD_NOMEM)); + } + *out = nvl; + + return (0); +} + +/* ARGSUSED */ +static int +dimm_ipmi_entity(topo_mod_t *mod, tnode_t *node, topo_version_t vers, + nvlist_t *in, nvlist_t **out) +{ + char *fmtstr, buf[BUFSZ]; + tnode_t *chip, *dimm; + int ret; + uint32_t offset; + nvlist_t *args, *nvl; + + if ((ret = nvlist_lookup_nvlist(in, TOPO_PROP_ARGS, &args)) != 0) { + topo_mod_dprintf(mod, "Failed to lookup 'args' list (%s)\n", + strerror(ret)); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + if ((ret = nvlist_lookup_uint32(args, "offset", &offset)) != 0) { + topo_mod_dprintf(mod, "Failed to lookup 'offset' arg (%s)\n", + strerror(ret)); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + + if ((fmtstr = get_fmtstr(mod, in)) == NULL) { + topo_mod_dprintf(mod, "Failed to retrieve 'format' arg\n"); + /* topo errno already set */ + return (-1); + } + + if (topo_node_flags(node) & TOPO_NODE_FACILITY) + dimm = topo_node_parent(node); + else + dimm = node; + + chip = topo_node_parent(topo_node_parent(dimm)); + + /* LINTED: E_SEC_PRINTF_VAR_FMT */ + (void) snprintf(buf, BUFSZ, fmtstr, topo_node_instance(chip), + (topo_node_instance(dimm) + offset)); + + if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 || + nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, "entity_ref") != 0 || + nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_STRING) != 0 || + nvlist_add_string(nvl, TOPO_PROP_VAL_VAL, buf) != 0) { + topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n"); + nvlist_free(nvl); + return (topo_mod_seterrno(mod, EMOD_NOMEM)); + } + *out = nvl; + + return (0); +} + +/*ARGSUSED*/ +static int +fac_prov_ipmi_enum(topo_mod_t *mod, tnode_t *rnode, const char *name, + topo_instance_t min, topo_instance_t max, void *arg, void *unused) +{ + topo_pgroup_info_t pgi; + int err; + + if (topo_node_flags(rnode) == TOPO_NODE_DEFAULT) { + pgi.tpi_name = TOPO_PGROUP_IPMI; + pgi.tpi_namestab = TOPO_STABILITY_PRIVATE; + pgi.tpi_datastab = TOPO_STABILITY_PRIVATE; + pgi.tpi_version = 1; + if (topo_pgroup_create(rnode, &pgi, &err) != 0) { + if (err != ETOPO_PROP_DEFD) { + topo_mod_dprintf(mod, + "pgroups create failure: %s\n", + topo_strerror(err)); + return (-1); + } + } + if (topo_method_register(mod, rnode, ipmi_node_methods) != 0) { + topo_mod_dprintf(mod, "fac_prov_ipmi_enum: " + "topo_method_register() failed: %s", + topo_mod_errmsg(mod)); + return (-1); + } + } else { + if (topo_method_register(mod, rnode, ipmi_fac_methods) != 0) { + topo_mod_dprintf(mod, "fac_prov_ipmi_enum: " + "topo_method_register() failed: %s", + topo_mod_errmsg(mod)); + return (-1); + } + } + return (0); +} diff --git a/usr/src/lib/libipmi/Makefile.com b/usr/src/lib/libipmi/Makefile.com index 69f52fc934..81baba0ee9 100644 --- a/usr/src/lib/libipmi/Makefile.com +++ b/usr/src/lib/libipmi/Makefile.com @@ -52,7 +52,7 @@ SRCDIR= ../common CLEANFILES += $(SRCDIR)/ipmi_tables.c INCS += -I$(SRCDIR) -LDLIBS += -lc +LDLIBS += -lc -lm CPPFLAGS += $(INCS) $(LINTLIB) := SRCS= $(SRCDIR)/$(LINTSRC) diff --git a/usr/src/lib/libipmi/common/ipmi_impl.h b/usr/src/lib/libipmi/common/ipmi_impl.h index 340e647e25..4058a0e38f 100644 --- a/usr/src/lib/libipmi/common/ipmi_impl.h +++ b/usr/src/lib/libipmi/common/ipmi_impl.h @@ -120,6 +120,7 @@ extern ipmi_name_trans_t ipmi_sensor_type_table[]; extern ipmi_name_trans_t ipmi_reading_type_table[]; extern ipmi_name_trans_t ipmi_errno_table[]; extern ipmi_name_trans_t ipmi_threshold_state_table[]; +extern ipmi_name_trans_t ipmi_units_type_table[]; extern ipmi_sensor_trans_t ipmi_reading_state_table[]; extern ipmi_sensor_trans_t ipmi_specific_state_table[]; diff --git a/usr/src/lib/libipmi/common/ipmi_sdr.c b/usr/src/lib/libipmi/common/ipmi_sdr.c index 44d41df721..325339f7bc 100644 --- a/usr/src/lib/libipmi/common/ipmi_sdr.c +++ b/usr/src/lib/libipmi/common/ipmi_sdr.c @@ -30,9 +30,57 @@ #include <stddef.h> #include <string.h> #include <strings.h> +#include <math.h> #include "ipmi_impl.h" +/* + * This macros are used by ipmi_sdr_conv_reading. They were taken verbatim from + * the source for ipmitool (v1.88) + */ +#define tos32(val, bits) ((val & ((1<<((bits)-1)))) ? (-((val) & \ + (1<<((bits)-1))) | (val)) : (val)) + +#define __TO_TOL(mtol) (uint16_t)(BSWAP_16(mtol) & 0x3f) + +#define __TO_M(mtol) (int16_t)(tos32((((BSWAP_16(mtol) & 0xff00) >> 8) | \ + ((BSWAP_16(mtol) & 0xc0) << 2)), 10)) + +#define __TO_B(bacc) (int32_t)(tos32((((BSWAP_32(bacc) & \ + 0xff000000) >> 24) | \ + ((BSWAP_32(bacc) & 0xc00000) >> 14)), 10)) + +#define __TO_ACC(bacc) (uint32_t)(((BSWAP_32(bacc) & 0x3f0000) >> 16) | \ + ((BSWAP_32(bacc) & 0xf000) >> 6)) + +#define __TO_ACC_EXP(bacc) (uint32_t)((BSWAP_32(bacc) & 0xc00) >> 10) +#define __TO_R_EXP(bacc) (int32_t)(tos32(((BSWAP_32(bacc) & 0xf0) >> 4),\ + 4)) +#define __TO_B_EXP(bacc) (int32_t)(tos32((BSWAP_32(bacc) & 0xf), 4)) + +#define SDR_SENSOR_L_LINEAR 0x00 +#define SDR_SENSOR_L_LN 0x01 +#define SDR_SENSOR_L_LOG10 0x02 +#define SDR_SENSOR_L_LOG2 0x03 +#define SDR_SENSOR_L_E 0x04 +#define SDR_SENSOR_L_EXP10 0x05 +#define SDR_SENSOR_L_EXP2 0x06 +#define SDR_SENSOR_L_1_X 0x07 +#define SDR_SENSOR_L_SQR 0x08 +#define SDR_SENSOR_L_CUBE 0x09 +#define SDR_SENSOR_L_SQRT 0x0a +#define SDR_SENSOR_L_CUBERT 0x0b +#define SDR_SENSOR_L_NONLINEAR 0x70 + +/* + * Analog sensor reading data formats + * + * See Section 43.1 + */ +#define IPMI_DATA_FMT_UNSIGNED 0 +#define IPMI_DATA_FMT_ONESCOMP 1 +#define IPMI_DATA_FMT_TWOSCOMP 2 + typedef struct ipmi_sdr_cache_ent { char *isc_name; struct ipmi_sdr *isc_sdr; @@ -530,3 +578,79 @@ ipmi_sdr_lookup_full_sensor(ipmi_handle_t *ihp, const char *idstr) return (ipmi_sdr_lookup_common(ihp, idstr, IPMI_SDR_TYPE_FULL_SENSOR)); } + +/* + * Mostly taken from ipmitool source v1.88 + * + * This function converts the raw sensor reading returned by + * ipmi_get_sensor_reading to a unit-based value of type double. + */ +int +ipmi_sdr_conv_reading(ipmi_sdr_full_sensor_t *sensor, uint8_t val, + double *result) +{ + int m, b, k1, k2; + + m = __TO_M(sensor->is_fs_mtol); + b = __TO_B(sensor->is_fs_bacc); + k1 = __TO_B_EXP(sensor->is_fs_bacc); + k2 = __TO_R_EXP(sensor->is_fs_bacc); + + switch (sensor->is_fs_analog_fmt) { + case IPMI_DATA_FMT_UNSIGNED: + *result = (double)(((m * val) + + (b * pow(10, k1))) * pow(10, k2)); + break; + case IPMI_DATA_FMT_ONESCOMP: + if (val & 0x80) + val++; + /* FALLTHRU */ + case IPMI_DATA_FMT_TWOSCOMP: + *result = (double)(((m * (int8_t)val) + + (b * pow(10, k1))) * pow(10, k2)); + break; + default: + /* This sensor does not return a numeric reading */ + return (-1); + } + + switch (sensor->is_fs_sensor_linear_type) { + case SDR_SENSOR_L_LN: + *result = log(*result); + break; + case SDR_SENSOR_L_LOG10: + *result = log10(*result); + break; + case SDR_SENSOR_L_LOG2: + *result = (double)(log(*result) / log(2.0)); + break; + case SDR_SENSOR_L_E: + *result = exp(*result); + break; + case SDR_SENSOR_L_EXP10: + *result = pow(10.0, *result); + break; + case SDR_SENSOR_L_EXP2: + *result = pow(2.0, *result); + break; + case SDR_SENSOR_L_1_X: + *result = pow(*result, -1.0); /* 1/x w/o exception */ + break; + case SDR_SENSOR_L_SQR: + *result = pow(*result, 2.0); + break; + case SDR_SENSOR_L_CUBE: + *result = pow(*result, 3.0); + break; + case SDR_SENSOR_L_SQRT: + *result = sqrt(*result); + break; + case SDR_SENSOR_L_CUBERT: + *result = cbrt(*result); + break; + case SDR_SENSOR_L_LINEAR: + default: + break; + } + return (0); +} diff --git a/usr/src/lib/libipmi/common/ipmi_util.c b/usr/src/lib/libipmi/common/ipmi_util.c index 70b3ed9e45..06466a9aab 100644 --- a/usr/src/lib/libipmi/common/ipmi_util.c +++ b/usr/src/lib/libipmi/common/ipmi_util.c @@ -169,6 +169,21 @@ ipmi_sensor_type_name(uint8_t type, char *buf, size_t len) } void +ipmi_sensor_units_name(uint8_t type, char *buf, size_t len) +{ + ipmi_name_trans_t *ntp; + + for (ntp = &ipmi_units_type_table[0]; ntp->int_name != NULL; ntp++) { + if (ntp->int_value == type) { + (void) strlcpy(buf, ntp->int_name, len); + return; + } + } + + (void) snprintf(buf, len, "0x%02x", type); +} + +void ipmi_sensor_reading_name(uint8_t sensor_type, uint8_t reading_type, char *buf, size_t len) { diff --git a/usr/src/lib/libipmi/common/libipmi.h b/usr/src/lib/libipmi/common/libipmi.h index bbe517443e..b73dbbf87e 100644 --- a/usr/src/lib/libipmi/common/libipmi.h +++ b/usr/src/lib/libipmi/common/libipmi.h @@ -1426,7 +1426,8 @@ typedef struct ipmi_sensor_reading { #define IPMI_SENSOR_THRESHOLD_UPPER_NONRECOV 0x0020 extern ipmi_sensor_reading_t *ipmi_get_sensor_reading(ipmi_handle_t *, uint8_t); - +extern int ipmi_sdr_conv_reading(ipmi_sdr_full_sensor_t *, uint8_t, + double *); /* * Set Sensor Reading. See section 35.14. */ @@ -1517,6 +1518,7 @@ extern int ipmi_fru_parse_product(ipmi_handle_t *, char *, */ void ipmi_entity_name(uint8_t, char *, size_t); void ipmi_sensor_type_name(uint8_t, char *, size_t); +void ipmi_sensor_units_name(uint8_t, char *, size_t); void ipmi_sensor_reading_name(uint8_t, uint8_t, char *, size_t); /* diff --git a/usr/src/lib/libipmi/common/mapfile-vers b/usr/src/lib/libipmi/common/mapfile-vers index beb74afb00..2d844fb403 100644 --- a/usr/src/lib/libipmi/common/mapfile-vers +++ b/usr/src/lib/libipmi/common/mapfile-vers @@ -46,6 +46,7 @@ SUNWprivate_1.1 { ipmi_get_sensor_reading; ipmi_open; ipmi_sdr_changed; + ipmi_sdr_conv_reading; ipmi_sdr_get; ipmi_sdr_iter; ipmi_sdr_lookup; @@ -62,6 +63,7 @@ SUNWprivate_1.1 { ipmi_sel_set_utc_offset; ipmi_sensor_reading_name; ipmi_sensor_type_name; + ipmi_sensor_units_name; ipmi_send; ipmi_set_sensor_reading; ipmi_sunoem_led_get; diff --git a/usr/src/lib/libipmi/common/mktables.sh b/usr/src/lib/libipmi/common/mktables.sh index 9377b1b8c2..d0c60a866c 100644 --- a/usr/src/lib/libipmi/common/mktables.sh +++ b/usr/src/lib/libipmi/common/mktables.sh @@ -107,3 +107,17 @@ cat $libipmi_h | sed -n "s/$pattern/$replace/p" || exit 1 echo "\t{ 0, NULL } };" + +# +# Units +# +echo "\nipmi_name_trans_t ipmi_units_type_table[] = {" + +pattern="#define IPMI_UNITS_\([A-Z0-9_]*\).*\$" +replace=" { IPMI_UNITS_\1, \"\1\" }," + +cat $libipmi_h | sed -n "s/$pattern/$replace/p" || exit 1 + +echo "\t{ 0, NULL } +};" + diff --git a/usr/src/lib/libnvpair/libnvpair.c b/usr/src/lib/libnvpair/libnvpair.c index 664a3fff6f..0845cb08cf 100644 --- a/usr/src/lib/libnvpair/libnvpair.c +++ b/usr/src/lib/libnvpair/libnvpair.c @@ -138,6 +138,12 @@ nvlist_print_with_indent(FILE *fp, nvlist_t *nvl, int depth) (void) fprintf(fp, " 0x%llx", (u_longlong_t)val); break; } + case DATA_TYPE_DOUBLE: { + double val; + (void) nvpair_value_double(nvp, &val); + (void) fprintf(fp, " 0x%llf", val); + break; + } case DATA_TYPE_STRING: { char *val; (void) nvpair_value_string(nvp, &val); @@ -583,6 +589,7 @@ nvpair_value_match_regex(nvpair_t *nvp, int ai, case DATA_TYPE_NVLIST: case DATA_TYPE_NVLIST_ARRAY: case DATA_TYPE_BOOLEAN: + case DATA_TYPE_DOUBLE: case DATA_TYPE_UNKNOWN: default: /* diff --git a/usr/src/lib/libnvpair/mapfile-vers b/usr/src/lib/libnvpair/mapfile-vers index fb80a984b1..4ac16f3512 100644 --- a/usr/src/lib/libnvpair/mapfile-vers +++ b/usr/src/lib/libnvpair/mapfile-vers @@ -25,6 +25,13 @@ # ident "%Z%%M% %I% %E% SMI" # +SUNW_1.4 { + global: + nvlist_add_double; + nvlist_lookup_double; + nvpair_value_double; +} SUNW_1.3; + SUNW_1.3 { global: nvlist_exists; |