8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / picl / plugins / sun4v / pri / io_dev_label.c
blob2d942bc46dbc59c573c4b4924e5e006a7e94384f
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include "priplugin.h"
31 static int
32 find_node_by_string_prop(picl_nodehdl_t rooth, const char *pname,
33 const char *pval, picl_nodehdl_t *nodeh);
34 static int
35 compare_string_propval(picl_nodehdl_t nodeh, const char *pname,
36 const char *pval);
39 * Gather IO device nodes from the PRI and use the info to
40 * find the corresponding nodes in PICL's device tree, insert
41 * a Label into the devtree containing the "nac" from the PRI,
42 * and add a reference property to the corresponding fru tree node.
44 void
45 io_dev_addlabel(md_t *mdp)
47 int status, substatus, i, node_count, component_count, busaddr_match;
48 int type_size, nac_size;
49 picl_nodehdl_t platnode, tpn;
50 char busaddr[PICL_PROPNAMELEN_MAX], *p, *q;
51 char path[PICL_PROPNAMELEN_MAX];
52 mde_cookie_t *components, md_rootnode;
53 char *type, *nac, *pri_path, *saved_path;
55 if (mdp == NULL)
56 return;
58 md_rootnode = md_root_node(mdp);
61 * Find and remember the roots of the /frutree and /platform trees.
63 if ((status = ptree_get_node_by_path(PLATFORM_PATH, &platnode)) !=
64 PICL_SUCCESS) {
65 pri_debug(LOG_NOTICE,
66 "io_dev_label: can't find platform node: %s\n",
67 picl_strerror(status));
68 return;
71 node_count = md_node_count(mdp);
72 if (node_count == 0) {
73 pri_debug(LOG_NOTICE, "io_dev_addlabel: no nodes to "
74 "process\n");
75 return;
77 components = (mde_cookie_t *)malloc(node_count *
78 sizeof (mde_cookie_t));
79 if (components == NULL) {
80 pri_debug(LOG_NOTICE,
81 "io_dev_addlabel: can't get memory for IO nodes\n");
82 return;
85 component_count = md_scan_dag(mdp, md_rootnode,
86 md_find_name(mdp, "component"),
87 md_find_name(mdp, "fwd"), components);
89 for (i = 0; i < component_count; ++i) {
90 tpn = platnode;
93 * Try to fetch the "type" as a string or as "data" until we
94 * can agree on what its tag type should be.
96 if (md_get_prop_str(mdp, components[i], "type", &type) ==
97 -1) {
98 if (md_get_prop_data(mdp, components[i], "type",
99 (uint8_t **)&type, &type_size)) {
100 pri_debug(LOG_NOTICE, "io_add_devlabel: "
101 "can't get type for component %d\n", i);
102 continue;
107 * Isolate components of type "io".
109 if (strcmp((const char *)type, "io")) {
110 pri_debug(LOG_NOTICE,
111 "io_add_devlabel: skipping component %d with "
112 "type %s\n", i, type);
113 continue;
117 * Now get the nac and raw path from the PRI.
119 if (md_get_prop_str(mdp, components[i], "nac", &nac) == -1) {
120 pri_debug(LOG_NOTICE,
121 "io_add_devlabel: can't get nac value for device "
122 "<%s>\n", type);
123 continue;
124 } else
125 nac_size = strlen(nac) + 1;
127 if (md_get_prop_str(mdp, components[i], "path", &pri_path) ==
128 -1) {
129 pri_debug(LOG_NOTICE,
130 "io_add_devlabel: can't get path value for "
131 "device <%s>\n", type);
132 continue;
135 (void) strlcpy(path, pri_path, sizeof (path));
137 pri_debug(LOG_NOTICE, "io_add_devlabel: processing component "
138 "%d, type <%s>, nac <%s>, path <%s>\n", i, type, nac,
139 path);
142 * This loop visits each path component where those
143 * components are delimited with '/' and '@' characters.
144 * Each path component is a search key into the /platform
145 * tree; we're looking to match the bus-addr field of
146 * a node if that field is defined. If each path component
147 * matches up then we now have the corresponding device
148 * path for that IO device. Add a Label property to the
149 * leaf node.
151 for (busaddr_match = 1, p = q = (char *)path; q; p = q + 1) {
154 * Isolate the bus address for this node by skipping
155 * over the first delimiter if present and writing
156 * a NUL character over the next '/'.
158 if (*p == '/')
159 ++p;
160 if (*p == '@')
161 ++p;
162 if ((q = strchr((const char *)p, '/')) != NULL)
163 *q = '\0';
166 * See if there's a match, at this level only, in the
167 * device tree. We cannot skip generations in the
168 * device tree, which is why we're not doing a
169 * recursive search for bus-addr. bus-addr must
170 * be found at each node along the way. By doing
171 * this we'll stay in sync with the path components
172 * in the PRI.
174 if ((status = find_node_by_string_prop(tpn,
175 PICL_PROP_BUS_ADDR, (const char *)p, &tpn)) !=
176 PICL_SUCCESS) {
177 pri_debug(LOG_NOTICE,
178 "can't find %s property of <%s> "
179 "for nac %s: %s\n",
180 PICL_PROP_BUS_ADDR, p, nac,
181 picl_strerror(status));
182 busaddr_match = 0;
183 break;
187 * Note path component for the leaf so we can use
188 * it below.
190 saved_path = p;
194 * We could not drill down through the bus-addrs, so skip this
195 * device and move on to the next.
197 if (busaddr_match == 0) {
198 pri_debug(LOG_NOTICE, "io_add_devlabel: no matching "
199 "bus-addr path for this nac - skipping\n");
200 continue;
203 nac_size = strlen((const char *)nac) + 1;
206 * This loop adds a Label property to all the functions
207 * on the device we matched from the PRI path.
209 for (status = PICL_SUCCESS; status == PICL_SUCCESS;
210 status = ptree_get_propval_by_name(tpn,
211 PICL_PROP_PEER, &tpn, sizeof (picl_nodehdl_t))) {
213 * Add Labels to peers that have the same bus-addr
214 * value (ignoring the function numbers.)
216 if ((substatus = ptree_get_propval_by_name(tpn,
217 PICL_PROP_BUS_ADDR,
218 busaddr, sizeof (busaddr))) != PICL_SUCCESS) {
219 pri_debug(LOG_NOTICE,
220 "io_add_device: can't get %s "
221 "property from picl devtree: %s\n",
222 PICL_PROP_BUS_ADDR,
223 picl_strerror(substatus));
224 } else {
225 if (strncmp(busaddr, saved_path,
226 PICL_PROPNAMELEN_MAX) == 0) {
227 add_md_prop(tpn, nac_size,
228 PICL_PROP_LABEL, nac,
229 PICL_PTYPE_CHARSTRING);
234 free(components);
238 * These two functions shamelessly stolen from picldevtree.c
242 * Return 1 if this node has this property with the given value.
244 static int
245 compare_string_propval(picl_nodehdl_t nodeh, const char *pname,
246 const char *pval)
248 char *pvalbuf;
249 int err;
250 int len;
251 ptree_propinfo_t pinfo;
252 picl_prophdl_t proph;
254 err = ptree_get_prop_by_name(nodeh, pname, &proph);
255 if (err != PICL_SUCCESS) /* prop doesn't exist */
256 return (0);
258 err = ptree_get_propinfo(proph, &pinfo);
259 if (pinfo.piclinfo.type != PICL_PTYPE_CHARSTRING)
260 return (0); /* not string prop */
262 len = strlen(pval) + 1;
264 pvalbuf = alloca(len);
265 if (pvalbuf == NULL)
266 return (0);
268 err = ptree_get_propval(proph, pvalbuf, len);
269 if ((err == PICL_SUCCESS) && (strcmp(pvalbuf, pval) == 0))
270 return (1); /* prop match */
272 return (0);
276 * Search this node's children for the given property.
278 static int
279 find_node_by_string_prop(picl_nodehdl_t rooth, const char *pname,
280 const char *pval, picl_nodehdl_t *nodeh)
282 picl_nodehdl_t childh;
283 int err;
285 for (err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &childh,
286 sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND;
287 err = ptree_get_propval_by_name(childh, PICL_PROP_PEER,
288 &childh, sizeof (picl_nodehdl_t))) {
289 if (err != PICL_SUCCESS)
290 return (err);
292 if (compare_string_propval(childh, pname, pval)) {
293 *nodeh = childh;
294 return (PICL_SUCCESS);
297 return (PICL_ENDOFLIST);