8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / mdb / common / modules / libtopo / libtopo.c
blob362f22219799afcc05bd7a21bb6d8c6a196b32d3
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 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include <sys/mdb_modapi.h>
29 #include <libelf.h>
30 #include <sys/fm/protocol.h>
31 #include <topo_mod.h>
32 #include <topo_tree.h>
33 #include <topo_module.h>
34 #include <stddef.h>
38 * We use this to keep track of which bucket we're in while walking
39 * the modhash and we also cache the length of the hash
41 static topo_modhash_t tmh;
42 static uint_t hash_idx;
44 static uintptr_t curr_pg;
45 static uint_t is_root;
46 static uint_t verbose;
47 static char *pgrp;
48 static char *tgt_scheme;
49 static char parent[255];
52 * This structure is used by the topo_nodehash walker instances to
53 * keep track of where they're at in the node hash
55 typedef struct tnwalk_state {
56 uint_t hash_idx;
57 topo_nodehash_t hash;
58 topo_nodehash_t *curr_hash;
59 } tnwalk_state_t;
62 static char *stab_lvls[] = {"Internal", "", "Private", "Obsolete", "External",
63 "Unstable", "Evolving", "Stable", "Standard", "Max"};
65 /*ARGSUSED*/
66 static int
67 topo_handle(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
69 char uuid[36], root[36], plat[36], isa[36], machine[36], product[36];
70 topo_hdl_t th;
73 * Read in the structure and then read in all of the string fields from
74 * the target's addr space
76 if (mdb_vread(&th, sizeof (th), addr) != sizeof (th)) {
77 mdb_warn("failed to read topo_hdl_t at %p", addr);
78 return (DCMD_ERR);
81 if (mdb_readstr(uuid, sizeof (uuid), (uintptr_t)th.th_uuid) < 0) {
82 (void) mdb_snprintf(uuid, sizeof (uuid), "<%p>", th.th_uuid);
84 if (mdb_readstr(root, sizeof (root), (uintptr_t)th.th_rootdir) < 0) {
85 (void) mdb_snprintf(root, sizeof (root), "<%p>", th.th_rootdir);
87 if (mdb_readstr(plat, sizeof (plat), (uintptr_t)th.th_platform) < 0) {
88 (void) mdb_snprintf(plat, sizeof (plat), "<%p>",
89 th.th_platform);
91 if (mdb_readstr(isa, sizeof (isa), (uintptr_t)th.th_isa) < 0) {
92 (void) mdb_snprintf(isa, sizeof (isa), "<%p>", th.th_isa);
94 if (mdb_readstr(machine, sizeof (machine), (uintptr_t)th.th_machine)
95 < 0) {
97 (void) mdb_snprintf(machine, sizeof (machine), "<%p>",
98 th.th_machine);
100 if (mdb_readstr(product, sizeof (product), (uintptr_t)th.th_product)
101 < 0) {
103 (void) mdb_snprintf(product, sizeof (product), "<%p>",
104 th.th_product);
108 * Dump it all out in a nice pretty format and keep it to 80 chars wide
110 if (DCMD_HDRSPEC(flags)) {
111 mdb_printf("%<u>%-12s %-36s %-30s%</u>\n", "FIELD", "VALUE",
112 "DESCR");
114 mdb_printf("%-12s 0x%-34p %-30s\n", "th_lock",
115 addr + offsetof(topo_hdl_t, th_lock),
116 "Mutex lock protecting handle");
117 mdb_printf("%-12s %-36s %-30s\n", "th_uuid", uuid,
118 "UUID of the topology snapshot");
119 mdb_printf("%-12s %-36s %-30s\n", "th_rootdir", root,
120 "Root directory of plugin paths");
121 mdb_printf("%-12s %-36s %-30s\n", "th_platform", plat, "Platform name");
122 mdb_printf("%-12s %-36s %-30s\n", "th_isa", isa, "ISA name");
123 mdb_printf("%-12s %-36s %-30s\n", "th_machine", machine,
124 "Machine name");
125 mdb_printf("%-12s %-36s %-30s\n", "th_product", product,
126 "Product name");
127 mdb_printf("%-12s 0x%-34p %-30s\n", "th_di", th.th_di,
128 "Handle to the root of the devinfo tree");
129 mdb_printf("%-12s 0x%-34p %-30s\n", "th_pi", th.th_pi,
130 "Handle to the root of the PROM tree");
131 mdb_printf("%-12s 0x%-34p %-30s\n", "th_modhash", th.th_modhash,
132 "Module hash");
133 mdb_printf("%-12s %-36s %-30s\n", "th_trees", "",
134 "Scheme-specific topo tree list");
135 mdb_printf(" %-12s 0x%-34p %-30s\n", "l_prev", th.th_trees.l_prev,
136 "");
137 mdb_printf(" %-12s 0x%-34p %-30s\n", "l_next", th.th_trees.l_next,
138 "");
139 mdb_printf("%-12s 0x%-34p %-30s\n", "th_alloc", th.th_alloc,
140 "Allocators");
141 mdb_printf("%-12s %-36d %-30s\n", "tm_ernno", th.th_errno, "errno");
142 mdb_printf("%-12s %-36d %-30s\n", "tm_debug", th.th_debug,
143 "Debug mask");
144 mdb_printf("%-12s %-36d %-30s\n", "tm_dbout", th.th_dbout,
145 "Debug channel");
147 return (DCMD_OK);
151 /*ARGSUSED*/
152 static int
153 topo_module(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
155 char name[36], path[36], root[36];
156 topo_mod_t tm;
159 * Read in the structure and then read in all of the string fields from
160 * the target's addr space
162 if (mdb_vread(&tm, sizeof (tm), addr) != sizeof (tm)) {
163 mdb_warn("failed to read topo_mod_t at %p", addr);
164 return (DCMD_ERR);
167 if (mdb_readstr(name, sizeof (name), (uintptr_t)tm.tm_name) < 0) {
168 (void) mdb_snprintf(name, sizeof (name), "<%p>", tm.tm_name);
170 if (mdb_readstr(path, sizeof (path), (uintptr_t)tm.tm_path) < 0) {
171 (void) mdb_snprintf(path, sizeof (path), "<%p>", tm.tm_path);
173 if (mdb_readstr(root, sizeof (root), (uintptr_t)tm.tm_rootdir) < 0) {
174 (void) mdb_snprintf(root, sizeof (root), "<%p>", tm.tm_rootdir);
178 * Dump it all out in a nice pretty format and keep it to 80 chars wide
180 if (DCMD_HDRSPEC(flags)) {
181 mdb_printf("%<u>%-12s %-36s %-30s%</u>\n",
182 "FIELD", "VALUE", "DESCR");
184 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_lock",
185 addr + offsetof(topo_mod_t, tm_lock),
186 "Lock for tm_cv/owner/flags/refs");
187 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_cv",
188 addr + offsetof(topo_mod_t, tm_cv),
189 "Module condition variable");
190 if (tm.tm_busy)
191 mdb_printf("%-12s %-36s %-30s\n", "tm_busy", "TRUE",
192 "Busy indicator");
193 else
194 mdb_printf("%-12s %-36s %-30s\n", "tm_busy", "FALSE",
195 "Busy indicator");
197 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_next", tm.tm_next,
198 "Next module in hash chain");
199 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_hdl", tm.tm_hdl,
200 "Topo handle for this module");
201 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_alloc", tm.tm_alloc,
202 "Allocators");
203 mdb_printf("%-12s %-36s %-30s\n", "tm_name", name,
204 "Basename of module");
205 mdb_printf("%-12s %-36s %-30s\n", "tm_path", path,
206 "Full pathname of module");
207 mdb_printf("%-12s %-36s %-30s\n", "tm_rootdir", root,
208 "Relative root directory of module");
209 mdb_printf("%-12s %-36u %-30s\n", "tm_refs", tm.tm_refs,
210 "Module reference count");
211 mdb_printf("%-12s %-36u %-30s\n", "tm_flags", tm.tm_flags,
212 "Module flags");
213 if (TOPO_MOD_INIT & tm.tm_flags) {
214 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_MOD_INIT",
215 "Module init completed");
217 if (TOPO_MOD_FINI & tm.tm_flags) {
218 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_MOD_FINI",
219 "Module fini completed");
221 if (TOPO_MOD_REG & tm.tm_flags) {
222 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_MOD_REG",
223 "Module registered");
225 if (TOPO_MOD_UNREG & tm.tm_flags) {
226 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_MOD_UNREG",
227 "Module unregistered");
230 mdb_printf("%-12s %-36u %-30s\n", "tm_debug", tm.tm_debug,
231 "Debug printf mask");
232 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_data", tm.tm_data,
233 "Private rtld/builtin data");
234 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_mops", tm.tm_mops,
235 "Module class ops vector");
236 mdb_printf("%-12s 0x%-34p %-30s\n", "tm_info", tm.tm_info,
237 "Module info registered with handle");
238 mdb_printf("%-12s %-36d %-30s\n", "tm_ernno", tm.tm_errno,
239 "Module errno");
241 return (DCMD_OK);
245 /*ARGSUSED*/
246 static int
247 topo_node(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
249 char name[36];
250 tnode_t tn;
252 if (!addr)
253 return (DCMD_ERR);
256 * Read in the structure and then read in all of the string fields from
257 * the target's addr space
259 if (mdb_vread(&tn, sizeof (tn), addr) != sizeof (tn)) {
260 mdb_warn("failed to read tnode_t at %p", addr);
261 return (DCMD_ERR);
264 if (mdb_readstr(name, sizeof (name), (uintptr_t)tn.tn_name) < 0) {
265 (void) mdb_snprintf(name, sizeof (name), "<%p>", tn.tn_name);
269 * Dump it all out in a nice pretty format and keep it to 80 chars wide
271 if (DCMD_HDRSPEC(flags)) {
272 mdb_printf("%<u>%-12s %-36s %-30s%</u>\n",
273 "FIELD", "VALUE", "DESCR");
276 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_lock",
277 addr + offsetof(tnode_t, tn_lock),
278 "Lock protecting node members");
279 mdb_printf("%-12s %-36s %-30s\n", "tn_name", name,
280 "Node name");
281 mdb_printf("%-12s %-36d %-30s\n", "tn_instance", tn.tn_instance,
282 "Node instance");
283 mdb_printf("%-12s %-36d %-30s\n", "tn_state", tn.tn_state,
284 "Node state");
285 if (TOPO_NODE_INIT & tn.tn_state) {
286 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_NODE_INIT", "");
288 if (TOPO_NODE_ROOT & tn.tn_state) {
289 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_NODE_ROOT", "");
291 if (TOPO_NODE_BOUND & tn.tn_state) {
292 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_NODE_BOUND", "");
294 if (TOPO_NODE_LINKED & tn.tn_state) {
295 mdb_printf("%-12s %-36s %-30s\n", "", "TOPO_NODE_LINKED", "");
297 mdb_printf("%-12s %-36d %-30s\n", "tn_fflags", tn.tn_fflags,
298 "FMRI flags");
299 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_parent", tn.tn_parent,
300 "Node parent");
301 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_phash", tn.tn_phash,
302 "Parent hash bucket");
303 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_hdl", tn.tn_hdl,
304 "Topo handle");
305 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_enum", tn.tn_enum,
306 "Enumerator module");
307 mdb_printf("%-12s %-36s %-30s\n", "tn_children", "",
308 "Hash table of child nodes");
309 mdb_printf(" %-12s 0x%-34p\n", "l_prev", tn.tn_children.l_prev);
310 mdb_printf(" %-12s 0x%-34p\n", "l_next", tn.tn_children.l_next);
311 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_pgroups", &(tn.tn_pgroups),
312 "Property group list");
313 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_methods", &(tn.tn_methods),
314 "Registered method list");
315 mdb_printf("%-12s 0x%-34p %-30s\n", "tn_priv", tn.tn_priv,
316 "Private enumerator data");
317 mdb_printf("%-12s %-36d %-30s\n", "tn_refs", tn.tn_refs,
318 "Node reference count");
320 return (DCMD_OK);
323 /*ARGSUSED*/
324 static int
325 find_tree_root(uintptr_t addr, const void *data, void *arg)
327 ttree_t *tree = (ttree_t *)data;
328 char scheme[36];
330 if (mdb_readstr(scheme, sizeof (scheme), (uintptr_t)tree->tt_scheme)
331 < 0) {
332 (void) mdb_snprintf(scheme, sizeof (scheme), "<%p>",
333 tree->tt_scheme);
336 if (strncmp(tgt_scheme, scheme, 36) == 0) {
337 *((tnode_t **)arg) = tree->tt_root;
338 return (WALK_DONE);
340 return (WALK_NEXT);
343 static void
344 dump_propmethod(uintptr_t addr)
346 topo_propmethod_t pm;
347 char mname[32];
349 if (mdb_vread(&pm, sizeof (pm), addr) != sizeof (pm)) {
350 mdb_warn("failed to read topo_propmethod at %p", addr);
351 return;
353 if (mdb_readstr(mname, sizeof (mname), (uintptr_t)pm.tpm_name) < 0) {
354 (void) mdb_snprintf(mname, sizeof (mname), "<%p>", pm.tpm_name);
357 mdb_printf(" method: %-32s version: %-16d args: %p\n",
358 mname, pm.tpm_version, pm.tpm_args);
362 * Dump the given property value. For the actual property values
363 * we dump a pointer to the nvlist which can be decoded using the ::nvlist
364 * dcmd from the libnvpair MDB module
366 /*ARGSUSED*/
367 static int
368 dump_propval(uintptr_t addr, const void *data, void *arg)
370 topo_proplist_t *plistp = (topo_proplist_t *)data;
371 topo_propval_t pval;
372 char name[32], *type;
374 if (mdb_vread(&pval, sizeof (pval), (uintptr_t)plistp->tp_pval)
375 != sizeof (pval)) {
377 mdb_warn("failed to read topo_propval_t at %p",
378 plistp->tp_pval);
379 return (WALK_ERR);
381 if (mdb_readstr(name, sizeof (name), (uintptr_t)pval.tp_name) < 0) {
382 (void) mdb_snprintf(name, sizeof (name), "<%p>", pval.tp_name);
384 switch (pval.tp_type) {
385 case TOPO_TYPE_BOOLEAN: type = "boolean"; break;
386 case TOPO_TYPE_INT32: type = "int32"; break;
387 case TOPO_TYPE_UINT32: type = "uint32"; break;
388 case TOPO_TYPE_INT64: type = "int64"; break;
389 case TOPO_TYPE_UINT64: type = "uint64"; break;
390 case TOPO_TYPE_STRING: type = "string"; break;
391 case TOPO_TYPE_FMRI: type = "fmri"; break;
392 case TOPO_TYPE_INT32_ARRAY: type = "int32[]"; break;
393 case TOPO_TYPE_UINT32_ARRAY: type = "uint32[]"; break;
394 case TOPO_TYPE_INT64_ARRAY: type = "int64[]"; break;
395 case TOPO_TYPE_UINT64_ARRAY: type = "uint64[]"; break;
396 case TOPO_TYPE_STRING_ARRAY: type = "string[]"; break;
397 case TOPO_TYPE_FMRI_ARRAY: type = "fmri[]"; break;
398 default: type = "unknown type";
400 mdb_printf(" %-32s %-16s value: %p\n", name, type, pval.tp_val);
402 if (pval.tp_method != NULL)
403 dump_propmethod((uintptr_t)pval.tp_method);
405 return (WALK_NEXT);
410 * Dumps the contents of the property group.
412 /*ARGSUSED*/
413 static int
414 dump_pgroup(uintptr_t addr, const void *data, void *arg)
416 topo_pgroup_t *pgp = (topo_pgroup_t *)data;
417 topo_ipgroup_info_t ipg;
418 char buf[32];
420 if (mdb_vread(&ipg, sizeof (ipg), (uintptr_t)pgp->tpg_info)
421 != sizeof (ipg)) {
423 mdb_warn("failed to read topo_ipgroup_info_t at %p",
424 pgp->tpg_info);
425 return (WALK_ERR);
427 if (mdb_readstr(buf, sizeof (buf), (uintptr_t)ipg.tpi_name) < 0) {
428 mdb_warn("failed to read string at %p", ipg.tpi_name);
429 return (WALK_ERR);
432 * If this property group is the one we're interested in or if the user
433 * specified the "all" property group, we'll dump it
435 if ((strncmp(pgrp, buf, sizeof (buf)) == 0) ||
436 (strncmp(pgrp, "all", sizeof (buf)) == 0)) {
438 mdb_printf(" group: %-32s version: %d, stability: %s/%s\n",
439 buf, ipg.tpi_version, stab_lvls[ipg.tpi_namestab],
440 stab_lvls[ipg.tpi_datastab]);
442 (void) mdb_pwalk("topo_proplist", dump_propval, NULL, curr_pg);
444 return (WALK_NEXT);
449 * Recursive function to dump the specified node and all of it's children
451 /*ARGSUSED*/
452 static int
453 dump_tnode(uintptr_t addr, const void *data, void *arg)
455 tnode_t node;
456 char pname[255], buf[80], old_pname[255];
458 if (!addr) {
459 return (WALK_NEXT);
462 if (mdb_vread(&node, sizeof (node), addr) != sizeof (node)) {
463 mdb_warn("failed to read tnode_t at %p", addr);
464 return (WALK_ERR);
466 if (mdb_readstr(buf, sizeof (buf), (uintptr_t)node.tn_name) < 0) {
467 (void) mdb_snprintf(buf, sizeof (buf), "<%p>",
468 node.tn_name);
471 if (is_root) {
472 mdb_snprintf(pname, sizeof (pname), "%s", parent);
473 is_root = 0;
474 } else {
475 mdb_snprintf(pname, sizeof (pname), "%s/%s=%u",
476 parent, buf, node.tn_instance);
478 if (verbose)
479 mdb_printf("%s\n tnode_t: %p\n", pname, addr);
480 else
481 mdb_printf("%s\n", pname);
483 mdb_snprintf(old_pname, sizeof (old_pname), "%s", parent);
484 mdb_snprintf(parent, sizeof (parent), "%s", pname);
486 if (pgrp)
487 (void) mdb_pwalk("topo_pgroup", dump_pgroup, NULL, addr);
489 (void) mdb_pwalk("topo_nodehash", dump_tnode, NULL, addr);
490 mdb_snprintf(parent, sizeof (parent), "%s", old_pname);
492 return (WALK_NEXT);
497 * Given a topo_hdl_t *, the topo dcmd dumps the topo tree. The format of the
498 * output is modeled after fmtopo. Like fmtopo, by default, we'll dump the
499 * "hc" scheme tree. The user can optionally specify a different tree via the
500 * "-s <scheme>" option.
502 * Specifying the "-v" option provides more verbose output. Currently it
503 * outputs the tnode_t * addr for each node, which is useful if you want to
504 * dump it with the topo_node dcmd.
506 * The functionality of the "-P" option is similar to fmtopo.
508 /*ARGSUSED*/
509 static int
510 fmtopo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
512 char product[36], *opt_s = NULL, *opt_P = NULL;
513 topo_hdl_t th;
514 tnode_t *tree_root;
515 uint_t opt_v = FALSE;
516 char *def_scheme = "hc";
518 if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &opt_v,
519 's', MDB_OPT_STR, &opt_s, 'P', MDB_OPT_STR, &opt_P, NULL)
520 != argc) {
521 return (DCMD_USAGE);
524 if (opt_s) {
525 tgt_scheme = opt_s;
526 } else {
527 tgt_scheme = def_scheme;
530 pgrp = opt_P;
531 verbose = opt_v;
532 is_root = 1;
535 * Read in the topo_handle and some of its string fields from
536 * the target's addr space
538 if (mdb_vread(&th, sizeof (th), addr) != sizeof (th)) {
539 mdb_warn("failed to read topo_hdl_t at %p", addr);
540 return (DCMD_ERR);
543 if (mdb_readstr(product, sizeof (product), (uintptr_t)th.th_product)
544 < 0) {
546 (void) mdb_snprintf(product, sizeof (product), "<%p>",
547 th.th_product);
550 mdb_snprintf(parent, sizeof (parent),
551 "%s://:product-id=%s", tgt_scheme, product);
554 * Walk the list of topo trees, looking for the one that is for the
555 * scheme we're interested in.
557 tree_root = NULL;
558 mdb_pwalk("topo_tree", find_tree_root, &tree_root, addr);
560 if (! tree_root) {
561 mdb_warn("failed to find a topo tree for scheme %s\n",
562 tgt_scheme);
563 return (DCMD_ERR);
566 return (dump_tnode((uintptr_t)tree_root, NULL, NULL));
570 static int
571 ttree_walk_init(mdb_walk_state_t *wsp)
573 topo_hdl_t th;
575 if (wsp->walk_addr == NULL) {
576 mdb_warn("NULL topo_hdl_t passed in");
577 return (WALK_ERR);
580 if (mdb_vread(&th, sizeof (th), wsp->walk_addr) != sizeof (th)) {
581 mdb_warn("failed to read topo_hdl_t at %p", wsp->walk_addr);
582 return (WALK_ERR);
585 wsp->walk_addr = (uintptr_t)th.th_trees.l_next;
586 wsp->walk_data = mdb_alloc(sizeof (ttree_t), UM_SLEEP);
588 return (WALK_NEXT);
592 static int
593 ttree_walk_step(mdb_walk_state_t *wsp)
595 int rv;
596 ttree_t *tree;
598 if (wsp->walk_addr == NULL)
599 return (WALK_DONE);
601 if (mdb_vread(wsp->walk_data, sizeof (ttree_t), wsp->walk_addr)
602 != sizeof (ttree_t)) {
604 mdb_warn("failed to read ttree_t at %p", wsp->walk_addr);
605 return (WALK_ERR);
608 rv = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
609 wsp->walk_cbdata);
611 tree = (ttree_t *)wsp->walk_data;
612 wsp->walk_addr = (uintptr_t)tree->tt_list.l_next;
614 return (rv);
618 static void
619 ttree_walk_fini(mdb_walk_state_t *wsp)
621 mdb_free(wsp->walk_data, sizeof (ttree_t));
625 static int
626 tmod_walk_init(mdb_walk_state_t *wsp)
628 topo_hdl_t th;
630 if (wsp->walk_addr == NULL) {
631 mdb_warn("NULL topo_hdl_t passed in");
632 return (WALK_ERR);
635 if (mdb_vread(&th, sizeof (th), wsp->walk_addr) != sizeof (th)) {
636 mdb_warn("failed to read topo_hdl_t at %p", wsp->walk_addr);
637 return (WALK_ERR);
640 if (mdb_vread(&tmh, sizeof (topo_modhash_t), (uintptr_t)th.th_modhash)
641 == -1) {
643 mdb_warn("failed to read topo_modhash_t at %p", wsp->walk_addr);
644 return (WALK_DONE);
647 hash_idx = 0;
649 if (mdb_vread(&(wsp->walk_addr), sizeof (uintptr_t *),
650 (uintptr_t)(tmh.mh_hash)) != sizeof (tnode_t *)) {
652 mdb_warn("failed to read %u bytes at %p", sizeof (tnode_t *),
653 tmh.mh_hash);
654 return (WALK_ERR);
657 wsp->walk_data = mdb_alloc(sizeof (topo_mod_t), UM_SLEEP);
659 return (WALK_NEXT);
663 static int
664 tmod_walk_step(mdb_walk_state_t *wsp)
666 int rv;
667 topo_mod_t *tm;
669 if (wsp->walk_addr == NULL)
670 return (WALK_DONE);
672 if (mdb_vread(wsp->walk_data, sizeof (topo_mod_t), wsp->walk_addr)
673 == -1) {
675 mdb_warn("failed to read topo_mod_t at %p", wsp->walk_addr);
676 return (WALK_DONE);
679 rv = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
680 wsp->walk_cbdata);
682 tm = (topo_mod_t *)wsp->walk_data;
684 if (tm->tm_next)
685 wsp->walk_addr = (uintptr_t)tm->tm_next;
686 else if (++hash_idx < tmh.mh_hashlen)
687 if (mdb_vread(&(wsp->walk_addr), sizeof (uintptr_t *),
688 (uintptr_t)(tmh.mh_hash+hash_idx)) != sizeof (tnode_t *)) {
690 mdb_warn("failed to read %u bytes at %p",
691 sizeof (tnode_t *), tmh.mh_hash+hash_idx);
692 return (DCMD_ERR);
694 else
695 wsp->walk_addr = NULL;
697 return (rv);
700 static void
701 tmod_walk_fini(mdb_walk_state_t *wsp)
703 mdb_free(wsp->walk_data, sizeof (topo_mod_t));
707 static int
708 tpg_walk_init(mdb_walk_state_t *wsp)
710 tnode_t node;
712 if (wsp->walk_addr == NULL) {
713 mdb_warn("NULL tnode_t passed in");
714 return (WALK_ERR);
717 if (mdb_vread(&node, sizeof (node), wsp->walk_addr) != sizeof (node)) {
718 mdb_warn("failed to read tnode_t at %p", wsp->walk_addr);
719 return (WALK_ERR);
722 wsp->walk_addr = (uintptr_t)node.tn_pgroups.l_next;
723 wsp->walk_data = mdb_alloc(sizeof (topo_pgroup_t), UM_SLEEP);
725 return (WALK_NEXT);
729 static int
730 tpg_walk_step(mdb_walk_state_t *wsp)
732 int rv;
733 topo_pgroup_t *tpgp;
735 if (wsp->walk_addr == NULL)
736 return (WALK_DONE);
738 if (mdb_vread(wsp->walk_data, sizeof (topo_pgroup_t), wsp->walk_addr)
739 == -1) {
741 mdb_warn("failed to read topo_pgroup_t at %p", wsp->walk_addr);
742 return (WALK_DONE);
745 curr_pg = wsp->walk_addr;
746 rv = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
747 wsp->walk_cbdata);
749 tpgp = (topo_pgroup_t *)wsp->walk_data;
750 wsp->walk_addr = (uintptr_t)tpgp->tpg_list.l_next;
752 return (rv);
756 static void
757 tpg_walk_fini(mdb_walk_state_t *wsp)
759 mdb_free(wsp->walk_data, sizeof (topo_pgroup_t));
763 static int
764 tpl_walk_init(mdb_walk_state_t *wsp)
766 topo_pgroup_t pg;
768 if (wsp->walk_addr == NULL) {
769 mdb_warn("NULL topo_pgroup_t passed in");
770 return (WALK_ERR);
773 if (mdb_vread(&pg, sizeof (pg), wsp->walk_addr) != sizeof (pg)) {
774 mdb_warn("failed to read topo_pgroup_t at %p", wsp->walk_addr);
775 return (WALK_ERR);
778 wsp->walk_addr = (uintptr_t)pg.tpg_pvals.l_next;
779 wsp->walk_data = mdb_alloc(sizeof (topo_proplist_t), UM_SLEEP);
781 return (WALK_NEXT);
785 static int
786 tpl_walk_step(mdb_walk_state_t *wsp)
788 int rv;
789 topo_proplist_t *plp;
791 if (wsp->walk_addr == NULL)
792 return (WALK_DONE);
794 if (mdb_vread(wsp->walk_data, sizeof (topo_proplist_t), wsp->walk_addr)
795 == -1) {
797 mdb_warn("failed to read topo_proplist_t at %p",
798 wsp->walk_addr);
799 return (WALK_DONE);
801 plp = (topo_proplist_t *)wsp->walk_data;
803 rv = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
804 wsp->walk_cbdata);
806 wsp->walk_addr = (uintptr_t)plp->tp_list.l_next;
808 return (rv);
812 static void
813 tpl_walk_fini(mdb_walk_state_t *wsp)
815 mdb_free(wsp->walk_data, sizeof (topo_proplist_t));
819 static int
820 tnh_walk_init(mdb_walk_state_t *wsp)
822 tnode_t node;
823 tnwalk_state_t *state;
825 if (wsp->walk_addr == NULL) {
826 mdb_warn("NULL tnode_t passed in");
827 return (WALK_ERR);
830 if (mdb_vread(&node, sizeof (node), wsp->walk_addr) != sizeof (node)) {
831 mdb_warn("failed to read tnode_t at %p", wsp->walk_addr);
832 return (WALK_ERR);
835 state = mdb_zalloc(sizeof (tnwalk_state_t), UM_SLEEP);
837 state->curr_hash = (topo_nodehash_t *)node.tn_children.l_next;
838 state->hash_idx = 0;
839 wsp->walk_data = state;
841 return (WALK_NEXT);
845 static int
846 tnh_walk_step(mdb_walk_state_t *wsp)
848 tnwalk_state_t *state = wsp->walk_data;
849 int rv, i = state->hash_idx++;
850 tnode_t *npp;
852 if (state->curr_hash == NULL)
853 return (WALK_DONE);
855 if (mdb_vread(&(state->hash), sizeof (topo_nodehash_t),
856 (uintptr_t)state->curr_hash) != sizeof (topo_nodehash_t)) {
858 mdb_warn("failed to read topo_nodehash_t at %p",
859 (uintptr_t)state->curr_hash);
860 return (WALK_ERR);
863 if (mdb_vread(&npp, sizeof (tnode_t *),
864 (uintptr_t)(state->hash.th_nodearr+i)) != sizeof (tnode_t *)) {
866 mdb_warn("failed to read %u bytes at %p", sizeof (tnode_t *),
867 state->hash.th_nodearr+i);
868 return (WALK_ERR);
870 wsp->walk_addr = (uintptr_t)npp;
872 rv = wsp->walk_callback(wsp->walk_addr, state, wsp->walk_cbdata);
874 if (state->hash_idx >= state->hash.th_arrlen) {
876 * move on to the next child hash bucket
878 state->curr_hash =
879 (topo_nodehash_t *)(state->hash.th_list.l_next);
880 state->hash_idx = 0;
883 return (rv);
887 static void
888 tnh_walk_fini(mdb_walk_state_t *wsp)
890 mdb_free(wsp->walk_data, sizeof (tnwalk_state_t));
894 static const mdb_dcmd_t dcmds[] = {
895 { "topo_handle", "", "print contents of a topo handle", topo_handle,
896 NULL },
897 { "topo_module", "", "print contents of a topo module handle",
898 topo_module, NULL },
899 { "topo_node", "", "print contents of a topo node", topo_node, NULL },
900 { "fmtopo", "[-P <pgroup>][-s <scheme>][-v]",
901 "print topology of the given handle", fmtopo, NULL },
902 { NULL }
905 static const mdb_walker_t walkers[] = {
906 { "topo_tree", "walk the tree list for a given topo handle",
907 ttree_walk_init, ttree_walk_step, ttree_walk_fini, NULL },
908 { "topo_module", "walk the module hash for a given topo handle",
909 tmod_walk_init, tmod_walk_step, tmod_walk_fini, NULL },
910 { "topo_pgroup", "walk the property groups for a given topo node",
911 tpg_walk_init, tpg_walk_step, tpg_walk_fini, NULL },
912 { "topo_proplist", "walk the property list for a given property group",
913 tpl_walk_init, tpl_walk_step, tpl_walk_fini, NULL },
914 { "topo_nodehash", "walk the child nodehash for a given topo node",
915 tnh_walk_init, tnh_walk_step, tnh_walk_fini, NULL },
916 { NULL }
919 static const mdb_modinfo_t modinfo = {
920 MDB_API_VERSION, dcmds, walkers
923 const mdb_modinfo_t *
924 _mdb_init(void)
926 return (&modinfo);