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]
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"
32 find_node_by_string_prop(picl_nodehdl_t rooth
, const char *pname
,
33 const char *pval
, picl_nodehdl_t
*nodeh
);
35 compare_string_propval(picl_nodehdl_t nodeh
, const char *pname
,
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.
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
;
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
)) !=
66 "io_dev_label: can't find platform node: %s\n",
67 picl_strerror(status
));
71 node_count
= md_node_count(mdp
);
72 if (node_count
== 0) {
73 pri_debug(LOG_NOTICE
, "io_dev_addlabel: no nodes to "
77 components
= (mde_cookie_t
*)malloc(node_count
*
78 sizeof (mde_cookie_t
));
79 if (components
== NULL
) {
81 "io_dev_addlabel: can't get memory for IO nodes\n");
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
) {
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
) ==
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
);
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
);
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 "
125 nac_size
= strlen(nac
) + 1;
127 if (md_get_prop_str(mdp
, components
[i
], "path", &pri_path
) ==
129 pri_debug(LOG_NOTICE
,
130 "io_add_devlabel: can't get path value for "
131 "device <%s>\n", type
);
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
,
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
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 '/'.
162 if ((q
= strchr((const char *)p
, '/')) != NULL
)
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
174 if ((status
= find_node_by_string_prop(tpn
,
175 PICL_PROP_BUS_ADDR
, (const char *)p
, &tpn
)) !=
177 pri_debug(LOG_NOTICE
,
178 "can't find %s property of <%s> "
180 PICL_PROP_BUS_ADDR
, p
, nac
,
181 picl_strerror(status
));
187 * Note path component for the leaf so we can use
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");
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
,
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",
223 picl_strerror(substatus
));
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
);
238 * These two functions shamelessly stolen from picldevtree.c
242 * Return 1 if this node has this property with the given value.
245 compare_string_propval(picl_nodehdl_t nodeh
, const char *pname
,
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 */
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
);
268 err
= ptree_get_propval(proph
, pvalbuf
, len
);
269 if ((err
== PICL_SUCCESS
) && (strcmp(pvalbuf
, pval
) == 0))
270 return (1); /* prop match */
276 * Search this node's children for the given property.
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
;
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
)
292 if (compare_string_propval(childh
, pname
, pval
)) {
294 return (PICL_SUCCESS
);
297 return (PICL_ENDOFLIST
);