]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/sun4v/cddl/mdesc/mdesc_scandag.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / sun4v / cddl / mdesc / mdesc_scandag.c
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  * $FreeBSD$
21  */
22
23 /*
24  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27
28 #include <sys/types.h>
29 #include <sys/param.h>
30 #ifdef _KERNEL
31 #include <sys/systm.h>
32 #else
33 #include <string.h>
34 #include <strings.h>
35 #endif
36
37 #include <machine/cddl/mdesc.h>
38 #include <machine/cddl/mdesc_impl.h>
39
40 static int
41 mdl_scan_dag(md_impl_t *mdp,
42         int nodeidx,
43         mde_str_cookie_t node_cookie,
44         mde_str_cookie_t arc_cookie,
45         uint8_t *dseenp,
46         int *idxp,
47         mde_cookie_t *stashp,
48         int level);
49
50
51 int
52 md_scan_dag(md_t *ptr,
53         mde_cookie_t startnode,
54         mde_str_cookie_t node_name_cookie,
55         mde_str_cookie_t arc_name_cookie,
56         mde_cookie_t *stashp)
57 {
58         int     res;
59         int     idx;
60         uint8_t *seenp;
61         md_impl_t *mdp;
62         int     start;
63
64         mdp = (md_impl_t *)ptr;
65
66         /*
67          * Possible the caller was lazy and didn't check the
68          * validitiy of either the node name or the arc name
69          * on calling ... in which case fail to find any
70          * nodes.
71          * This is distinct, from a fail (-1) since we return
72          * that nothing was found.
73          */
74
75         if (node_name_cookie == MDE_INVAL_STR_COOKIE ||
76                 arc_name_cookie == MDE_INVAL_STR_COOKIE) return 0;
77
78         /*
79          * if we want to start at the top, start at index 0
80          */
81
82         start = (int)startnode;
83         if (start == MDE_INVAL_ELEM_COOKIE) start = 0;
84
85         /*
86          * Scan from the start point until the first node.
87          */
88         while (MDE_TAG(&mdp->mdep[start]) == MDET_NULL) start++;
89
90         /*
91          * This was a bogus start point if no node found
92          */
93         if (MDE_TAG(&mdp->mdep[start]) != MDET_NODE) {
94                 return (-1);    /* illegal start node specified */
95         }
96
97         /*
98          * Allocate a recursion mask on the local stack fail
99          * if we can't allocate the recursion detection.
100          */
101         seenp = (uint8_t *)mdp->allocp(mdp->element_count);
102         if (seenp == NULL)
103                 return (-1);
104         (void) memset(seenp, 0, mdp->element_count);
105
106         /*
107          * Now build the list of requested nodes.
108          */
109         idx = 0;
110         res = mdl_scan_dag(mdp, start,
111                 node_name_cookie, arc_name_cookie,
112                 seenp, &idx, stashp, 0);
113
114         mdp->freep(seenp, mdp->element_count);
115
116         return (res >= 0 ? idx : res);
117 }
118
119
120
121
122
123 static int
124 mdl_scan_dag(md_impl_t *mdp,
125         int nodeidx,
126         mde_str_cookie_t node_name_cookie,
127         mde_str_cookie_t arc_name_cookie,
128         uint8_t *seenp,
129         int *idxp,
130         mde_cookie_t *stashp,
131         int level)
132 {
133         md_element_t *mdep;
134
135         mdep = &(mdp->mdep[nodeidx]);
136
137         /* see if cookie is infact a node */
138         if (MDE_TAG(mdep) != MDET_NODE)
139                 return (-1);
140
141         /* have we been here before ? */
142         if (seenp[nodeidx])
143                 return (0);
144         seenp[nodeidx] = 1;
145
146         /* is this node of the type we seek ? */
147
148 #ifdef  DEBUG_LIBMDESC
149         {
150         int x;
151         for (x = 0; x < level; x++)
152                 printf("-");
153         printf("%d (%s)\n", nodeidx, (char *)(mdp->datap + MDE_NAME(mdep)));
154         }
155 #endif
156
157         if (MDE_NAME(mdep) == node_name_cookie) {
158                 /* record the node in the list and keep searching */
159                 if (stashp != NULL) {
160                         stashp[*idxp] = (mde_cookie_t)nodeidx;
161                 }
162                 (*idxp)++;
163 #ifdef  DEBUG_LIBMDESC
164                 printf("\t* %d\n", *idxp);
165 #endif
166         }
167
168         /*
169          * Simply walk the elements in the node.
170          * if we find a matching arc, then recursively call
171          * the subordinate looking for a match
172          */
173
174         for (mdep++; MDE_TAG(mdep) != MDET_NODE_END; mdep++) {
175                 if (MDE_TAG(mdep) == MDET_PROP_ARC &&
176                         MDE_NAME(mdep) == arc_name_cookie) {
177                         int res;
178
179                         res = mdl_scan_dag(mdp,
180                             (int)mdep->d.prop_idx,
181                             node_name_cookie,
182                             arc_name_cookie,
183                             seenp, idxp, stashp, level+1);
184
185                         if (res == -1)
186                                 return (res);
187                 }
188         }
189
190         return (0);
191 }