summaryrefslogtreecommitdiffstats
path: root/sys/sun4v/cddl
diff options
context:
space:
mode:
authorkmacy <kmacy@FreeBSD.org>2006-11-24 01:56:46 +0000
committerkmacy <kmacy@FreeBSD.org>2006-11-24 01:56:46 +0000
commitcceb584eb3c30510c29dc942777634c05bbd9434 (patch)
tree089afbeb72a0949952f927f63448aac057edf0d0 /sys/sun4v/cddl
parent9b41c97e919c599add63de6b22acbb6f0ce477ed (diff)
downloadFreeBSD-src-cceb584eb3c30510c29dc942777634c05bbd9434.zip
FreeBSD-src-cceb584eb3c30510c29dc942777634c05bbd9434.tar.gz
move CDDL licensed machine description support routine files to cddl directory
update files.sun4v accordingly
Diffstat (limited to 'sys/sun4v/cddl')
-rw-r--r--sys/sun4v/cddl/mdesc/mdesc_diff.c603
-rw-r--r--sys/sun4v/cddl/mdesc/mdesc_findname.c67
-rw-r--r--sys/sun4v/cddl/mdesc/mdesc_findnodeprop.c76
-rw-r--r--sys/sun4v/cddl/mdesc/mdesc_fini.c48
-rw-r--r--sys/sun4v/cddl/mdesc/mdesc_getbinsize.c46
-rw-r--r--sys/sun4v/cddl/mdesc/mdesc_getgen.c46
-rw-r--r--sys/sun4v/cddl/mdesc/mdesc_getpropdata.c65
-rw-r--r--sys/sun4v/cddl/mdesc/mdesc_getpropstr.c62
-rw-r--r--sys/sun4v/cddl/mdesc/mdesc_getpropval.c68
-rw-r--r--sys/sun4v/cddl/mdesc/mdesc_init_intern.c178
-rw-r--r--sys/sun4v/cddl/mdesc/mdesc_nodecount.c44
-rw-r--r--sys/sun4v/cddl/mdesc/mdesc_rootnode.c44
-rw-r--r--sys/sun4v/cddl/mdesc/mdesc_scandag.c191
13 files changed, 1538 insertions, 0 deletions
diff --git a/sys/sun4v/cddl/mdesc/mdesc_diff.c b/sys/sun4v/cddl/mdesc/mdesc_diff.c
new file mode 100644
index 0000000..4bd2334
--- /dev/null
+++ b/sys/sun4v/cddl/mdesc/mdesc_diff.c
@@ -0,0 +1,603 @@
+/*
+ * 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
+ * $FreeBSD$
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "@(#)mdesc_diff.c 1.1 06/05/16 SMI"
+
+#include <sys/types.h>
+#ifdef _KERNEL
+#include <sys/systm.h>
+#else /* _KERNEL */
+#include <string.h>
+#include <strings.h>
+#endif /* _KERNEL */
+#include <sys/note.h>
+#include <sys/mdesc.h>
+#include <sys/mdesc_impl.h>
+
+#define MDD_FREE_CHECK(mdp, ptr, sz) \
+ do { \
+ if (ptr) mdp->freep(ptr, sz); \
+ _NOTE(CONSTCOND) } while (0)
+
+#define MD_DIFF_MAGIC 0x4D445F4449464621ull /* 'MD_DIFF!' */
+#define MD_DIFF_NOMATCH (-1)
+#define MD_DIFF_MATCH (1)
+
+typedef struct {
+ mde_cookie_t *mdep;
+ uint_t nelem;
+} md_diff_t;
+
+typedef struct {
+ uint64_t mdd_magic;
+ md_diff_t added;
+ md_diff_t removed;
+ md_diff_t match1;
+ md_diff_t match2;
+ void *(*allocp)(size_t);
+ void (*freep)(void *, size_t);
+} md_diff_impl_t;
+
+/*
+ * Internal utility functions
+ */
+static int mdd_scan_for_nodes(md_t *mdp, mde_cookie_t start,
+ char *compnodep, int *countp, mde_cookie_t **nodespp);
+
+static boolean_t mdd_any_dup_nodes(md_impl_t *mdp, md_prop_match_t *pmp,
+ int count, mde_cookie_t *nodesp);
+
+static int mdd_node_list_match(md_impl_t *md1, md_impl_t *md2,
+ md_element_t *match_nodep, mde_cookie_t *match_listp,
+ uint8_t *match_seenp, int start, int end, md_prop_match_t *match_elemsp);
+
+static int mdd_node_compare(md_impl_t *mdap, md_impl_t *mdbp,
+ md_element_t *nodeap, md_element_t *nodebp, md_prop_match_t *match_elemsp);
+
+/*
+ * Given two DAGs and information about how to uniquely identify
+ * the nodes of interest, determine which nodes have been added
+ * to the second MD, removed from the first MD, or exist in both
+ * MDs. This information is recorded and can be accessed using the
+ * opaque cookie returned to the caller.
+ */
+md_diff_cookie_t
+md_diff_init(md_t *md1p, mde_cookie_t start1, md_t *md2p, mde_cookie_t start2,
+ char *compnodep, md_prop_match_t *match_fieldsp)
+{
+ int idx;
+ md_impl_t *md1 = (md_impl_t *)md1p;
+ md_impl_t *md2 = (md_impl_t *)md2p;
+ mde_cookie_t *md1nodesp = NULL;
+ mde_cookie_t *md2nodesp = NULL;
+ int md1count = 0;
+ int md2count = 0;
+ uint8_t *seenp = NULL;
+
+ /* variables used to gather results */
+ md_diff_impl_t *diff_res;
+ mde_cookie_t *mde_add_scr;
+ mde_cookie_t *mde_rem_scr;
+ mde_cookie_t *mde_match1_scr;
+ mde_cookie_t *mde_match2_scr;
+ int nadd = 0;
+ int nrem = 0;
+ int nmatch = 0;
+
+ /* sanity check params */
+ if ((md1p == NULL) || (md2p == NULL))
+ return (MD_INVAL_DIFF_COOKIE);
+
+ if ((start1 == MDE_INVAL_ELEM_COOKIE) ||
+ (start2 == MDE_INVAL_ELEM_COOKIE))
+ return (MD_INVAL_DIFF_COOKIE);
+
+ if ((compnodep == NULL) || (match_fieldsp == NULL))
+ return (MD_INVAL_DIFF_COOKIE);
+
+ /*
+ * Prepare an array of the matching nodes from the first MD.
+ */
+ if (mdd_scan_for_nodes(md1p,
+ start1, compnodep, &md1count, &md1nodesp) == -1)
+ return (MD_INVAL_DIFF_COOKIE);
+
+ /* sanity check that all nodes are unique */
+ if (md1nodesp &&
+ mdd_any_dup_nodes(md1, match_fieldsp, md1count, md1nodesp)) {
+ MDD_FREE_CHECK(md1, md1nodesp, sizeof (mde_cookie_t) *
+ md1count);
+ return (MD_INVAL_DIFF_COOKIE);
+ }
+
+
+ /*
+ * Prepare an array of the matching nodes from the second MD.
+ */
+ if (mdd_scan_for_nodes(md2p,
+ start2, compnodep, &md2count, &md2nodesp) == -1)
+ return (MD_INVAL_DIFF_COOKIE);
+
+ /* sanity check that all nodes are unique */
+ if (md2nodesp &&
+ mdd_any_dup_nodes(md2, match_fieldsp, md2count, md2nodesp)) {
+ MDD_FREE_CHECK(md1, md1nodesp, sizeof (mde_cookie_t) *
+ md1count);
+ MDD_FREE_CHECK(md2, md2nodesp, sizeof (mde_cookie_t) *
+ md2count);
+ return (MD_INVAL_DIFF_COOKIE);
+ }
+
+ /* setup our result structure */
+ diff_res = md1->allocp(sizeof (md_diff_impl_t));
+ bzero(diff_res, sizeof (md_diff_impl_t));
+ diff_res->allocp = md1->allocp;
+ diff_res->freep = md1->freep;
+ diff_res->mdd_magic = MD_DIFF_MAGIC;
+
+ /*
+ * Special cases for empty lists
+ */
+ if ((md1count == 0) && (md2count != 0)) {
+ /* all the nodes found were added */
+ diff_res->added.mdep = md2nodesp;
+ diff_res->added.nelem = md2count;
+ return ((mde_cookie_t)diff_res);
+ }
+
+ if ((md1count != 0) && (md2count == 0)) {
+ /* all the nodes found were removed */
+ diff_res->removed.mdep = md1nodesp;
+ diff_res->removed.nelem = md1count;
+ return ((mde_cookie_t)diff_res);
+ }
+
+ if ((md1count == 0) && (md2count == 0))
+ /* no nodes found */
+ return ((mde_cookie_t)diff_res);
+
+ /*
+ * Both lists have some elements. Allocate some scratch
+ * buffers to sort them into our three categories, added,
+ * removed, and matched pairs.
+ */
+ mde_add_scr = diff_res->allocp(sizeof (mde_cookie_t) * md2count);
+ mde_rem_scr = diff_res->allocp(sizeof (mde_cookie_t) * md1count);
+ mde_match1_scr = diff_res->allocp(sizeof (mde_cookie_t) * md1count);
+ mde_match2_scr = diff_res->allocp(sizeof (mde_cookie_t) * md2count);
+
+ /* array of seen flags only needed for md2 */
+ seenp = (uint8_t *)diff_res->allocp(sizeof (uint8_t) * md2count);
+ bzero(seenp, sizeof (uint8_t) * md2count);
+
+ /*
+ * Make a pass through the md1 node array. Make note of
+ * any nodes not in the md2 array, indicating that they
+ * have been removed. Also keep track of the nodes that
+ * are present in both arrays for the matched pair results.
+ */
+ for (idx = 0; idx < md1count; idx++) {
+
+ md_element_t *elem = &(md1->mdep[md1nodesp[idx]]);
+
+ int match = mdd_node_list_match(md1, md2, elem, md2nodesp,
+ seenp, 0, md2count - 1, match_fieldsp);
+
+ if (match == MD_DIFF_NOMATCH)
+ /* record deleted node */
+ mde_rem_scr[nrem++] = md1nodesp[idx];
+ else {
+ /* record matched node pair */
+ mde_match1_scr[nmatch] = md1nodesp[idx];
+ mde_match2_scr[nmatch] = md2nodesp[match];
+ nmatch++;
+
+ /* mark that this match has been recorded */
+ seenp[match] = 1;
+ }
+ }
+
+ /*
+ * Make a pass through the md2 array. Any nodes that have
+ * not been marked as seen have been added.
+ */
+ for (idx = 0; idx < md2count; idx++) {
+ if (!seenp[idx])
+ /* record added node */
+ mde_add_scr[nadd++] = md2nodesp[idx];
+ }
+
+ /* fill in the added node list */
+ if (nadd) {
+ int addsz = sizeof (mde_cookie_t) * nadd;
+ diff_res->added.mdep = (mde_cookie_t *)diff_res->allocp(addsz);
+
+ bcopy(mde_add_scr, diff_res->added.mdep, addsz);
+
+ diff_res->added.nelem = nadd;
+ }
+
+ /* fill in the removed node list */
+ if (nrem) {
+ int remsz = sizeof (mde_cookie_t) * nrem;
+ diff_res->removed.mdep =
+ (mde_cookie_t *)diff_res->allocp(remsz);
+
+ bcopy(mde_rem_scr, diff_res->removed.mdep, remsz);
+ diff_res->removed.nelem = nrem;
+ }
+
+ /* fill in the matching node lists */
+ if (nmatch) {
+ int matchsz = sizeof (mde_cookie_t) * nmatch;
+ diff_res->match1.mdep =
+ (mde_cookie_t *)diff_res->allocp(matchsz);
+ diff_res->match2.mdep =
+ (mde_cookie_t *)diff_res->allocp(matchsz);
+
+ bcopy(mde_match1_scr, diff_res->match1.mdep, matchsz);
+ bcopy(mde_match2_scr, diff_res->match2.mdep, matchsz);
+ diff_res->match1.nelem = nmatch;
+ diff_res->match2.nelem = nmatch;
+ }
+
+ /* clean up */
+ md1->freep(md1nodesp, sizeof (mde_cookie_t) * md1count);
+ md2->freep(md2nodesp, sizeof (mde_cookie_t) * md2count);
+
+ diff_res->freep(mde_add_scr, sizeof (mde_cookie_t) * md2count);
+ diff_res->freep(mde_rem_scr, sizeof (mde_cookie_t) * md1count);
+ diff_res->freep(mde_match1_scr, sizeof (mde_cookie_t) * md1count);
+ diff_res->freep(mde_match2_scr, sizeof (mde_cookie_t) * md2count);
+
+ diff_res->freep(seenp, sizeof (uint8_t) * md2count);
+
+ return ((md_diff_cookie_t)diff_res);
+}
+
+/*
+ * Returns an array of the nodes added to the second MD in a
+ * previous md_diff_init() call. Returns the number of elements
+ * in the returned array. If the value is zero, the pointer
+ * passed back will be NULL.
+ */
+int
+md_diff_added(md_diff_cookie_t mdd, mde_cookie_t **mde_addedp)
+{
+ md_diff_impl_t *mddp = (md_diff_impl_t *)mdd;
+
+ if ((mddp == NULL) || (mddp->mdd_magic != MD_DIFF_MAGIC))
+ return (-1);
+
+ *mde_addedp = mddp->added.mdep;
+
+ return (mddp->added.nelem);
+}
+
+/*
+ * Returns an array of the nodes removed from the first MD in a
+ * previous md_diff_init() call. Returns the number of elements
+ * in the returned array. If the value is zero, the pointer
+ * passed back will be NULL.
+ */
+int
+md_diff_removed(md_diff_cookie_t mdd, mde_cookie_t **mde_removedp)
+{
+ md_diff_impl_t *mddp = (md_diff_impl_t *)mdd;
+
+ if ((mddp == NULL) || (mddp->mdd_magic != MD_DIFF_MAGIC))
+ return (-1);
+
+ *mde_removedp = mddp->removed.mdep;
+
+ return (mddp->removed.nelem);
+}
+
+/*
+ * Returns a pair of parallel arrays that contain nodes that were
+ * considered matching based on the match criteria passed in to
+ * a previous md_diff_init() call. Returns the number of elements
+ * in the arrays. If the value is zero, both pointers passed back
+ * will be NULL.
+ */
+int
+md_diff_matched(md_diff_cookie_t mdd, mde_cookie_t **mde_match1p,
+ mde_cookie_t **mde_match2p)
+{
+ md_diff_impl_t *mddp = (md_diff_impl_t *)mdd;
+
+ if ((mddp == NULL) || (mddp->mdd_magic != MD_DIFF_MAGIC))
+ return (-1);
+
+ *mde_match1p = mddp->match1.mdep;
+ *mde_match2p = mddp->match2.mdep;
+
+ return (mddp->match1.nelem);
+}
+
+/*
+ * Deallocate any storage used to store results of a previous
+ * md_diff_init() call. Returns 0 on success and -1 on failure.
+ */
+int
+md_diff_fini(md_diff_cookie_t mdd)
+{
+ md_diff_impl_t *mddp = (md_diff_impl_t *)mdd;
+
+ if ((mddp == NULL) || (mddp->mdd_magic != MD_DIFF_MAGIC))
+ return (-1);
+
+ mddp->mdd_magic = 0;
+
+ MDD_FREE_CHECK(mddp, mddp->added.mdep, mddp->added.nelem *
+ sizeof (mde_cookie_t));
+
+ MDD_FREE_CHECK(mddp, mddp->removed.mdep, mddp->removed.nelem *
+ sizeof (mde_cookie_t));
+
+ MDD_FREE_CHECK(mddp, mddp->match1.mdep, mddp->match1.nelem *
+ sizeof (mde_cookie_t));
+
+ MDD_FREE_CHECK(mddp, mddp->match2.mdep, mddp->match2.nelem *
+ sizeof (mde_cookie_t));
+
+ mddp->freep(mddp, sizeof (md_diff_impl_t));
+
+ return (0);
+}
+
+/*
+ * Walk the "fwd" DAG in an MD and return an array of nodes that are
+ * of the specified type. The start param is used to start the walk
+ * from an arbitrary location in the DAG. Returns an array of nodes
+ * as well as a count of the number of nodes in the array. If the
+ * count is zero, the node pointer will be passed back as NULL.
+ *
+ * Returns: 0 success; -1 failure
+ */
+static int
+mdd_scan_for_nodes(md_t *mdp,
+ mde_cookie_t start, char *compnodep, int *countp, mde_cookie_t **nodespp)
+{
+ mde_str_cookie_t cname;
+ mde_str_cookie_t aname;
+ md_impl_t *mdip = (md_impl_t *)mdp;
+
+ if (mdip == NULL)
+ return (-1);
+
+ cname = md_find_name(mdp, compnodep);
+ aname = md_find_name(mdp, "fwd");
+
+ /* get the number of nodes of interest in the DAG */
+ *countp = md_scan_dag(mdp, start, cname, aname, NULL);
+ if (*countp == 0) {
+ *nodespp = NULL;
+ return (0);
+ }
+
+ /* allocate the storage */
+ *nodespp = mdip->allocp(sizeof (mde_cookie_t) * (*countp));
+
+ /* populate our array with the matching nodes */
+ (void) md_scan_dag(mdp, start, cname, aname, *nodespp);
+
+ return (0);
+}
+
+/*
+ * Walk an array of nodes and check if there are any duplicate
+ * nodes. A duplicate is determined based on the specified match
+ * criteria. Returns B_TRUE if there are any duplicates and B_FALSE
+ * otherwise.
+ */
+static boolean_t
+mdd_any_dup_nodes(md_impl_t *mdp, md_prop_match_t *pmp, int count,
+ mde_cookie_t *nodesp)
+{
+ int idx;
+ int match;
+ md_element_t *elem;
+
+ ASSERT(count > 0 || nodesp == NULL);
+
+ for (idx = 0; idx < count; idx++) {
+ elem = &(mdp->mdep[nodesp[idx]]);
+
+ match = mdd_node_list_match(mdp, mdp, elem, nodesp, NULL,
+ idx + 1, count - 1, pmp);
+
+ if (match != MD_DIFF_NOMATCH)
+ return (B_TRUE);
+ }
+
+ return (B_FALSE);
+}
+
+/*
+ * Given a node and a array of nodes, compare the node to all elements
+ * in the specified start-end range of the array. If the node matches
+ * one of the nodes in the array, return the index of that node. Otherwise
+ * return MD_DIFF_NOMATCH.
+ *
+ * The optional seen array parameter can be used to optimize repeated
+ * calls to this function. If the seen array indicates that an element
+ * has already been matched, the full comparison is not necessary.
+ */
+static int
+mdd_node_list_match(md_impl_t *md1, md_impl_t *md2, md_element_t *match_nodep,
+ mde_cookie_t *match_listp, uint8_t *match_seenp, int start, int end,
+ md_prop_match_t *match_elemsp)
+{
+ int match;
+ int idx;
+ md_element_t *elem;
+
+ for (idx = start; idx <= end; idx++) {
+
+ if ((match_seenp != NULL) && (match_seenp[idx]))
+ continue;
+
+ elem = &(md2->mdep[match_listp[idx]]);
+
+ match = mdd_node_compare(md1, md2, match_nodep, elem,
+ match_elemsp);
+ if (match == MD_DIFF_MATCH)
+ return (idx);
+ }
+
+ return (MD_DIFF_NOMATCH);
+}
+
+/*
+ * Given two nodes and a list of properties, compare the nodes.
+ * A match is concluded if both nodes have all of the specified
+ * properties and all the values of those properties are the
+ * same. Returns MD_DIFF_NOMATCH if the nodes do not match and
+ * MD_DIFF_MATCH otherwise.
+ */
+static int
+mdd_node_compare(md_impl_t *mdap, md_impl_t *mdbp, md_element_t *nodeap,
+ md_element_t *nodebp, md_prop_match_t *match_elemsp)
+{
+ md_element_t *ap;
+ md_element_t *bp;
+ boolean_t nodea_interest;
+ boolean_t nodeb_interest;
+ int idx;
+
+ /* make sure we are starting at the beginning of the nodes */
+ if ((MDE_TAG(nodeap) != MDET_NODE) || (MDE_TAG(nodebp) != MDET_NODE))
+ return (MD_DIFF_NOMATCH);
+
+ for (idx = 0; match_elemsp[idx].type != MDET_LIST_END; idx++) {
+
+ int type;
+
+ nodea_interest = B_FALSE;
+ nodeb_interest = B_FALSE;
+
+ type = match_elemsp[idx].type;
+
+ /*
+ * Check node A for the property of interest
+ */
+ for (ap = nodeap; MDE_TAG(ap) != MDET_NODE_END; ap++) {
+ char *elemname;
+
+ if (MDE_TAG(ap) != type)
+ continue;
+
+ elemname = mdap->namep + MDE_NAME(ap);
+
+ if (strcmp(elemname, match_elemsp[idx].namep) == 0) {
+ /* found the property of interest */
+ nodea_interest = B_TRUE;
+ break;
+ }
+ }
+
+ /* node A is not of interest */
+ if (!nodea_interest)
+ return (MD_DIFF_NOMATCH);
+
+ /*
+ * Check node B for the property of interest
+ */
+ for (bp = nodebp; MDE_TAG(bp) != MDET_NODE_END; bp++) {
+ char *elemname;
+
+ if (MDE_TAG(bp) != type)
+ continue;
+
+ elemname = mdbp->namep + MDE_NAME(bp);
+
+ if (strcmp(elemname, match_elemsp[idx].namep) == 0) {
+ nodeb_interest = B_TRUE;
+ break;
+ }
+ }
+
+ /* node B is not of interest */
+ if (!nodeb_interest)
+ return (MD_DIFF_NOMATCH);
+
+ /*
+ * Both nodes have the property of interest. The
+ * nodes are not a match unless the value of that
+ * property match
+ */
+ switch (type) {
+ case MDET_PROP_VAL:
+ if (MDE_PROP_VALUE(ap) != MDE_PROP_VALUE(bp))
+ return (MD_DIFF_NOMATCH);
+ break;
+
+ case MDET_PROP_STR: {
+ char *stra = (char *)(mdap->datap +
+ MDE_PROP_DATA_OFFSET(ap));
+ char *strb = (char *)(mdbp->datap +
+ MDE_PROP_DATA_OFFSET(bp));
+
+ if (strcmp(stra, strb) != 0)
+ return (MD_DIFF_NOMATCH);
+ break;
+ }
+
+ case MDET_PROP_DAT: {
+
+ caddr_t dataa;
+ caddr_t datab;
+
+ if (MDE_PROP_DATA_LEN(ap) != MDE_PROP_DATA_LEN(bp))
+ return (MD_DIFF_NOMATCH);
+
+ dataa = (caddr_t)(mdap->datap +
+ MDE_PROP_DATA_OFFSET(ap));
+ datab = (caddr_t)(mdbp->datap +
+ MDE_PROP_DATA_OFFSET(bp));
+
+ if (memcmp(dataa, datab, MDE_PROP_DATA_LEN(ap)) != 0)
+ return (MD_DIFF_NOMATCH);
+
+ break;
+ }
+
+ default:
+ /* unsupported prop type */
+ return (MD_DIFF_NOMATCH);
+ }
+ }
+
+ /*
+ * All the specified properties exist in both
+ * nodes and have the same value. The two nodes
+ * match.
+ */
+
+ return (MD_DIFF_MATCH);
+}
diff --git a/sys/sun4v/cddl/mdesc/mdesc_findname.c b/sys/sun4v/cddl/mdesc/mdesc_findname.c
new file mode 100644
index 0000000..c961619
--- /dev/null
+++ b/sys/sun4v/cddl/mdesc/mdesc_findname.c
@@ -0,0 +1,67 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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
+ * $FreeBSD$
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+
+#include <sys/types.h>
+
+#ifdef _KERNEL
+#include <sys/systm.h>
+#else
+#include <strings.h>
+#endif
+
+#include <machine/cddl/mdesc.h>
+#include <machine/cddl/mdesc_impl.h>
+
+mde_str_cookie_t
+md_find_name(md_t *ptr, char *namep)
+{
+ int idx, len;
+ md_impl_t *mdp;
+
+ mdp = (md_impl_t *)ptr;
+
+ /*
+ * At some point init should build a local hash table to
+ * speed these name searches ... for now use brute force
+ * because the machien descriptions are so small anyway.
+ */
+
+ for (idx = 0; idx < mdp->name_blk_size; idx += len) {
+ char *p;
+
+ p = &(mdp->namep[idx]);
+
+ len = strlen(p)+1;
+
+ if (strcmp(p, namep) == 0)
+ return ((mde_str_cookie_t)idx);
+ }
+
+ return (MDE_INVAL_STR_COOKIE);
+}
diff --git a/sys/sun4v/cddl/mdesc/mdesc_findnodeprop.c b/sys/sun4v/cddl/mdesc/mdesc_findnodeprop.c
new file mode 100644
index 0000000..558b976
--- /dev/null
+++ b/sys/sun4v/cddl/mdesc/mdesc_findnodeprop.c
@@ -0,0 +1,76 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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
+ * $FreeBSD$
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <machine/cddl/mdesc.h>
+#include <machine/cddl/mdesc_impl.h>
+
+mde_cookie_t
+md_find_node_prop(md_impl_t *mdp,
+ mde_cookie_t node,
+ mde_str_cookie_t prop_name,
+ int tag_type)
+{
+ md_element_t *mdep;
+ int idx;
+
+ if (node == MDE_INVAL_ELEM_COOKIE ||
+ prop_name == MDE_INVAL_STR_COOKIE) {
+ return (MDE_INVAL_ELEM_COOKIE);
+ }
+
+ idx = (int)node;
+ mdep = &(mdp->mdep[idx]);
+
+ /* Skip over any empty elements */
+ while (MDE_TAG(mdep) == MDET_NULL) {
+ idx++;
+ mdep++;
+ }
+
+ /* see if cookie is infact a node */
+ if (MDE_TAG(mdep) != MDET_NODE) {
+ return (MDE_INVAL_ELEM_COOKIE);
+ }
+
+ /*
+ * Simply walk the elements in the node
+ * looking for a property with a matching name.
+ */
+
+ for (idx++, mdep++; MDE_TAG(mdep) != MDET_NODE_END; idx++, mdep++) {
+ if (MDE_TAG(mdep) == tag_type) {
+ if (MDE_NAME(mdep) == prop_name) {
+ return ((mde_cookie_t)idx);
+ }
+ }
+ }
+
+ return (MDE_INVAL_ELEM_COOKIE); /* no such property name */
+}
diff --git a/sys/sun4v/cddl/mdesc/mdesc_fini.c b/sys/sun4v/cddl/mdesc/mdesc_fini.c
new file mode 100644
index 0000000..ff32ce8
--- /dev/null
+++ b/sys/sun4v/cddl/mdesc/mdesc_fini.c
@@ -0,0 +1,48 @@
+/*
+ * 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
+ * $FreeBSD$
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "@(#)mdesc_fini.c 1.4 06/05/16 SMI"
+
+#include <sys/types.h>
+#include <sys/mdesc.h>
+#include <sys/mdesc_impl.h>
+
+/*
+ * Cleanup the internal MD structure. Does not
+ * deallocate the buffer holding the MD.
+ */
+int
+md_fini(md_t *ptr)
+{
+ md_impl_t *mdp;
+
+ mdp = (md_impl_t *)ptr;
+
+ mdp->freep(mdp, sizeof (md_impl_t));
+
+ return (0);
+}
diff --git a/sys/sun4v/cddl/mdesc/mdesc_getbinsize.c b/sys/sun4v/cddl/mdesc/mdesc_getbinsize.c
new file mode 100644
index 0000000..c3e2386
--- /dev/null
+++ b/sys/sun4v/cddl/mdesc/mdesc_getbinsize.c
@@ -0,0 +1,46 @@
+/*
+ * 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
+ * $FreeBSD$
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "@(#)mdesc_getbinsize.c 1.1 06/05/16 SMI"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mdesc.h>
+#include <sys/mdesc_impl.h>
+
+size_t
+md_get_bin_size(md_t *ptr)
+{
+ md_impl_t *mdp;
+
+ mdp = (md_impl_t *)ptr;
+
+ if (mdp == NULL)
+ return (0);
+
+ return (mdp->size);
+}
diff --git a/sys/sun4v/cddl/mdesc/mdesc_getgen.c b/sys/sun4v/cddl/mdesc/mdesc_getgen.c
new file mode 100644
index 0000000..7d1ad51
--- /dev/null
+++ b/sys/sun4v/cddl/mdesc/mdesc_getgen.c
@@ -0,0 +1,46 @@
+/*
+ * 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
+ * $FreeBSD$
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "@(#)mdesc_getgen.c 1.1 06/05/16 SMI"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mdesc.h>
+#include <sys/mdesc_impl.h>
+
+uint64_t
+md_get_gen(md_t *ptr)
+{
+ md_impl_t *mdp;
+
+ mdp = (md_impl_t *)ptr;
+
+ if (mdp == NULL)
+ return (MDESC_INVAL_GEN);
+
+ return (mdp->gen);
+}
diff --git a/sys/sun4v/cddl/mdesc/mdesc_getpropdata.c b/sys/sun4v/cddl/mdesc/mdesc_getpropdata.c
new file mode 100644
index 0000000..199a436
--- /dev/null
+++ b/sys/sun4v/cddl/mdesc/mdesc_getpropdata.c
@@ -0,0 +1,65 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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
+ * $FreeBSD$
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "@(#)mdesc_getpropdata.c 1.2 05/06/08 SMI"
+
+#include <sys/types.h>
+#include <sys/mdesc.h>
+#include <sys/mdesc_impl.h>
+
+int
+md_get_prop_data(md_t *ptr, mde_cookie_t node, char *namep,
+ uint8_t **datap, int *lenp)
+{
+ mde_str_cookie_t prop_name;
+ md_impl_t *mdp;
+ mde_cookie_t elem;
+
+ mdp = (md_impl_t *)ptr;
+
+ if (node == MDE_INVAL_ELEM_COOKIE) {
+ return (-1);
+ }
+
+ prop_name = md_find_name(ptr, namep);
+ if (prop_name == MDE_INVAL_STR_COOKIE) {
+ return (-1);
+ }
+
+ elem = md_find_node_prop(mdp, node, prop_name, MDET_PROP_DAT);
+
+ if (elem != MDE_INVAL_ELEM_COOKIE) {
+ md_element_t *mdep;
+ mdep = &(mdp->mdep[(int)elem]);
+
+ *lenp = (int)MDE_PROP_DATA_LEN(mdep);
+ *datap = mdp->datap+(int)MDE_PROP_DATA_OFFSET(mdep);
+ return (0);
+ }
+
+ return (-1); /* no such property name */
+}
diff --git a/sys/sun4v/cddl/mdesc/mdesc_getpropstr.c b/sys/sun4v/cddl/mdesc/mdesc_getpropstr.c
new file mode 100644
index 0000000..61f9c30
--- /dev/null
+++ b/sys/sun4v/cddl/mdesc/mdesc_getpropstr.c
@@ -0,0 +1,62 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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
+ * $FreeBSD$
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <machine/cddl/mdesc.h>
+#include <machine/cddl/mdesc_impl.h>
+
+int
+md_get_prop_str(md_t *ptr, mde_cookie_t node, char *namep, char **strp)
+{
+ mde_str_cookie_t prop_name;
+ md_impl_t *mdp;
+ mde_cookie_t elem;
+
+ mdp = (md_impl_t *)ptr;
+
+ if (node == MDE_INVAL_ELEM_COOKIE) {
+ return (-1);
+ }
+
+ prop_name = md_find_name(ptr, namep);
+ if (prop_name == MDE_INVAL_STR_COOKIE) {
+ return (-1);
+ }
+
+ elem = md_find_node_prop(mdp, node, prop_name, MDET_PROP_STR);
+
+ if (elem != MDE_INVAL_ELEM_COOKIE) {
+ md_element_t *mdep;
+ mdep = &(mdp->mdep[(int)elem]);
+
+ *strp = (char *)(mdp->datap+
+ MDE_PROP_DATA_OFFSET(mdep));
+ return (0);
+ }
+
+ return (-1); /* no such property name */
+}
diff --git a/sys/sun4v/cddl/mdesc/mdesc_getpropval.c b/sys/sun4v/cddl/mdesc/mdesc_getpropval.c
new file mode 100644
index 0000000..3a17d5c
--- /dev/null
+++ b/sys/sun4v/cddl/mdesc/mdesc_getpropval.c
@@ -0,0 +1,68 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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
+ * $FreeBSD$
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#include <sys/types.h>
+#ifdef _KERNEL
+#include <sys/systm.h>
+#else
+#include <strings.h>
+#endif
+
+#include <machine/cddl/mdesc.h>
+#include <machine/cddl/mdesc_impl.h>
+
+int
+md_get_prop_val(md_t *ptr, mde_cookie_t node, char *namep, uint64_t *valp)
+{
+ mde_str_cookie_t prop_name;
+ md_impl_t *mdp;
+ mde_cookie_t elem;
+
+ mdp = (md_impl_t *)ptr;
+
+ if (node == MDE_INVAL_ELEM_COOKIE) {
+ return (-1);
+ }
+
+ prop_name = md_find_name(ptr, namep);
+ if (prop_name == MDE_INVAL_STR_COOKIE) {
+ return (-1);
+ }
+
+ elem = md_find_node_prop(mdp, node, prop_name, MDET_PROP_VAL);
+
+ if (elem != MDE_INVAL_ELEM_COOKIE) {
+ md_element_t *mdep;
+ mdep = &(mdp->mdep[(int)elem]);
+
+ *valp = MDE_PROP_VALUE(mdep);
+ return (0);
+ }
+
+ return (-1); /* no such property name */
+}
diff --git a/sys/sun4v/cddl/mdesc/mdesc_init_intern.c b/sys/sun4v/cddl/mdesc/mdesc_init_intern.c
new file mode 100644
index 0000000..dd5973e
--- /dev/null
+++ b/sys/sun4v/cddl/mdesc/mdesc_init_intern.c
@@ -0,0 +1,178 @@
+/*
+ * 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
+ * $FreeBSD$
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <machine/cddl/mdesc.h>
+#include <machine/cddl/mdesc_impl.h>
+
+md_t *
+md_init_intern(uint64_t *ptr, void *(*allocp)(size_t),
+ void (*freep)(void *, size_t))
+{
+ md_impl_t *mdp;
+ int idx;
+ int count;
+ int done;
+ uint64_t gen;
+ mde_str_cookie_t root_name;
+
+ /*
+ * Very basic checkup for alignment to avoid
+ * bus error issues.
+ */
+ if ((((uintptr_t)ptr) & 7) != 0)
+ return (NULL);
+
+ mdp = (md_impl_t *)allocp(sizeof (md_impl_t));
+
+ if (mdp == NULL)
+ return (NULL);
+
+ mdp->allocp = allocp;
+ mdp->freep = freep;
+
+ mdp->caddr = (char *)ptr;
+
+ /*
+ * setup internal structures
+ */
+
+ mdp->headerp = (md_header_t *)mdp->caddr;
+
+ if (mdtoh32(mdp->headerp->transport_version) != MD_TRANSPORT_VERSION) {
+ goto cleanup_nohash;
+ }
+
+ mdp->node_blk_size = mdtoh32(mdp->headerp->node_blk_sz);
+ mdp->name_blk_size = mdtoh32(mdp->headerp->name_blk_sz);
+ mdp->data_blk_size = mdtoh32(mdp->headerp->data_blk_sz);
+
+ mdp->size = MD_HEADER_SIZE + mdp->node_blk_size +
+ mdp->name_blk_size + mdp->data_blk_size;
+
+ mdp->mdep = (md_element_t *)(mdp->caddr + MD_HEADER_SIZE);
+ mdp->namep = (char *)(mdp->caddr + MD_HEADER_SIZE + mdp->node_blk_size);
+ mdp->datap = (uint8_t *)(mdp->caddr + MD_HEADER_SIZE +
+ mdp->name_blk_size + mdp->node_blk_size);
+
+ mdp->root_node = MDE_INVAL_ELEM_COOKIE;
+
+
+ /*
+ * Should do a lot more sanity checking here.
+ */
+
+ /*
+ * Should initialize a name hash here if we intend to use one
+ */
+
+ /*
+ * Setup to find the root node
+ */
+ root_name = md_find_name((md_t *)mdp, "root");
+ if (root_name == MDE_INVAL_STR_COOKIE) {
+ goto cleanup;
+ }
+
+ /*
+ * One more property we need is the count of nodes in the
+ * DAG, not just the number of elements.
+ *
+ * We try and pickup the root node along the way here.
+ */
+
+ for (done = 0, idx = 0, count = 0; !done; ) {
+ md_element_t *np;
+
+ np = &(mdp->mdep[idx]);
+
+ switch (MDE_TAG(np)) {
+ case MDET_LIST_END:
+ done = 1;
+ break;
+
+ case MDET_NODE:
+ if (root_name == MDE_NAME(np)) {
+ if (mdp->root_node != MDE_INVAL_ELEM_COOKIE) {
+ /* Gah .. more than one root */
+ goto cleanup;
+ }
+ mdp->root_node = (mde_cookie_t)idx;
+ }
+ idx = MDE_PROP_INDEX(np);
+ count++;
+ break;
+
+ default:
+ idx++; /* ignore */
+ }
+ }
+
+ /*
+ * Ensure there is a root node
+ */
+ if (mdp->root_node == MDE_INVAL_ELEM_COOKIE) {
+ goto cleanup;
+ }
+
+ /*
+ * Register the counts
+ */
+
+ mdp->element_count = idx + 1; /* include LIST_END */
+ mdp->node_count = count;
+
+ /*
+ * Final sanity check that everything adds up
+ */
+ if (mdp->element_count != (mdp->node_blk_size / MD_ELEMENT_SIZE))
+ goto cleanup;
+
+ mdp->md_magic = LIBMD_MAGIC;
+
+ /*
+ * Setup MD generation
+ */
+ if (md_get_prop_val((md_t *)mdp, mdp->root_node,
+ "md-generation#", &gen) != 0)
+ mdp->gen = MDESC_INVAL_GEN;
+ else
+ mdp->gen = gen;
+
+ return ((md_t *)mdp);
+
+cleanup:
+ /*
+ * Clean up here - including a name hash if
+ * we build one.
+ */
+
+cleanup_nohash:
+ mdp->freep(mdp, sizeof (md_impl_t));
+ return (NULL);
+}
diff --git a/sys/sun4v/cddl/mdesc/mdesc_nodecount.c b/sys/sun4v/cddl/mdesc/mdesc_nodecount.c
new file mode 100644
index 0000000..1c0376d
--- /dev/null
+++ b/sys/sun4v/cddl/mdesc/mdesc_nodecount.c
@@ -0,0 +1,44 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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
+ * $FreeBSD$
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#include <sys/types.h>
+#include <machine/cddl/mdesc.h>
+#include <machine/cddl/mdesc_impl.h>
+
+int
+md_node_count(md_t *ptr)
+{
+ md_impl_t *mdp;
+
+ mdp = (md_impl_t *)ptr;
+
+ if (mdp->md_magic != LIBMD_MAGIC)
+ return (-1);
+
+ return (mdp->node_count);
+}
diff --git a/sys/sun4v/cddl/mdesc/mdesc_rootnode.c b/sys/sun4v/cddl/mdesc/mdesc_rootnode.c
new file mode 100644
index 0000000..2e4437a
--- /dev/null
+++ b/sys/sun4v/cddl/mdesc/mdesc_rootnode.c
@@ -0,0 +1,44 @@
+/*
+ * 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
+ * $FreeBSD$
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#include <sys/types.h>
+#include <machine/cddl/mdesc.h>
+#include <machine/cddl/mdesc_impl.h>
+
+mde_cookie_t
+md_root_node(md_t *ptr)
+{
+ md_impl_t *mdp;
+
+ mdp = (md_impl_t *)ptr;
+
+ if (mdp->md_magic != LIBMD_MAGIC)
+ return (MDE_INVAL_ELEM_COOKIE);
+
+ return (mdp->root_node);
+}
diff --git a/sys/sun4v/cddl/mdesc/mdesc_scandag.c b/sys/sun4v/cddl/mdesc/mdesc_scandag.c
new file mode 100644
index 0000000..4d7716a
--- /dev/null
+++ b/sys/sun4v/cddl/mdesc/mdesc_scandag.c
@@ -0,0 +1,191 @@
+/*
+ * 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
+ * $FreeBSD$
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#ifdef _KERNEL
+#include <sys/systm.h>
+#else
+#include <string.h>
+#include <strings.h>
+#endif
+
+#include <machine/cddl/mdesc.h>
+#include <machine/cddl/mdesc_impl.h>
+
+static int
+mdl_scan_dag(md_impl_t *mdp,
+ int nodeidx,
+ mde_str_cookie_t node_cookie,
+ mde_str_cookie_t arc_cookie,
+ uint8_t *dseenp,
+ int *idxp,
+ mde_cookie_t *stashp,
+ int level);
+
+
+int
+md_scan_dag(md_t *ptr,
+ mde_cookie_t startnode,
+ mde_str_cookie_t node_name_cookie,
+ mde_str_cookie_t arc_name_cookie,
+ mde_cookie_t *stashp)
+{
+ int res;
+ int idx;
+ uint8_t *seenp;
+ md_impl_t *mdp;
+ int start;
+
+ mdp = (md_impl_t *)ptr;
+
+ /*
+ * Possible the caller was lazy and didn't check the
+ * validitiy of either the node name or the arc name
+ * on calling ... in which case fail to find any
+ * nodes.
+ * This is distinct, from a fail (-1) since we return
+ * that nothing was found.
+ */
+
+ if (node_name_cookie == MDE_INVAL_STR_COOKIE ||
+ arc_name_cookie == MDE_INVAL_STR_COOKIE) return 0;
+
+ /*
+ * if we want to start at the top, start at index 0
+ */
+
+ start = (int)startnode;
+ if (start == MDE_INVAL_ELEM_COOKIE) start = 0;
+
+ /*
+ * Scan from the start point until the first node.
+ */
+ while (MDE_TAG(&mdp->mdep[start]) == MDET_NULL) start++;
+
+ /*
+ * This was a bogus start point if no node found
+ */
+ if (MDE_TAG(&mdp->mdep[start]) != MDET_NODE) {
+ return (-1); /* illegal start node specified */
+ }
+
+ /*
+ * Allocate a recursion mask on the local stack fail
+ * if we can't allocate the recursion detection.
+ */
+ seenp = (uint8_t *)mdp->allocp(mdp->element_count);
+ if (seenp == NULL)
+ return (-1);
+ (void) memset(seenp, 0, mdp->element_count);
+
+ /*
+ * Now build the list of requested nodes.
+ */
+ idx = 0;
+ res = mdl_scan_dag(mdp, start,
+ node_name_cookie, arc_name_cookie,
+ seenp, &idx, stashp, 0);
+
+ mdp->freep(seenp, mdp->element_count);
+
+ return (res >= 0 ? idx : res);
+}
+
+
+
+
+
+static int
+mdl_scan_dag(md_impl_t *mdp,
+ int nodeidx,
+ mde_str_cookie_t node_name_cookie,
+ mde_str_cookie_t arc_name_cookie,
+ uint8_t *seenp,
+ int *idxp,
+ mde_cookie_t *stashp,
+ int level)
+{
+ md_element_t *mdep;
+
+ mdep = &(mdp->mdep[nodeidx]);
+
+ /* see if cookie is infact a node */
+ if (MDE_TAG(mdep) != MDET_NODE)
+ return (-1);
+
+ /* have we been here before ? */
+ if (seenp[nodeidx])
+ return (0);
+ seenp[nodeidx] = 1;
+
+ /* is this node of the type we seek ? */
+
+#ifdef DEBUG_LIBMDESC
+ {
+ int x;
+ for (x = 0; x < level; x++)
+ printf("-");
+ printf("%d (%s)\n", nodeidx, (char *)(mdp->datap + MDE_NAME(mdep)));
+ }
+#endif
+
+ if (MDE_NAME(mdep) == node_name_cookie) {
+ /* record the node in the list and keep searching */
+ if (stashp != NULL) {
+ stashp[*idxp] = (mde_cookie_t)nodeidx;
+ }
+ (*idxp)++;
+#ifdef DEBUG_LIBMDESC
+ printf("\t* %d\n", *idxp);
+#endif
+ }
+
+ /*
+ * Simply walk the elements in the node.
+ * if we find a matching arc, then recursively call
+ * the subordinate looking for a match
+ */
+
+ for (mdep++; MDE_TAG(mdep) != MDET_NODE_END; mdep++) {
+ if (MDE_TAG(mdep) == MDET_PROP_ARC &&
+ MDE_NAME(mdep) == arc_name_cookie) {
+ int res;
+
+ res = mdl_scan_dag(mdp,
+ (int)mdep->d.prop_idx,
+ node_name_cookie,
+ arc_name_cookie,
+ seenp, idxp, stashp, level+1);
+
+ if (res == -1)
+ return (res);
+ }
+ }
+
+ return (0);
+}
OpenPOWER on IntegriCloud