17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
552cac543Sramat * Common Development and Distribution License (the "License").
652cac543Sramat * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*8451e9c3SGavin Maltby * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate #include <sys/types.h>
267c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
277c478bd9Sstevel@tonic-gate #include <sys/dditypes.h>
287c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
297c478bd9Sstevel@tonic-gate #include <sys/ddifm.h>
307c478bd9Sstevel@tonic-gate #include <sys/ddipropdefs.h>
317c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
327c478bd9Sstevel@tonic-gate #include <sys/hwconf.h>
337c478bd9Sstevel@tonic-gate #include <sys/stat.h>
347c478bd9Sstevel@tonic-gate #include <errno.h>
357c478bd9Sstevel@tonic-gate #include <sys/sunmdi.h>
367c478bd9Sstevel@tonic-gate #include <sys/mdi_impldefs.h>
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate #include <ctype.h>
397c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
407c478bd9Sstevel@tonic-gate #include <mdb/mdb_ks.h>
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate #include "nvpair.h"
4326947304SEvan Yan #include "devinfo.h"
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate #define DEVINFO_TREE_INDENT 4 /* Indent for devs one down in tree */
467c478bd9Sstevel@tonic-gate #define DEVINFO_PROP_INDENT 4 /* Indent for properties */
477c478bd9Sstevel@tonic-gate #define DEVINFO_PROPLIST_INDENT 8 /* Indent for properties lists */
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate /*
507c478bd9Sstevel@tonic-gate * devinfo node state map. Used by devinfo() and devinfo_audit().
517c478bd9Sstevel@tonic-gate * Long words are deliberately truncated so that output
527c478bd9Sstevel@tonic-gate * fits in 80 column with 64-bit addresses.
537c478bd9Sstevel@tonic-gate */
547c478bd9Sstevel@tonic-gate static const char *const di_state[] = {
557c478bd9Sstevel@tonic-gate "DS_INVAL",
567c478bd9Sstevel@tonic-gate "DS_PROTO",
577c478bd9Sstevel@tonic-gate "DS_LINKED",
587c478bd9Sstevel@tonic-gate "DS_BOUND",
597c478bd9Sstevel@tonic-gate "DS_INITIA",
607c478bd9Sstevel@tonic-gate "DS_PROBED",
617c478bd9Sstevel@tonic-gate "DS_ATTACH",
627c478bd9Sstevel@tonic-gate "DS_READY",
637c478bd9Sstevel@tonic-gate "?"
647c478bd9Sstevel@tonic-gate };
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate #define DI_STATE_MAX ((sizeof (di_state) / sizeof (char *)) - 1)
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate void
prtconf_help(void)697c478bd9Sstevel@tonic-gate prtconf_help(void)
707c478bd9Sstevel@tonic-gate {
717c478bd9Sstevel@tonic-gate mdb_printf("Prints the devinfo tree from a given node.\n"
727c478bd9Sstevel@tonic-gate "Without the address of a \"struct devinfo\" given, "
737c478bd9Sstevel@tonic-gate "prints from the root;\n"
747c478bd9Sstevel@tonic-gate "with an address, prints the parents of, "
757c478bd9Sstevel@tonic-gate "and all children of, that address.\n\n"
767c478bd9Sstevel@tonic-gate "Switches:\n"
777c478bd9Sstevel@tonic-gate " -v be verbose - print device property lists\n"
787c478bd9Sstevel@tonic-gate " -p only print the ancestors of the given node\n"
797c478bd9Sstevel@tonic-gate " -c only print the children of the given node\n");
807c478bd9Sstevel@tonic-gate }
817c478bd9Sstevel@tonic-gate
827c478bd9Sstevel@tonic-gate void
devinfo_help(void)837c478bd9Sstevel@tonic-gate devinfo_help(void)
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate mdb_printf("Switches:\n"
867c478bd9Sstevel@tonic-gate " -q be quiet - don't print device property lists\n"
877c478bd9Sstevel@tonic-gate " -s print summary of dev_info structures\n");
887c478bd9Sstevel@tonic-gate }
897c478bd9Sstevel@tonic-gate
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate /*
927c478bd9Sstevel@tonic-gate * Devinfo walker.
937c478bd9Sstevel@tonic-gate */
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate typedef struct {
967c478bd9Sstevel@tonic-gate /*
977c478bd9Sstevel@tonic-gate * The "struct dev_info" must be the first thing in this structure.
987c478bd9Sstevel@tonic-gate */
997c478bd9Sstevel@tonic-gate struct dev_info din_dev;
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate /*
1027c478bd9Sstevel@tonic-gate * This is for the benefit of prtconf().
1037c478bd9Sstevel@tonic-gate */
1047c478bd9Sstevel@tonic-gate int din_depth;
1057c478bd9Sstevel@tonic-gate } devinfo_node_t;
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate typedef struct devinfo_parents_walk_data {
1087c478bd9Sstevel@tonic-gate devinfo_node_t dip_node;
1097c478bd9Sstevel@tonic-gate #define dip_dev dip_node.din_dev
1107c478bd9Sstevel@tonic-gate #define dip_depth dip_node.din_depth
1117c478bd9Sstevel@tonic-gate struct dev_info *dip_end;
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate /*
1147c478bd9Sstevel@tonic-gate * The following three elements are for walking the parents of a node:
1157c478bd9Sstevel@tonic-gate * "dip_base_depth" is the depth of the given node from the root.
1167c478bd9Sstevel@tonic-gate * This starts at 1 (if we're walking devinfo_root), because
1177c478bd9Sstevel@tonic-gate * it's the size of the dip_parent_{nodes,addresses} arrays,
1187c478bd9Sstevel@tonic-gate * and has to include the given node.
1197c478bd9Sstevel@tonic-gate * "dip_parent_nodes" is a collection of the parent node structures,
1207c478bd9Sstevel@tonic-gate * already read in via mdb_vread(). dip_parent_nodes[0] is the
1217c478bd9Sstevel@tonic-gate * root, dip_parent_nodes[1] is a child of the root, etc.
1227c478bd9Sstevel@tonic-gate * "dip_parent_addresses" holds the vaddrs of all the parent nodes.
1237c478bd9Sstevel@tonic-gate */
1247c478bd9Sstevel@tonic-gate int dip_base_depth;
1257c478bd9Sstevel@tonic-gate devinfo_node_t *dip_parent_nodes;
1267c478bd9Sstevel@tonic-gate uintptr_t *dip_parent_addresses;
1277c478bd9Sstevel@tonic-gate } devinfo_parents_walk_data_t;
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate int
devinfo_parents_walk_init(mdb_walk_state_t * wsp)1307c478bd9Sstevel@tonic-gate devinfo_parents_walk_init(mdb_walk_state_t *wsp)
1317c478bd9Sstevel@tonic-gate {
1327c478bd9Sstevel@tonic-gate devinfo_parents_walk_data_t *dip;
1337c478bd9Sstevel@tonic-gate uintptr_t addr;
13414ef2b2fSdmick uintptr_t devinfo_root; /* Address of root of devinfo tree */
1357c478bd9Sstevel@tonic-gate int i;
1367c478bd9Sstevel@tonic-gate
13714ef2b2fSdmick if (mdb_readvar(&devinfo_root, "top_devinfo") == -1) {
13814ef2b2fSdmick mdb_warn("failed to read 'top_devinfo'");
13914ef2b2fSdmick return (NULL);
14014ef2b2fSdmick }
14114ef2b2fSdmick
1427c478bd9Sstevel@tonic-gate if (wsp->walk_addr == NULL)
1437c478bd9Sstevel@tonic-gate wsp->walk_addr = devinfo_root;
1447c478bd9Sstevel@tonic-gate addr = wsp->walk_addr;
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate dip = mdb_alloc(sizeof (devinfo_parents_walk_data_t), UM_SLEEP);
1477c478bd9Sstevel@tonic-gate wsp->walk_data = dip;
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate dip->dip_end = (struct dev_info *)wsp->walk_addr;
1507c478bd9Sstevel@tonic-gate dip->dip_depth = 0;
1517c478bd9Sstevel@tonic-gate dip->dip_base_depth = 1;
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate do {
1547c478bd9Sstevel@tonic-gate if (mdb_vread(&dip->dip_dev, sizeof (dip->dip_dev),
1557c478bd9Sstevel@tonic-gate addr) == -1) {
1567c478bd9Sstevel@tonic-gate mdb_warn("failed to read devinfo at %p", addr);
1577c478bd9Sstevel@tonic-gate mdb_free(dip, sizeof (devinfo_parents_walk_data_t));
1587c478bd9Sstevel@tonic-gate wsp->walk_data = NULL;
1597c478bd9Sstevel@tonic-gate return (WALK_ERR);
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate addr = (uintptr_t)dip->dip_dev.devi_parent;
1627c478bd9Sstevel@tonic-gate if (addr != 0)
1637c478bd9Sstevel@tonic-gate dip->dip_base_depth++;
1647c478bd9Sstevel@tonic-gate } while (addr != 0);
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate addr = wsp->walk_addr;
1677c478bd9Sstevel@tonic-gate
1687c478bd9Sstevel@tonic-gate dip->dip_parent_nodes = mdb_alloc(
1697c478bd9Sstevel@tonic-gate dip->dip_base_depth * sizeof (devinfo_node_t), UM_SLEEP);
1707c478bd9Sstevel@tonic-gate dip->dip_parent_addresses = mdb_alloc(
1717c478bd9Sstevel@tonic-gate dip->dip_base_depth * sizeof (uintptr_t), UM_SLEEP);
1727c478bd9Sstevel@tonic-gate for (i = dip->dip_base_depth - 1; i >= 0; i--) {
1737c478bd9Sstevel@tonic-gate if (mdb_vread(&dip->dip_parent_nodes[i].din_dev,
1747c478bd9Sstevel@tonic-gate sizeof (struct dev_info), addr) == -1) {
1757c478bd9Sstevel@tonic-gate mdb_warn("failed to read devinfo at %p", addr);
1767c478bd9Sstevel@tonic-gate return (WALK_ERR);
1777c478bd9Sstevel@tonic-gate }
1787c478bd9Sstevel@tonic-gate dip->dip_parent_nodes[i].din_depth = i;
1797c478bd9Sstevel@tonic-gate dip->dip_parent_addresses[i] = addr;
1807c478bd9Sstevel@tonic-gate addr = (uintptr_t)
1817c478bd9Sstevel@tonic-gate dip->dip_parent_nodes[i].din_dev.devi_parent;
1827c478bd9Sstevel@tonic-gate }
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate return (WALK_NEXT);
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate int
devinfo_parents_walk_step(mdb_walk_state_t * wsp)1887c478bd9Sstevel@tonic-gate devinfo_parents_walk_step(mdb_walk_state_t *wsp)
1897c478bd9Sstevel@tonic-gate {
1907c478bd9Sstevel@tonic-gate devinfo_parents_walk_data_t *dip = wsp->walk_data;
1917c478bd9Sstevel@tonic-gate int status;
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate if (dip->dip_depth == dip->dip_base_depth)
1947c478bd9Sstevel@tonic-gate return (WALK_DONE);
1957c478bd9Sstevel@tonic-gate
1967c478bd9Sstevel@tonic-gate status = wsp->walk_callback(
1977c478bd9Sstevel@tonic-gate dip->dip_parent_addresses[dip->dip_depth],
1987c478bd9Sstevel@tonic-gate &dip->dip_parent_nodes[dip->dip_depth],
1997c478bd9Sstevel@tonic-gate wsp->walk_cbdata);
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate dip->dip_depth++;
2027c478bd9Sstevel@tonic-gate return (status);
2037c478bd9Sstevel@tonic-gate }
2047c478bd9Sstevel@tonic-gate
2057c478bd9Sstevel@tonic-gate void
devinfo_parents_walk_fini(mdb_walk_state_t * wsp)2067c478bd9Sstevel@tonic-gate devinfo_parents_walk_fini(mdb_walk_state_t *wsp)
2077c478bd9Sstevel@tonic-gate {
2087c478bd9Sstevel@tonic-gate devinfo_parents_walk_data_t *dip = wsp->walk_data;
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate mdb_free(dip->dip_parent_nodes,
2117c478bd9Sstevel@tonic-gate dip->dip_base_depth * sizeof (devinfo_node_t));
2127c478bd9Sstevel@tonic-gate mdb_free(dip->dip_parent_addresses,
2137c478bd9Sstevel@tonic-gate dip->dip_base_depth * sizeof (uintptr_t));
2147c478bd9Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (devinfo_parents_walk_data_t));
2157c478bd9Sstevel@tonic-gate }
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate
2187c478bd9Sstevel@tonic-gate typedef struct devinfo_children_walk_data {
2197c478bd9Sstevel@tonic-gate devinfo_node_t dic_node;
2207c478bd9Sstevel@tonic-gate #define dic_dev dic_node.din_dev
2217c478bd9Sstevel@tonic-gate #define dic_depth dic_node.din_depth
2227c478bd9Sstevel@tonic-gate struct dev_info *dic_end;
2237c478bd9Sstevel@tonic-gate int dic_print_first_node;
2247c478bd9Sstevel@tonic-gate } devinfo_children_walk_data_t;
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate int
devinfo_children_walk_init(mdb_walk_state_t * wsp)2277c478bd9Sstevel@tonic-gate devinfo_children_walk_init(mdb_walk_state_t *wsp)
2287c478bd9Sstevel@tonic-gate {
2297c478bd9Sstevel@tonic-gate devinfo_children_walk_data_t *dic;
23014ef2b2fSdmick uintptr_t devinfo_root; /* Address of root of devinfo tree */
23114ef2b2fSdmick
23214ef2b2fSdmick if (mdb_readvar(&devinfo_root, "top_devinfo") == -1) {
23314ef2b2fSdmick mdb_warn("failed to read 'top_devinfo'");
23414ef2b2fSdmick return (NULL);
23514ef2b2fSdmick }
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate if (wsp->walk_addr == NULL)
2387c478bd9Sstevel@tonic-gate wsp->walk_addr = devinfo_root;
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate dic = mdb_alloc(sizeof (devinfo_children_walk_data_t), UM_SLEEP);
2417c478bd9Sstevel@tonic-gate wsp->walk_data = dic;
2427c478bd9Sstevel@tonic-gate dic->dic_end = (struct dev_info *)wsp->walk_addr;
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate /*
2457c478bd9Sstevel@tonic-gate * This could be set by devinfo_walk_init().
2467c478bd9Sstevel@tonic-gate */
2477c478bd9Sstevel@tonic-gate if (wsp->walk_arg != NULL) {
2487c478bd9Sstevel@tonic-gate dic->dic_depth = (*(int *)wsp->walk_arg - 1);
2497c478bd9Sstevel@tonic-gate dic->dic_print_first_node = 0;
2507c478bd9Sstevel@tonic-gate } else {
2517c478bd9Sstevel@tonic-gate dic->dic_depth = 0;
2527c478bd9Sstevel@tonic-gate dic->dic_print_first_node = 1;
2537c478bd9Sstevel@tonic-gate }
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate return (WALK_NEXT);
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate int
devinfo_children_walk_step(mdb_walk_state_t * wsp)2597c478bd9Sstevel@tonic-gate devinfo_children_walk_step(mdb_walk_state_t *wsp)
2607c478bd9Sstevel@tonic-gate {
2617c478bd9Sstevel@tonic-gate devinfo_children_walk_data_t *dic = wsp->walk_data;
2627c478bd9Sstevel@tonic-gate struct dev_info *v;
2637c478bd9Sstevel@tonic-gate devinfo_node_t *cur;
2647c478bd9Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr;
2657c478bd9Sstevel@tonic-gate int status = WALK_NEXT;
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate if (wsp->walk_addr == NULL)
2687c478bd9Sstevel@tonic-gate return (WALK_DONE);
2697c478bd9Sstevel@tonic-gate
2707c478bd9Sstevel@tonic-gate if (mdb_vread(&dic->dic_dev, sizeof (dic->dic_dev), addr) == -1) {
2717c478bd9Sstevel@tonic-gate mdb_warn("failed to read devinfo at %p", addr);
2727c478bd9Sstevel@tonic-gate return (WALK_DONE);
2737c478bd9Sstevel@tonic-gate }
2747c478bd9Sstevel@tonic-gate cur = &dic->dic_node;
2757c478bd9Sstevel@tonic-gate
2767c478bd9Sstevel@tonic-gate if (dic->dic_print_first_node == 0)
2777c478bd9Sstevel@tonic-gate dic->dic_print_first_node = 1;
2787c478bd9Sstevel@tonic-gate else
2797c478bd9Sstevel@tonic-gate status = wsp->walk_callback(addr, cur, wsp->walk_cbdata);
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate /*
2827c478bd9Sstevel@tonic-gate * "v" is always a virtual address pointer,
2837c478bd9Sstevel@tonic-gate * i.e. can't be deref'ed.
2847c478bd9Sstevel@tonic-gate */
2857c478bd9Sstevel@tonic-gate v = (struct dev_info *)addr;
2867c478bd9Sstevel@tonic-gate
2877c478bd9Sstevel@tonic-gate if (dic->dic_dev.devi_child != NULL) {
2887c478bd9Sstevel@tonic-gate v = dic->dic_dev.devi_child;
2897c478bd9Sstevel@tonic-gate dic->dic_depth++;
2907c478bd9Sstevel@tonic-gate } else if (dic->dic_dev.devi_sibling != NULL && v != dic->dic_end) {
2917c478bd9Sstevel@tonic-gate v = dic->dic_dev.devi_sibling;
2927c478bd9Sstevel@tonic-gate } else {
2937c478bd9Sstevel@tonic-gate while (v != NULL && v != dic->dic_end &&
2947c478bd9Sstevel@tonic-gate dic->dic_dev.devi_sibling == NULL) {
2957c478bd9Sstevel@tonic-gate v = dic->dic_dev.devi_parent;
2967c478bd9Sstevel@tonic-gate if (v == NULL)
2977c478bd9Sstevel@tonic-gate break;
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate mdb_vread(&dic->dic_dev,
3007c478bd9Sstevel@tonic-gate sizeof (struct dev_info), (uintptr_t)v);
3017c478bd9Sstevel@tonic-gate dic->dic_depth--;
3027c478bd9Sstevel@tonic-gate }
3037c478bd9Sstevel@tonic-gate if (v != NULL && v != dic->dic_end)
3047c478bd9Sstevel@tonic-gate v = dic->dic_dev.devi_sibling;
3057c478bd9Sstevel@tonic-gate if (v == dic->dic_end)
3067c478bd9Sstevel@tonic-gate v = NULL; /* Done */
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)v;
3107c478bd9Sstevel@tonic-gate return (status);
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate void
devinfo_children_walk_fini(mdb_walk_state_t * wsp)3147c478bd9Sstevel@tonic-gate devinfo_children_walk_fini(mdb_walk_state_t *wsp)
3157c478bd9Sstevel@tonic-gate {
3167c478bd9Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (devinfo_children_walk_data_t));
3177c478bd9Sstevel@tonic-gate }
3187c478bd9Sstevel@tonic-gate
3197c478bd9Sstevel@tonic-gate typedef struct devinfo_walk_data {
3207c478bd9Sstevel@tonic-gate mdb_walk_state_t diw_parent, diw_child;
3217c478bd9Sstevel@tonic-gate enum { DIW_PARENT, DIW_CHILD, DIW_DONE } diw_mode;
3227c478bd9Sstevel@tonic-gate } devinfo_walk_data_t;
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate int
devinfo_walk_init(mdb_walk_state_t * wsp)3257c478bd9Sstevel@tonic-gate devinfo_walk_init(mdb_walk_state_t *wsp)
3267c478bd9Sstevel@tonic-gate {
3277c478bd9Sstevel@tonic-gate devinfo_walk_data_t *diw;
3287c478bd9Sstevel@tonic-gate devinfo_parents_walk_data_t *dip;
3297c478bd9Sstevel@tonic-gate
3307c478bd9Sstevel@tonic-gate diw = mdb_alloc(sizeof (devinfo_walk_data_t), UM_SLEEP);
3317c478bd9Sstevel@tonic-gate diw->diw_parent = *wsp;
3327c478bd9Sstevel@tonic-gate diw->diw_child = *wsp;
3337c478bd9Sstevel@tonic-gate wsp->walk_data = diw;
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate diw->diw_mode = DIW_PARENT;
3367c478bd9Sstevel@tonic-gate
3377c478bd9Sstevel@tonic-gate if (devinfo_parents_walk_init(&diw->diw_parent) == -1) {
3387c478bd9Sstevel@tonic-gate mdb_free(diw, sizeof (devinfo_walk_data_t));
3397c478bd9Sstevel@tonic-gate return (WALK_ERR);
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate
3427c478bd9Sstevel@tonic-gate /*
3437c478bd9Sstevel@tonic-gate * This is why the "devinfo" walker needs to be marginally
3447c478bd9Sstevel@tonic-gate * complicated - the child walker needs this initialization
3457c478bd9Sstevel@tonic-gate * data, and the best way to get it is out of the parent walker.
3467c478bd9Sstevel@tonic-gate */
3477c478bd9Sstevel@tonic-gate dip = diw->diw_parent.walk_data;
3487c478bd9Sstevel@tonic-gate diw->diw_child.walk_arg = &dip->dip_base_depth;
3497c478bd9Sstevel@tonic-gate
3507c478bd9Sstevel@tonic-gate if (devinfo_children_walk_init(&diw->diw_child) == -1) {
3517c478bd9Sstevel@tonic-gate devinfo_parents_walk_fini(&diw->diw_parent);
3527c478bd9Sstevel@tonic-gate mdb_free(diw, sizeof (devinfo_walk_data_t));
3537c478bd9Sstevel@tonic-gate return (WALK_ERR);
3547c478bd9Sstevel@tonic-gate }
3557c478bd9Sstevel@tonic-gate
3567c478bd9Sstevel@tonic-gate return (WALK_NEXT);
3577c478bd9Sstevel@tonic-gate }
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate int
devinfo_walk_step(mdb_walk_state_t * wsp)3607c478bd9Sstevel@tonic-gate devinfo_walk_step(mdb_walk_state_t *wsp)
3617c478bd9Sstevel@tonic-gate {
3627c478bd9Sstevel@tonic-gate devinfo_walk_data_t *diw = wsp->walk_data;
3637c478bd9Sstevel@tonic-gate int status = WALK_NEXT;
3647c478bd9Sstevel@tonic-gate
3657c478bd9Sstevel@tonic-gate if (diw->diw_mode == DIW_PARENT) {
3667c478bd9Sstevel@tonic-gate status = devinfo_parents_walk_step(&diw->diw_parent);
3677c478bd9Sstevel@tonic-gate if (status != WALK_NEXT) {
3687c478bd9Sstevel@tonic-gate /*
3697c478bd9Sstevel@tonic-gate * Keep on going even if the parents walk hit an error.
3707c478bd9Sstevel@tonic-gate */
3717c478bd9Sstevel@tonic-gate diw->diw_mode = DIW_CHILD;
3727c478bd9Sstevel@tonic-gate status = WALK_NEXT;
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate } else if (diw->diw_mode == DIW_CHILD) {
3757c478bd9Sstevel@tonic-gate status = devinfo_children_walk_step(&diw->diw_child);
3767c478bd9Sstevel@tonic-gate if (status != WALK_NEXT) {
3777c478bd9Sstevel@tonic-gate diw->diw_mode = DIW_DONE;
3787c478bd9Sstevel@tonic-gate status = WALK_DONE;
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate } else
3817c478bd9Sstevel@tonic-gate status = WALK_DONE;
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate return (status);
3847c478bd9Sstevel@tonic-gate }
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate void
devinfo_walk_fini(mdb_walk_state_t * wsp)3877c478bd9Sstevel@tonic-gate devinfo_walk_fini(mdb_walk_state_t *wsp)
3887c478bd9Sstevel@tonic-gate {
3897c478bd9Sstevel@tonic-gate devinfo_walk_data_t *diw = wsp->walk_data;
3907c478bd9Sstevel@tonic-gate
3917c478bd9Sstevel@tonic-gate devinfo_children_walk_fini(&diw->diw_child);
3927c478bd9Sstevel@tonic-gate devinfo_parents_walk_fini(&diw->diw_parent);
3937c478bd9Sstevel@tonic-gate mdb_free(diw, sizeof (devinfo_walk_data_t));
3947c478bd9Sstevel@tonic-gate }
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate /*
3977c478bd9Sstevel@tonic-gate * Given a devinfo pointer, figure out which driver is associated
3987c478bd9Sstevel@tonic-gate * with the node (by driver name, from the devnames array).
3997c478bd9Sstevel@tonic-gate */
4007c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4017c478bd9Sstevel@tonic-gate int
devinfo2driver(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)4027c478bd9Sstevel@tonic-gate devinfo2driver(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
4037c478bd9Sstevel@tonic-gate {
4047c478bd9Sstevel@tonic-gate char dname[MODMAXNAMELEN + 1];
4057c478bd9Sstevel@tonic-gate struct dev_info devi;
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate
4087c478bd9Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC))
4097c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate if (mdb_vread(&devi, sizeof (devi), addr) == -1) {
4127c478bd9Sstevel@tonic-gate mdb_warn("failed to read devinfo struct at %p", addr);
4137c478bd9Sstevel@tonic-gate return (DCMD_ERR);
4147c478bd9Sstevel@tonic-gate }
4157c478bd9Sstevel@tonic-gate
416f723faa1Seschrock if (devi.devi_node_state < DS_ATTACHED) {
4177c478bd9Sstevel@tonic-gate /* No driver attached to this devinfo - nothing to do. */
4187c478bd9Sstevel@tonic-gate mdb_warn("%p: No driver attached to this devinfo node\n", addr);
4197c478bd9Sstevel@tonic-gate return (DCMD_ERR);
4207c478bd9Sstevel@tonic-gate }
4217c478bd9Sstevel@tonic-gate
4227c478bd9Sstevel@tonic-gate if (mdb_devinfo2driver(addr, dname, sizeof (dname)) != 0) {
4237c478bd9Sstevel@tonic-gate mdb_warn("failed to determine driver name");
4247c478bd9Sstevel@tonic-gate return (DCMD_ERR);
4257c478bd9Sstevel@tonic-gate }
4267c478bd9Sstevel@tonic-gate
4277c478bd9Sstevel@tonic-gate mdb_printf("Driver '%s' is associated with devinfo %p.\n", dname, addr);
4287c478bd9Sstevel@tonic-gate
4297c478bd9Sstevel@tonic-gate return (DCMD_OK);
4307c478bd9Sstevel@tonic-gate }
4317c478bd9Sstevel@tonic-gate
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate typedef struct devnames_walk {
4347c478bd9Sstevel@tonic-gate struct devnames *dnw_names;
4357c478bd9Sstevel@tonic-gate int dnw_ndx;
4367c478bd9Sstevel@tonic-gate int dnw_devcnt;
4377c478bd9Sstevel@tonic-gate uintptr_t dnw_base;
4387c478bd9Sstevel@tonic-gate uintptr_t dnw_size;
4397c478bd9Sstevel@tonic-gate } devnames_walk_t;
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate int
devnames_walk_init(mdb_walk_state_t * wsp)4427c478bd9Sstevel@tonic-gate devnames_walk_init(mdb_walk_state_t *wsp)
4437c478bd9Sstevel@tonic-gate {
4447c478bd9Sstevel@tonic-gate devnames_walk_t *dnw;
4457c478bd9Sstevel@tonic-gate int devcnt;
4467c478bd9Sstevel@tonic-gate uintptr_t devnamesp;
4477c478bd9Sstevel@tonic-gate
4487c478bd9Sstevel@tonic-gate if (wsp->walk_addr != NULL) {
4497c478bd9Sstevel@tonic-gate mdb_warn("devnames walker only supports global walks\n");
4507c478bd9Sstevel@tonic-gate return (WALK_ERR);
4517c478bd9Sstevel@tonic-gate }
4527c478bd9Sstevel@tonic-gate
4537c478bd9Sstevel@tonic-gate if (mdb_readvar(&devcnt, "devcnt") == -1) {
4547c478bd9Sstevel@tonic-gate mdb_warn("failed to read 'devcnt'");
4557c478bd9Sstevel@tonic-gate return (WALK_ERR);
4567c478bd9Sstevel@tonic-gate }
4577c478bd9Sstevel@tonic-gate
4587c478bd9Sstevel@tonic-gate if (mdb_readvar(&devnamesp, "devnamesp") == -1) {
4597c478bd9Sstevel@tonic-gate mdb_warn("failed to read 'devnamesp'");
4607c478bd9Sstevel@tonic-gate return (WALK_ERR);
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate
4637c478bd9Sstevel@tonic-gate dnw = mdb_zalloc(sizeof (devnames_walk_t), UM_SLEEP);
4647c478bd9Sstevel@tonic-gate dnw->dnw_size = sizeof (struct devnames) * devcnt;
4657c478bd9Sstevel@tonic-gate dnw->dnw_devcnt = devcnt;
4667c478bd9Sstevel@tonic-gate dnw->dnw_base = devnamesp;
4677c478bd9Sstevel@tonic-gate dnw->dnw_names = mdb_alloc(dnw->dnw_size, UM_SLEEP);
4687c478bd9Sstevel@tonic-gate
4697c478bd9Sstevel@tonic-gate if (mdb_vread(dnw->dnw_names, dnw->dnw_size, dnw->dnw_base) == -1) {
4707c478bd9Sstevel@tonic-gate mdb_warn("couldn't read devnames array at %p", devnamesp);
4717c478bd9Sstevel@tonic-gate return (WALK_ERR);
4727c478bd9Sstevel@tonic-gate }
4737c478bd9Sstevel@tonic-gate
4747c478bd9Sstevel@tonic-gate wsp->walk_data = dnw;
4757c478bd9Sstevel@tonic-gate return (WALK_NEXT);
4767c478bd9Sstevel@tonic-gate }
4777c478bd9Sstevel@tonic-gate
4787c478bd9Sstevel@tonic-gate int
devnames_walk_step(mdb_walk_state_t * wsp)4797c478bd9Sstevel@tonic-gate devnames_walk_step(mdb_walk_state_t *wsp)
4807c478bd9Sstevel@tonic-gate {
4817c478bd9Sstevel@tonic-gate devnames_walk_t *dnw = wsp->walk_data;
4827c478bd9Sstevel@tonic-gate int status;
4837c478bd9Sstevel@tonic-gate
4847c478bd9Sstevel@tonic-gate if (dnw->dnw_ndx == dnw->dnw_devcnt)
4857c478bd9Sstevel@tonic-gate return (WALK_DONE);
4867c478bd9Sstevel@tonic-gate
4877c478bd9Sstevel@tonic-gate status = wsp->walk_callback(dnw->dnw_ndx * sizeof (struct devnames) +
4887c478bd9Sstevel@tonic-gate dnw->dnw_base, &dnw->dnw_names[dnw->dnw_ndx], wsp->walk_cbdata);
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate dnw->dnw_ndx++;
4917c478bd9Sstevel@tonic-gate return (status);
4927c478bd9Sstevel@tonic-gate }
4937c478bd9Sstevel@tonic-gate
4947c478bd9Sstevel@tonic-gate void
devnames_walk_fini(mdb_walk_state_t * wsp)4957c478bd9Sstevel@tonic-gate devnames_walk_fini(mdb_walk_state_t *wsp)
4967c478bd9Sstevel@tonic-gate {
4977c478bd9Sstevel@tonic-gate devnames_walk_t *dnw = wsp->walk_data;
4987c478bd9Sstevel@tonic-gate
4997c478bd9Sstevel@tonic-gate mdb_free(dnw->dnw_names, dnw->dnw_size);
5007c478bd9Sstevel@tonic-gate mdb_free(dnw, sizeof (devnames_walk_t));
5017c478bd9Sstevel@tonic-gate }
5027c478bd9Sstevel@tonic-gate
5037c478bd9Sstevel@tonic-gate int
devinfo_siblings_walk_init(mdb_walk_state_t * wsp)5047c478bd9Sstevel@tonic-gate devinfo_siblings_walk_init(mdb_walk_state_t *wsp)
5057c478bd9Sstevel@tonic-gate {
5067c478bd9Sstevel@tonic-gate struct dev_info di;
5077c478bd9Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr;
5087c478bd9Sstevel@tonic-gate
5097c478bd9Sstevel@tonic-gate if (addr == NULL) {
5107c478bd9Sstevel@tonic-gate mdb_warn("a dev_info struct address must be provided\n");
5117c478bd9Sstevel@tonic-gate return (WALK_ERR);
5127c478bd9Sstevel@tonic-gate }
5137c478bd9Sstevel@tonic-gate
5147c478bd9Sstevel@tonic-gate if (mdb_vread(&di, sizeof (di), addr) == -1) {
5157c478bd9Sstevel@tonic-gate mdb_warn("failed to read dev_info struct at %p", addr);
5167c478bd9Sstevel@tonic-gate return (WALK_ERR);
5177c478bd9Sstevel@tonic-gate }
5187c478bd9Sstevel@tonic-gate
5197c478bd9Sstevel@tonic-gate if (di.devi_parent == NULL) {
5207c478bd9Sstevel@tonic-gate mdb_warn("no parent for devinfo at %p", addr);
5217c478bd9Sstevel@tonic-gate return (WALK_DONE);
5227c478bd9Sstevel@tonic-gate }
5237c478bd9Sstevel@tonic-gate
5247c478bd9Sstevel@tonic-gate if (mdb_vread(&di, sizeof (di), (uintptr_t)di.devi_parent) == -1) {
5257c478bd9Sstevel@tonic-gate mdb_warn("failed to read parent dev_info struct at %p",
5267c478bd9Sstevel@tonic-gate (uintptr_t)di.devi_parent);
5277c478bd9Sstevel@tonic-gate return (WALK_ERR);
5287c478bd9Sstevel@tonic-gate }
5297c478bd9Sstevel@tonic-gate
5307c478bd9Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)di.devi_child;
5317c478bd9Sstevel@tonic-gate return (WALK_NEXT);
5327c478bd9Sstevel@tonic-gate }
5337c478bd9Sstevel@tonic-gate
5347c478bd9Sstevel@tonic-gate int
devinfo_siblings_walk_step(mdb_walk_state_t * wsp)5357c478bd9Sstevel@tonic-gate devinfo_siblings_walk_step(mdb_walk_state_t *wsp)
5367c478bd9Sstevel@tonic-gate {
5377c478bd9Sstevel@tonic-gate struct dev_info di;
5387c478bd9Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr;
5397c478bd9Sstevel@tonic-gate
5407c478bd9Sstevel@tonic-gate if (addr == NULL)
5417c478bd9Sstevel@tonic-gate return (WALK_DONE);
5427c478bd9Sstevel@tonic-gate
5437c478bd9Sstevel@tonic-gate if (mdb_vread(&di, sizeof (di), addr) == -1) {
5447c478bd9Sstevel@tonic-gate mdb_warn("failed to read dev_info struct at %p", addr);
5457c478bd9Sstevel@tonic-gate return (WALK_DONE);
5467c478bd9Sstevel@tonic-gate }
5477c478bd9Sstevel@tonic-gate
5487c478bd9Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)di.devi_sibling;
5497c478bd9Sstevel@tonic-gate return (wsp->walk_callback(addr, &di, wsp->walk_cbdata));
5507c478bd9Sstevel@tonic-gate }
5517c478bd9Sstevel@tonic-gate
5527c478bd9Sstevel@tonic-gate int
devi_next_walk_step(mdb_walk_state_t * wsp)5537c478bd9Sstevel@tonic-gate devi_next_walk_step(mdb_walk_state_t *wsp)
5547c478bd9Sstevel@tonic-gate {
5557c478bd9Sstevel@tonic-gate struct dev_info di;
5567c478bd9Sstevel@tonic-gate int status;
5577c478bd9Sstevel@tonic-gate
5587c478bd9Sstevel@tonic-gate if (wsp->walk_addr == NULL)
5597c478bd9Sstevel@tonic-gate return (WALK_DONE);
5607c478bd9Sstevel@tonic-gate
5617c478bd9Sstevel@tonic-gate if (mdb_vread(&di, sizeof (di), wsp->walk_addr) == -1)
5627c478bd9Sstevel@tonic-gate return (WALK_DONE);
5637c478bd9Sstevel@tonic-gate
5647c478bd9Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, &di, wsp->walk_cbdata);
5657c478bd9Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)di.devi_next;
5667c478bd9Sstevel@tonic-gate return (status);
5677c478bd9Sstevel@tonic-gate }
5687c478bd9Sstevel@tonic-gate
5697c478bd9Sstevel@tonic-gate /*
5707c478bd9Sstevel@tonic-gate * Helper functions.
5717c478bd9Sstevel@tonic-gate */
5727c478bd9Sstevel@tonic-gate
5737c478bd9Sstevel@tonic-gate static int
is_printable_string(unsigned char * prop_value)5747c478bd9Sstevel@tonic-gate is_printable_string(unsigned char *prop_value)
5757c478bd9Sstevel@tonic-gate {
5767c478bd9Sstevel@tonic-gate while (*prop_value != 0)
5777c478bd9Sstevel@tonic-gate if (!isprint(*prop_value++))
5787c478bd9Sstevel@tonic-gate return (0);
5797c478bd9Sstevel@tonic-gate return (1);
5807c478bd9Sstevel@tonic-gate }
5817c478bd9Sstevel@tonic-gate
5827c478bd9Sstevel@tonic-gate static void
devinfo_print_props_type(int type)5837c478bd9Sstevel@tonic-gate devinfo_print_props_type(int type) {
5847c478bd9Sstevel@tonic-gate char *type_str = NULL;
5857c478bd9Sstevel@tonic-gate
5867c478bd9Sstevel@tonic-gate switch (type) {
5877c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_ANY:
5887c478bd9Sstevel@tonic-gate type_str = "any";
5897c478bd9Sstevel@tonic-gate break;
5907c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_COMPOSITE:
5917c478bd9Sstevel@tonic-gate type_str = "composite";
5927c478bd9Sstevel@tonic-gate break;
5937c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_INT64:
5947c478bd9Sstevel@tonic-gate type_str = "int64";
5957c478bd9Sstevel@tonic-gate break;
5967c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_INT:
5977c478bd9Sstevel@tonic-gate type_str = "int";
5987c478bd9Sstevel@tonic-gate break;
5997c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_BYTE:
6007c478bd9Sstevel@tonic-gate type_str = "byte";
6017c478bd9Sstevel@tonic-gate break;
6027c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_STRING:
6037c478bd9Sstevel@tonic-gate type_str = "string";
6047c478bd9Sstevel@tonic-gate break;
6057c478bd9Sstevel@tonic-gate }
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate if (type_str != NULL)
6087c478bd9Sstevel@tonic-gate mdb_printf("type=%s", type_str);
6097c478bd9Sstevel@tonic-gate else
6107c478bd9Sstevel@tonic-gate mdb_printf("type=0x%x", type);
6117c478bd9Sstevel@tonic-gate }
6127c478bd9Sstevel@tonic-gate
6137c478bd9Sstevel@tonic-gate static void
devinfo_print_props_value(int elem_size,int nelem,unsigned char * prop_value,int prop_value_len)6147c478bd9Sstevel@tonic-gate devinfo_print_props_value(int elem_size, int nelem,
6157c478bd9Sstevel@tonic-gate unsigned char *prop_value, int prop_value_len)
6167c478bd9Sstevel@tonic-gate {
6177c478bd9Sstevel@tonic-gate int i;
6187c478bd9Sstevel@tonic-gate
6197c478bd9Sstevel@tonic-gate mdb_printf("value=");
6207c478bd9Sstevel@tonic-gate
6217c478bd9Sstevel@tonic-gate if (elem_size == 0) {
6227c478bd9Sstevel@tonic-gate /* if elem_size == 0, then we are printing out string(s) */
6237c478bd9Sstevel@tonic-gate char *p = (char *)prop_value;
6247c478bd9Sstevel@tonic-gate
6257c478bd9Sstevel@tonic-gate for (i = 0; i < nelem - 1; i++) {
6267c478bd9Sstevel@tonic-gate mdb_printf("'%s' + ", p);
6277c478bd9Sstevel@tonic-gate p += strlen(p) + 1;
6287c478bd9Sstevel@tonic-gate }
6297c478bd9Sstevel@tonic-gate mdb_printf("'%s'", p);
6307c478bd9Sstevel@tonic-gate } else {
6317c478bd9Sstevel@tonic-gate /*
6327c478bd9Sstevel@tonic-gate * if elem_size != 0 then we are printing out an array
6337c478bd9Sstevel@tonic-gate * where each element is of elem_size
6347c478bd9Sstevel@tonic-gate */
6357c478bd9Sstevel@tonic-gate mdb_nhconvert(prop_value, prop_value, elem_size);
6367c478bd9Sstevel@tonic-gate mdb_printf("%02x", *prop_value);
6377c478bd9Sstevel@tonic-gate for (i = 1; i < prop_value_len; i++) {
6387c478bd9Sstevel@tonic-gate if ((i % elem_size) == 0) {
6397c478bd9Sstevel@tonic-gate mdb_nhconvert(&prop_value[i],
6407c478bd9Sstevel@tonic-gate &prop_value[i], elem_size);
6417c478bd9Sstevel@tonic-gate mdb_printf(".");
6427c478bd9Sstevel@tonic-gate }
6437c478bd9Sstevel@tonic-gate
6447c478bd9Sstevel@tonic-gate mdb_printf("%02x", prop_value[i]);
6457c478bd9Sstevel@tonic-gate }
6467c478bd9Sstevel@tonic-gate }
6477c478bd9Sstevel@tonic-gate }
6487c478bd9Sstevel@tonic-gate
6497c478bd9Sstevel@tonic-gate /*
6507c478bd9Sstevel@tonic-gate * devinfo_print_props_guess()
6517c478bd9Sstevel@tonic-gate * Guesses how to interpret the value of the property
6527c478bd9Sstevel@tonic-gate *
6537c478bd9Sstevel@tonic-gate * Params:
6547c478bd9Sstevel@tonic-gate * type - Should be the type value of the property
6557c478bd9Sstevel@tonic-gate * prop_val - Pointer to the property value data buffer
6567c478bd9Sstevel@tonic-gate * prop_len - Length of the property value data buffer
6577c478bd9Sstevel@tonic-gate *
6587c478bd9Sstevel@tonic-gate * Return values:
6597c478bd9Sstevel@tonic-gate * nelem - The number of elements stored in the property value
6607c478bd9Sstevel@tonic-gate * data buffer pointed to by prop_val.
6617c478bd9Sstevel@tonic-gate * elem_size - The size (in bytes) of the elements stored in the property
6627c478bd9Sstevel@tonic-gate * value data buffer pointed to by prop_val.
6637c478bd9Sstevel@tonic-gate * Upon return if elem_size == 0 and nelem != 0 then
6647c478bd9Sstevel@tonic-gate * the property value data buffer contains strings
6657c478bd9Sstevel@tonic-gate * len_err - There was an error with the length of the data buffer.
6667c478bd9Sstevel@tonic-gate * Its size is not a multiple of the array value type.
6677c478bd9Sstevel@tonic-gate * It will be interpreted as an array of bytes.
6687c478bd9Sstevel@tonic-gate */
6697c478bd9Sstevel@tonic-gate static void
devinfo_print_props_guess(int type,unsigned char * prop_val,int prop_len,int * elem_size,int * nelem,int * len_err)6707c478bd9Sstevel@tonic-gate devinfo_print_props_guess(int type, unsigned char *prop_val, int prop_len,
6717c478bd9Sstevel@tonic-gate int *elem_size, int *nelem, int *len_err)
6727c478bd9Sstevel@tonic-gate {
6737c478bd9Sstevel@tonic-gate *len_err = 0;
6747c478bd9Sstevel@tonic-gate if (prop_len == NULL) {
6757c478bd9Sstevel@tonic-gate *elem_size = 0;
6767c478bd9Sstevel@tonic-gate *nelem = 0;
6777c478bd9Sstevel@tonic-gate return;
6787c478bd9Sstevel@tonic-gate }
6797c478bd9Sstevel@tonic-gate
6807c478bd9Sstevel@tonic-gate /* by default, assume an array of bytes */
6817c478bd9Sstevel@tonic-gate *elem_size = 1;
6827c478bd9Sstevel@tonic-gate *nelem = prop_len;
6837c478bd9Sstevel@tonic-gate
6847c478bd9Sstevel@tonic-gate switch (type) {
6857c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_BYTE:
6867c478bd9Sstevel@tonic-gate /* default case, that was easy */
6877c478bd9Sstevel@tonic-gate break;
6887c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_INT64:
6897c478bd9Sstevel@tonic-gate if ((prop_len % sizeof (int64_t)) == 0) {
6907c478bd9Sstevel@tonic-gate *elem_size = sizeof (int64_t);
6917c478bd9Sstevel@tonic-gate *nelem = prop_len / *elem_size;
6927c478bd9Sstevel@tonic-gate } else {
6937c478bd9Sstevel@tonic-gate /* array is not a multiple of type size, error */
6947c478bd9Sstevel@tonic-gate *len_err = 1;
6957c478bd9Sstevel@tonic-gate }
6967c478bd9Sstevel@tonic-gate break;
6977c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_INT:
6987c478bd9Sstevel@tonic-gate if ((prop_len % sizeof (int)) == 0) {
6997c478bd9Sstevel@tonic-gate *elem_size = sizeof (int);
7007c478bd9Sstevel@tonic-gate *nelem = prop_len / *elem_size;
7017c478bd9Sstevel@tonic-gate } else {
7027c478bd9Sstevel@tonic-gate /* array is not a multiple of type size, error */
7037c478bd9Sstevel@tonic-gate *len_err = 1;
7047c478bd9Sstevel@tonic-gate }
7057c478bd9Sstevel@tonic-gate break;
7067c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_STRING:
7077c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_COMPOSITE:
7087c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_ANY:
7097c478bd9Sstevel@tonic-gate default:
7107c478bd9Sstevel@tonic-gate /*
7117c478bd9Sstevel@tonic-gate * if we made it here the type is either unknown
7127c478bd9Sstevel@tonic-gate * or a string. Try to interpret is as a string
7137c478bd9Sstevel@tonic-gate * and if that fails assume an array of bytes.
7147c478bd9Sstevel@tonic-gate */
7157c478bd9Sstevel@tonic-gate if (prop_val[prop_len - 1] == '\0') {
7167c478bd9Sstevel@tonic-gate unsigned char *s = prop_val;
7177c478bd9Sstevel@tonic-gate int i;
7187c478bd9Sstevel@tonic-gate
7197c478bd9Sstevel@tonic-gate /* assume an array of strings */
7207c478bd9Sstevel@tonic-gate *elem_size = 0;
7217c478bd9Sstevel@tonic-gate *nelem = 0;
7227c478bd9Sstevel@tonic-gate
7237c478bd9Sstevel@tonic-gate for (i = 0; i < prop_len; i++) {
7247c478bd9Sstevel@tonic-gate if (prop_val[i] != '\0')
7257c478bd9Sstevel@tonic-gate continue;
7267c478bd9Sstevel@tonic-gate
7277c478bd9Sstevel@tonic-gate /*
7287c478bd9Sstevel@tonic-gate * If the property is typed as a string
7297c478bd9Sstevel@tonic-gate * property, then interpret empty strings
7307c478bd9Sstevel@tonic-gate * as strings. Otherwise default to an
7317c478bd9Sstevel@tonic-gate * array of bytes. If there are unprintable
7327c478bd9Sstevel@tonic-gate * characters, always default to an array of
7337c478bd9Sstevel@tonic-gate * bytes.
7347c478bd9Sstevel@tonic-gate */
7357c478bd9Sstevel@tonic-gate if ((*s == '\0' && type !=
7367c478bd9Sstevel@tonic-gate DDI_PROP_TYPE_STRING) ||
7377c478bd9Sstevel@tonic-gate !is_printable_string(s)) {
7387c478bd9Sstevel@tonic-gate *elem_size = 1;
7397c478bd9Sstevel@tonic-gate *nelem = prop_len;
7407c478bd9Sstevel@tonic-gate break;
7417c478bd9Sstevel@tonic-gate }
7427c478bd9Sstevel@tonic-gate
7437c478bd9Sstevel@tonic-gate (*nelem)++;
7447c478bd9Sstevel@tonic-gate s = &prop_val[i + 1];
7457c478bd9Sstevel@tonic-gate }
7467c478bd9Sstevel@tonic-gate }
7477c478bd9Sstevel@tonic-gate break;
7487c478bd9Sstevel@tonic-gate }
7497c478bd9Sstevel@tonic-gate }
7507c478bd9Sstevel@tonic-gate
7517c478bd9Sstevel@tonic-gate static void
devinfo_print_props(char * name,ddi_prop_t * p)7527c478bd9Sstevel@tonic-gate devinfo_print_props(char *name, ddi_prop_t *p)
7537c478bd9Sstevel@tonic-gate {
7547c478bd9Sstevel@tonic-gate if (p == NULL)
7557c478bd9Sstevel@tonic-gate return;
7567c478bd9Sstevel@tonic-gate
7577c478bd9Sstevel@tonic-gate if (name != NULL)
7587c478bd9Sstevel@tonic-gate mdb_printf("%s ", name);
7597c478bd9Sstevel@tonic-gate
7607c478bd9Sstevel@tonic-gate mdb_printf("properties at %p:\n", p);
7617c478bd9Sstevel@tonic-gate mdb_inc_indent(DEVINFO_PROP_INDENT);
7627c478bd9Sstevel@tonic-gate
7637c478bd9Sstevel@tonic-gate while (p != NULL) {
7647c478bd9Sstevel@tonic-gate ddi_prop_t prop;
7657c478bd9Sstevel@tonic-gate char prop_name[128];
7667c478bd9Sstevel@tonic-gate unsigned char *prop_value;
7677c478bd9Sstevel@tonic-gate int type, elem_size, nelem, prop_len_error;
7687c478bd9Sstevel@tonic-gate
7697c478bd9Sstevel@tonic-gate /* read in the property struct */
7707c478bd9Sstevel@tonic-gate if (mdb_vread(&prop, sizeof (prop), (uintptr_t)p) == -1) {
7717c478bd9Sstevel@tonic-gate mdb_warn("could not read property at 0x%p", p);
7727c478bd9Sstevel@tonic-gate break;
7737c478bd9Sstevel@tonic-gate }
7747c478bd9Sstevel@tonic-gate
7757c478bd9Sstevel@tonic-gate /* print the property name */
7767c478bd9Sstevel@tonic-gate if (mdb_readstr(prop_name, sizeof (prop_name),
7777c478bd9Sstevel@tonic-gate (uintptr_t)prop.prop_name) == -1) {
7787c478bd9Sstevel@tonic-gate mdb_warn("could not read property name at 0x%p",
7797c478bd9Sstevel@tonic-gate prop.prop_name);
7807c478bd9Sstevel@tonic-gate goto next;
7817c478bd9Sstevel@tonic-gate }
7827c478bd9Sstevel@tonic-gate mdb_printf("name='%s' ", prop_name);
7837c478bd9Sstevel@tonic-gate
7847c478bd9Sstevel@tonic-gate /* get the property type and print it out */
7857c478bd9Sstevel@tonic-gate type = (prop.prop_flags & DDI_PROP_TYPE_MASK);
7867c478bd9Sstevel@tonic-gate devinfo_print_props_type(type);
7877c478bd9Sstevel@tonic-gate
7887c478bd9Sstevel@tonic-gate /* get the property value */
7897c478bd9Sstevel@tonic-gate if (prop.prop_len > 0) {
7907c478bd9Sstevel@tonic-gate prop_value = mdb_alloc(prop.prop_len, UM_SLEEP|UM_GC);
7917c478bd9Sstevel@tonic-gate if (mdb_vread(prop_value, prop.prop_len,
7927c478bd9Sstevel@tonic-gate (uintptr_t)prop.prop_val) == -1) {
7937c478bd9Sstevel@tonic-gate mdb_warn("could not read property value at "
7947c478bd9Sstevel@tonic-gate "0x%p", prop.prop_val);
7957c478bd9Sstevel@tonic-gate goto next;
7967c478bd9Sstevel@tonic-gate }
7977c478bd9Sstevel@tonic-gate } else {
7987c478bd9Sstevel@tonic-gate prop_value = NULL;
7997c478bd9Sstevel@tonic-gate }
8007c478bd9Sstevel@tonic-gate
8017c478bd9Sstevel@tonic-gate /* take a guess at interpreting the property value */
8027c478bd9Sstevel@tonic-gate devinfo_print_props_guess(type, prop_value, prop.prop_len,
8037c478bd9Sstevel@tonic-gate &elem_size, &nelem, &prop_len_error);
8047c478bd9Sstevel@tonic-gate
8057c478bd9Sstevel@tonic-gate /* print out the number ot items */
8067c478bd9Sstevel@tonic-gate mdb_printf(" items=%d", nelem);
8077c478bd9Sstevel@tonic-gate
8087c478bd9Sstevel@tonic-gate /* print out any associated device information */
8097c478bd9Sstevel@tonic-gate if (prop.prop_dev != DDI_DEV_T_NONE) {
8107c478bd9Sstevel@tonic-gate mdb_printf(" dev=");
8117c478bd9Sstevel@tonic-gate if (prop.prop_dev == DDI_DEV_T_ANY)
8127c478bd9Sstevel@tonic-gate mdb_printf("any");
8137c478bd9Sstevel@tonic-gate else if (prop.prop_dev == DDI_MAJOR_T_UNKNOWN)
8147c478bd9Sstevel@tonic-gate mdb_printf("unknown");
8157c478bd9Sstevel@tonic-gate else
8167c478bd9Sstevel@tonic-gate mdb_printf("(%u,%u)",
8177c478bd9Sstevel@tonic-gate getmajor(prop.prop_dev),
8187c478bd9Sstevel@tonic-gate getminor(prop.prop_dev));
8197c478bd9Sstevel@tonic-gate }
8207c478bd9Sstevel@tonic-gate
8217c478bd9Sstevel@tonic-gate /* print out the property value */
8227c478bd9Sstevel@tonic-gate if (prop_value != NULL) {
8237c478bd9Sstevel@tonic-gate mdb_printf("\n");
8247c478bd9Sstevel@tonic-gate mdb_inc_indent(DEVINFO_PROP_INDENT);
8257c478bd9Sstevel@tonic-gate if (prop_len_error)
8267c478bd9Sstevel@tonic-gate mdb_printf("NOTE: prop length is not a "
8277c478bd9Sstevel@tonic-gate "multiple of element size\n");
8287c478bd9Sstevel@tonic-gate devinfo_print_props_value(elem_size, nelem,
8297c478bd9Sstevel@tonic-gate prop_value, prop.prop_len);
8307c478bd9Sstevel@tonic-gate mdb_dec_indent(DEVINFO_PROP_INDENT);
8317c478bd9Sstevel@tonic-gate }
8327c478bd9Sstevel@tonic-gate
8337c478bd9Sstevel@tonic-gate next:
8347c478bd9Sstevel@tonic-gate mdb_printf("\n");
8357c478bd9Sstevel@tonic-gate p = prop.prop_next;
8367c478bd9Sstevel@tonic-gate }
8377c478bd9Sstevel@tonic-gate
8387c478bd9Sstevel@tonic-gate mdb_dec_indent(DEVINFO_PROP_INDENT);
8397c478bd9Sstevel@tonic-gate }
8407c478bd9Sstevel@tonic-gate
8417c478bd9Sstevel@tonic-gate static void
devinfo_pathinfo_state(mdi_pathinfo_state_t state)8427c478bd9Sstevel@tonic-gate devinfo_pathinfo_state(mdi_pathinfo_state_t state) {
8437c478bd9Sstevel@tonic-gate char *type_str = NULL;
8447c478bd9Sstevel@tonic-gate
8457c478bd9Sstevel@tonic-gate switch (state) {
8467c478bd9Sstevel@tonic-gate case MDI_PATHINFO_STATE_INIT:
8477c478bd9Sstevel@tonic-gate type_str = "init";
8487c478bd9Sstevel@tonic-gate break;
8497c478bd9Sstevel@tonic-gate case MDI_PATHINFO_STATE_ONLINE:
8507c478bd9Sstevel@tonic-gate type_str = "online";
8517c478bd9Sstevel@tonic-gate break;
8527c478bd9Sstevel@tonic-gate case MDI_PATHINFO_STATE_STANDBY:
8537c478bd9Sstevel@tonic-gate type_str = "standby";
8547c478bd9Sstevel@tonic-gate break;
8557c478bd9Sstevel@tonic-gate case MDI_PATHINFO_STATE_FAULT:
8567c478bd9Sstevel@tonic-gate type_str = "fault";
8577c478bd9Sstevel@tonic-gate break;
8587c478bd9Sstevel@tonic-gate case MDI_PATHINFO_STATE_OFFLINE:
8597c478bd9Sstevel@tonic-gate type_str = "offline";
8607c478bd9Sstevel@tonic-gate break;
8617c478bd9Sstevel@tonic-gate }
8627c478bd9Sstevel@tonic-gate if (type_str != NULL)
8637c478bd9Sstevel@tonic-gate mdb_printf("state=%s\n", type_str);
8647c478bd9Sstevel@tonic-gate else
8657c478bd9Sstevel@tonic-gate mdb_printf("state=0x%x\n", state);
8667c478bd9Sstevel@tonic-gate }
8677c478bd9Sstevel@tonic-gate
8687c478bd9Sstevel@tonic-gate static void
devinfo_print_pathing(int mdi_component,void * mdi_client)8697c478bd9Sstevel@tonic-gate devinfo_print_pathing(int mdi_component, void *mdi_client) {
8707c478bd9Sstevel@tonic-gate mdi_client_t mdi_c;
8717c478bd9Sstevel@tonic-gate struct mdi_pathinfo *pip;
8727c478bd9Sstevel@tonic-gate
8737c478bd9Sstevel@tonic-gate /* we only print out multipathing info for client nodes */
8747c478bd9Sstevel@tonic-gate if ((mdi_component & MDI_COMPONENT_CLIENT) == 0)
8757c478bd9Sstevel@tonic-gate return;
8767c478bd9Sstevel@tonic-gate
8777c478bd9Sstevel@tonic-gate mdb_printf("Client multipath info at: 0x%p\n", mdi_client);
8787c478bd9Sstevel@tonic-gate mdb_inc_indent(DEVINFO_PROP_INDENT);
8797c478bd9Sstevel@tonic-gate
8807c478bd9Sstevel@tonic-gate /* read in the client multipathing info */
8817c478bd9Sstevel@tonic-gate if (mdb_readstr((void*) &mdi_c, sizeof (mdi_c),
8827c478bd9Sstevel@tonic-gate (uintptr_t)mdi_client) == -1) {
8837c478bd9Sstevel@tonic-gate mdb_warn("failed to read mdi_client at %p",
8847c478bd9Sstevel@tonic-gate (uintptr_t)mdi_client);
8857c478bd9Sstevel@tonic-gate goto exit;
8867c478bd9Sstevel@tonic-gate }
8877c478bd9Sstevel@tonic-gate
8887c478bd9Sstevel@tonic-gate /*
8897c478bd9Sstevel@tonic-gate * walk through the clients list of pathinfo structures and print
8907c478bd9Sstevel@tonic-gate * out the properties for each path
8917c478bd9Sstevel@tonic-gate */
8927c478bd9Sstevel@tonic-gate pip = (struct mdi_pathinfo *)mdi_c.ct_path_head;
8937c478bd9Sstevel@tonic-gate while (pip != NULL) {
8947c478bd9Sstevel@tonic-gate char binding_name[128];
8957c478bd9Sstevel@tonic-gate struct mdi_pathinfo pi;
8967c478bd9Sstevel@tonic-gate mdi_phci_t ph;
8977c478bd9Sstevel@tonic-gate struct dev_info ph_di;
8987c478bd9Sstevel@tonic-gate
8997c478bd9Sstevel@tonic-gate /* read in the pathinfo structure */
9007c478bd9Sstevel@tonic-gate if (mdb_vread((void*)&pi, sizeof (pi),
9017c478bd9Sstevel@tonic-gate (uintptr_t)pip) == -1) {
9027c478bd9Sstevel@tonic-gate mdb_warn("failed to read mdi_pathinfo at %p",
9037c478bd9Sstevel@tonic-gate (uintptr_t)pip);
9047c478bd9Sstevel@tonic-gate goto exit;
9057c478bd9Sstevel@tonic-gate }
9067c478bd9Sstevel@tonic-gate
9077c478bd9Sstevel@tonic-gate /* read in the pchi (path host adapter) info */
9087c478bd9Sstevel@tonic-gate if (mdb_vread((void*)&ph, sizeof (ph),
9097c478bd9Sstevel@tonic-gate (uintptr_t)pi.pi_phci) == -1) {
9107c478bd9Sstevel@tonic-gate mdb_warn("failed to read mdi_pchi at %p",
9117c478bd9Sstevel@tonic-gate (uintptr_t)pi.pi_phci);
9127c478bd9Sstevel@tonic-gate goto exit;
9137c478bd9Sstevel@tonic-gate }
9147c478bd9Sstevel@tonic-gate
9157c478bd9Sstevel@tonic-gate /* read in the dip of the phci so we can get it's name */
9167c478bd9Sstevel@tonic-gate if (mdb_vread((void*)&ph_di, sizeof (ph_di),
9177c478bd9Sstevel@tonic-gate (uintptr_t)ph.ph_dip) == -1) {
9187c478bd9Sstevel@tonic-gate mdb_warn("failed to read mdi_pchi at %p",
9197c478bd9Sstevel@tonic-gate (uintptr_t)ph.ph_dip);
9207c478bd9Sstevel@tonic-gate goto exit;
9217c478bd9Sstevel@tonic-gate }
9227c478bd9Sstevel@tonic-gate if (mdb_vread(binding_name, sizeof (binding_name),
9237c478bd9Sstevel@tonic-gate (uintptr_t)ph_di.devi_binding_name) == -1) {
9247c478bd9Sstevel@tonic-gate mdb_warn("failed to read binding_name at %p",
9257c478bd9Sstevel@tonic-gate (uintptr_t)ph_di.devi_binding_name);
9267c478bd9Sstevel@tonic-gate goto exit;
9277c478bd9Sstevel@tonic-gate }
9287c478bd9Sstevel@tonic-gate
9297c478bd9Sstevel@tonic-gate mdb_printf("%s#%d, ", binding_name, ph_di.devi_instance);
9307c478bd9Sstevel@tonic-gate devinfo_pathinfo_state(pi.pi_state);
9317c478bd9Sstevel@tonic-gate
9327c478bd9Sstevel@tonic-gate /* print out the pathing info */
9337c478bd9Sstevel@tonic-gate mdb_inc_indent(DEVINFO_PROP_INDENT);
9347c478bd9Sstevel@tonic-gate if (mdb_pwalk_dcmd(NVPAIR_WALKER_FQNAME, NVPAIR_DCMD_FQNAME,
9357c478bd9Sstevel@tonic-gate 0, NULL, (uintptr_t)pi.pi_prop) != 0) {
9367c478bd9Sstevel@tonic-gate mdb_dec_indent(DEVINFO_PROP_INDENT);
9377c478bd9Sstevel@tonic-gate goto exit;
9387c478bd9Sstevel@tonic-gate }
9397c478bd9Sstevel@tonic-gate mdb_dec_indent(DEVINFO_PROP_INDENT);
9407c478bd9Sstevel@tonic-gate pip = pi.pi_client_link;
9417c478bd9Sstevel@tonic-gate }
9427c478bd9Sstevel@tonic-gate
9437c478bd9Sstevel@tonic-gate exit:
9447c478bd9Sstevel@tonic-gate mdb_dec_indent(DEVINFO_PROP_INDENT);
9457c478bd9Sstevel@tonic-gate }
9467c478bd9Sstevel@tonic-gate
9477c478bd9Sstevel@tonic-gate static int
devinfo_print(uintptr_t addr,struct dev_info * dev,devinfo_cb_data_t * data)9487c478bd9Sstevel@tonic-gate devinfo_print(uintptr_t addr, struct dev_info *dev, devinfo_cb_data_t *data)
9497c478bd9Sstevel@tonic-gate {
9507c478bd9Sstevel@tonic-gate /*
9517c478bd9Sstevel@tonic-gate * We know the walker passes us extra data after the dev_info.
9527c478bd9Sstevel@tonic-gate */
9537c478bd9Sstevel@tonic-gate char binding_name[128];
954f723faa1Seschrock char dname[MODMAXNAMELEN + 1];
9557c478bd9Sstevel@tonic-gate devinfo_node_t *din = (devinfo_node_t *)dev;
9567c478bd9Sstevel@tonic-gate ddi_prop_t *global_props = NULL;
9577c478bd9Sstevel@tonic-gate
9587c478bd9Sstevel@tonic-gate if (mdb_readstr(binding_name, sizeof (binding_name),
9597c478bd9Sstevel@tonic-gate (uintptr_t)dev->devi_binding_name) == -1) {
9607c478bd9Sstevel@tonic-gate mdb_warn("failed to read binding_name at %p",
9617c478bd9Sstevel@tonic-gate (uintptr_t)dev->devi_binding_name);
9627c478bd9Sstevel@tonic-gate return (WALK_ERR);
9637c478bd9Sstevel@tonic-gate }
9647c478bd9Sstevel@tonic-gate
9657c478bd9Sstevel@tonic-gate /* if there are any global properties, get a pointer to them */
9667c478bd9Sstevel@tonic-gate if (dev->devi_global_prop_list != NULL) {
9677c478bd9Sstevel@tonic-gate ddi_prop_list_t plist;
9687c478bd9Sstevel@tonic-gate if (mdb_vread((void*)&plist, sizeof (plist),
9697c478bd9Sstevel@tonic-gate (uintptr_t)dev->devi_global_prop_list) == -1) {
9707c478bd9Sstevel@tonic-gate mdb_warn("failed to read global prop_list at %p",
9717c478bd9Sstevel@tonic-gate (uintptr_t)dev->devi_global_prop_list);
9727c478bd9Sstevel@tonic-gate return (WALK_ERR);
9737c478bd9Sstevel@tonic-gate }
9747c478bd9Sstevel@tonic-gate global_props = plist.prop_list;
9757c478bd9Sstevel@tonic-gate }
9767c478bd9Sstevel@tonic-gate
9777c478bd9Sstevel@tonic-gate mdb_inc_indent(din->din_depth * DEVINFO_TREE_INDENT);
9787c478bd9Sstevel@tonic-gate if ((addr == data->di_base) || (data->di_flags & DEVINFO_ALLBOLD))
9797c478bd9Sstevel@tonic-gate mdb_printf("%<b>");
9807c478bd9Sstevel@tonic-gate mdb_printf("%-0?p %s", addr, binding_name);
9817c478bd9Sstevel@tonic-gate if ((addr == data->di_base) || (data->di_flags & DEVINFO_ALLBOLD))
9827c478bd9Sstevel@tonic-gate mdb_printf("%</b>");
9837c478bd9Sstevel@tonic-gate if (dev->devi_instance >= 0)
9847c478bd9Sstevel@tonic-gate mdb_printf(", instance #%d", dev->devi_instance);
985f723faa1Seschrock
986f723faa1Seschrock if (dev->devi_node_state < DS_ATTACHED)
9877c478bd9Sstevel@tonic-gate mdb_printf(" (driver not attached)");
988f723faa1Seschrock else if (mdb_devinfo2driver(addr, dname, sizeof (dname)) != 0)
989f723faa1Seschrock mdb_printf(" (could not determine driver name)");
990f723faa1Seschrock else
991f723faa1Seschrock mdb_printf(" (driver name: %s)", dname);
992f723faa1Seschrock
9937c478bd9Sstevel@tonic-gate mdb_printf("\n");
9947c478bd9Sstevel@tonic-gate if (data->di_flags & DEVINFO_VERBOSE) {
9957c478bd9Sstevel@tonic-gate mdb_inc_indent(DEVINFO_PROPLIST_INDENT);
9967c478bd9Sstevel@tonic-gate devinfo_print_props("System", dev->devi_sys_prop_ptr);
9977c478bd9Sstevel@tonic-gate devinfo_print_props("Driver", dev->devi_drv_prop_ptr);
9987c478bd9Sstevel@tonic-gate devinfo_print_props("Hardware", dev->devi_hw_prop_ptr);
9997c478bd9Sstevel@tonic-gate devinfo_print_props("Global", global_props);
10007c478bd9Sstevel@tonic-gate
10017c478bd9Sstevel@tonic-gate devinfo_print_pathing(dev->devi_mdi_component,
10027c478bd9Sstevel@tonic-gate dev->devi_mdi_client);
10037c478bd9Sstevel@tonic-gate
10047c478bd9Sstevel@tonic-gate mdb_dec_indent(DEVINFO_PROPLIST_INDENT);
10057c478bd9Sstevel@tonic-gate }
10067c478bd9Sstevel@tonic-gate
10077c478bd9Sstevel@tonic-gate mdb_dec_indent(din->din_depth * DEVINFO_TREE_INDENT);
10087c478bd9Sstevel@tonic-gate return (WALK_NEXT);
10097c478bd9Sstevel@tonic-gate }
10107c478bd9Sstevel@tonic-gate
10117c478bd9Sstevel@tonic-gate /*ARGSUSED*/
10127c478bd9Sstevel@tonic-gate int
prtconf(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)10137c478bd9Sstevel@tonic-gate prtconf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
10147c478bd9Sstevel@tonic-gate {
10157c478bd9Sstevel@tonic-gate devinfo_cb_data_t data;
101614ef2b2fSdmick uintptr_t devinfo_root; /* Address of root of devinfo tree */
10177c478bd9Sstevel@tonic-gate int status;
10187c478bd9Sstevel@tonic-gate
10197c478bd9Sstevel@tonic-gate data.di_flags = DEVINFO_PARENT | DEVINFO_CHILD;
10207c478bd9Sstevel@tonic-gate
10217c478bd9Sstevel@tonic-gate if (mdb_getopts(argc, argv,
10227c478bd9Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, DEVINFO_VERBOSE, &data.di_flags,
10237c478bd9Sstevel@tonic-gate 'p', MDB_OPT_CLRBITS, DEVINFO_CHILD, &data.di_flags,
10247c478bd9Sstevel@tonic-gate 'c', MDB_OPT_CLRBITS, DEVINFO_PARENT, &data.di_flags, NULL) != argc)
10257c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
10267c478bd9Sstevel@tonic-gate
102714ef2b2fSdmick if (mdb_readvar(&devinfo_root, "top_devinfo") == -1) {
102814ef2b2fSdmick mdb_warn("failed to read 'top_devinfo'");
102914ef2b2fSdmick return (NULL);
103014ef2b2fSdmick }
103114ef2b2fSdmick
10327c478bd9Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) == 0) {
10337c478bd9Sstevel@tonic-gate addr = devinfo_root;
10347c478bd9Sstevel@tonic-gate if (data.di_flags & DEVINFO_VERBOSE)
10357c478bd9Sstevel@tonic-gate data.di_flags |= DEVINFO_ALLBOLD;
10367c478bd9Sstevel@tonic-gate }
10377c478bd9Sstevel@tonic-gate
10387c478bd9Sstevel@tonic-gate data.di_base = addr;
10397c478bd9Sstevel@tonic-gate mdb_printf("%<u>%-?s %-50s%</u>\n", "DEVINFO", "NAME");
10407c478bd9Sstevel@tonic-gate
10417c478bd9Sstevel@tonic-gate if ((data.di_flags & (DEVINFO_PARENT | DEVINFO_CHILD)) ==
10427c478bd9Sstevel@tonic-gate (DEVINFO_PARENT | DEVINFO_CHILD)) {
10437c478bd9Sstevel@tonic-gate status = mdb_pwalk("devinfo",
10447c478bd9Sstevel@tonic-gate (mdb_walk_cb_t)devinfo_print, &data, addr);
10457c478bd9Sstevel@tonic-gate } else if (data.di_flags & DEVINFO_PARENT) {
10467c478bd9Sstevel@tonic-gate status = mdb_pwalk("devinfo_parents",
10477c478bd9Sstevel@tonic-gate (mdb_walk_cb_t)devinfo_print, &data, addr);
10487c478bd9Sstevel@tonic-gate } else if (data.di_flags & DEVINFO_CHILD) {
10497c478bd9Sstevel@tonic-gate status = mdb_pwalk("devinfo_children",
10507c478bd9Sstevel@tonic-gate (mdb_walk_cb_t)devinfo_print, &data, addr);
10517c478bd9Sstevel@tonic-gate } else {
10527c478bd9Sstevel@tonic-gate devinfo_node_t din;
10537c478bd9Sstevel@tonic-gate if (mdb_vread(&din.din_dev, sizeof (din.din_dev), addr) == -1) {
10547c478bd9Sstevel@tonic-gate mdb_warn("failed to read device");
10557c478bd9Sstevel@tonic-gate return (DCMD_ERR);
10567c478bd9Sstevel@tonic-gate }
10577c478bd9Sstevel@tonic-gate din.din_depth = 0;
10587c478bd9Sstevel@tonic-gate return (devinfo_print(addr, (struct dev_info *)&din, &data));
10597c478bd9Sstevel@tonic-gate }
10607c478bd9Sstevel@tonic-gate
10617c478bd9Sstevel@tonic-gate if (status == -1) {
10627c478bd9Sstevel@tonic-gate mdb_warn("couldn't walk devinfo tree");
10637c478bd9Sstevel@tonic-gate return (DCMD_ERR);
10647c478bd9Sstevel@tonic-gate }
10657c478bd9Sstevel@tonic-gate
10667c478bd9Sstevel@tonic-gate return (DCMD_OK);
10677c478bd9Sstevel@tonic-gate }
10687c478bd9Sstevel@tonic-gate
10697c478bd9Sstevel@tonic-gate /*ARGSUSED*/
10707c478bd9Sstevel@tonic-gate int
devinfo(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)10717c478bd9Sstevel@tonic-gate devinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
10727c478bd9Sstevel@tonic-gate {
10737c478bd9Sstevel@tonic-gate char tmpstr[MODMAXNAMELEN];
10747c478bd9Sstevel@tonic-gate char nodename[MODMAXNAMELEN];
1075f4da9be0Scth char bindname[MAXPATHLEN];
10767c478bd9Sstevel@tonic-gate int size, length;
10777c478bd9Sstevel@tonic-gate struct dev_info devi;
10787c478bd9Sstevel@tonic-gate devinfo_node_t din;
10797c478bd9Sstevel@tonic-gate devinfo_cb_data_t data;
10807c478bd9Sstevel@tonic-gate
10817c478bd9Sstevel@tonic-gate static const mdb_bitmask_t devi_state_masks[] = {
10827c478bd9Sstevel@tonic-gate { "DEVICE_OFFLINE", DEVI_DEVICE_OFFLINE, DEVI_DEVICE_OFFLINE },
10837c478bd9Sstevel@tonic-gate { "DEVICE_DOWN", DEVI_DEVICE_DOWN, DEVI_DEVICE_DOWN },
10847c478bd9Sstevel@tonic-gate { "DEVICE_DEGRADED", DEVI_DEVICE_DEGRADED, DEVI_DEVICE_DEGRADED },
1085f4da9be0Scth { "DEVICE_REMOVED", DEVI_DEVICE_REMOVED, DEVI_DEVICE_REMOVED },
10867c478bd9Sstevel@tonic-gate { "BUS_QUIESCED", DEVI_BUS_QUIESCED, DEVI_BUS_QUIESCED },
10877c478bd9Sstevel@tonic-gate { "BUS_DOWN", DEVI_BUS_DOWN, DEVI_BUS_DOWN },
10887c478bd9Sstevel@tonic-gate { "NDI_CONFIG", DEVI_NDI_CONFIG, DEVI_NDI_CONFIG },
10897c478bd9Sstevel@tonic-gate
10907c478bd9Sstevel@tonic-gate { "S_ATTACHING", DEVI_S_ATTACHING, DEVI_S_ATTACHING },
10917c478bd9Sstevel@tonic-gate { "S_DETACHING", DEVI_S_DETACHING, DEVI_S_DETACHING },
10927c478bd9Sstevel@tonic-gate { "S_ONLINING", DEVI_S_ONLINING, DEVI_S_ONLINING },
10937c478bd9Sstevel@tonic-gate { "S_OFFLINING", DEVI_S_OFFLINING, DEVI_S_OFFLINING },
10947c478bd9Sstevel@tonic-gate { "S_INVOKING_DACF", DEVI_S_INVOKING_DACF, DEVI_S_INVOKING_DACF },
10957c478bd9Sstevel@tonic-gate { "S_UNBOUND", DEVI_S_UNBOUND, DEVI_S_UNBOUND },
10967c478bd9Sstevel@tonic-gate { "S_REPORT", DEVI_S_REPORT, DEVI_S_REPORT },
10977c478bd9Sstevel@tonic-gate { "S_EVADD", DEVI_S_EVADD, DEVI_S_EVADD },
10987c478bd9Sstevel@tonic-gate { "S_EVREMOVE", DEVI_S_EVREMOVE, DEVI_S_EVREMOVE },
1099f4da9be0Scth { "S_NEED_RESET", DEVI_S_NEED_RESET, DEVI_S_NEED_RESET },
11007c478bd9Sstevel@tonic-gate { NULL, 0, 0 }
11017c478bd9Sstevel@tonic-gate };
11027c478bd9Sstevel@tonic-gate
11037c478bd9Sstevel@tonic-gate static const mdb_bitmask_t devi_flags_masks[] = {
11047c478bd9Sstevel@tonic-gate { "BUSY", DEVI_BUSY, DEVI_BUSY },
11057c478bd9Sstevel@tonic-gate { "MADE_CHILDREN", DEVI_MADE_CHILDREN, DEVI_MADE_CHILDREN },
11067c478bd9Sstevel@tonic-gate { "ATTACHED_CHILDREN",
11077c478bd9Sstevel@tonic-gate DEVI_ATTACHED_CHILDREN, DEVI_ATTACHED_CHILDREN},
11087c478bd9Sstevel@tonic-gate { "BRANCH_HELD", DEVI_BRANCH_HELD, DEVI_BRANCH_HELD },
1109f4da9be0Scth { "NO_BIND", DEVI_NO_BIND, DEVI_NO_BIND },
1110*8451e9c3SGavin Maltby { "DEVI_CACHED_DEVID",
1111*8451e9c3SGavin Maltby DEVI_CACHED_DEVID, DEVI_CACHED_DEVID },
1112f4da9be0Scth { "PHCI_SIGNALS_VHCI",
1113f4da9be0Scth DEVI_PHCI_SIGNALS_VHCI,
1114f4da9be0Scth DEVI_PHCI_SIGNALS_VHCI },
1115f4da9be0Scth { "REBIND", DEVI_REBIND, DEVI_REBIND },
11167c478bd9Sstevel@tonic-gate { NULL, 0, 0 }
11177c478bd9Sstevel@tonic-gate };
11187c478bd9Sstevel@tonic-gate
11197c478bd9Sstevel@tonic-gate data.di_flags = DEVINFO_VERBOSE;
11207c478bd9Sstevel@tonic-gate data.di_base = addr;
11217c478bd9Sstevel@tonic-gate
11227c478bd9Sstevel@tonic-gate if (mdb_getopts(argc, argv,
11237c478bd9Sstevel@tonic-gate 'q', MDB_OPT_CLRBITS, DEVINFO_VERBOSE, &data.di_flags,
11247c478bd9Sstevel@tonic-gate 's', MDB_OPT_SETBITS, DEVINFO_SUMMARY, &data.di_flags, NULL)
11257c478bd9Sstevel@tonic-gate != argc)
11267c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
11277c478bd9Sstevel@tonic-gate
11287c478bd9Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) == 0) {
11297c478bd9Sstevel@tonic-gate mdb_warn(
11307c478bd9Sstevel@tonic-gate "devinfo doesn't give global information (try prtconf)\n");
11317c478bd9Sstevel@tonic-gate return (DCMD_ERR);
11327c478bd9Sstevel@tonic-gate }
11337c478bd9Sstevel@tonic-gate
11347c478bd9Sstevel@tonic-gate if (DCMD_HDRSPEC(flags) && data.di_flags & DEVINFO_SUMMARY)
11357c478bd9Sstevel@tonic-gate mdb_printf(
11367c478bd9Sstevel@tonic-gate "%-?s %5s %?s %-20s %-s\n"
11377c478bd9Sstevel@tonic-gate "%-?s %5s %?s %-20s %-s\n"
11387c478bd9Sstevel@tonic-gate "%<u>%-?s %5s %?s %-20s %-15s%</u>\n",
11397c478bd9Sstevel@tonic-gate "DEVINFO", "MAJ", "REFCNT", "NODENAME", "NODESTATE",
11407c478bd9Sstevel@tonic-gate "", "INST", "CIRCULAR", "BINDNAME", "STATE",
11417c478bd9Sstevel@tonic-gate "", "", "THREAD", "", "FLAGS");
11427c478bd9Sstevel@tonic-gate
11437c478bd9Sstevel@tonic-gate if (mdb_vread(&devi, sizeof (devi), addr) == -1) {
11447c478bd9Sstevel@tonic-gate mdb_warn("failed to read device");
11457c478bd9Sstevel@tonic-gate return (DCMD_ERR);
11467c478bd9Sstevel@tonic-gate }
11477c478bd9Sstevel@tonic-gate
11487c478bd9Sstevel@tonic-gate if (data.di_flags & DEVINFO_SUMMARY) {
11497c478bd9Sstevel@tonic-gate *nodename = '\0';
11507c478bd9Sstevel@tonic-gate size = sizeof (nodename);
11517c478bd9Sstevel@tonic-gate
11527c478bd9Sstevel@tonic-gate if ((length = mdb_readstr(tmpstr, size,
11537c478bd9Sstevel@tonic-gate (uintptr_t)devi.devi_node_name)) > 0) {
11547c478bd9Sstevel@tonic-gate strcat(nodename, tmpstr);
11557c478bd9Sstevel@tonic-gate size -= length;
11567c478bd9Sstevel@tonic-gate }
11577c478bd9Sstevel@tonic-gate
11587c478bd9Sstevel@tonic-gate if (devi.devi_addr != NULL && mdb_readstr(tmpstr, size - 1,
11597c478bd9Sstevel@tonic-gate (uintptr_t)devi.devi_addr) > 0) {
11607c478bd9Sstevel@tonic-gate strcat(nodename, "@");
11617c478bd9Sstevel@tonic-gate strcat(nodename, tmpstr);
11627c478bd9Sstevel@tonic-gate }
11637c478bd9Sstevel@tonic-gate
11647c478bd9Sstevel@tonic-gate if (mdb_readstr(bindname, sizeof (bindname),
11657c478bd9Sstevel@tonic-gate (uintptr_t)devi.devi_binding_name) == -1)
11667c478bd9Sstevel@tonic-gate *bindname = '\0';
11677c478bd9Sstevel@tonic-gate
11687c478bd9Sstevel@tonic-gate mdb_printf("%0?p %5d %?d %-20s %s\n",
11697c478bd9Sstevel@tonic-gate addr, devi.devi_major, devi.devi_ref, nodename,
11707c478bd9Sstevel@tonic-gate di_state[MIN(devi.devi_node_state + 1, DI_STATE_MAX)]);
11717c478bd9Sstevel@tonic-gate mdb_printf("%?s %5d %?d %-20s <%b>\n",
11727c478bd9Sstevel@tonic-gate "", devi.devi_instance, devi.devi_circular, bindname,
11737c478bd9Sstevel@tonic-gate devi.devi_state, devi_state_masks);
11747c478bd9Sstevel@tonic-gate mdb_printf("%?s %5s %?p %-20s <%b>\n\n",
11757c478bd9Sstevel@tonic-gate "", "", devi.devi_busy_thread, "",
11767c478bd9Sstevel@tonic-gate devi.devi_flags, devi_flags_masks);
11777c478bd9Sstevel@tonic-gate
11787c478bd9Sstevel@tonic-gate return (DCMD_OK);
11797c478bd9Sstevel@tonic-gate } else {
11807c478bd9Sstevel@tonic-gate din.din_dev = devi;
11817c478bd9Sstevel@tonic-gate din.din_depth = 0;
11827c478bd9Sstevel@tonic-gate return (devinfo_print(addr, (struct dev_info *)&din, &data));
11837c478bd9Sstevel@tonic-gate }
11847c478bd9Sstevel@tonic-gate }
11857c478bd9Sstevel@tonic-gate
11867c478bd9Sstevel@tonic-gate /*ARGSUSED*/
11877c478bd9Sstevel@tonic-gate int
m2d_walk_dinfo(uintptr_t addr,struct dev_info * di,char * mod_name)11887c478bd9Sstevel@tonic-gate m2d_walk_dinfo(uintptr_t addr, struct dev_info *di, char *mod_name)
11897c478bd9Sstevel@tonic-gate {
11907c478bd9Sstevel@tonic-gate char name[MODMAXNAMELEN];
11917c478bd9Sstevel@tonic-gate
11927c478bd9Sstevel@tonic-gate if (mdb_readstr(name, MODMAXNAMELEN,
11937c478bd9Sstevel@tonic-gate (uintptr_t)di->devi_binding_name) == -1) {
11947c478bd9Sstevel@tonic-gate mdb_warn("couldn't read devi_binding_name at %p",
11957c478bd9Sstevel@tonic-gate di->devi_binding_name);
11967c478bd9Sstevel@tonic-gate return (WALK_ERR);
11977c478bd9Sstevel@tonic-gate }
11987c478bd9Sstevel@tonic-gate
11997c478bd9Sstevel@tonic-gate if (strcmp(name, mod_name) == 0)
12007c478bd9Sstevel@tonic-gate mdb_printf("%p\n", addr);
12017c478bd9Sstevel@tonic-gate
12027c478bd9Sstevel@tonic-gate return (WALK_NEXT);
12037c478bd9Sstevel@tonic-gate }
12047c478bd9Sstevel@tonic-gate
12057c478bd9Sstevel@tonic-gate /*ARGSUSED*/
12067c478bd9Sstevel@tonic-gate int
modctl2devinfo(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)12077c478bd9Sstevel@tonic-gate modctl2devinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
12087c478bd9Sstevel@tonic-gate {
12097c478bd9Sstevel@tonic-gate struct modctl modctl;
12107c478bd9Sstevel@tonic-gate char name[MODMAXNAMELEN];
12117c478bd9Sstevel@tonic-gate
12127c478bd9Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC))
12137c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
12147c478bd9Sstevel@tonic-gate
12157c478bd9Sstevel@tonic-gate if (mdb_vread(&modctl, sizeof (modctl), addr) == -1) {
12167c478bd9Sstevel@tonic-gate mdb_warn("couldn't read modctl at %p", addr);
12177c478bd9Sstevel@tonic-gate return (DCMD_ERR);
12187c478bd9Sstevel@tonic-gate }
12197c478bd9Sstevel@tonic-gate
12207c478bd9Sstevel@tonic-gate if (mdb_readstr(name, MODMAXNAMELEN,
12217c478bd9Sstevel@tonic-gate (uintptr_t)modctl.mod_modname) == -1) {
12227c478bd9Sstevel@tonic-gate mdb_warn("couldn't read modname at %p", modctl.mod_modname);
12237c478bd9Sstevel@tonic-gate return (DCMD_ERR);
12247c478bd9Sstevel@tonic-gate }
12257c478bd9Sstevel@tonic-gate
12267c478bd9Sstevel@tonic-gate if (mdb_walk("devinfo", (mdb_walk_cb_t)m2d_walk_dinfo, name) == -1) {
12277c478bd9Sstevel@tonic-gate mdb_warn("couldn't walk devinfo");
12287c478bd9Sstevel@tonic-gate return (DCMD_ERR);
12297c478bd9Sstevel@tonic-gate }
12307c478bd9Sstevel@tonic-gate
12317c478bd9Sstevel@tonic-gate return (DCMD_OK);
12327c478bd9Sstevel@tonic-gate }
12337c478bd9Sstevel@tonic-gate
12347c478bd9Sstevel@tonic-gate static int
major_to_addr(major_t major,uintptr_t * vaddr)12357c478bd9Sstevel@tonic-gate major_to_addr(major_t major, uintptr_t *vaddr)
12367c478bd9Sstevel@tonic-gate {
12377c478bd9Sstevel@tonic-gate uint_t devcnt;
12387c478bd9Sstevel@tonic-gate uintptr_t devnamesp;
12397c478bd9Sstevel@tonic-gate
12407c478bd9Sstevel@tonic-gate if (mdb_readvar(&devcnt, "devcnt") == -1) {
12417c478bd9Sstevel@tonic-gate mdb_warn("failed to read 'devcnt'");
12427c478bd9Sstevel@tonic-gate return (-1);
12437c478bd9Sstevel@tonic-gate }
12447c478bd9Sstevel@tonic-gate
12457c478bd9Sstevel@tonic-gate if (mdb_readvar(&devnamesp, "devnamesp") == -1) {
12467c478bd9Sstevel@tonic-gate mdb_warn("failed to read 'devnamesp'");
12477c478bd9Sstevel@tonic-gate return (-1);
12487c478bd9Sstevel@tonic-gate }
12497c478bd9Sstevel@tonic-gate
12507c478bd9Sstevel@tonic-gate if (major >= devcnt) {
12517c478bd9Sstevel@tonic-gate mdb_warn("%x is out of range [0x0-0x%x]\n", major, devcnt - 1);
12527c478bd9Sstevel@tonic-gate return (-1);
12537c478bd9Sstevel@tonic-gate }
12547c478bd9Sstevel@tonic-gate
12557c478bd9Sstevel@tonic-gate *vaddr = devnamesp + (major * sizeof (struct devnames));
12567c478bd9Sstevel@tonic-gate return (0);
12577c478bd9Sstevel@tonic-gate }
12587c478bd9Sstevel@tonic-gate
12597c478bd9Sstevel@tonic-gate /*ARGSUSED*/
12607c478bd9Sstevel@tonic-gate int
devnames(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)12617c478bd9Sstevel@tonic-gate devnames(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
12627c478bd9Sstevel@tonic-gate {
12637c478bd9Sstevel@tonic-gate static const mdb_bitmask_t dn_flag_bits[] = {
12647c478bd9Sstevel@tonic-gate { "DN_CONF_PARSED", DN_CONF_PARSED, DN_CONF_PARSED },
12657c478bd9Sstevel@tonic-gate { "DN_DRIVER_BUSY", DN_DRIVER_BUSY, DN_DRIVER_BUSY },
12667c478bd9Sstevel@tonic-gate { "DN_DRIVER_HELD", DN_DRIVER_HELD, DN_DRIVER_HELD },
12677c478bd9Sstevel@tonic-gate { "DN_TAKEN_GETUDEV", DN_TAKEN_GETUDEV, DN_TAKEN_GETUDEV },
12687c478bd9Sstevel@tonic-gate { "DN_DRIVER_REMOVED", DN_DRIVER_REMOVED, DN_DRIVER_REMOVED},
12697c478bd9Sstevel@tonic-gate { "DN_FORCE_ATTACH", DN_FORCE_ATTACH, DN_FORCE_ATTACH},
12707c478bd9Sstevel@tonic-gate { "DN_LEAF_DRIVER", DN_LEAF_DRIVER, DN_LEAF_DRIVER},
12717c478bd9Sstevel@tonic-gate { "DN_NETWORK_DRIVER", DN_NETWORK_DRIVER, DN_NETWORK_DRIVER},
12727c478bd9Sstevel@tonic-gate { "DN_NO_AUTODETACH", DN_NO_AUTODETACH, DN_NO_AUTODETACH },
12736e13b8c3Scth { "DN_GLDV3_DRIVER", DN_GLDV3_DRIVER, DN_GLDV3_DRIVER},
127452cac543Sramat { "DN_PHCI_DRIVER", DN_PHCI_DRIVER, DN_PHCI_DRIVER},
1275602ca9eaScth { "DN_OPEN_RETURNS_EINTR", \
1276602ca9eaScth DN_OPEN_RETURNS_EINTR, DN_OPEN_RETURNS_EINTR},
1277602ca9eaScth { "DN_SCSI_SIZE_CLEAN", DN_SCSI_SIZE_CLEAN, DN_SCSI_SIZE_CLEAN},
1278095be824SCathy Zhou { "DN_NETWORK_PHYSDRIVER", \
1279095be824SCathy Zhou DN_NETWORK_PHYSDRIVER, DN_NETWORK_PHYSDRIVER},
12807c478bd9Sstevel@tonic-gate { NULL, 0, 0 }
12817c478bd9Sstevel@tonic-gate };
12827c478bd9Sstevel@tonic-gate
12837c478bd9Sstevel@tonic-gate const mdb_arg_t *argp = NULL;
12847c478bd9Sstevel@tonic-gate uint_t opt_v = FALSE, opt_m = FALSE;
12857c478bd9Sstevel@tonic-gate major_t major;
12867c478bd9Sstevel@tonic-gate size_t i;
12877c478bd9Sstevel@tonic-gate
12887c478bd9Sstevel@tonic-gate char name[MODMAXNAMELEN + 1];
12897c478bd9Sstevel@tonic-gate struct devnames dn;
12907c478bd9Sstevel@tonic-gate
12917c478bd9Sstevel@tonic-gate if ((i = mdb_getopts(argc, argv,
12927c478bd9Sstevel@tonic-gate 'm', MDB_OPT_SETBITS, TRUE, &opt_m,
12937c478bd9Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, TRUE, &opt_v,
12947c478bd9Sstevel@tonic-gate NULL)) != argc) {
12957c478bd9Sstevel@tonic-gate if (argc - i > 1)
12967c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
12977c478bd9Sstevel@tonic-gate argp = &argv[i];
12987c478bd9Sstevel@tonic-gate }
12997c478bd9Sstevel@tonic-gate
13007c478bd9Sstevel@tonic-gate if (opt_m) {
13017c478bd9Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC))
13027c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
13037c478bd9Sstevel@tonic-gate
13047c478bd9Sstevel@tonic-gate if (major_to_addr(addr, &addr) == -1)
13057c478bd9Sstevel@tonic-gate return (DCMD_ERR);
13067c478bd9Sstevel@tonic-gate
13077c478bd9Sstevel@tonic-gate } else if (!(flags & DCMD_ADDRSPEC)) {
13087c478bd9Sstevel@tonic-gate if (argp == NULL) {
13097c478bd9Sstevel@tonic-gate if (mdb_walk_dcmd("devnames", "devnames", argc, argv)) {
13107c478bd9Sstevel@tonic-gate mdb_warn("failed to walk devnames");
13117c478bd9Sstevel@tonic-gate return (DCMD_ERR);
13127c478bd9Sstevel@tonic-gate }
13137c478bd9Sstevel@tonic-gate return (DCMD_OK);
13147c478bd9Sstevel@tonic-gate }
13157c478bd9Sstevel@tonic-gate
13167c478bd9Sstevel@tonic-gate if (argp->a_type == MDB_TYPE_IMMEDIATE)
13177c478bd9Sstevel@tonic-gate major = (major_t)argp->a_un.a_val;
13187c478bd9Sstevel@tonic-gate else
13197c478bd9Sstevel@tonic-gate major = (major_t)mdb_strtoull(argp->a_un.a_str);
13207c478bd9Sstevel@tonic-gate
13217c478bd9Sstevel@tonic-gate if (major_to_addr(major, &addr) == -1)
13227c478bd9Sstevel@tonic-gate return (DCMD_ERR);
13237c478bd9Sstevel@tonic-gate }
13247c478bd9Sstevel@tonic-gate
13257c478bd9Sstevel@tonic-gate if (mdb_vread(&dn, sizeof (struct devnames), addr) == -1) {
13267c478bd9Sstevel@tonic-gate mdb_warn("failed to read devnames struct at %p", addr);
13277c478bd9Sstevel@tonic-gate return (DCMD_ERR);
13287c478bd9Sstevel@tonic-gate }
13297c478bd9Sstevel@tonic-gate
13307c478bd9Sstevel@tonic-gate if (DCMD_HDRSPEC(flags)) {
13317c478bd9Sstevel@tonic-gate if (opt_v)
13327c478bd9Sstevel@tonic-gate mdb_printf("%<u>%-16s%</u>\n", "NAME");
13337c478bd9Sstevel@tonic-gate else
13347c478bd9Sstevel@tonic-gate mdb_printf("%<u>%-16s %-?s%</u>\n", "NAME", "DN_HEAD");
13357c478bd9Sstevel@tonic-gate }
13367c478bd9Sstevel@tonic-gate
13377c478bd9Sstevel@tonic-gate if ((flags & DCMD_LOOP) && (dn.dn_name == NULL))
13387c478bd9Sstevel@tonic-gate return (DCMD_OK); /* Skip empty slots if we're printing table */
13397c478bd9Sstevel@tonic-gate
13407c478bd9Sstevel@tonic-gate if (mdb_readstr(name, sizeof (name), (uintptr_t)dn.dn_name) == -1)
13417c478bd9Sstevel@tonic-gate (void) mdb_snprintf(name, sizeof (name), "0x%p", dn.dn_name);
13427c478bd9Sstevel@tonic-gate
13437c478bd9Sstevel@tonic-gate if (opt_v) {
13447c478bd9Sstevel@tonic-gate ddi_prop_list_t prop_list;
13457c478bd9Sstevel@tonic-gate mdb_printf("%<b>%-16s%</b>\n", name);
13467c478bd9Sstevel@tonic-gate mdb_inc_indent(2);
13477c478bd9Sstevel@tonic-gate
13487c478bd9Sstevel@tonic-gate mdb_printf(" flags %b\n", dn.dn_flags, dn_flag_bits);
13497c478bd9Sstevel@tonic-gate mdb_printf(" pl %p\n", (void *)dn.dn_pl);
13507c478bd9Sstevel@tonic-gate mdb_printf(" head %p\n", dn.dn_head);
13517c478bd9Sstevel@tonic-gate mdb_printf(" instance %d\n", dn.dn_instance);
13527c478bd9Sstevel@tonic-gate mdb_printf(" inlist %p\n", dn.dn_inlist);
13537c478bd9Sstevel@tonic-gate mdb_printf("global_prop_ptr %p\n", dn.dn_global_prop_ptr);
13547c478bd9Sstevel@tonic-gate if (mdb_vread(&prop_list, sizeof (ddi_prop_list_t),
13557c478bd9Sstevel@tonic-gate (uintptr_t)dn.dn_global_prop_ptr) != -1) {
13567c478bd9Sstevel@tonic-gate devinfo_print_props(NULL, prop_list.prop_list);
13577c478bd9Sstevel@tonic-gate }
13587c478bd9Sstevel@tonic-gate
13597c478bd9Sstevel@tonic-gate mdb_dec_indent(2);
13607c478bd9Sstevel@tonic-gate } else
13617c478bd9Sstevel@tonic-gate mdb_printf("%-16s %-?p\n", name, dn.dn_head);
13627c478bd9Sstevel@tonic-gate
13637c478bd9Sstevel@tonic-gate return (DCMD_OK);
13647c478bd9Sstevel@tonic-gate }
13657c478bd9Sstevel@tonic-gate
13667c478bd9Sstevel@tonic-gate /*ARGSUSED*/
13677c478bd9Sstevel@tonic-gate int
name2major(uintptr_t vaddr,uint_t flags,int argc,const mdb_arg_t * argv)13687c478bd9Sstevel@tonic-gate name2major(uintptr_t vaddr, uint_t flags, int argc, const mdb_arg_t *argv)
13697c478bd9Sstevel@tonic-gate {
13707c478bd9Sstevel@tonic-gate major_t major;
13717c478bd9Sstevel@tonic-gate
13727c478bd9Sstevel@tonic-gate if (flags & DCMD_ADDRSPEC)
13737c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
13747c478bd9Sstevel@tonic-gate
13757c478bd9Sstevel@tonic-gate if (argc != 1 || argv->a_type != MDB_TYPE_STRING)
13767c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
13777c478bd9Sstevel@tonic-gate
13787c478bd9Sstevel@tonic-gate if (mdb_name_to_major(argv->a_un.a_str, &major) != 0) {
13797c478bd9Sstevel@tonic-gate mdb_warn("failed to convert name to major number\n");
13807c478bd9Sstevel@tonic-gate return (DCMD_ERR);
13817c478bd9Sstevel@tonic-gate }
13827c478bd9Sstevel@tonic-gate
13837c478bd9Sstevel@tonic-gate mdb_printf("0x%x\n", major);
13847c478bd9Sstevel@tonic-gate return (DCMD_OK);
13857c478bd9Sstevel@tonic-gate }
13867c478bd9Sstevel@tonic-gate
13877c478bd9Sstevel@tonic-gate /*
13887c478bd9Sstevel@tonic-gate * Get a numerical argument of a dcmd from addr if an address is specified
13897c478bd9Sstevel@tonic-gate * or from argv if no address is specified. Return the argument in ret.
13907c478bd9Sstevel@tonic-gate */
13917c478bd9Sstevel@tonic-gate static int
getarg(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv,uintptr_t * ret)13927c478bd9Sstevel@tonic-gate getarg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv,
13937c478bd9Sstevel@tonic-gate uintptr_t *ret)
13947c478bd9Sstevel@tonic-gate {
13957c478bd9Sstevel@tonic-gate if (argc == 0 && (flags & DCMD_ADDRSPEC)) {
13967c478bd9Sstevel@tonic-gate *ret = addr;
13977c478bd9Sstevel@tonic-gate
13987c478bd9Sstevel@tonic-gate } else if (argc == 1 && !(flags & DCMD_ADDRSPEC)) {
13997c478bd9Sstevel@tonic-gate *ret = (argv[0].a_type == MDB_TYPE_IMMEDIATE) ?
14007c478bd9Sstevel@tonic-gate (uintptr_t)argv[0].a_un.a_val :
14017c478bd9Sstevel@tonic-gate (uintptr_t)mdb_strtoull(argv->a_un.a_str);
14027c478bd9Sstevel@tonic-gate
14037c478bd9Sstevel@tonic-gate } else {
14047c478bd9Sstevel@tonic-gate return (-1);
14057c478bd9Sstevel@tonic-gate }
14067c478bd9Sstevel@tonic-gate
14077c478bd9Sstevel@tonic-gate return (0);
14087c478bd9Sstevel@tonic-gate }
14097c478bd9Sstevel@tonic-gate
14107c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14117c478bd9Sstevel@tonic-gate int
major2name(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)14127c478bd9Sstevel@tonic-gate major2name(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
14137c478bd9Sstevel@tonic-gate {
14147c478bd9Sstevel@tonic-gate uintptr_t major;
14157c478bd9Sstevel@tonic-gate const char *name;
14167c478bd9Sstevel@tonic-gate
14177c478bd9Sstevel@tonic-gate if (getarg(addr, flags, argc, argv, &major) < 0)
14187c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
14197c478bd9Sstevel@tonic-gate
14207c478bd9Sstevel@tonic-gate if ((name = mdb_major_to_name((major_t)major)) == NULL) {
14217c478bd9Sstevel@tonic-gate mdb_warn("failed to convert major number to name\n");
14227c478bd9Sstevel@tonic-gate return (DCMD_ERR);
14237c478bd9Sstevel@tonic-gate }
14247c478bd9Sstevel@tonic-gate
14257c478bd9Sstevel@tonic-gate mdb_printf("%s\n", name);
14267c478bd9Sstevel@tonic-gate return (DCMD_OK);
14277c478bd9Sstevel@tonic-gate }
14287c478bd9Sstevel@tonic-gate
14297c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14307c478bd9Sstevel@tonic-gate int
dev2major(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)14317c478bd9Sstevel@tonic-gate dev2major(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
14327c478bd9Sstevel@tonic-gate {
14337c478bd9Sstevel@tonic-gate uintptr_t dev;
14347c478bd9Sstevel@tonic-gate
14357c478bd9Sstevel@tonic-gate if (getarg(addr, flags, argc, argv, &dev) < 0)
14367c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
14377c478bd9Sstevel@tonic-gate
14387c478bd9Sstevel@tonic-gate if (flags & DCMD_PIPE_OUT)
14397c478bd9Sstevel@tonic-gate mdb_printf("%x\n", getmajor(dev));
14407c478bd9Sstevel@tonic-gate else
14417c478bd9Sstevel@tonic-gate mdb_printf("0x%x (0t%d)\n", getmajor(dev), getmajor(dev));
14427c478bd9Sstevel@tonic-gate
14437c478bd9Sstevel@tonic-gate return (DCMD_OK);
14447c478bd9Sstevel@tonic-gate }
14457c478bd9Sstevel@tonic-gate
14467c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14477c478bd9Sstevel@tonic-gate int
dev2minor(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)14487c478bd9Sstevel@tonic-gate dev2minor(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
14497c478bd9Sstevel@tonic-gate {
14507c478bd9Sstevel@tonic-gate uintptr_t dev;
14517c478bd9Sstevel@tonic-gate
14527c478bd9Sstevel@tonic-gate if (getarg(addr, flags, argc, argv, &dev) < 0)
14537c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
14547c478bd9Sstevel@tonic-gate
14557c478bd9Sstevel@tonic-gate if (flags & DCMD_PIPE_OUT)
14567c478bd9Sstevel@tonic-gate mdb_printf("%x\n", getminor(dev));
14577c478bd9Sstevel@tonic-gate else
14587c478bd9Sstevel@tonic-gate mdb_printf("0x%x (0t%d)\n", getminor(dev), getminor(dev));
14597c478bd9Sstevel@tonic-gate
14607c478bd9Sstevel@tonic-gate return (DCMD_OK);
14617c478bd9Sstevel@tonic-gate }
14627c478bd9Sstevel@tonic-gate
14637c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14647c478bd9Sstevel@tonic-gate int
devt(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)14657c478bd9Sstevel@tonic-gate devt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
14667c478bd9Sstevel@tonic-gate {
14677c478bd9Sstevel@tonic-gate uintptr_t dev;
14687c478bd9Sstevel@tonic-gate
14697c478bd9Sstevel@tonic-gate if (getarg(addr, flags, argc, argv, &dev) < 0)
14707c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
14717c478bd9Sstevel@tonic-gate
14727c478bd9Sstevel@tonic-gate if (DCMD_HDRSPEC(flags)) {
14737c478bd9Sstevel@tonic-gate mdb_printf("%<u>%10s%</u> %<u>%10s%</u>\n", "MAJOR",
14747c478bd9Sstevel@tonic-gate "MINOR");
14757c478bd9Sstevel@tonic-gate }
14767c478bd9Sstevel@tonic-gate
14777c478bd9Sstevel@tonic-gate mdb_printf("%10d %10d\n", getmajor(dev), getminor(dev));
14787c478bd9Sstevel@tonic-gate
14797c478bd9Sstevel@tonic-gate return (DCMD_OK);
14807c478bd9Sstevel@tonic-gate }
14817c478bd9Sstevel@tonic-gate
14827c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14837c478bd9Sstevel@tonic-gate int
softstate(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)14847c478bd9Sstevel@tonic-gate softstate(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
14857c478bd9Sstevel@tonic-gate {
14867c478bd9Sstevel@tonic-gate uintptr_t statep;
14877c478bd9Sstevel@tonic-gate int instance;
14887c478bd9Sstevel@tonic-gate
14897c478bd9Sstevel@tonic-gate
14907c478bd9Sstevel@tonic-gate if (argc != 1) {
14917c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
14927c478bd9Sstevel@tonic-gate }
14937c478bd9Sstevel@tonic-gate
14947c478bd9Sstevel@tonic-gate if (argv[0].a_type == MDB_TYPE_IMMEDIATE)
14957c478bd9Sstevel@tonic-gate instance = argv[0].a_un.a_val;
14967c478bd9Sstevel@tonic-gate else
14977c478bd9Sstevel@tonic-gate instance = mdb_strtoull(argv->a_un.a_str);
14987c478bd9Sstevel@tonic-gate
14997c478bd9Sstevel@tonic-gate if (mdb_get_soft_state_byaddr(addr, instance, &statep, NULL, 0) == -1) {
15007c478bd9Sstevel@tonic-gate if (errno == ENOENT) {
15017c478bd9Sstevel@tonic-gate mdb_warn("instance %d unused\n", instance);
15027c478bd9Sstevel@tonic-gate } else {
15037c478bd9Sstevel@tonic-gate mdb_warn("couldn't determine softstate for "
15047c478bd9Sstevel@tonic-gate "instance %d", instance);
15057c478bd9Sstevel@tonic-gate }
15067c478bd9Sstevel@tonic-gate
15077c478bd9Sstevel@tonic-gate return (DCMD_ERR);
15087c478bd9Sstevel@tonic-gate }
15097c478bd9Sstevel@tonic-gate
15107c478bd9Sstevel@tonic-gate mdb_printf("%p\n", statep);
15117c478bd9Sstevel@tonic-gate return (DCMD_OK);
15127c478bd9Sstevel@tonic-gate }
15137c478bd9Sstevel@tonic-gate
15147c478bd9Sstevel@tonic-gate /*
15157c478bd9Sstevel@tonic-gate * Walker for all possible pointers to a driver state struct in an
15167c478bd9Sstevel@tonic-gate * i_ddi_soft_state instance chain. Returns all non-NULL pointers.
15177c478bd9Sstevel@tonic-gate */
15187c478bd9Sstevel@tonic-gate typedef struct soft_state_walk {
15197c478bd9Sstevel@tonic-gate struct i_ddi_soft_state ssw_ss; /* Local copy of i_ddi_soft_state */
15207c478bd9Sstevel@tonic-gate void **ssw_pointers; /* to driver state structs */
15217c478bd9Sstevel@tonic-gate uint_t ssw_index; /* array entry we're using */
15227c478bd9Sstevel@tonic-gate } soft_state_walk_t;
15237c478bd9Sstevel@tonic-gate
15247c478bd9Sstevel@tonic-gate int
soft_state_walk_init(mdb_walk_state_t * wsp)15257c478bd9Sstevel@tonic-gate soft_state_walk_init(mdb_walk_state_t *wsp)
15267c478bd9Sstevel@tonic-gate {
15277c478bd9Sstevel@tonic-gate soft_state_walk_t *sst;
15287c478bd9Sstevel@tonic-gate
15297c478bd9Sstevel@tonic-gate
15307c478bd9Sstevel@tonic-gate if (wsp->walk_addr == NULL)
15317c478bd9Sstevel@tonic-gate return (WALK_DONE);
15327c478bd9Sstevel@tonic-gate
15337c478bd9Sstevel@tonic-gate sst = mdb_zalloc(sizeof (soft_state_walk_t), UM_SLEEP|UM_GC);
15347c478bd9Sstevel@tonic-gate wsp->walk_data = sst;
15357c478bd9Sstevel@tonic-gate
15367c478bd9Sstevel@tonic-gate
15377c478bd9Sstevel@tonic-gate if (mdb_vread(&(sst->ssw_ss), sizeof (sst->ssw_ss), wsp->walk_addr) !=
15387c478bd9Sstevel@tonic-gate sizeof (sst->ssw_ss)) {
15397c478bd9Sstevel@tonic-gate mdb_warn("failed to read i_ddi_soft_state at %p",
15407c478bd9Sstevel@tonic-gate wsp->walk_addr);
15417c478bd9Sstevel@tonic-gate return (WALK_ERR);
15427c478bd9Sstevel@tonic-gate }
15437c478bd9Sstevel@tonic-gate
15447c478bd9Sstevel@tonic-gate
15457c478bd9Sstevel@tonic-gate /* Read array of pointers to state structs into local storage. */
15467c478bd9Sstevel@tonic-gate sst->ssw_pointers = mdb_alloc((sst->ssw_ss.n_items * sizeof (void *)),
15477c478bd9Sstevel@tonic-gate UM_SLEEP|UM_GC);
15487c478bd9Sstevel@tonic-gate
15497c478bd9Sstevel@tonic-gate if (mdb_vread(sst->ssw_pointers, (sst->ssw_ss.n_items *
15507c478bd9Sstevel@tonic-gate sizeof (void *)), (uintptr_t)sst->ssw_ss.array) !=
15517c478bd9Sstevel@tonic-gate (sst->ssw_ss.n_items * sizeof (void *))) {
15527c478bd9Sstevel@tonic-gate mdb_warn("failed to read i_ddi_soft_state at %p",
15537c478bd9Sstevel@tonic-gate wsp->walk_addr);
15547c478bd9Sstevel@tonic-gate return (WALK_ERR);
15557c478bd9Sstevel@tonic-gate }
15567c478bd9Sstevel@tonic-gate
15577c478bd9Sstevel@tonic-gate sst->ssw_index = 0;
15587c478bd9Sstevel@tonic-gate
15597c478bd9Sstevel@tonic-gate return (WALK_NEXT);
15607c478bd9Sstevel@tonic-gate }
15617c478bd9Sstevel@tonic-gate
15627c478bd9Sstevel@tonic-gate int
soft_state_walk_step(mdb_walk_state_t * wsp)15637c478bd9Sstevel@tonic-gate soft_state_walk_step(mdb_walk_state_t *wsp)
15647c478bd9Sstevel@tonic-gate {
15657c478bd9Sstevel@tonic-gate soft_state_walk_t *sst = (soft_state_walk_t *)wsp->walk_data;
15667c478bd9Sstevel@tonic-gate int status = WALK_NEXT;
15677c478bd9Sstevel@tonic-gate
15687c478bd9Sstevel@tonic-gate
15697c478bd9Sstevel@tonic-gate /*
15707c478bd9Sstevel@tonic-gate * If the entry indexed has a valid pointer to a soft state struct,
15717c478bd9Sstevel@tonic-gate * invoke caller's callback func.
15727c478bd9Sstevel@tonic-gate */
15737c478bd9Sstevel@tonic-gate if (sst->ssw_pointers[sst->ssw_index] != NULL) {
15747c478bd9Sstevel@tonic-gate status = wsp->walk_callback(
15757c478bd9Sstevel@tonic-gate (uintptr_t)(sst->ssw_pointers[sst->ssw_index]), NULL,
15767c478bd9Sstevel@tonic-gate wsp->walk_cbdata);
15777c478bd9Sstevel@tonic-gate }
15787c478bd9Sstevel@tonic-gate
15797c478bd9Sstevel@tonic-gate sst->ssw_index += 1;
15807c478bd9Sstevel@tonic-gate
15817c478bd9Sstevel@tonic-gate if (sst->ssw_index == sst->ssw_ss.n_items)
15827c478bd9Sstevel@tonic-gate return (WALK_DONE);
15837c478bd9Sstevel@tonic-gate
15847c478bd9Sstevel@tonic-gate return (status);
15857c478bd9Sstevel@tonic-gate }
15867c478bd9Sstevel@tonic-gate
15877c478bd9Sstevel@tonic-gate int
soft_state_all_walk_step(mdb_walk_state_t * wsp)15887c478bd9Sstevel@tonic-gate soft_state_all_walk_step(mdb_walk_state_t *wsp)
15897c478bd9Sstevel@tonic-gate {
15907c478bd9Sstevel@tonic-gate soft_state_walk_t *sst = (soft_state_walk_t *)wsp->walk_data;
15917c478bd9Sstevel@tonic-gate int status = WALK_NEXT;
15927c478bd9Sstevel@tonic-gate
15937c478bd9Sstevel@tonic-gate
15947c478bd9Sstevel@tonic-gate status = wsp->walk_callback(
15957c478bd9Sstevel@tonic-gate (uintptr_t)(sst->ssw_pointers[sst->ssw_index]), NULL,
15967c478bd9Sstevel@tonic-gate wsp->walk_cbdata);
15977c478bd9Sstevel@tonic-gate
15987c478bd9Sstevel@tonic-gate sst->ssw_index += 1;
15997c478bd9Sstevel@tonic-gate
16007c478bd9Sstevel@tonic-gate if (sst->ssw_index == sst->ssw_ss.n_items)
16017c478bd9Sstevel@tonic-gate return (WALK_DONE);
16027c478bd9Sstevel@tonic-gate
16037c478bd9Sstevel@tonic-gate return (status);
16047c478bd9Sstevel@tonic-gate }
16057c478bd9Sstevel@tonic-gate
16067c478bd9Sstevel@tonic-gate /*ARGSUSED*/
16077c478bd9Sstevel@tonic-gate int
devbindings(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)16087c478bd9Sstevel@tonic-gate devbindings(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
16097c478bd9Sstevel@tonic-gate {
16107c478bd9Sstevel@tonic-gate const mdb_arg_t *arg;
16117c478bd9Sstevel@tonic-gate struct devnames dn;
16127c478bd9Sstevel@tonic-gate uintptr_t dn_addr;
16137c478bd9Sstevel@tonic-gate major_t major;
16147c478bd9Sstevel@tonic-gate
16157c478bd9Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC) && argc < 1)
16167c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
16177c478bd9Sstevel@tonic-gate
16187c478bd9Sstevel@tonic-gate if (flags & DCMD_ADDRSPEC) {
16197c478bd9Sstevel@tonic-gate /*
16207c478bd9Sstevel@tonic-gate * If there's an address, then it's a major number
16217c478bd9Sstevel@tonic-gate */
16227c478bd9Sstevel@tonic-gate major = addr;
16237c478bd9Sstevel@tonic-gate } else {
16247c478bd9Sstevel@tonic-gate /*
16257c478bd9Sstevel@tonic-gate * We interpret the last argument. Any other arguments are
16267c478bd9Sstevel@tonic-gate * forwarded to "devinfo"
16277c478bd9Sstevel@tonic-gate */
16287c478bd9Sstevel@tonic-gate arg = &argv[argc - 1];
16297c478bd9Sstevel@tonic-gate argc--;
16307c478bd9Sstevel@tonic-gate
16317c478bd9Sstevel@tonic-gate if (arg->a_type == MDB_TYPE_IMMEDIATE) {
16327c478bd9Sstevel@tonic-gate major = (uintptr_t)arg->a_un.a_val;
16337c478bd9Sstevel@tonic-gate
16347c478bd9Sstevel@tonic-gate } else if (arg->a_un.a_str[0] == '-') {
16357c478bd9Sstevel@tonic-gate /* the argument shouldn't be an option */
16367c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
16377c478bd9Sstevel@tonic-gate
16387c478bd9Sstevel@tonic-gate } else if (isdigit(arg->a_un.a_str[0])) {
16397c478bd9Sstevel@tonic-gate major = (uintptr_t)mdb_strtoull(arg->a_un.a_str);
16407c478bd9Sstevel@tonic-gate
16417c478bd9Sstevel@tonic-gate } else {
16427c478bd9Sstevel@tonic-gate if (mdb_name_to_major(arg->a_un.a_str, &major) != 0) {
16437c478bd9Sstevel@tonic-gate mdb_warn("failed to get major number for %s\n",
16447c478bd9Sstevel@tonic-gate arg->a_un.a_str);
16457c478bd9Sstevel@tonic-gate return (DCMD_ERR);
16467c478bd9Sstevel@tonic-gate }
16477c478bd9Sstevel@tonic-gate }
16487c478bd9Sstevel@tonic-gate }
16497c478bd9Sstevel@tonic-gate
16507c478bd9Sstevel@tonic-gate if (major_to_addr(major, &dn_addr) != 0)
16517c478bd9Sstevel@tonic-gate return (DCMD_ERR);
16527c478bd9Sstevel@tonic-gate
16537c478bd9Sstevel@tonic-gate if (mdb_vread(&dn, sizeof (struct devnames), dn_addr) == -1) {
16547c478bd9Sstevel@tonic-gate mdb_warn("couldn't read devnames array at %p", dn_addr);
16557c478bd9Sstevel@tonic-gate return (DCMD_ERR);
16567c478bd9Sstevel@tonic-gate }
16577c478bd9Sstevel@tonic-gate
16587c478bd9Sstevel@tonic-gate if (mdb_pwalk_dcmd("devi_next", "devinfo", argc, argv,
16597c478bd9Sstevel@tonic-gate (uintptr_t)dn.dn_head) != 0) {
16607c478bd9Sstevel@tonic-gate mdb_warn("couldn't walk the devinfo chain at %p", dn.dn_head);
16617c478bd9Sstevel@tonic-gate return (DCMD_ERR);
16627c478bd9Sstevel@tonic-gate }
16637c478bd9Sstevel@tonic-gate
16647c478bd9Sstevel@tonic-gate return (DCMD_OK);
16657c478bd9Sstevel@tonic-gate }
16667c478bd9Sstevel@tonic-gate
16677c478bd9Sstevel@tonic-gate /*
16687c478bd9Sstevel@tonic-gate * walk binding hashtable (as of of driver names (e.g., mb_hashtab))
16697c478bd9Sstevel@tonic-gate */
16707c478bd9Sstevel@tonic-gate int
binding_hash_walk_init(mdb_walk_state_t * wsp)16717c478bd9Sstevel@tonic-gate binding_hash_walk_init(mdb_walk_state_t *wsp)
16727c478bd9Sstevel@tonic-gate {
16737c478bd9Sstevel@tonic-gate if (wsp->walk_addr == NULL)
16747c478bd9Sstevel@tonic-gate return (WALK_ERR);
16757c478bd9Sstevel@tonic-gate
16767c478bd9Sstevel@tonic-gate wsp->walk_data = mdb_alloc(sizeof (void *) * MOD_BIND_HASHSIZE,
16777c478bd9Sstevel@tonic-gate UM_SLEEP|UM_GC);
16787c478bd9Sstevel@tonic-gate if (mdb_vread(wsp->walk_data, sizeof (void *) * MOD_BIND_HASHSIZE,
16797c478bd9Sstevel@tonic-gate wsp->walk_addr) == -1) {
16807c478bd9Sstevel@tonic-gate mdb_warn("failed to read mb_hashtab");
16817c478bd9Sstevel@tonic-gate return (WALK_ERR);
16827c478bd9Sstevel@tonic-gate }
16837c478bd9Sstevel@tonic-gate
16847c478bd9Sstevel@tonic-gate wsp->walk_arg = 0; /* index into mb_hashtab array to start */
16857c478bd9Sstevel@tonic-gate
16867c478bd9Sstevel@tonic-gate return (WALK_NEXT);
16877c478bd9Sstevel@tonic-gate }
16887c478bd9Sstevel@tonic-gate
16897c478bd9Sstevel@tonic-gate int
binding_hash_walk_step(mdb_walk_state_t * wsp)16907c478bd9Sstevel@tonic-gate binding_hash_walk_step(mdb_walk_state_t *wsp)
16917c478bd9Sstevel@tonic-gate {
16927c478bd9Sstevel@tonic-gate int status;
16937c478bd9Sstevel@tonic-gate uintptr_t bind_p;
16947c478bd9Sstevel@tonic-gate struct bind bind;
16957c478bd9Sstevel@tonic-gate
16967c478bd9Sstevel@tonic-gate
16977c478bd9Sstevel@tonic-gate /*
16987c478bd9Sstevel@tonic-gate * Walk the singly-linked list of struct bind
16997c478bd9Sstevel@tonic-gate */
17007c478bd9Sstevel@tonic-gate bind_p = ((uintptr_t *)wsp->walk_data)[(ulong_t)wsp->walk_arg];
17017c478bd9Sstevel@tonic-gate while (bind_p != NULL) {
17027c478bd9Sstevel@tonic-gate
17037c478bd9Sstevel@tonic-gate if (mdb_vread(&bind, sizeof (bind), bind_p) == -1) {
17047c478bd9Sstevel@tonic-gate mdb_warn("failed to read bind struct at %p",
17057c478bd9Sstevel@tonic-gate wsp->walk_addr);
17067c478bd9Sstevel@tonic-gate return (WALK_ERR);
17077c478bd9Sstevel@tonic-gate }
17087c478bd9Sstevel@tonic-gate
17097c478bd9Sstevel@tonic-gate if ((status = wsp->walk_callback(bind_p, &bind,
17107c478bd9Sstevel@tonic-gate wsp->walk_cbdata)) != WALK_NEXT) {
17117c478bd9Sstevel@tonic-gate return (status);
17127c478bd9Sstevel@tonic-gate }
17137c478bd9Sstevel@tonic-gate
17147c478bd9Sstevel@tonic-gate bind_p = (uintptr_t)bind.b_next;
17157c478bd9Sstevel@tonic-gate }
17167c478bd9Sstevel@tonic-gate
17177c478bd9Sstevel@tonic-gate wsp->walk_arg = (void *)((char *)wsp->walk_arg + 1);
17187c478bd9Sstevel@tonic-gate
17197c478bd9Sstevel@tonic-gate if (wsp->walk_arg == (void *)(MOD_BIND_HASHSIZE - 1))
17207c478bd9Sstevel@tonic-gate return (WALK_DONE);
17217c478bd9Sstevel@tonic-gate
17227c478bd9Sstevel@tonic-gate return (WALK_NEXT);
17237c478bd9Sstevel@tonic-gate }
17247c478bd9Sstevel@tonic-gate
17257c478bd9Sstevel@tonic-gate /*ARGSUSED*/
17267c478bd9Sstevel@tonic-gate int
binding_hash_entry(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)17277c478bd9Sstevel@tonic-gate binding_hash_entry(uintptr_t addr, uint_t flags, int argc,
17287c478bd9Sstevel@tonic-gate const mdb_arg_t *argv)
17297c478bd9Sstevel@tonic-gate {
17307c478bd9Sstevel@tonic-gate struct bind bind;
17317c478bd9Sstevel@tonic-gate /* Arbitrary lengths based on output format below */
1732f4da9be0Scth char name[MAXPATHLEN] = "???";
1733f4da9be0Scth char bind_name[MAXPATHLEN] = "<null>";
17347c478bd9Sstevel@tonic-gate
17357c478bd9Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) == NULL)
17367c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
17377c478bd9Sstevel@tonic-gate
17387c478bd9Sstevel@tonic-gate /* Allow null addresses to be passed (as from a walker) */
17397c478bd9Sstevel@tonic-gate if (addr == NULL)
17407c478bd9Sstevel@tonic-gate return (DCMD_OK);
17417c478bd9Sstevel@tonic-gate
17427c478bd9Sstevel@tonic-gate if (mdb_vread(&bind, sizeof (bind), addr) == -1) {
17437c478bd9Sstevel@tonic-gate mdb_warn("failed to read struct bind at %p", addr);
17447c478bd9Sstevel@tonic-gate return (DCMD_ERR);
17457c478bd9Sstevel@tonic-gate }
17467c478bd9Sstevel@tonic-gate
17477c478bd9Sstevel@tonic-gate if (DCMD_HDRSPEC(flags)) {
1748f4da9be0Scth mdb_printf("%<u>%?s% %-5s %s%</u>\n",
1749f4da9be0Scth "NEXT", "MAJOR", "NAME(S)");
17507c478bd9Sstevel@tonic-gate }
17517c478bd9Sstevel@tonic-gate
17527c478bd9Sstevel@tonic-gate if (mdb_readstr(name, sizeof (name), (uintptr_t)bind.b_name) == -1)
17537c478bd9Sstevel@tonic-gate mdb_warn("failed to read 'name'");
17547c478bd9Sstevel@tonic-gate
1755f4da9be0Scth /* There may be bind_name, so this may fail */
1756f4da9be0Scth if (mdb_readstr(bind_name, sizeof (bind_name),
1757f4da9be0Scth (uintptr_t)bind.b_bind_name) == -1) {
1758f4da9be0Scth mdb_printf("%?p %5d %s\n",
1759f4da9be0Scth bind.b_next, bind.b_num, name);
1760f4da9be0Scth } else {
1761f4da9be0Scth mdb_printf("%?p %5d %s %s\n",
1762f4da9be0Scth bind.b_next, bind.b_num, name, bind_name);
1763f4da9be0Scth }
17647c478bd9Sstevel@tonic-gate
17657c478bd9Sstevel@tonic-gate return (DCMD_OK);
17667c478bd9Sstevel@tonic-gate }
17677c478bd9Sstevel@tonic-gate
17687c478bd9Sstevel@tonic-gate typedef struct devinfo_audit_log_walk_data {
17697c478bd9Sstevel@tonic-gate devinfo_audit_t dil_buf; /* buffer of last entry */
17707c478bd9Sstevel@tonic-gate uintptr_t dil_base; /* starting address of log buffer */
17717c478bd9Sstevel@tonic-gate int dil_max; /* maximum index */
17727c478bd9Sstevel@tonic-gate int dil_start; /* starting index */
17737c478bd9Sstevel@tonic-gate int dil_index; /* current walking index */
17747c478bd9Sstevel@tonic-gate } devinfo_audit_log_walk_data_t;
17757c478bd9Sstevel@tonic-gate
17767c478bd9Sstevel@tonic-gate int
devinfo_audit_log_walk_init(mdb_walk_state_t * wsp)17777c478bd9Sstevel@tonic-gate devinfo_audit_log_walk_init(mdb_walk_state_t *wsp)
17787c478bd9Sstevel@tonic-gate {
17797c478bd9Sstevel@tonic-gate devinfo_log_header_t header;
17807c478bd9Sstevel@tonic-gate devinfo_audit_log_walk_data_t *dil;
17817c478bd9Sstevel@tonic-gate uintptr_t devinfo_audit_log;
17827c478bd9Sstevel@tonic-gate
17837c478bd9Sstevel@tonic-gate /* read in devinfo_log_header structure */
17847c478bd9Sstevel@tonic-gate if (mdb_readvar(&devinfo_audit_log, "devinfo_audit_log") == -1) {
17857c478bd9Sstevel@tonic-gate mdb_warn("failed to read 'devinfo_audit_log'");
17867c478bd9Sstevel@tonic-gate return (WALK_ERR);
17877c478bd9Sstevel@tonic-gate }
17887c478bd9Sstevel@tonic-gate
17897c478bd9Sstevel@tonic-gate if (mdb_vread(&header, sizeof (devinfo_log_header_t),
17907c478bd9Sstevel@tonic-gate devinfo_audit_log) == -1) {
17917c478bd9Sstevel@tonic-gate mdb_warn("couldn't read devinfo_log_header at %p",
17927c478bd9Sstevel@tonic-gate devinfo_audit_log);
17937c478bd9Sstevel@tonic-gate return (WALK_ERR);
17947c478bd9Sstevel@tonic-gate }
17957c478bd9Sstevel@tonic-gate
17967c478bd9Sstevel@tonic-gate dil = mdb_zalloc(sizeof (devinfo_audit_log_walk_data_t), UM_SLEEP);
17977c478bd9Sstevel@tonic-gate wsp->walk_data = dil;
17987c478bd9Sstevel@tonic-gate
17997c478bd9Sstevel@tonic-gate dil->dil_start = dil->dil_index = header.dh_curr;
18007c478bd9Sstevel@tonic-gate dil->dil_max = header.dh_max;
18017c478bd9Sstevel@tonic-gate if (dil->dil_start < 0) /* no log entries */
18027c478bd9Sstevel@tonic-gate return (WALK_DONE);
18037c478bd9Sstevel@tonic-gate
18047c478bd9Sstevel@tonic-gate dil->dil_base = devinfo_audit_log +
18057c478bd9Sstevel@tonic-gate offsetof(devinfo_log_header_t, dh_entry);
18067c478bd9Sstevel@tonic-gate wsp->walk_addr = dil->dil_base +
18077c478bd9Sstevel@tonic-gate dil->dil_index * sizeof (devinfo_audit_t);
18087c478bd9Sstevel@tonic-gate
18097c478bd9Sstevel@tonic-gate return (WALK_NEXT);
18107c478bd9Sstevel@tonic-gate }
18117c478bd9Sstevel@tonic-gate
18127c478bd9Sstevel@tonic-gate int
devinfo_audit_log_walk_step(mdb_walk_state_t * wsp)18137c478bd9Sstevel@tonic-gate devinfo_audit_log_walk_step(mdb_walk_state_t *wsp)
18147c478bd9Sstevel@tonic-gate {
18157c478bd9Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr;
18167c478bd9Sstevel@tonic-gate devinfo_audit_log_walk_data_t *dil = wsp->walk_data;
18177c478bd9Sstevel@tonic-gate devinfo_audit_t *da = &dil->dil_buf;
18187c478bd9Sstevel@tonic-gate int status = WALK_NEXT;
18197c478bd9Sstevel@tonic-gate
18207c478bd9Sstevel@tonic-gate /* read in current entry and invoke callback */
18217c478bd9Sstevel@tonic-gate if (addr == NULL)
18227c478bd9Sstevel@tonic-gate return (WALK_DONE);
18237c478bd9Sstevel@tonic-gate
18247c478bd9Sstevel@tonic-gate if (mdb_vread(&dil->dil_buf, sizeof (devinfo_audit_t), addr) == -1) {
18257c478bd9Sstevel@tonic-gate mdb_warn("failed to read devinfo_audit at %p", addr);
18267c478bd9Sstevel@tonic-gate status = WALK_DONE;
18277c478bd9Sstevel@tonic-gate }
18287c478bd9Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, da, wsp->walk_cbdata);
18297c478bd9Sstevel@tonic-gate
18307c478bd9Sstevel@tonic-gate /* step to the previous log entry in time */
18317c478bd9Sstevel@tonic-gate if (--dil->dil_index < 0)
18327c478bd9Sstevel@tonic-gate dil->dil_index += dil->dil_max;
18337c478bd9Sstevel@tonic-gate if (dil->dil_index == dil->dil_start) {
18347c478bd9Sstevel@tonic-gate wsp->walk_addr = NULL;
18357c478bd9Sstevel@tonic-gate return (WALK_DONE);
18367c478bd9Sstevel@tonic-gate }
18377c478bd9Sstevel@tonic-gate
18387c478bd9Sstevel@tonic-gate wsp->walk_addr = dil->dil_base +
18397c478bd9Sstevel@tonic-gate dil->dil_index * sizeof (devinfo_audit_t);
18407c478bd9Sstevel@tonic-gate return (status);
18417c478bd9Sstevel@tonic-gate }
18427c478bd9Sstevel@tonic-gate
18437c478bd9Sstevel@tonic-gate void
devinfo_audit_log_walk_fini(mdb_walk_state_t * wsp)18447c478bd9Sstevel@tonic-gate devinfo_audit_log_walk_fini(mdb_walk_state_t *wsp)
18457c478bd9Sstevel@tonic-gate {
18467c478bd9Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (devinfo_audit_log_walk_data_t));
18477c478bd9Sstevel@tonic-gate }
18487c478bd9Sstevel@tonic-gate
18497c478bd9Sstevel@tonic-gate /*
18507c478bd9Sstevel@tonic-gate * display devinfo_audit_t stack trace
18517c478bd9Sstevel@tonic-gate */
18527c478bd9Sstevel@tonic-gate /*ARGSUSED*/
18537c478bd9Sstevel@tonic-gate int
devinfo_audit(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)18547c478bd9Sstevel@tonic-gate devinfo_audit(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
18557c478bd9Sstevel@tonic-gate {
18567c478bd9Sstevel@tonic-gate uint_t verbose = FALSE;
18577c478bd9Sstevel@tonic-gate devinfo_audit_t da;
18587c478bd9Sstevel@tonic-gate int i, depth;
18597c478bd9Sstevel@tonic-gate
18607c478bd9Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) == 0)
18617c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
18627c478bd9Sstevel@tonic-gate
18637c478bd9Sstevel@tonic-gate if (mdb_getopts(argc, argv,
18647c478bd9Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc)
18657c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
18667c478bd9Sstevel@tonic-gate
18677c478bd9Sstevel@tonic-gate if (DCMD_HDRSPEC(flags)) {
18687c478bd9Sstevel@tonic-gate mdb_printf(" %-?s %16s %-?s %-?s %5s\n",
18697c478bd9Sstevel@tonic-gate "AUDIT", "TIMESTAMP", "THREAD", "DEVINFO", "STATE");
18707c478bd9Sstevel@tonic-gate }
18717c478bd9Sstevel@tonic-gate
18727c478bd9Sstevel@tonic-gate if (mdb_vread(&da, sizeof (da), addr) == -1) {
18737c478bd9Sstevel@tonic-gate mdb_warn("couldn't read devinfo_audit at %p", addr);
18747c478bd9Sstevel@tonic-gate return (DCMD_ERR);
18757c478bd9Sstevel@tonic-gate }
18767c478bd9Sstevel@tonic-gate
18777c478bd9Sstevel@tonic-gate mdb_printf(" %0?p %16llx %0?p %0?p %s\n",
18787c478bd9Sstevel@tonic-gate addr, da.da_timestamp, da.da_thread, da.da_devinfo,
18797c478bd9Sstevel@tonic-gate di_state[MIN(da.da_node_state + 1, DI_STATE_MAX)]);
18807c478bd9Sstevel@tonic-gate
18817c478bd9Sstevel@tonic-gate if (!verbose)
18827c478bd9Sstevel@tonic-gate return (DCMD_OK);
18837c478bd9Sstevel@tonic-gate
18847c478bd9Sstevel@tonic-gate mdb_inc_indent(4);
18857c478bd9Sstevel@tonic-gate
18867c478bd9Sstevel@tonic-gate /*
18877c478bd9Sstevel@tonic-gate * Guard against bogus da_depth in case the devinfo_audit_t
18887c478bd9Sstevel@tonic-gate * is corrupt or the address does not really refer to a
18897c478bd9Sstevel@tonic-gate * devinfo_audit_t.
18907c478bd9Sstevel@tonic-gate */
18917c478bd9Sstevel@tonic-gate depth = MIN(da.da_depth, DDI_STACK_DEPTH);
18927c478bd9Sstevel@tonic-gate
18937c478bd9Sstevel@tonic-gate for (i = 0; i < depth; i++)
18947c478bd9Sstevel@tonic-gate mdb_printf("%a\n", da.da_stack[i]);
18957c478bd9Sstevel@tonic-gate
18967c478bd9Sstevel@tonic-gate mdb_printf("\n");
18977c478bd9Sstevel@tonic-gate mdb_dec_indent(4);
18987c478bd9Sstevel@tonic-gate
18997c478bd9Sstevel@tonic-gate return (DCMD_OK);
19007c478bd9Sstevel@tonic-gate }
19017c478bd9Sstevel@tonic-gate
19027c478bd9Sstevel@tonic-gate int
devinfo_audit_log(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)19037c478bd9Sstevel@tonic-gate devinfo_audit_log(uintptr_t addr, uint_t flags, int argc,
19047c478bd9Sstevel@tonic-gate const mdb_arg_t *argv)
19057c478bd9Sstevel@tonic-gate {
19067c478bd9Sstevel@tonic-gate if (flags & DCMD_ADDRSPEC)
19077c478bd9Sstevel@tonic-gate return (devinfo_audit(addr, flags, argc, argv));
19087c478bd9Sstevel@tonic-gate
19097c478bd9Sstevel@tonic-gate (void) mdb_walk_dcmd("devinfo_audit_log", "devinfo_audit", argc, argv);
19107c478bd9Sstevel@tonic-gate return (DCMD_OK);
19117c478bd9Sstevel@tonic-gate }
19127c478bd9Sstevel@tonic-gate
19137c478bd9Sstevel@tonic-gate typedef struct devinfo_audit_node_walk_data {
19147c478bd9Sstevel@tonic-gate devinfo_audit_t dih_buf; /* buffer of last entry */
19157c478bd9Sstevel@tonic-gate uintptr_t dih_dip; /* address of dev_info */
19167c478bd9Sstevel@tonic-gate int dih_on_devinfo; /* devi_audit on dev_info struct */
19177c478bd9Sstevel@tonic-gate } devinfo_audit_node_walk_data_t;
19187c478bd9Sstevel@tonic-gate
19197c478bd9Sstevel@tonic-gate int
devinfo_audit_node_walk_init(mdb_walk_state_t * wsp)19207c478bd9Sstevel@tonic-gate devinfo_audit_node_walk_init(mdb_walk_state_t *wsp)
19217c478bd9Sstevel@tonic-gate {
19227c478bd9Sstevel@tonic-gate devinfo_audit_node_walk_data_t *dih;
19237c478bd9Sstevel@tonic-gate devinfo_audit_t *da;
19247c478bd9Sstevel@tonic-gate struct dev_info devi;
19257c478bd9Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr;
19267c478bd9Sstevel@tonic-gate
19277c478bd9Sstevel@tonic-gate /* read in devinfo structure */
19287c478bd9Sstevel@tonic-gate if (mdb_vread(&devi, sizeof (struct dev_info), addr) == -1) {
19297c478bd9Sstevel@tonic-gate mdb_warn("couldn't read dev_info at %p", addr);
19307c478bd9Sstevel@tonic-gate return (WALK_ERR);
19317c478bd9Sstevel@tonic-gate }
19327c478bd9Sstevel@tonic-gate
19337c478bd9Sstevel@tonic-gate dih = mdb_zalloc(sizeof (devinfo_audit_node_walk_data_t), UM_SLEEP);
19347c478bd9Sstevel@tonic-gate wsp->walk_data = dih;
19357c478bd9Sstevel@tonic-gate da = &dih->dih_buf;
19367c478bd9Sstevel@tonic-gate
19377c478bd9Sstevel@tonic-gate /* read in devi_audit structure */
19387c478bd9Sstevel@tonic-gate if (mdb_vread(da, sizeof (devinfo_audit_t), (uintptr_t)devi.devi_audit)
19397c478bd9Sstevel@tonic-gate == -1) {
19407c478bd9Sstevel@tonic-gate mdb_warn("couldn't read devi_audit at %p", devi.devi_audit);
19417c478bd9Sstevel@tonic-gate return (WALK_ERR);
19427c478bd9Sstevel@tonic-gate }
19437c478bd9Sstevel@tonic-gate dih->dih_dip = addr;
19447c478bd9Sstevel@tonic-gate dih->dih_on_devinfo = 1;
19457c478bd9Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)devi.devi_audit;
19467c478bd9Sstevel@tonic-gate
19477c478bd9Sstevel@tonic-gate return (WALK_NEXT);
19487c478bd9Sstevel@tonic-gate }
19497c478bd9Sstevel@tonic-gate
19507c478bd9Sstevel@tonic-gate int
devinfo_audit_node_walk_step(mdb_walk_state_t * wsp)19517c478bd9Sstevel@tonic-gate devinfo_audit_node_walk_step(mdb_walk_state_t *wsp)
19527c478bd9Sstevel@tonic-gate {
19537c478bd9Sstevel@tonic-gate uintptr_t addr;
19547c478bd9Sstevel@tonic-gate devinfo_audit_node_walk_data_t *dih = wsp->walk_data;
19557c478bd9Sstevel@tonic-gate devinfo_audit_t *da = &dih->dih_buf;
19567c478bd9Sstevel@tonic-gate
19577c478bd9Sstevel@tonic-gate if (wsp->walk_addr == NULL)
19587c478bd9Sstevel@tonic-gate return (WALK_DONE);
19597c478bd9Sstevel@tonic-gate (void) wsp->walk_callback(wsp->walk_addr, NULL, wsp->walk_cbdata);
19607c478bd9Sstevel@tonic-gate
19617c478bd9Sstevel@tonic-gate skip:
19627c478bd9Sstevel@tonic-gate /* read in previous entry */
19637c478bd9Sstevel@tonic-gate if ((addr = (uintptr_t)da->da_lastlog) == 0)
19647c478bd9Sstevel@tonic-gate return (WALK_DONE);
19657c478bd9Sstevel@tonic-gate
19667c478bd9Sstevel@tonic-gate if (mdb_vread(&dih->dih_buf, sizeof (devinfo_audit_t), addr) == -1) {
19677c478bd9Sstevel@tonic-gate mdb_warn("failed to read devinfo_audit at %p", addr);
19687c478bd9Sstevel@tonic-gate return (WALK_DONE);
19697c478bd9Sstevel@tonic-gate }
19707c478bd9Sstevel@tonic-gate
19717c478bd9Sstevel@tonic-gate /* check if last log was over-written */
19727c478bd9Sstevel@tonic-gate if ((uintptr_t)da->da_devinfo != dih->dih_dip)
19737c478bd9Sstevel@tonic-gate return (WALK_DONE);
19747c478bd9Sstevel@tonic-gate
19757c478bd9Sstevel@tonic-gate /*
19767c478bd9Sstevel@tonic-gate * skip the first common log entry, which is a duplicate of
19777c478bd9Sstevel@tonic-gate * the devi_audit buffer on the dev_info structure
19787c478bd9Sstevel@tonic-gate */
19797c478bd9Sstevel@tonic-gate if (dih->dih_on_devinfo) {
19807c478bd9Sstevel@tonic-gate dih->dih_on_devinfo = 0;
19817c478bd9Sstevel@tonic-gate goto skip;
19827c478bd9Sstevel@tonic-gate }
19837c478bd9Sstevel@tonic-gate wsp->walk_addr = addr;
19847c478bd9Sstevel@tonic-gate
19857c478bd9Sstevel@tonic-gate return (WALK_NEXT);
19867c478bd9Sstevel@tonic-gate }
19877c478bd9Sstevel@tonic-gate
19887c478bd9Sstevel@tonic-gate void
devinfo_audit_node_walk_fini(mdb_walk_state_t * wsp)19897c478bd9Sstevel@tonic-gate devinfo_audit_node_walk_fini(mdb_walk_state_t *wsp)
19907c478bd9Sstevel@tonic-gate {
19917c478bd9Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (devinfo_audit_node_walk_data_t));
19927c478bd9Sstevel@tonic-gate }
19937c478bd9Sstevel@tonic-gate
19947c478bd9Sstevel@tonic-gate int
devinfo_audit_node(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)19957c478bd9Sstevel@tonic-gate devinfo_audit_node(uintptr_t addr, uint_t flags, int argc,
19967c478bd9Sstevel@tonic-gate const mdb_arg_t *argv)
19977c478bd9Sstevel@tonic-gate {
19987c478bd9Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC))
19997c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
20007c478bd9Sstevel@tonic-gate
20017c478bd9Sstevel@tonic-gate (void) mdb_pwalk_dcmd("devinfo_audit_node", "devinfo_audit",
20027c478bd9Sstevel@tonic-gate argc, argv, addr);
20037c478bd9Sstevel@tonic-gate return (DCMD_OK);
20047c478bd9Sstevel@tonic-gate }
20057c478bd9Sstevel@tonic-gate
20067c478bd9Sstevel@tonic-gate /*
20077c478bd9Sstevel@tonic-gate * mdb support for per-devinfo fault management data
20087c478bd9Sstevel@tonic-gate */
20097c478bd9Sstevel@tonic-gate /*ARGSUSED*/
20107c478bd9Sstevel@tonic-gate int
devinfo_fm(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)20117c478bd9Sstevel@tonic-gate devinfo_fm(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
20127c478bd9Sstevel@tonic-gate {
20137c478bd9Sstevel@tonic-gate struct dev_info devi;
20147c478bd9Sstevel@tonic-gate struct i_ddi_fmhdl fhdl;
20157c478bd9Sstevel@tonic-gate
20167c478bd9Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) == 0)
20177c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
20187c478bd9Sstevel@tonic-gate
20197c478bd9Sstevel@tonic-gate if (DCMD_HDRSPEC(flags)) {
2020a5667d81SCheng Sean Ye mdb_printf("%<u>%?s IPL CAPS DROP FMCFULL FMCMISS ACCERR "
2021a5667d81SCheng Sean Ye "DMAERR %?s %?s%</u>\n", "ADDR", "DMACACHE", "ACCCACHE");
20227c478bd9Sstevel@tonic-gate }
20237c478bd9Sstevel@tonic-gate
20247c478bd9Sstevel@tonic-gate if (mdb_vread(&devi, sizeof (devi), addr) == -1) {
20257c478bd9Sstevel@tonic-gate mdb_warn("failed to read devinfo struct at %p", addr);
20267c478bd9Sstevel@tonic-gate return (DCMD_ERR);
20277c478bd9Sstevel@tonic-gate }
20287c478bd9Sstevel@tonic-gate
20297c478bd9Sstevel@tonic-gate if (mdb_vread(&fhdl, sizeof (fhdl), (uintptr_t)devi.devi_fmhdl) == -1) {
20307c478bd9Sstevel@tonic-gate mdb_warn("failed to read devinfo fm struct at %p",
20317c478bd9Sstevel@tonic-gate (uintptr_t)devi.devi_fmhdl);
20327c478bd9Sstevel@tonic-gate return (DCMD_ERR);
20337c478bd9Sstevel@tonic-gate }
20347c478bd9Sstevel@tonic-gate
2035a5667d81SCheng Sean Ye mdb_printf("%?p %3u %c%c%c%c %4llu %7llu %7llu %6llu %6llu %?p %?p\n",
20367c478bd9Sstevel@tonic-gate (uintptr_t)devi.devi_fmhdl, fhdl.fh_ibc,
20377c478bd9Sstevel@tonic-gate (DDI_FM_EREPORT_CAP(fhdl.fh_cap) ? 'E' : '-'),
20387c478bd9Sstevel@tonic-gate (DDI_FM_ERRCB_CAP(fhdl.fh_cap) ? 'C' : '-'),
20397c478bd9Sstevel@tonic-gate (DDI_FM_ACC_ERR_CAP(fhdl.fh_cap) ? 'A' : '-'),
20407c478bd9Sstevel@tonic-gate (DDI_FM_DMA_ERR_CAP(fhdl.fh_cap) ? 'D' : '-'),
20417c478bd9Sstevel@tonic-gate fhdl.fh_kstat.fek_erpt_dropped.value.ui64,
20427c478bd9Sstevel@tonic-gate fhdl.fh_kstat.fek_fmc_full.value.ui64,
2043a5667d81SCheng Sean Ye fhdl.fh_kstat.fek_fmc_miss.value.ui64,
20447c478bd9Sstevel@tonic-gate fhdl.fh_kstat.fek_acc_err.value.ui64,
20457c478bd9Sstevel@tonic-gate fhdl.fh_kstat.fek_dma_err.value.ui64,
20467c478bd9Sstevel@tonic-gate fhdl.fh_dma_cache, fhdl.fh_acc_cache);
20477c478bd9Sstevel@tonic-gate
20487c478bd9Sstevel@tonic-gate
20497c478bd9Sstevel@tonic-gate return (DCMD_OK);
20507c478bd9Sstevel@tonic-gate }
20517c478bd9Sstevel@tonic-gate
20527c478bd9Sstevel@tonic-gate /*ARGSUSED*/
20537c478bd9Sstevel@tonic-gate int
devinfo_fmce(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)20547c478bd9Sstevel@tonic-gate devinfo_fmce(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
20557c478bd9Sstevel@tonic-gate {
20567c478bd9Sstevel@tonic-gate struct i_ddi_fmc_entry fce;
20577c478bd9Sstevel@tonic-gate
20587c478bd9Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) == 0)
20597c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
20607c478bd9Sstevel@tonic-gate
20617c478bd9Sstevel@tonic-gate if (DCMD_HDRSPEC(flags)) {
2062a5667d81SCheng Sean Ye mdb_printf("%<u>%?s %?s %?s%</u>\n", "ADDR",
20637c478bd9Sstevel@tonic-gate "RESOURCE", "BUS_SPECIFIC");
20647c478bd9Sstevel@tonic-gate }
20657c478bd9Sstevel@tonic-gate
20667c478bd9Sstevel@tonic-gate if (mdb_vread(&fce, sizeof (fce), addr) == -1) {
20677c478bd9Sstevel@tonic-gate mdb_warn("failed to read fm cache struct at %p", addr);
20687c478bd9Sstevel@tonic-gate return (DCMD_ERR);
20697c478bd9Sstevel@tonic-gate }
20707c478bd9Sstevel@tonic-gate
2071a5667d81SCheng Sean Ye mdb_printf("%?p %?p %?p\n",
20727c478bd9Sstevel@tonic-gate (uintptr_t)addr, fce.fce_resource, fce.fce_bus_specific);
20737c478bd9Sstevel@tonic-gate
20747c478bd9Sstevel@tonic-gate
20757c478bd9Sstevel@tonic-gate return (DCMD_OK);
20767c478bd9Sstevel@tonic-gate }
20777c478bd9Sstevel@tonic-gate
20787c478bd9Sstevel@tonic-gate int
devinfo_fmc_walk_init(mdb_walk_state_t * wsp)20797c478bd9Sstevel@tonic-gate devinfo_fmc_walk_init(mdb_walk_state_t *wsp)
20807c478bd9Sstevel@tonic-gate {
20817c478bd9Sstevel@tonic-gate struct i_ddi_fmc fec;
20827c478bd9Sstevel@tonic-gate
20837c478bd9Sstevel@tonic-gate if (wsp->walk_addr == NULL)
20847c478bd9Sstevel@tonic-gate return (WALK_ERR);
20857c478bd9Sstevel@tonic-gate
20867c478bd9Sstevel@tonic-gate if (mdb_vread(&fec, sizeof (fec), wsp->walk_addr) == -1) {
20877c478bd9Sstevel@tonic-gate mdb_warn("failed to read fm cache at %p", wsp->walk_addr);
20887c478bd9Sstevel@tonic-gate return (WALK_ERR);
20897c478bd9Sstevel@tonic-gate }
20907c478bd9Sstevel@tonic-gate
2091a5667d81SCheng Sean Ye if (fec.fc_head == NULL)
20927c478bd9Sstevel@tonic-gate return (WALK_DONE);
20937c478bd9Sstevel@tonic-gate
2094a5667d81SCheng Sean Ye wsp->walk_addr = (uintptr_t)fec.fc_head;
20957c478bd9Sstevel@tonic-gate return (WALK_NEXT);
20967c478bd9Sstevel@tonic-gate }
20977c478bd9Sstevel@tonic-gate
20987c478bd9Sstevel@tonic-gate int
devinfo_fmc_walk_step(mdb_walk_state_t * wsp)20997c478bd9Sstevel@tonic-gate devinfo_fmc_walk_step(mdb_walk_state_t *wsp)
21007c478bd9Sstevel@tonic-gate {
21017c478bd9Sstevel@tonic-gate int status;
21027c478bd9Sstevel@tonic-gate struct i_ddi_fmc_entry fe;
21037c478bd9Sstevel@tonic-gate
21047c478bd9Sstevel@tonic-gate if (mdb_vread(&fe, sizeof (fe), wsp->walk_addr) == -1) {
21057c478bd9Sstevel@tonic-gate mdb_warn("failed to read active fm cache entry at %p",
21067c478bd9Sstevel@tonic-gate wsp->walk_addr);
21077c478bd9Sstevel@tonic-gate return (WALK_DONE);
21087c478bd9Sstevel@tonic-gate }
21097c478bd9Sstevel@tonic-gate
21107c478bd9Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, &fe, wsp->walk_cbdata);
21117c478bd9Sstevel@tonic-gate
21127c478bd9Sstevel@tonic-gate if (fe.fce_next == NULL)
21137c478bd9Sstevel@tonic-gate return (WALK_DONE);
21147c478bd9Sstevel@tonic-gate
21157c478bd9Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)fe.fce_next;
21167c478bd9Sstevel@tonic-gate return (status);
21177c478bd9Sstevel@tonic-gate }
21187c478bd9Sstevel@tonic-gate
21197c478bd9Sstevel@tonic-gate int
minornode_walk_init(mdb_walk_state_t * wsp)21207c478bd9Sstevel@tonic-gate minornode_walk_init(mdb_walk_state_t *wsp)
21217c478bd9Sstevel@tonic-gate {
21227c478bd9Sstevel@tonic-gate struct dev_info di;
21237c478bd9Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr;
21247c478bd9Sstevel@tonic-gate
21257c478bd9Sstevel@tonic-gate if (addr == NULL) {
21267c478bd9Sstevel@tonic-gate mdb_warn("a dev_info struct address must be provided\n");
21277c478bd9Sstevel@tonic-gate return (WALK_ERR);
21287c478bd9Sstevel@tonic-gate }
21297c478bd9Sstevel@tonic-gate
21307c478bd9Sstevel@tonic-gate if (mdb_vread(&di, sizeof (di), wsp->walk_addr) == -1) {
21317c478bd9Sstevel@tonic-gate mdb_warn("failed to read dev_info struct at %p", addr);
21327c478bd9Sstevel@tonic-gate return (WALK_ERR);
21337c478bd9Sstevel@tonic-gate }
21347c478bd9Sstevel@tonic-gate
21357c478bd9Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)di.devi_minor;
21367c478bd9Sstevel@tonic-gate return (WALK_NEXT);
21377c478bd9Sstevel@tonic-gate }
21387c478bd9Sstevel@tonic-gate
21397c478bd9Sstevel@tonic-gate int
minornode_walk_step(mdb_walk_state_t * wsp)21407c478bd9Sstevel@tonic-gate minornode_walk_step(mdb_walk_state_t *wsp)
21417c478bd9Sstevel@tonic-gate {
21427c478bd9Sstevel@tonic-gate struct ddi_minor_data md;
21437c478bd9Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr;
21447c478bd9Sstevel@tonic-gate
21457c478bd9Sstevel@tonic-gate if (addr == NULL)
21467c478bd9Sstevel@tonic-gate return (WALK_DONE);
21477c478bd9Sstevel@tonic-gate
21487c478bd9Sstevel@tonic-gate if (mdb_vread(&md, sizeof (md), addr) == -1) {
21497c478bd9Sstevel@tonic-gate mdb_warn("failed to read dev_info struct at %p", addr);
21507c478bd9Sstevel@tonic-gate return (WALK_DONE);
21517c478bd9Sstevel@tonic-gate }
21527c478bd9Sstevel@tonic-gate
21537c478bd9Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)md.next;
21547c478bd9Sstevel@tonic-gate return (wsp->walk_callback(addr, &md, wsp->walk_cbdata));
21557c478bd9Sstevel@tonic-gate }
21567c478bd9Sstevel@tonic-gate
21577c478bd9Sstevel@tonic-gate static const char *const md_type[] = {
21587c478bd9Sstevel@tonic-gate "DDI_MINOR",
21597c478bd9Sstevel@tonic-gate "DDI_ALIAS",
21607c478bd9Sstevel@tonic-gate "DDI_DEFAULT",
21617c478bd9Sstevel@tonic-gate "DDI_I_PATH",
21627c478bd9Sstevel@tonic-gate "?"
21637c478bd9Sstevel@tonic-gate };
21647c478bd9Sstevel@tonic-gate
21657c478bd9Sstevel@tonic-gate #define MD_TYPE_MAX ((sizeof (md_type) / sizeof (char *)) - 1)
21667c478bd9Sstevel@tonic-gate
21677c478bd9Sstevel@tonic-gate /*ARGSUSED*/
21687c478bd9Sstevel@tonic-gate static int
print_minornode(uintptr_t addr,const void * arg,void * data)21697c478bd9Sstevel@tonic-gate print_minornode(uintptr_t addr, const void *arg, void *data)
21707c478bd9Sstevel@tonic-gate {
21717c478bd9Sstevel@tonic-gate char name[128];
21727c478bd9Sstevel@tonic-gate char nodetype[128];
21737c478bd9Sstevel@tonic-gate char *spectype;
21747c478bd9Sstevel@tonic-gate struct ddi_minor_data *mdp = (struct ddi_minor_data *)arg;
21757c478bd9Sstevel@tonic-gate
21767c478bd9Sstevel@tonic-gate if (mdb_readstr(name, sizeof (name), (uintptr_t)mdp->ddm_name) == -1)
21777c478bd9Sstevel@tonic-gate *name = '\0';
21787c478bd9Sstevel@tonic-gate
21797c478bd9Sstevel@tonic-gate if (mdb_readstr(nodetype, sizeof (nodetype),
21807c478bd9Sstevel@tonic-gate (uintptr_t)mdp->ddm_node_type) == -1)
21817c478bd9Sstevel@tonic-gate *nodetype = '\0';
21827c478bd9Sstevel@tonic-gate
21837c478bd9Sstevel@tonic-gate switch (mdp->ddm_spec_type) {
21847c478bd9Sstevel@tonic-gate case S_IFCHR: spectype = "c"; break;
21857c478bd9Sstevel@tonic-gate case S_IFBLK: spectype = "b"; break;
21867c478bd9Sstevel@tonic-gate default: spectype = "?"; break;
21877c478bd9Sstevel@tonic-gate }
21887c478bd9Sstevel@tonic-gate
21897c478bd9Sstevel@tonic-gate mdb_printf("%?p %16lx %-4s %-11s %-10s %s\n",
21907c478bd9Sstevel@tonic-gate addr, mdp->ddm_dev, spectype, md_type[MIN(mdp->type, MD_TYPE_MAX)],
21917c478bd9Sstevel@tonic-gate name, nodetype);
21927c478bd9Sstevel@tonic-gate
21937c478bd9Sstevel@tonic-gate return (WALK_NEXT);
21947c478bd9Sstevel@tonic-gate }
21957c478bd9Sstevel@tonic-gate
21967c478bd9Sstevel@tonic-gate /*ARGSUSED*/
21977c478bd9Sstevel@tonic-gate int
minornodes(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)21987c478bd9Sstevel@tonic-gate minornodes(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
21997c478bd9Sstevel@tonic-gate {
22007c478bd9Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC) || argc != 0)
22017c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
22027c478bd9Sstevel@tonic-gate
22037c478bd9Sstevel@tonic-gate if (DCMD_HDRSPEC(flags))
22047c478bd9Sstevel@tonic-gate mdb_printf("%<u>%?s %16s %-4s %-11s %-10s %-16s%</u>\n",
22057c478bd9Sstevel@tonic-gate "ADDR", "DEV", "SPEC", "TYPE", "NAME", "NODETYPE");
22067c478bd9Sstevel@tonic-gate
22077c478bd9Sstevel@tonic-gate if (mdb_pwalk("minornode", print_minornode, NULL, addr) == -1) {
22087c478bd9Sstevel@tonic-gate mdb_warn("can't walk minornode");
22097c478bd9Sstevel@tonic-gate return (DCMD_ERR);
22107c478bd9Sstevel@tonic-gate }
22117c478bd9Sstevel@tonic-gate
22127c478bd9Sstevel@tonic-gate return (DCMD_OK);
22137c478bd9Sstevel@tonic-gate }
2214