1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/types.h> 30*0Sstevel@tonic-gate #include <sys/sysmacros.h> 31*0Sstevel@tonic-gate #include <sys/dditypes.h> 32*0Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 33*0Sstevel@tonic-gate #include <sys/ddifm.h> 34*0Sstevel@tonic-gate #include <sys/ddipropdefs.h> 35*0Sstevel@tonic-gate #include <sys/modctl.h> 36*0Sstevel@tonic-gate #include <sys/hwconf.h> 37*0Sstevel@tonic-gate #include <sys/stat.h> 38*0Sstevel@tonic-gate #include <errno.h> 39*0Sstevel@tonic-gate #include <sys/sunmdi.h> 40*0Sstevel@tonic-gate #include <sys/mdi_impldefs.h> 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate #include <ctype.h> 43*0Sstevel@tonic-gate #include <mdb/mdb_modapi.h> 44*0Sstevel@tonic-gate #include <mdb/mdb_ks.h> 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate #include "nvpair.h" 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate #define DEVINFO_TREE_INDENT 4 /* Indent for devs one down in tree */ 49*0Sstevel@tonic-gate #define DEVINFO_PROP_INDENT 4 /* Indent for properties */ 50*0Sstevel@tonic-gate #define DEVINFO_PROPLIST_INDENT 8 /* Indent for properties lists */ 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate /* 54*0Sstevel@tonic-gate * Options for prtconf/devinfo dcmd. 55*0Sstevel@tonic-gate */ 56*0Sstevel@tonic-gate #define DEVINFO_VERBOSE 0x1 57*0Sstevel@tonic-gate #define DEVINFO_PARENT 0x2 58*0Sstevel@tonic-gate #define DEVINFO_CHILD 0x4 59*0Sstevel@tonic-gate #define DEVINFO_ALLBOLD 0x8 60*0Sstevel@tonic-gate #define DEVINFO_SUMMARY 0x10 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate /* 63*0Sstevel@tonic-gate * devinfo node state map. Used by devinfo() and devinfo_audit(). 64*0Sstevel@tonic-gate * Long words are deliberately truncated so that output 65*0Sstevel@tonic-gate * fits in 80 column with 64-bit addresses. 66*0Sstevel@tonic-gate */ 67*0Sstevel@tonic-gate static const char *const di_state[] = { 68*0Sstevel@tonic-gate "DS_INVAL", 69*0Sstevel@tonic-gate "DS_PROTO", 70*0Sstevel@tonic-gate "DS_LINKED", 71*0Sstevel@tonic-gate "DS_BOUND", 72*0Sstevel@tonic-gate "DS_INITIA", 73*0Sstevel@tonic-gate "DS_PROBED", 74*0Sstevel@tonic-gate "DS_ATTACH", 75*0Sstevel@tonic-gate "DS_READY", 76*0Sstevel@tonic-gate "?" 77*0Sstevel@tonic-gate }; 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate #define DI_STATE_MAX ((sizeof (di_state) / sizeof (char *)) - 1) 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate void 82*0Sstevel@tonic-gate prtconf_help(void) 83*0Sstevel@tonic-gate { 84*0Sstevel@tonic-gate mdb_printf("Prints the devinfo tree from a given node.\n" 85*0Sstevel@tonic-gate "Without the address of a \"struct devinfo\" given, " 86*0Sstevel@tonic-gate "prints from the root;\n" 87*0Sstevel@tonic-gate "with an address, prints the parents of, " 88*0Sstevel@tonic-gate "and all children of, that address.\n\n" 89*0Sstevel@tonic-gate "Switches:\n" 90*0Sstevel@tonic-gate " -v be verbose - print device property lists\n" 91*0Sstevel@tonic-gate " -p only print the ancestors of the given node\n" 92*0Sstevel@tonic-gate " -c only print the children of the given node\n"); 93*0Sstevel@tonic-gate } 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate void 96*0Sstevel@tonic-gate devinfo_help(void) 97*0Sstevel@tonic-gate { 98*0Sstevel@tonic-gate mdb_printf("Switches:\n" 99*0Sstevel@tonic-gate " -q be quiet - don't print device property lists\n" 100*0Sstevel@tonic-gate " -s print summary of dev_info structures\n"); 101*0Sstevel@tonic-gate } 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate uintptr_t devinfo_root; /* Address of root of devinfo tree */ 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate /* 106*0Sstevel@tonic-gate * Devinfo walker. 107*0Sstevel@tonic-gate */ 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate typedef struct { 110*0Sstevel@tonic-gate /* 111*0Sstevel@tonic-gate * The "struct dev_info" must be the first thing in this structure. 112*0Sstevel@tonic-gate */ 113*0Sstevel@tonic-gate struct dev_info din_dev; 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate /* 116*0Sstevel@tonic-gate * This is for the benefit of prtconf(). 117*0Sstevel@tonic-gate */ 118*0Sstevel@tonic-gate int din_depth; 119*0Sstevel@tonic-gate } devinfo_node_t; 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate typedef struct devinfo_parents_walk_data { 122*0Sstevel@tonic-gate devinfo_node_t dip_node; 123*0Sstevel@tonic-gate #define dip_dev dip_node.din_dev 124*0Sstevel@tonic-gate #define dip_depth dip_node.din_depth 125*0Sstevel@tonic-gate struct dev_info *dip_end; 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate /* 128*0Sstevel@tonic-gate * The following three elements are for walking the parents of a node: 129*0Sstevel@tonic-gate * "dip_base_depth" is the depth of the given node from the root. 130*0Sstevel@tonic-gate * This starts at 1 (if we're walking devinfo_root), because 131*0Sstevel@tonic-gate * it's the size of the dip_parent_{nodes,addresses} arrays, 132*0Sstevel@tonic-gate * and has to include the given node. 133*0Sstevel@tonic-gate * "dip_parent_nodes" is a collection of the parent node structures, 134*0Sstevel@tonic-gate * already read in via mdb_vread(). dip_parent_nodes[0] is the 135*0Sstevel@tonic-gate * root, dip_parent_nodes[1] is a child of the root, etc. 136*0Sstevel@tonic-gate * "dip_parent_addresses" holds the vaddrs of all the parent nodes. 137*0Sstevel@tonic-gate */ 138*0Sstevel@tonic-gate int dip_base_depth; 139*0Sstevel@tonic-gate devinfo_node_t *dip_parent_nodes; 140*0Sstevel@tonic-gate uintptr_t *dip_parent_addresses; 141*0Sstevel@tonic-gate } devinfo_parents_walk_data_t; 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate int 144*0Sstevel@tonic-gate devinfo_parents_walk_init(mdb_walk_state_t *wsp) 145*0Sstevel@tonic-gate { 146*0Sstevel@tonic-gate devinfo_parents_walk_data_t *dip; 147*0Sstevel@tonic-gate uintptr_t addr; 148*0Sstevel@tonic-gate int i; 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate if (wsp->walk_addr == NULL) 151*0Sstevel@tonic-gate wsp->walk_addr = devinfo_root; 152*0Sstevel@tonic-gate addr = wsp->walk_addr; 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate dip = mdb_alloc(sizeof (devinfo_parents_walk_data_t), UM_SLEEP); 155*0Sstevel@tonic-gate wsp->walk_data = dip; 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate dip->dip_end = (struct dev_info *)wsp->walk_addr; 158*0Sstevel@tonic-gate dip->dip_depth = 0; 159*0Sstevel@tonic-gate dip->dip_base_depth = 1; 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate do { 162*0Sstevel@tonic-gate if (mdb_vread(&dip->dip_dev, sizeof (dip->dip_dev), 163*0Sstevel@tonic-gate addr) == -1) { 164*0Sstevel@tonic-gate mdb_warn("failed to read devinfo at %p", addr); 165*0Sstevel@tonic-gate mdb_free(dip, sizeof (devinfo_parents_walk_data_t)); 166*0Sstevel@tonic-gate wsp->walk_data = NULL; 167*0Sstevel@tonic-gate return (WALK_ERR); 168*0Sstevel@tonic-gate } 169*0Sstevel@tonic-gate addr = (uintptr_t)dip->dip_dev.devi_parent; 170*0Sstevel@tonic-gate if (addr != 0) 171*0Sstevel@tonic-gate dip->dip_base_depth++; 172*0Sstevel@tonic-gate } while (addr != 0); 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate addr = wsp->walk_addr; 175*0Sstevel@tonic-gate 176*0Sstevel@tonic-gate dip->dip_parent_nodes = mdb_alloc( 177*0Sstevel@tonic-gate dip->dip_base_depth * sizeof (devinfo_node_t), UM_SLEEP); 178*0Sstevel@tonic-gate dip->dip_parent_addresses = mdb_alloc( 179*0Sstevel@tonic-gate dip->dip_base_depth * sizeof (uintptr_t), UM_SLEEP); 180*0Sstevel@tonic-gate for (i = dip->dip_base_depth - 1; i >= 0; i--) { 181*0Sstevel@tonic-gate if (mdb_vread(&dip->dip_parent_nodes[i].din_dev, 182*0Sstevel@tonic-gate sizeof (struct dev_info), addr) == -1) { 183*0Sstevel@tonic-gate mdb_warn("failed to read devinfo at %p", addr); 184*0Sstevel@tonic-gate return (WALK_ERR); 185*0Sstevel@tonic-gate } 186*0Sstevel@tonic-gate dip->dip_parent_nodes[i].din_depth = i; 187*0Sstevel@tonic-gate dip->dip_parent_addresses[i] = addr; 188*0Sstevel@tonic-gate addr = (uintptr_t) 189*0Sstevel@tonic-gate dip->dip_parent_nodes[i].din_dev.devi_parent; 190*0Sstevel@tonic-gate } 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate return (WALK_NEXT); 193*0Sstevel@tonic-gate } 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate int 196*0Sstevel@tonic-gate devinfo_parents_walk_step(mdb_walk_state_t *wsp) 197*0Sstevel@tonic-gate { 198*0Sstevel@tonic-gate devinfo_parents_walk_data_t *dip = wsp->walk_data; 199*0Sstevel@tonic-gate int status; 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate if (dip->dip_depth == dip->dip_base_depth) 202*0Sstevel@tonic-gate return (WALK_DONE); 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate status = wsp->walk_callback( 205*0Sstevel@tonic-gate dip->dip_parent_addresses[dip->dip_depth], 206*0Sstevel@tonic-gate &dip->dip_parent_nodes[dip->dip_depth], 207*0Sstevel@tonic-gate wsp->walk_cbdata); 208*0Sstevel@tonic-gate 209*0Sstevel@tonic-gate dip->dip_depth++; 210*0Sstevel@tonic-gate return (status); 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate void 214*0Sstevel@tonic-gate devinfo_parents_walk_fini(mdb_walk_state_t *wsp) 215*0Sstevel@tonic-gate { 216*0Sstevel@tonic-gate devinfo_parents_walk_data_t *dip = wsp->walk_data; 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate mdb_free(dip->dip_parent_nodes, 219*0Sstevel@tonic-gate dip->dip_base_depth * sizeof (devinfo_node_t)); 220*0Sstevel@tonic-gate mdb_free(dip->dip_parent_addresses, 221*0Sstevel@tonic-gate dip->dip_base_depth * sizeof (uintptr_t)); 222*0Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (devinfo_parents_walk_data_t)); 223*0Sstevel@tonic-gate } 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate typedef struct devinfo_children_walk_data { 227*0Sstevel@tonic-gate devinfo_node_t dic_node; 228*0Sstevel@tonic-gate #define dic_dev dic_node.din_dev 229*0Sstevel@tonic-gate #define dic_depth dic_node.din_depth 230*0Sstevel@tonic-gate struct dev_info *dic_end; 231*0Sstevel@tonic-gate int dic_print_first_node; 232*0Sstevel@tonic-gate } devinfo_children_walk_data_t; 233*0Sstevel@tonic-gate 234*0Sstevel@tonic-gate int 235*0Sstevel@tonic-gate devinfo_children_walk_init(mdb_walk_state_t *wsp) 236*0Sstevel@tonic-gate { 237*0Sstevel@tonic-gate devinfo_children_walk_data_t *dic; 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate if (wsp->walk_addr == NULL) 240*0Sstevel@tonic-gate wsp->walk_addr = devinfo_root; 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate dic = mdb_alloc(sizeof (devinfo_children_walk_data_t), UM_SLEEP); 243*0Sstevel@tonic-gate wsp->walk_data = dic; 244*0Sstevel@tonic-gate dic->dic_end = (struct dev_info *)wsp->walk_addr; 245*0Sstevel@tonic-gate 246*0Sstevel@tonic-gate /* 247*0Sstevel@tonic-gate * This could be set by devinfo_walk_init(). 248*0Sstevel@tonic-gate */ 249*0Sstevel@tonic-gate if (wsp->walk_arg != NULL) { 250*0Sstevel@tonic-gate dic->dic_depth = (*(int *)wsp->walk_arg - 1); 251*0Sstevel@tonic-gate dic->dic_print_first_node = 0; 252*0Sstevel@tonic-gate } else { 253*0Sstevel@tonic-gate dic->dic_depth = 0; 254*0Sstevel@tonic-gate dic->dic_print_first_node = 1; 255*0Sstevel@tonic-gate } 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate return (WALK_NEXT); 258*0Sstevel@tonic-gate } 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate int 261*0Sstevel@tonic-gate devinfo_children_walk_step(mdb_walk_state_t *wsp) 262*0Sstevel@tonic-gate { 263*0Sstevel@tonic-gate devinfo_children_walk_data_t *dic = wsp->walk_data; 264*0Sstevel@tonic-gate struct dev_info *v; 265*0Sstevel@tonic-gate devinfo_node_t *cur; 266*0Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr; 267*0Sstevel@tonic-gate int status = WALK_NEXT; 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate if (wsp->walk_addr == NULL) 270*0Sstevel@tonic-gate return (WALK_DONE); 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate if (mdb_vread(&dic->dic_dev, sizeof (dic->dic_dev), addr) == -1) { 273*0Sstevel@tonic-gate mdb_warn("failed to read devinfo at %p", addr); 274*0Sstevel@tonic-gate return (WALK_DONE); 275*0Sstevel@tonic-gate } 276*0Sstevel@tonic-gate cur = &dic->dic_node; 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate if (dic->dic_print_first_node == 0) 279*0Sstevel@tonic-gate dic->dic_print_first_node = 1; 280*0Sstevel@tonic-gate else 281*0Sstevel@tonic-gate status = wsp->walk_callback(addr, cur, wsp->walk_cbdata); 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate /* 284*0Sstevel@tonic-gate * "v" is always a virtual address pointer, 285*0Sstevel@tonic-gate * i.e. can't be deref'ed. 286*0Sstevel@tonic-gate */ 287*0Sstevel@tonic-gate v = (struct dev_info *)addr; 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gate if (dic->dic_dev.devi_child != NULL) { 290*0Sstevel@tonic-gate v = dic->dic_dev.devi_child; 291*0Sstevel@tonic-gate dic->dic_depth++; 292*0Sstevel@tonic-gate } else if (dic->dic_dev.devi_sibling != NULL && v != dic->dic_end) { 293*0Sstevel@tonic-gate v = dic->dic_dev.devi_sibling; 294*0Sstevel@tonic-gate } else { 295*0Sstevel@tonic-gate while (v != NULL && v != dic->dic_end && 296*0Sstevel@tonic-gate dic->dic_dev.devi_sibling == NULL) { 297*0Sstevel@tonic-gate v = dic->dic_dev.devi_parent; 298*0Sstevel@tonic-gate if (v == NULL) 299*0Sstevel@tonic-gate break; 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate mdb_vread(&dic->dic_dev, 302*0Sstevel@tonic-gate sizeof (struct dev_info), (uintptr_t)v); 303*0Sstevel@tonic-gate dic->dic_depth--; 304*0Sstevel@tonic-gate } 305*0Sstevel@tonic-gate if (v != NULL && v != dic->dic_end) 306*0Sstevel@tonic-gate v = dic->dic_dev.devi_sibling; 307*0Sstevel@tonic-gate if (v == dic->dic_end) 308*0Sstevel@tonic-gate v = NULL; /* Done */ 309*0Sstevel@tonic-gate } 310*0Sstevel@tonic-gate 311*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)v; 312*0Sstevel@tonic-gate return (status); 313*0Sstevel@tonic-gate } 314*0Sstevel@tonic-gate 315*0Sstevel@tonic-gate void 316*0Sstevel@tonic-gate devinfo_children_walk_fini(mdb_walk_state_t *wsp) 317*0Sstevel@tonic-gate { 318*0Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (devinfo_children_walk_data_t)); 319*0Sstevel@tonic-gate } 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate typedef struct devinfo_walk_data { 322*0Sstevel@tonic-gate mdb_walk_state_t diw_parent, diw_child; 323*0Sstevel@tonic-gate enum { DIW_PARENT, DIW_CHILD, DIW_DONE } diw_mode; 324*0Sstevel@tonic-gate } devinfo_walk_data_t; 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gate int 327*0Sstevel@tonic-gate devinfo_walk_init(mdb_walk_state_t *wsp) 328*0Sstevel@tonic-gate { 329*0Sstevel@tonic-gate devinfo_walk_data_t *diw; 330*0Sstevel@tonic-gate devinfo_parents_walk_data_t *dip; 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate diw = mdb_alloc(sizeof (devinfo_walk_data_t), UM_SLEEP); 333*0Sstevel@tonic-gate diw->diw_parent = *wsp; 334*0Sstevel@tonic-gate diw->diw_child = *wsp; 335*0Sstevel@tonic-gate wsp->walk_data = diw; 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate diw->diw_mode = DIW_PARENT; 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate if (devinfo_parents_walk_init(&diw->diw_parent) == -1) { 340*0Sstevel@tonic-gate mdb_free(diw, sizeof (devinfo_walk_data_t)); 341*0Sstevel@tonic-gate return (WALK_ERR); 342*0Sstevel@tonic-gate } 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gate /* 345*0Sstevel@tonic-gate * This is why the "devinfo" walker needs to be marginally 346*0Sstevel@tonic-gate * complicated - the child walker needs this initialization 347*0Sstevel@tonic-gate * data, and the best way to get it is out of the parent walker. 348*0Sstevel@tonic-gate */ 349*0Sstevel@tonic-gate dip = diw->diw_parent.walk_data; 350*0Sstevel@tonic-gate diw->diw_child.walk_arg = &dip->dip_base_depth; 351*0Sstevel@tonic-gate 352*0Sstevel@tonic-gate if (devinfo_children_walk_init(&diw->diw_child) == -1) { 353*0Sstevel@tonic-gate devinfo_parents_walk_fini(&diw->diw_parent); 354*0Sstevel@tonic-gate mdb_free(diw, sizeof (devinfo_walk_data_t)); 355*0Sstevel@tonic-gate return (WALK_ERR); 356*0Sstevel@tonic-gate } 357*0Sstevel@tonic-gate 358*0Sstevel@tonic-gate return (WALK_NEXT); 359*0Sstevel@tonic-gate } 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate int 362*0Sstevel@tonic-gate devinfo_walk_step(mdb_walk_state_t *wsp) 363*0Sstevel@tonic-gate { 364*0Sstevel@tonic-gate devinfo_walk_data_t *diw = wsp->walk_data; 365*0Sstevel@tonic-gate int status = WALK_NEXT; 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate if (diw->diw_mode == DIW_PARENT) { 368*0Sstevel@tonic-gate status = devinfo_parents_walk_step(&diw->diw_parent); 369*0Sstevel@tonic-gate if (status != WALK_NEXT) { 370*0Sstevel@tonic-gate /* 371*0Sstevel@tonic-gate * Keep on going even if the parents walk hit an error. 372*0Sstevel@tonic-gate */ 373*0Sstevel@tonic-gate diw->diw_mode = DIW_CHILD; 374*0Sstevel@tonic-gate status = WALK_NEXT; 375*0Sstevel@tonic-gate } 376*0Sstevel@tonic-gate } else if (diw->diw_mode == DIW_CHILD) { 377*0Sstevel@tonic-gate status = devinfo_children_walk_step(&diw->diw_child); 378*0Sstevel@tonic-gate if (status != WALK_NEXT) { 379*0Sstevel@tonic-gate diw->diw_mode = DIW_DONE; 380*0Sstevel@tonic-gate status = WALK_DONE; 381*0Sstevel@tonic-gate } 382*0Sstevel@tonic-gate } else 383*0Sstevel@tonic-gate status = WALK_DONE; 384*0Sstevel@tonic-gate 385*0Sstevel@tonic-gate return (status); 386*0Sstevel@tonic-gate } 387*0Sstevel@tonic-gate 388*0Sstevel@tonic-gate void 389*0Sstevel@tonic-gate devinfo_walk_fini(mdb_walk_state_t *wsp) 390*0Sstevel@tonic-gate { 391*0Sstevel@tonic-gate devinfo_walk_data_t *diw = wsp->walk_data; 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate devinfo_children_walk_fini(&diw->diw_child); 394*0Sstevel@tonic-gate devinfo_parents_walk_fini(&diw->diw_parent); 395*0Sstevel@tonic-gate mdb_free(diw, sizeof (devinfo_walk_data_t)); 396*0Sstevel@tonic-gate } 397*0Sstevel@tonic-gate 398*0Sstevel@tonic-gate /* 399*0Sstevel@tonic-gate * Given a devinfo pointer, figure out which driver is associated 400*0Sstevel@tonic-gate * with the node (by driver name, from the devnames array). 401*0Sstevel@tonic-gate */ 402*0Sstevel@tonic-gate /*ARGSUSED*/ 403*0Sstevel@tonic-gate int 404*0Sstevel@tonic-gate devinfo2driver(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 405*0Sstevel@tonic-gate { 406*0Sstevel@tonic-gate char dname[MODMAXNAMELEN + 1]; 407*0Sstevel@tonic-gate struct dev_info devi; 408*0Sstevel@tonic-gate 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) 411*0Sstevel@tonic-gate return (DCMD_USAGE); 412*0Sstevel@tonic-gate 413*0Sstevel@tonic-gate if (mdb_vread(&devi, sizeof (devi), addr) == -1) { 414*0Sstevel@tonic-gate mdb_warn("failed to read devinfo struct at %p", addr); 415*0Sstevel@tonic-gate return (DCMD_ERR); 416*0Sstevel@tonic-gate } 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate if (!DDI_CF2(&devi)) { 420*0Sstevel@tonic-gate /* No driver attached to this devinfo - nothing to do. */ 421*0Sstevel@tonic-gate mdb_warn("%p: No driver attached to this devinfo node\n", addr); 422*0Sstevel@tonic-gate return (DCMD_ERR); 423*0Sstevel@tonic-gate } 424*0Sstevel@tonic-gate 425*0Sstevel@tonic-gate if (mdb_devinfo2driver(addr, dname, sizeof (dname)) != 0) { 426*0Sstevel@tonic-gate mdb_warn("failed to determine driver name"); 427*0Sstevel@tonic-gate return (DCMD_ERR); 428*0Sstevel@tonic-gate } 429*0Sstevel@tonic-gate 430*0Sstevel@tonic-gate mdb_printf("Driver '%s' is associated with devinfo %p.\n", dname, addr); 431*0Sstevel@tonic-gate 432*0Sstevel@tonic-gate return (DCMD_OK); 433*0Sstevel@tonic-gate } 434*0Sstevel@tonic-gate 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate typedef struct devnames_walk { 437*0Sstevel@tonic-gate struct devnames *dnw_names; 438*0Sstevel@tonic-gate int dnw_ndx; 439*0Sstevel@tonic-gate int dnw_devcnt; 440*0Sstevel@tonic-gate uintptr_t dnw_base; 441*0Sstevel@tonic-gate uintptr_t dnw_size; 442*0Sstevel@tonic-gate } devnames_walk_t; 443*0Sstevel@tonic-gate 444*0Sstevel@tonic-gate int 445*0Sstevel@tonic-gate devnames_walk_init(mdb_walk_state_t *wsp) 446*0Sstevel@tonic-gate { 447*0Sstevel@tonic-gate devnames_walk_t *dnw; 448*0Sstevel@tonic-gate int devcnt; 449*0Sstevel@tonic-gate uintptr_t devnamesp; 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate if (wsp->walk_addr != NULL) { 452*0Sstevel@tonic-gate mdb_warn("devnames walker only supports global walks\n"); 453*0Sstevel@tonic-gate return (WALK_ERR); 454*0Sstevel@tonic-gate } 455*0Sstevel@tonic-gate 456*0Sstevel@tonic-gate if (mdb_readvar(&devcnt, "devcnt") == -1) { 457*0Sstevel@tonic-gate mdb_warn("failed to read 'devcnt'"); 458*0Sstevel@tonic-gate return (WALK_ERR); 459*0Sstevel@tonic-gate } 460*0Sstevel@tonic-gate 461*0Sstevel@tonic-gate if (mdb_readvar(&devnamesp, "devnamesp") == -1) { 462*0Sstevel@tonic-gate mdb_warn("failed to read 'devnamesp'"); 463*0Sstevel@tonic-gate return (WALK_ERR); 464*0Sstevel@tonic-gate } 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate dnw = mdb_zalloc(sizeof (devnames_walk_t), UM_SLEEP); 467*0Sstevel@tonic-gate dnw->dnw_size = sizeof (struct devnames) * devcnt; 468*0Sstevel@tonic-gate dnw->dnw_devcnt = devcnt; 469*0Sstevel@tonic-gate dnw->dnw_base = devnamesp; 470*0Sstevel@tonic-gate dnw->dnw_names = mdb_alloc(dnw->dnw_size, UM_SLEEP); 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate if (mdb_vread(dnw->dnw_names, dnw->dnw_size, dnw->dnw_base) == -1) { 473*0Sstevel@tonic-gate mdb_warn("couldn't read devnames array at %p", devnamesp); 474*0Sstevel@tonic-gate return (WALK_ERR); 475*0Sstevel@tonic-gate } 476*0Sstevel@tonic-gate 477*0Sstevel@tonic-gate wsp->walk_data = dnw; 478*0Sstevel@tonic-gate return (WALK_NEXT); 479*0Sstevel@tonic-gate } 480*0Sstevel@tonic-gate 481*0Sstevel@tonic-gate int 482*0Sstevel@tonic-gate devnames_walk_step(mdb_walk_state_t *wsp) 483*0Sstevel@tonic-gate { 484*0Sstevel@tonic-gate devnames_walk_t *dnw = wsp->walk_data; 485*0Sstevel@tonic-gate int status; 486*0Sstevel@tonic-gate 487*0Sstevel@tonic-gate if (dnw->dnw_ndx == dnw->dnw_devcnt) 488*0Sstevel@tonic-gate return (WALK_DONE); 489*0Sstevel@tonic-gate 490*0Sstevel@tonic-gate status = wsp->walk_callback(dnw->dnw_ndx * sizeof (struct devnames) + 491*0Sstevel@tonic-gate dnw->dnw_base, &dnw->dnw_names[dnw->dnw_ndx], wsp->walk_cbdata); 492*0Sstevel@tonic-gate 493*0Sstevel@tonic-gate dnw->dnw_ndx++; 494*0Sstevel@tonic-gate return (status); 495*0Sstevel@tonic-gate } 496*0Sstevel@tonic-gate 497*0Sstevel@tonic-gate void 498*0Sstevel@tonic-gate devnames_walk_fini(mdb_walk_state_t *wsp) 499*0Sstevel@tonic-gate { 500*0Sstevel@tonic-gate devnames_walk_t *dnw = wsp->walk_data; 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate mdb_free(dnw->dnw_names, dnw->dnw_size); 503*0Sstevel@tonic-gate mdb_free(dnw, sizeof (devnames_walk_t)); 504*0Sstevel@tonic-gate } 505*0Sstevel@tonic-gate 506*0Sstevel@tonic-gate int 507*0Sstevel@tonic-gate devinfo_siblings_walk_init(mdb_walk_state_t *wsp) 508*0Sstevel@tonic-gate { 509*0Sstevel@tonic-gate struct dev_info di; 510*0Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr; 511*0Sstevel@tonic-gate 512*0Sstevel@tonic-gate if (addr == NULL) { 513*0Sstevel@tonic-gate mdb_warn("a dev_info struct address must be provided\n"); 514*0Sstevel@tonic-gate return (WALK_ERR); 515*0Sstevel@tonic-gate } 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate if (mdb_vread(&di, sizeof (di), addr) == -1) { 518*0Sstevel@tonic-gate mdb_warn("failed to read dev_info struct at %p", addr); 519*0Sstevel@tonic-gate return (WALK_ERR); 520*0Sstevel@tonic-gate } 521*0Sstevel@tonic-gate 522*0Sstevel@tonic-gate if (di.devi_parent == NULL) { 523*0Sstevel@tonic-gate mdb_warn("no parent for devinfo at %p", addr); 524*0Sstevel@tonic-gate return (WALK_DONE); 525*0Sstevel@tonic-gate } 526*0Sstevel@tonic-gate 527*0Sstevel@tonic-gate if (mdb_vread(&di, sizeof (di), (uintptr_t)di.devi_parent) == -1) { 528*0Sstevel@tonic-gate mdb_warn("failed to read parent dev_info struct at %p", 529*0Sstevel@tonic-gate (uintptr_t)di.devi_parent); 530*0Sstevel@tonic-gate return (WALK_ERR); 531*0Sstevel@tonic-gate } 532*0Sstevel@tonic-gate 533*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)di.devi_child; 534*0Sstevel@tonic-gate return (WALK_NEXT); 535*0Sstevel@tonic-gate } 536*0Sstevel@tonic-gate 537*0Sstevel@tonic-gate int 538*0Sstevel@tonic-gate devinfo_siblings_walk_step(mdb_walk_state_t *wsp) 539*0Sstevel@tonic-gate { 540*0Sstevel@tonic-gate struct dev_info di; 541*0Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr; 542*0Sstevel@tonic-gate 543*0Sstevel@tonic-gate if (addr == NULL) 544*0Sstevel@tonic-gate return (WALK_DONE); 545*0Sstevel@tonic-gate 546*0Sstevel@tonic-gate if (mdb_vread(&di, sizeof (di), addr) == -1) { 547*0Sstevel@tonic-gate mdb_warn("failed to read dev_info struct at %p", addr); 548*0Sstevel@tonic-gate return (WALK_DONE); 549*0Sstevel@tonic-gate } 550*0Sstevel@tonic-gate 551*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)di.devi_sibling; 552*0Sstevel@tonic-gate return (wsp->walk_callback(addr, &di, wsp->walk_cbdata)); 553*0Sstevel@tonic-gate } 554*0Sstevel@tonic-gate 555*0Sstevel@tonic-gate int 556*0Sstevel@tonic-gate devi_next_walk_step(mdb_walk_state_t *wsp) 557*0Sstevel@tonic-gate { 558*0Sstevel@tonic-gate struct dev_info di; 559*0Sstevel@tonic-gate int status; 560*0Sstevel@tonic-gate 561*0Sstevel@tonic-gate if (wsp->walk_addr == NULL) 562*0Sstevel@tonic-gate return (WALK_DONE); 563*0Sstevel@tonic-gate 564*0Sstevel@tonic-gate if (mdb_vread(&di, sizeof (di), wsp->walk_addr) == -1) 565*0Sstevel@tonic-gate return (WALK_DONE); 566*0Sstevel@tonic-gate 567*0Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, &di, wsp->walk_cbdata); 568*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)di.devi_next; 569*0Sstevel@tonic-gate return (status); 570*0Sstevel@tonic-gate } 571*0Sstevel@tonic-gate 572*0Sstevel@tonic-gate /* 573*0Sstevel@tonic-gate * Helper functions. 574*0Sstevel@tonic-gate */ 575*0Sstevel@tonic-gate 576*0Sstevel@tonic-gate static int 577*0Sstevel@tonic-gate is_printable_string(unsigned char *prop_value) 578*0Sstevel@tonic-gate { 579*0Sstevel@tonic-gate while (*prop_value != 0) 580*0Sstevel@tonic-gate if (!isprint(*prop_value++)) 581*0Sstevel@tonic-gate return (0); 582*0Sstevel@tonic-gate return (1); 583*0Sstevel@tonic-gate } 584*0Sstevel@tonic-gate 585*0Sstevel@tonic-gate static void 586*0Sstevel@tonic-gate devinfo_print_props_type(int type) { 587*0Sstevel@tonic-gate char *type_str = NULL; 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate switch (type) { 590*0Sstevel@tonic-gate case DDI_PROP_TYPE_ANY: 591*0Sstevel@tonic-gate type_str = "any"; 592*0Sstevel@tonic-gate break; 593*0Sstevel@tonic-gate case DDI_PROP_TYPE_COMPOSITE: 594*0Sstevel@tonic-gate type_str = "composite"; 595*0Sstevel@tonic-gate break; 596*0Sstevel@tonic-gate case DDI_PROP_TYPE_INT64: 597*0Sstevel@tonic-gate type_str = "int64"; 598*0Sstevel@tonic-gate break; 599*0Sstevel@tonic-gate case DDI_PROP_TYPE_INT: 600*0Sstevel@tonic-gate type_str = "int"; 601*0Sstevel@tonic-gate break; 602*0Sstevel@tonic-gate case DDI_PROP_TYPE_BYTE: 603*0Sstevel@tonic-gate type_str = "byte"; 604*0Sstevel@tonic-gate break; 605*0Sstevel@tonic-gate case DDI_PROP_TYPE_STRING: 606*0Sstevel@tonic-gate type_str = "string"; 607*0Sstevel@tonic-gate break; 608*0Sstevel@tonic-gate } 609*0Sstevel@tonic-gate 610*0Sstevel@tonic-gate if (type_str != NULL) 611*0Sstevel@tonic-gate mdb_printf("type=%s", type_str); 612*0Sstevel@tonic-gate else 613*0Sstevel@tonic-gate mdb_printf("type=0x%x", type); 614*0Sstevel@tonic-gate } 615*0Sstevel@tonic-gate 616*0Sstevel@tonic-gate static void 617*0Sstevel@tonic-gate devinfo_print_props_value(int elem_size, int nelem, 618*0Sstevel@tonic-gate unsigned char *prop_value, int prop_value_len) 619*0Sstevel@tonic-gate { 620*0Sstevel@tonic-gate int i; 621*0Sstevel@tonic-gate 622*0Sstevel@tonic-gate mdb_printf("value="); 623*0Sstevel@tonic-gate 624*0Sstevel@tonic-gate if (elem_size == 0) { 625*0Sstevel@tonic-gate /* if elem_size == 0, then we are printing out string(s) */ 626*0Sstevel@tonic-gate char *p = (char *)prop_value; 627*0Sstevel@tonic-gate 628*0Sstevel@tonic-gate for (i = 0; i < nelem - 1; i++) { 629*0Sstevel@tonic-gate mdb_printf("'%s' + ", p); 630*0Sstevel@tonic-gate p += strlen(p) + 1; 631*0Sstevel@tonic-gate } 632*0Sstevel@tonic-gate mdb_printf("'%s'", p); 633*0Sstevel@tonic-gate } else { 634*0Sstevel@tonic-gate /* 635*0Sstevel@tonic-gate * if elem_size != 0 then we are printing out an array 636*0Sstevel@tonic-gate * where each element is of elem_size 637*0Sstevel@tonic-gate */ 638*0Sstevel@tonic-gate mdb_nhconvert(prop_value, prop_value, elem_size); 639*0Sstevel@tonic-gate mdb_printf("%02x", *prop_value); 640*0Sstevel@tonic-gate for (i = 1; i < prop_value_len; i++) { 641*0Sstevel@tonic-gate if ((i % elem_size) == 0) { 642*0Sstevel@tonic-gate mdb_nhconvert(&prop_value[i], 643*0Sstevel@tonic-gate &prop_value[i], elem_size); 644*0Sstevel@tonic-gate mdb_printf("."); 645*0Sstevel@tonic-gate } 646*0Sstevel@tonic-gate 647*0Sstevel@tonic-gate mdb_printf("%02x", prop_value[i]); 648*0Sstevel@tonic-gate } 649*0Sstevel@tonic-gate } 650*0Sstevel@tonic-gate } 651*0Sstevel@tonic-gate 652*0Sstevel@tonic-gate /* 653*0Sstevel@tonic-gate * devinfo_print_props_guess() 654*0Sstevel@tonic-gate * Guesses how to interpret the value of the property 655*0Sstevel@tonic-gate * 656*0Sstevel@tonic-gate * Params: 657*0Sstevel@tonic-gate * type - Should be the type value of the property 658*0Sstevel@tonic-gate * prop_val - Pointer to the property value data buffer 659*0Sstevel@tonic-gate * prop_len - Length of the property value data buffer 660*0Sstevel@tonic-gate * 661*0Sstevel@tonic-gate * Return values: 662*0Sstevel@tonic-gate * nelem - The number of elements stored in the property value 663*0Sstevel@tonic-gate * data buffer pointed to by prop_val. 664*0Sstevel@tonic-gate * elem_size - The size (in bytes) of the elements stored in the property 665*0Sstevel@tonic-gate * value data buffer pointed to by prop_val. 666*0Sstevel@tonic-gate * Upon return if elem_size == 0 and nelem != 0 then 667*0Sstevel@tonic-gate * the property value data buffer contains strings 668*0Sstevel@tonic-gate * len_err - There was an error with the length of the data buffer. 669*0Sstevel@tonic-gate * Its size is not a multiple of the array value type. 670*0Sstevel@tonic-gate * It will be interpreted as an array of bytes. 671*0Sstevel@tonic-gate */ 672*0Sstevel@tonic-gate static void 673*0Sstevel@tonic-gate devinfo_print_props_guess(int type, unsigned char *prop_val, int prop_len, 674*0Sstevel@tonic-gate int *elem_size, int *nelem, int *len_err) 675*0Sstevel@tonic-gate { 676*0Sstevel@tonic-gate *len_err = 0; 677*0Sstevel@tonic-gate if (prop_len == NULL) { 678*0Sstevel@tonic-gate *elem_size = 0; 679*0Sstevel@tonic-gate *nelem = 0; 680*0Sstevel@tonic-gate return; 681*0Sstevel@tonic-gate } 682*0Sstevel@tonic-gate 683*0Sstevel@tonic-gate /* by default, assume an array of bytes */ 684*0Sstevel@tonic-gate *elem_size = 1; 685*0Sstevel@tonic-gate *nelem = prop_len; 686*0Sstevel@tonic-gate 687*0Sstevel@tonic-gate switch (type) { 688*0Sstevel@tonic-gate case DDI_PROP_TYPE_BYTE: 689*0Sstevel@tonic-gate /* default case, that was easy */ 690*0Sstevel@tonic-gate break; 691*0Sstevel@tonic-gate case DDI_PROP_TYPE_INT64: 692*0Sstevel@tonic-gate if ((prop_len % sizeof (int64_t)) == 0) { 693*0Sstevel@tonic-gate *elem_size = sizeof (int64_t); 694*0Sstevel@tonic-gate *nelem = prop_len / *elem_size; 695*0Sstevel@tonic-gate } else { 696*0Sstevel@tonic-gate /* array is not a multiple of type size, error */ 697*0Sstevel@tonic-gate *len_err = 1; 698*0Sstevel@tonic-gate } 699*0Sstevel@tonic-gate break; 700*0Sstevel@tonic-gate case DDI_PROP_TYPE_INT: 701*0Sstevel@tonic-gate if ((prop_len % sizeof (int)) == 0) { 702*0Sstevel@tonic-gate *elem_size = sizeof (int); 703*0Sstevel@tonic-gate *nelem = prop_len / *elem_size; 704*0Sstevel@tonic-gate } else { 705*0Sstevel@tonic-gate /* array is not a multiple of type size, error */ 706*0Sstevel@tonic-gate *len_err = 1; 707*0Sstevel@tonic-gate } 708*0Sstevel@tonic-gate break; 709*0Sstevel@tonic-gate case DDI_PROP_TYPE_STRING: 710*0Sstevel@tonic-gate case DDI_PROP_TYPE_COMPOSITE: 711*0Sstevel@tonic-gate case DDI_PROP_TYPE_ANY: 712*0Sstevel@tonic-gate default: 713*0Sstevel@tonic-gate /* 714*0Sstevel@tonic-gate * if we made it here the type is either unknown 715*0Sstevel@tonic-gate * or a string. Try to interpret is as a string 716*0Sstevel@tonic-gate * and if that fails assume an array of bytes. 717*0Sstevel@tonic-gate */ 718*0Sstevel@tonic-gate if (prop_val[prop_len - 1] == '\0') { 719*0Sstevel@tonic-gate unsigned char *s = prop_val; 720*0Sstevel@tonic-gate int i; 721*0Sstevel@tonic-gate 722*0Sstevel@tonic-gate /* assume an array of strings */ 723*0Sstevel@tonic-gate *elem_size = 0; 724*0Sstevel@tonic-gate *nelem = 0; 725*0Sstevel@tonic-gate 726*0Sstevel@tonic-gate for (i = 0; i < prop_len; i++) { 727*0Sstevel@tonic-gate if (prop_val[i] != '\0') 728*0Sstevel@tonic-gate continue; 729*0Sstevel@tonic-gate 730*0Sstevel@tonic-gate /* 731*0Sstevel@tonic-gate * If the property is typed as a string 732*0Sstevel@tonic-gate * property, then interpret empty strings 733*0Sstevel@tonic-gate * as strings. Otherwise default to an 734*0Sstevel@tonic-gate * array of bytes. If there are unprintable 735*0Sstevel@tonic-gate * characters, always default to an array of 736*0Sstevel@tonic-gate * bytes. 737*0Sstevel@tonic-gate */ 738*0Sstevel@tonic-gate if ((*s == '\0' && type != 739*0Sstevel@tonic-gate DDI_PROP_TYPE_STRING) || 740*0Sstevel@tonic-gate !is_printable_string(s)) { 741*0Sstevel@tonic-gate *elem_size = 1; 742*0Sstevel@tonic-gate *nelem = prop_len; 743*0Sstevel@tonic-gate break; 744*0Sstevel@tonic-gate } 745*0Sstevel@tonic-gate 746*0Sstevel@tonic-gate (*nelem)++; 747*0Sstevel@tonic-gate s = &prop_val[i + 1]; 748*0Sstevel@tonic-gate } 749*0Sstevel@tonic-gate } 750*0Sstevel@tonic-gate break; 751*0Sstevel@tonic-gate } 752*0Sstevel@tonic-gate } 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate static void 755*0Sstevel@tonic-gate devinfo_print_props(char *name, ddi_prop_t *p) 756*0Sstevel@tonic-gate { 757*0Sstevel@tonic-gate if (p == NULL) 758*0Sstevel@tonic-gate return; 759*0Sstevel@tonic-gate 760*0Sstevel@tonic-gate if (name != NULL) 761*0Sstevel@tonic-gate mdb_printf("%s ", name); 762*0Sstevel@tonic-gate 763*0Sstevel@tonic-gate mdb_printf("properties at %p:\n", p); 764*0Sstevel@tonic-gate mdb_inc_indent(DEVINFO_PROP_INDENT); 765*0Sstevel@tonic-gate 766*0Sstevel@tonic-gate while (p != NULL) { 767*0Sstevel@tonic-gate ddi_prop_t prop; 768*0Sstevel@tonic-gate char prop_name[128]; 769*0Sstevel@tonic-gate unsigned char *prop_value; 770*0Sstevel@tonic-gate int type, elem_size, nelem, prop_len_error; 771*0Sstevel@tonic-gate 772*0Sstevel@tonic-gate /* read in the property struct */ 773*0Sstevel@tonic-gate if (mdb_vread(&prop, sizeof (prop), (uintptr_t)p) == -1) { 774*0Sstevel@tonic-gate mdb_warn("could not read property at 0x%p", p); 775*0Sstevel@tonic-gate break; 776*0Sstevel@tonic-gate } 777*0Sstevel@tonic-gate 778*0Sstevel@tonic-gate /* print the property name */ 779*0Sstevel@tonic-gate if (mdb_readstr(prop_name, sizeof (prop_name), 780*0Sstevel@tonic-gate (uintptr_t)prop.prop_name) == -1) { 781*0Sstevel@tonic-gate mdb_warn("could not read property name at 0x%p", 782*0Sstevel@tonic-gate prop.prop_name); 783*0Sstevel@tonic-gate goto next; 784*0Sstevel@tonic-gate } 785*0Sstevel@tonic-gate mdb_printf("name='%s' ", prop_name); 786*0Sstevel@tonic-gate 787*0Sstevel@tonic-gate /* get the property type and print it out */ 788*0Sstevel@tonic-gate type = (prop.prop_flags & DDI_PROP_TYPE_MASK); 789*0Sstevel@tonic-gate devinfo_print_props_type(type); 790*0Sstevel@tonic-gate 791*0Sstevel@tonic-gate /* get the property value */ 792*0Sstevel@tonic-gate if (prop.prop_len > 0) { 793*0Sstevel@tonic-gate prop_value = mdb_alloc(prop.prop_len, UM_SLEEP|UM_GC); 794*0Sstevel@tonic-gate if (mdb_vread(prop_value, prop.prop_len, 795*0Sstevel@tonic-gate (uintptr_t)prop.prop_val) == -1) { 796*0Sstevel@tonic-gate mdb_warn("could not read property value at " 797*0Sstevel@tonic-gate "0x%p", prop.prop_val); 798*0Sstevel@tonic-gate goto next; 799*0Sstevel@tonic-gate } 800*0Sstevel@tonic-gate } else { 801*0Sstevel@tonic-gate prop_value = NULL; 802*0Sstevel@tonic-gate } 803*0Sstevel@tonic-gate 804*0Sstevel@tonic-gate /* take a guess at interpreting the property value */ 805*0Sstevel@tonic-gate devinfo_print_props_guess(type, prop_value, prop.prop_len, 806*0Sstevel@tonic-gate &elem_size, &nelem, &prop_len_error); 807*0Sstevel@tonic-gate 808*0Sstevel@tonic-gate /* print out the number ot items */ 809*0Sstevel@tonic-gate mdb_printf(" items=%d", nelem); 810*0Sstevel@tonic-gate 811*0Sstevel@tonic-gate /* print out any associated device information */ 812*0Sstevel@tonic-gate if (prop.prop_dev != DDI_DEV_T_NONE) { 813*0Sstevel@tonic-gate mdb_printf(" dev="); 814*0Sstevel@tonic-gate if (prop.prop_dev == DDI_DEV_T_ANY) 815*0Sstevel@tonic-gate mdb_printf("any"); 816*0Sstevel@tonic-gate else if (prop.prop_dev == DDI_MAJOR_T_UNKNOWN) 817*0Sstevel@tonic-gate mdb_printf("unknown"); 818*0Sstevel@tonic-gate else 819*0Sstevel@tonic-gate mdb_printf("(%u,%u)", 820*0Sstevel@tonic-gate getmajor(prop.prop_dev), 821*0Sstevel@tonic-gate getminor(prop.prop_dev)); 822*0Sstevel@tonic-gate } 823*0Sstevel@tonic-gate 824*0Sstevel@tonic-gate /* print out the property value */ 825*0Sstevel@tonic-gate if (prop_value != NULL) { 826*0Sstevel@tonic-gate mdb_printf("\n"); 827*0Sstevel@tonic-gate mdb_inc_indent(DEVINFO_PROP_INDENT); 828*0Sstevel@tonic-gate if (prop_len_error) 829*0Sstevel@tonic-gate mdb_printf("NOTE: prop length is not a " 830*0Sstevel@tonic-gate "multiple of element size\n"); 831*0Sstevel@tonic-gate devinfo_print_props_value(elem_size, nelem, 832*0Sstevel@tonic-gate prop_value, prop.prop_len); 833*0Sstevel@tonic-gate mdb_dec_indent(DEVINFO_PROP_INDENT); 834*0Sstevel@tonic-gate } 835*0Sstevel@tonic-gate 836*0Sstevel@tonic-gate next: 837*0Sstevel@tonic-gate mdb_printf("\n"); 838*0Sstevel@tonic-gate p = prop.prop_next; 839*0Sstevel@tonic-gate } 840*0Sstevel@tonic-gate 841*0Sstevel@tonic-gate mdb_dec_indent(DEVINFO_PROP_INDENT); 842*0Sstevel@tonic-gate } 843*0Sstevel@tonic-gate 844*0Sstevel@tonic-gate static void 845*0Sstevel@tonic-gate devinfo_pathinfo_state(mdi_pathinfo_state_t state) { 846*0Sstevel@tonic-gate char *type_str = NULL; 847*0Sstevel@tonic-gate 848*0Sstevel@tonic-gate switch (state) { 849*0Sstevel@tonic-gate case MDI_PATHINFO_STATE_INIT: 850*0Sstevel@tonic-gate type_str = "init"; 851*0Sstevel@tonic-gate break; 852*0Sstevel@tonic-gate case MDI_PATHINFO_STATE_ONLINE: 853*0Sstevel@tonic-gate type_str = "online"; 854*0Sstevel@tonic-gate break; 855*0Sstevel@tonic-gate case MDI_PATHINFO_STATE_STANDBY: 856*0Sstevel@tonic-gate type_str = "standby"; 857*0Sstevel@tonic-gate break; 858*0Sstevel@tonic-gate case MDI_PATHINFO_STATE_FAULT: 859*0Sstevel@tonic-gate type_str = "fault"; 860*0Sstevel@tonic-gate break; 861*0Sstevel@tonic-gate case MDI_PATHINFO_STATE_OFFLINE: 862*0Sstevel@tonic-gate type_str = "offline"; 863*0Sstevel@tonic-gate break; 864*0Sstevel@tonic-gate } 865*0Sstevel@tonic-gate if (type_str != NULL) 866*0Sstevel@tonic-gate mdb_printf("state=%s\n", type_str); 867*0Sstevel@tonic-gate else 868*0Sstevel@tonic-gate mdb_printf("state=0x%x\n", state); 869*0Sstevel@tonic-gate } 870*0Sstevel@tonic-gate 871*0Sstevel@tonic-gate static void 872*0Sstevel@tonic-gate devinfo_print_pathing(int mdi_component, void *mdi_client) { 873*0Sstevel@tonic-gate mdi_client_t mdi_c; 874*0Sstevel@tonic-gate struct mdi_pathinfo *pip; 875*0Sstevel@tonic-gate 876*0Sstevel@tonic-gate /* we only print out multipathing info for client nodes */ 877*0Sstevel@tonic-gate if ((mdi_component & MDI_COMPONENT_CLIENT) == 0) 878*0Sstevel@tonic-gate return; 879*0Sstevel@tonic-gate 880*0Sstevel@tonic-gate mdb_printf("Client multipath info at: 0x%p\n", mdi_client); 881*0Sstevel@tonic-gate mdb_inc_indent(DEVINFO_PROP_INDENT); 882*0Sstevel@tonic-gate 883*0Sstevel@tonic-gate /* read in the client multipathing info */ 884*0Sstevel@tonic-gate if (mdb_readstr((void*) &mdi_c, sizeof (mdi_c), 885*0Sstevel@tonic-gate (uintptr_t)mdi_client) == -1) { 886*0Sstevel@tonic-gate mdb_warn("failed to read mdi_client at %p", 887*0Sstevel@tonic-gate (uintptr_t)mdi_client); 888*0Sstevel@tonic-gate goto exit; 889*0Sstevel@tonic-gate } 890*0Sstevel@tonic-gate 891*0Sstevel@tonic-gate /* 892*0Sstevel@tonic-gate * walk through the clients list of pathinfo structures and print 893*0Sstevel@tonic-gate * out the properties for each path 894*0Sstevel@tonic-gate */ 895*0Sstevel@tonic-gate pip = (struct mdi_pathinfo *)mdi_c.ct_path_head; 896*0Sstevel@tonic-gate while (pip != NULL) { 897*0Sstevel@tonic-gate char binding_name[128]; 898*0Sstevel@tonic-gate struct mdi_pathinfo pi; 899*0Sstevel@tonic-gate mdi_phci_t ph; 900*0Sstevel@tonic-gate struct dev_info ph_di; 901*0Sstevel@tonic-gate 902*0Sstevel@tonic-gate /* read in the pathinfo structure */ 903*0Sstevel@tonic-gate if (mdb_vread((void*)&pi, sizeof (pi), 904*0Sstevel@tonic-gate (uintptr_t)pip) == -1) { 905*0Sstevel@tonic-gate mdb_warn("failed to read mdi_pathinfo at %p", 906*0Sstevel@tonic-gate (uintptr_t)pip); 907*0Sstevel@tonic-gate goto exit; 908*0Sstevel@tonic-gate } 909*0Sstevel@tonic-gate 910*0Sstevel@tonic-gate /* read in the pchi (path host adapter) info */ 911*0Sstevel@tonic-gate if (mdb_vread((void*)&ph, sizeof (ph), 912*0Sstevel@tonic-gate (uintptr_t)pi.pi_phci) == -1) { 913*0Sstevel@tonic-gate mdb_warn("failed to read mdi_pchi at %p", 914*0Sstevel@tonic-gate (uintptr_t)pi.pi_phci); 915*0Sstevel@tonic-gate goto exit; 916*0Sstevel@tonic-gate } 917*0Sstevel@tonic-gate 918*0Sstevel@tonic-gate /* read in the dip of the phci so we can get it's name */ 919*0Sstevel@tonic-gate if (mdb_vread((void*)&ph_di, sizeof (ph_di), 920*0Sstevel@tonic-gate (uintptr_t)ph.ph_dip) == -1) { 921*0Sstevel@tonic-gate mdb_warn("failed to read mdi_pchi at %p", 922*0Sstevel@tonic-gate (uintptr_t)ph.ph_dip); 923*0Sstevel@tonic-gate goto exit; 924*0Sstevel@tonic-gate } 925*0Sstevel@tonic-gate if (mdb_vread(binding_name, sizeof (binding_name), 926*0Sstevel@tonic-gate (uintptr_t)ph_di.devi_binding_name) == -1) { 927*0Sstevel@tonic-gate mdb_warn("failed to read binding_name at %p", 928*0Sstevel@tonic-gate (uintptr_t)ph_di.devi_binding_name); 929*0Sstevel@tonic-gate goto exit; 930*0Sstevel@tonic-gate } 931*0Sstevel@tonic-gate 932*0Sstevel@tonic-gate mdb_printf("%s#%d, ", binding_name, ph_di.devi_instance); 933*0Sstevel@tonic-gate devinfo_pathinfo_state(pi.pi_state); 934*0Sstevel@tonic-gate 935*0Sstevel@tonic-gate /* print out the pathing info */ 936*0Sstevel@tonic-gate mdb_inc_indent(DEVINFO_PROP_INDENT); 937*0Sstevel@tonic-gate if (mdb_pwalk_dcmd(NVPAIR_WALKER_FQNAME, NVPAIR_DCMD_FQNAME, 938*0Sstevel@tonic-gate 0, NULL, (uintptr_t)pi.pi_prop) != 0) { 939*0Sstevel@tonic-gate mdb_dec_indent(DEVINFO_PROP_INDENT); 940*0Sstevel@tonic-gate goto exit; 941*0Sstevel@tonic-gate } 942*0Sstevel@tonic-gate mdb_dec_indent(DEVINFO_PROP_INDENT); 943*0Sstevel@tonic-gate pip = pi.pi_client_link; 944*0Sstevel@tonic-gate } 945*0Sstevel@tonic-gate 946*0Sstevel@tonic-gate exit: 947*0Sstevel@tonic-gate mdb_dec_indent(DEVINFO_PROP_INDENT); 948*0Sstevel@tonic-gate } 949*0Sstevel@tonic-gate 950*0Sstevel@tonic-gate typedef struct devinfo_cb_data { 951*0Sstevel@tonic-gate uintptr_t di_base; 952*0Sstevel@tonic-gate uint_t di_flags; 953*0Sstevel@tonic-gate } devinfo_cb_data_t; 954*0Sstevel@tonic-gate 955*0Sstevel@tonic-gate /* 956*0Sstevel@tonic-gate * Yet to be added: 957*0Sstevel@tonic-gate * 958*0Sstevel@tonic-gate * struct devnames *devnamesp; 959*0Sstevel@tonic-gate * <sys/autoconf.h>:26 - type definition 960*0Sstevel@tonic-gate * uts/common/os/modctl.c:106 - devnamesp definition 961*0Sstevel@tonic-gate * 962*0Sstevel@tonic-gate * int devcnt; 963*0Sstevel@tonic-gate * uts/common/io/conf.c:62 - devcnt definition 964*0Sstevel@tonic-gate * 965*0Sstevel@tonic-gate * "devnamesp" is an array of "devcnt" "devnames" structures, 966*0Sstevel@tonic-gate * indexed by major number. This gets us "prtconf -D". 967*0Sstevel@tonic-gate */ 968*0Sstevel@tonic-gate static int 969*0Sstevel@tonic-gate devinfo_print(uintptr_t addr, struct dev_info *dev, devinfo_cb_data_t *data) 970*0Sstevel@tonic-gate { 971*0Sstevel@tonic-gate /* 972*0Sstevel@tonic-gate * We know the walker passes us extra data after the dev_info. 973*0Sstevel@tonic-gate */ 974*0Sstevel@tonic-gate char binding_name[128]; 975*0Sstevel@tonic-gate devinfo_node_t *din = (devinfo_node_t *)dev; 976*0Sstevel@tonic-gate ddi_prop_t *global_props = NULL; 977*0Sstevel@tonic-gate 978*0Sstevel@tonic-gate if (mdb_readstr(binding_name, sizeof (binding_name), 979*0Sstevel@tonic-gate (uintptr_t)dev->devi_binding_name) == -1) { 980*0Sstevel@tonic-gate mdb_warn("failed to read binding_name at %p", 981*0Sstevel@tonic-gate (uintptr_t)dev->devi_binding_name); 982*0Sstevel@tonic-gate return (WALK_ERR); 983*0Sstevel@tonic-gate } 984*0Sstevel@tonic-gate 985*0Sstevel@tonic-gate /* if there are any global properties, get a pointer to them */ 986*0Sstevel@tonic-gate if (dev->devi_global_prop_list != NULL) { 987*0Sstevel@tonic-gate ddi_prop_list_t plist; 988*0Sstevel@tonic-gate if (mdb_vread((void*)&plist, sizeof (plist), 989*0Sstevel@tonic-gate (uintptr_t)dev->devi_global_prop_list) == -1) { 990*0Sstevel@tonic-gate mdb_warn("failed to read global prop_list at %p", 991*0Sstevel@tonic-gate (uintptr_t)dev->devi_global_prop_list); 992*0Sstevel@tonic-gate return (WALK_ERR); 993*0Sstevel@tonic-gate } 994*0Sstevel@tonic-gate global_props = plist.prop_list; 995*0Sstevel@tonic-gate } 996*0Sstevel@tonic-gate 997*0Sstevel@tonic-gate mdb_inc_indent(din->din_depth * DEVINFO_TREE_INDENT); 998*0Sstevel@tonic-gate if ((addr == data->di_base) || (data->di_flags & DEVINFO_ALLBOLD)) 999*0Sstevel@tonic-gate mdb_printf("%<b>"); 1000*0Sstevel@tonic-gate mdb_printf("%-0?p %s", addr, binding_name); 1001*0Sstevel@tonic-gate if ((addr == data->di_base) || (data->di_flags & DEVINFO_ALLBOLD)) 1002*0Sstevel@tonic-gate mdb_printf("%</b>"); 1003*0Sstevel@tonic-gate if (dev->devi_instance >= 0) 1004*0Sstevel@tonic-gate mdb_printf(", instance #%d", dev->devi_instance); 1005*0Sstevel@tonic-gate if (dev->devi_ops == NULL) 1006*0Sstevel@tonic-gate mdb_printf(" (driver not attached)"); 1007*0Sstevel@tonic-gate mdb_printf("\n"); 1008*0Sstevel@tonic-gate if (data->di_flags & DEVINFO_VERBOSE) { 1009*0Sstevel@tonic-gate mdb_inc_indent(DEVINFO_PROPLIST_INDENT); 1010*0Sstevel@tonic-gate devinfo_print_props("System", dev->devi_sys_prop_ptr); 1011*0Sstevel@tonic-gate devinfo_print_props("Driver", dev->devi_drv_prop_ptr); 1012*0Sstevel@tonic-gate devinfo_print_props("Hardware", dev->devi_hw_prop_ptr); 1013*0Sstevel@tonic-gate devinfo_print_props("Global", global_props); 1014*0Sstevel@tonic-gate 1015*0Sstevel@tonic-gate devinfo_print_pathing(dev->devi_mdi_component, 1016*0Sstevel@tonic-gate dev->devi_mdi_client); 1017*0Sstevel@tonic-gate 1018*0Sstevel@tonic-gate mdb_dec_indent(DEVINFO_PROPLIST_INDENT); 1019*0Sstevel@tonic-gate } 1020*0Sstevel@tonic-gate 1021*0Sstevel@tonic-gate mdb_dec_indent(din->din_depth * DEVINFO_TREE_INDENT); 1022*0Sstevel@tonic-gate return (WALK_NEXT); 1023*0Sstevel@tonic-gate } 1024*0Sstevel@tonic-gate 1025*0Sstevel@tonic-gate /*ARGSUSED*/ 1026*0Sstevel@tonic-gate int 1027*0Sstevel@tonic-gate prtconf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1028*0Sstevel@tonic-gate { 1029*0Sstevel@tonic-gate devinfo_cb_data_t data; 1030*0Sstevel@tonic-gate int status; 1031*0Sstevel@tonic-gate 1032*0Sstevel@tonic-gate data.di_flags = DEVINFO_PARENT | DEVINFO_CHILD; 1033*0Sstevel@tonic-gate 1034*0Sstevel@tonic-gate if (mdb_getopts(argc, argv, 1035*0Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, DEVINFO_VERBOSE, &data.di_flags, 1036*0Sstevel@tonic-gate 'p', MDB_OPT_CLRBITS, DEVINFO_CHILD, &data.di_flags, 1037*0Sstevel@tonic-gate 'c', MDB_OPT_CLRBITS, DEVINFO_PARENT, &data.di_flags, NULL) != argc) 1038*0Sstevel@tonic-gate return (DCMD_USAGE); 1039*0Sstevel@tonic-gate 1040*0Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) == 0) { 1041*0Sstevel@tonic-gate addr = devinfo_root; 1042*0Sstevel@tonic-gate if (data.di_flags & DEVINFO_VERBOSE) 1043*0Sstevel@tonic-gate data.di_flags |= DEVINFO_ALLBOLD; 1044*0Sstevel@tonic-gate } 1045*0Sstevel@tonic-gate 1046*0Sstevel@tonic-gate data.di_base = addr; 1047*0Sstevel@tonic-gate mdb_printf("%<u>%-?s %-50s%</u>\n", "DEVINFO", "NAME"); 1048*0Sstevel@tonic-gate 1049*0Sstevel@tonic-gate if ((data.di_flags & (DEVINFO_PARENT | DEVINFO_CHILD)) == 1050*0Sstevel@tonic-gate (DEVINFO_PARENT | DEVINFO_CHILD)) { 1051*0Sstevel@tonic-gate status = mdb_pwalk("devinfo", 1052*0Sstevel@tonic-gate (mdb_walk_cb_t)devinfo_print, &data, addr); 1053*0Sstevel@tonic-gate } else if (data.di_flags & DEVINFO_PARENT) { 1054*0Sstevel@tonic-gate status = mdb_pwalk("devinfo_parents", 1055*0Sstevel@tonic-gate (mdb_walk_cb_t)devinfo_print, &data, addr); 1056*0Sstevel@tonic-gate } else if (data.di_flags & DEVINFO_CHILD) { 1057*0Sstevel@tonic-gate status = mdb_pwalk("devinfo_children", 1058*0Sstevel@tonic-gate (mdb_walk_cb_t)devinfo_print, &data, addr); 1059*0Sstevel@tonic-gate } else { 1060*0Sstevel@tonic-gate devinfo_node_t din; 1061*0Sstevel@tonic-gate if (mdb_vread(&din.din_dev, sizeof (din.din_dev), addr) == -1) { 1062*0Sstevel@tonic-gate mdb_warn("failed to read device"); 1063*0Sstevel@tonic-gate return (DCMD_ERR); 1064*0Sstevel@tonic-gate } 1065*0Sstevel@tonic-gate din.din_depth = 0; 1066*0Sstevel@tonic-gate return (devinfo_print(addr, (struct dev_info *)&din, &data)); 1067*0Sstevel@tonic-gate } 1068*0Sstevel@tonic-gate 1069*0Sstevel@tonic-gate if (status == -1) { 1070*0Sstevel@tonic-gate mdb_warn("couldn't walk devinfo tree"); 1071*0Sstevel@tonic-gate return (DCMD_ERR); 1072*0Sstevel@tonic-gate } 1073*0Sstevel@tonic-gate 1074*0Sstevel@tonic-gate return (DCMD_OK); 1075*0Sstevel@tonic-gate } 1076*0Sstevel@tonic-gate 1077*0Sstevel@tonic-gate /*ARGSUSED*/ 1078*0Sstevel@tonic-gate int 1079*0Sstevel@tonic-gate devinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1080*0Sstevel@tonic-gate { 1081*0Sstevel@tonic-gate char tmpstr[MODMAXNAMELEN]; 1082*0Sstevel@tonic-gate char nodename[MODMAXNAMELEN]; 1083*0Sstevel@tonic-gate char bindname[MODMAXNAMELEN]; 1084*0Sstevel@tonic-gate int size, length; 1085*0Sstevel@tonic-gate struct dev_info devi; 1086*0Sstevel@tonic-gate devinfo_node_t din; 1087*0Sstevel@tonic-gate devinfo_cb_data_t data; 1088*0Sstevel@tonic-gate 1089*0Sstevel@tonic-gate static const mdb_bitmask_t devi_state_masks[] = { 1090*0Sstevel@tonic-gate { "DEVICE_OFFLINE", DEVI_DEVICE_OFFLINE, DEVI_DEVICE_OFFLINE }, 1091*0Sstevel@tonic-gate { "DEVICE_DOWN", DEVI_DEVICE_DOWN, DEVI_DEVICE_DOWN }, 1092*0Sstevel@tonic-gate { "DEVICE_DEGRADED", DEVI_DEVICE_DEGRADED, DEVI_DEVICE_DEGRADED }, 1093*0Sstevel@tonic-gate { "BUS_QUIESCED", DEVI_BUS_QUIESCED, DEVI_BUS_QUIESCED }, 1094*0Sstevel@tonic-gate { "BUS_DOWN", DEVI_BUS_DOWN, DEVI_BUS_DOWN }, 1095*0Sstevel@tonic-gate { "NDI_CONFIG", DEVI_NDI_CONFIG, DEVI_NDI_CONFIG }, 1096*0Sstevel@tonic-gate 1097*0Sstevel@tonic-gate { "S_ATTACHING", DEVI_S_ATTACHING, DEVI_S_ATTACHING }, 1098*0Sstevel@tonic-gate { "S_DETACHING", DEVI_S_DETACHING, DEVI_S_DETACHING }, 1099*0Sstevel@tonic-gate { "S_ONLINING", DEVI_S_ONLINING, DEVI_S_ONLINING }, 1100*0Sstevel@tonic-gate { "S_OFFLINING", DEVI_S_OFFLINING, DEVI_S_OFFLINING }, 1101*0Sstevel@tonic-gate { "S_INVOKING_DACF", DEVI_S_INVOKING_DACF, DEVI_S_INVOKING_DACF }, 1102*0Sstevel@tonic-gate { "S_UNBOUND", DEVI_S_UNBOUND, DEVI_S_UNBOUND }, 1103*0Sstevel@tonic-gate { "S_MD_UPDATE", DEVI_S_MD_UPDATE, DEVI_S_MD_UPDATE }, 1104*0Sstevel@tonic-gate { "S_REPORT", DEVI_S_REPORT, DEVI_S_REPORT }, 1105*0Sstevel@tonic-gate { "S_EVADD", DEVI_S_EVADD, DEVI_S_EVADD }, 1106*0Sstevel@tonic-gate { "S_EVREMOVE", DEVI_S_EVREMOVE, DEVI_S_EVREMOVE }, 1107*0Sstevel@tonic-gate { NULL, 0, 0 } 1108*0Sstevel@tonic-gate }; 1109*0Sstevel@tonic-gate 1110*0Sstevel@tonic-gate static const mdb_bitmask_t devi_flags_masks[] = { 1111*0Sstevel@tonic-gate { "BUSY", DEVI_BUSY, DEVI_BUSY }, 1112*0Sstevel@tonic-gate { "MADE_CHILDREN", DEVI_MADE_CHILDREN, DEVI_MADE_CHILDREN }, 1113*0Sstevel@tonic-gate { "ATTACHED_CHILDREN", 1114*0Sstevel@tonic-gate DEVI_ATTACHED_CHILDREN, DEVI_ATTACHED_CHILDREN}, 1115*0Sstevel@tonic-gate { "BRANCH_HELD", DEVI_BRANCH_HELD, DEVI_BRANCH_HELD }, 1116*0Sstevel@tonic-gate { NULL, 0, 0 } 1117*0Sstevel@tonic-gate }; 1118*0Sstevel@tonic-gate 1119*0Sstevel@tonic-gate data.di_flags = DEVINFO_VERBOSE; 1120*0Sstevel@tonic-gate data.di_base = addr; 1121*0Sstevel@tonic-gate 1122*0Sstevel@tonic-gate if (mdb_getopts(argc, argv, 1123*0Sstevel@tonic-gate 'q', MDB_OPT_CLRBITS, DEVINFO_VERBOSE, &data.di_flags, 1124*0Sstevel@tonic-gate 's', MDB_OPT_SETBITS, DEVINFO_SUMMARY, &data.di_flags, NULL) 1125*0Sstevel@tonic-gate != argc) 1126*0Sstevel@tonic-gate return (DCMD_USAGE); 1127*0Sstevel@tonic-gate 1128*0Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) == 0) { 1129*0Sstevel@tonic-gate mdb_warn( 1130*0Sstevel@tonic-gate "devinfo doesn't give global information (try prtconf)\n"); 1131*0Sstevel@tonic-gate return (DCMD_ERR); 1132*0Sstevel@tonic-gate } 1133*0Sstevel@tonic-gate 1134*0Sstevel@tonic-gate if (DCMD_HDRSPEC(flags) && data.di_flags & DEVINFO_SUMMARY) 1135*0Sstevel@tonic-gate mdb_printf( 1136*0Sstevel@tonic-gate "%-?s %5s %?s %-20s %-s\n" 1137*0Sstevel@tonic-gate "%-?s %5s %?s %-20s %-s\n" 1138*0Sstevel@tonic-gate "%<u>%-?s %5s %?s %-20s %-15s%</u>\n", 1139*0Sstevel@tonic-gate "DEVINFO", "MAJ", "REFCNT", "NODENAME", "NODESTATE", 1140*0Sstevel@tonic-gate "", "INST", "CIRCULAR", "BINDNAME", "STATE", 1141*0Sstevel@tonic-gate "", "", "THREAD", "", "FLAGS"); 1142*0Sstevel@tonic-gate 1143*0Sstevel@tonic-gate if (mdb_vread(&devi, sizeof (devi), addr) == -1) { 1144*0Sstevel@tonic-gate mdb_warn("failed to read device"); 1145*0Sstevel@tonic-gate return (DCMD_ERR); 1146*0Sstevel@tonic-gate } 1147*0Sstevel@tonic-gate 1148*0Sstevel@tonic-gate if (data.di_flags & DEVINFO_SUMMARY) { 1149*0Sstevel@tonic-gate *nodename = '\0'; 1150*0Sstevel@tonic-gate size = sizeof (nodename); 1151*0Sstevel@tonic-gate 1152*0Sstevel@tonic-gate if ((length = mdb_readstr(tmpstr, size, 1153*0Sstevel@tonic-gate (uintptr_t)devi.devi_node_name)) > 0) { 1154*0Sstevel@tonic-gate strcat(nodename, tmpstr); 1155*0Sstevel@tonic-gate size -= length; 1156*0Sstevel@tonic-gate } 1157*0Sstevel@tonic-gate 1158*0Sstevel@tonic-gate if (devi.devi_addr != NULL && mdb_readstr(tmpstr, size - 1, 1159*0Sstevel@tonic-gate (uintptr_t)devi.devi_addr) > 0) { 1160*0Sstevel@tonic-gate strcat(nodename, "@"); 1161*0Sstevel@tonic-gate strcat(nodename, tmpstr); 1162*0Sstevel@tonic-gate } 1163*0Sstevel@tonic-gate 1164*0Sstevel@tonic-gate if (mdb_readstr(bindname, sizeof (bindname), 1165*0Sstevel@tonic-gate (uintptr_t)devi.devi_binding_name) == -1) 1166*0Sstevel@tonic-gate *bindname = '\0'; 1167*0Sstevel@tonic-gate 1168*0Sstevel@tonic-gate mdb_printf("%0?p %5d %?d %-20s %s\n", 1169*0Sstevel@tonic-gate addr, devi.devi_major, devi.devi_ref, nodename, 1170*0Sstevel@tonic-gate di_state[MIN(devi.devi_node_state + 1, DI_STATE_MAX)]); 1171*0Sstevel@tonic-gate mdb_printf("%?s %5d %?d %-20s <%b>\n", 1172*0Sstevel@tonic-gate "", devi.devi_instance, devi.devi_circular, bindname, 1173*0Sstevel@tonic-gate devi.devi_state, devi_state_masks); 1174*0Sstevel@tonic-gate mdb_printf("%?s %5s %?p %-20s <%b>\n\n", 1175*0Sstevel@tonic-gate "", "", devi.devi_busy_thread, "", 1176*0Sstevel@tonic-gate devi.devi_flags, devi_flags_masks); 1177*0Sstevel@tonic-gate 1178*0Sstevel@tonic-gate return (DCMD_OK); 1179*0Sstevel@tonic-gate } else { 1180*0Sstevel@tonic-gate din.din_dev = devi; 1181*0Sstevel@tonic-gate din.din_depth = 0; 1182*0Sstevel@tonic-gate return (devinfo_print(addr, (struct dev_info *)&din, &data)); 1183*0Sstevel@tonic-gate } 1184*0Sstevel@tonic-gate } 1185*0Sstevel@tonic-gate 1186*0Sstevel@tonic-gate /*ARGSUSED*/ 1187*0Sstevel@tonic-gate int 1188*0Sstevel@tonic-gate m2d_walk_dinfo(uintptr_t addr, struct dev_info *di, char *mod_name) 1189*0Sstevel@tonic-gate { 1190*0Sstevel@tonic-gate char name[MODMAXNAMELEN]; 1191*0Sstevel@tonic-gate 1192*0Sstevel@tonic-gate if (mdb_readstr(name, MODMAXNAMELEN, 1193*0Sstevel@tonic-gate (uintptr_t)di->devi_binding_name) == -1) { 1194*0Sstevel@tonic-gate mdb_warn("couldn't read devi_binding_name at %p", 1195*0Sstevel@tonic-gate di->devi_binding_name); 1196*0Sstevel@tonic-gate return (WALK_ERR); 1197*0Sstevel@tonic-gate } 1198*0Sstevel@tonic-gate 1199*0Sstevel@tonic-gate if (strcmp(name, mod_name) == 0) 1200*0Sstevel@tonic-gate mdb_printf("%p\n", addr); 1201*0Sstevel@tonic-gate 1202*0Sstevel@tonic-gate return (WALK_NEXT); 1203*0Sstevel@tonic-gate } 1204*0Sstevel@tonic-gate 1205*0Sstevel@tonic-gate /*ARGSUSED*/ 1206*0Sstevel@tonic-gate int 1207*0Sstevel@tonic-gate modctl2devinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1208*0Sstevel@tonic-gate { 1209*0Sstevel@tonic-gate struct modctl modctl; 1210*0Sstevel@tonic-gate char name[MODMAXNAMELEN]; 1211*0Sstevel@tonic-gate 1212*0Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) 1213*0Sstevel@tonic-gate return (DCMD_USAGE); 1214*0Sstevel@tonic-gate 1215*0Sstevel@tonic-gate if (mdb_vread(&modctl, sizeof (modctl), addr) == -1) { 1216*0Sstevel@tonic-gate mdb_warn("couldn't read modctl at %p", addr); 1217*0Sstevel@tonic-gate return (DCMD_ERR); 1218*0Sstevel@tonic-gate } 1219*0Sstevel@tonic-gate 1220*0Sstevel@tonic-gate if (mdb_readstr(name, MODMAXNAMELEN, 1221*0Sstevel@tonic-gate (uintptr_t)modctl.mod_modname) == -1) { 1222*0Sstevel@tonic-gate mdb_warn("couldn't read modname at %p", modctl.mod_modname); 1223*0Sstevel@tonic-gate return (DCMD_ERR); 1224*0Sstevel@tonic-gate } 1225*0Sstevel@tonic-gate 1226*0Sstevel@tonic-gate if (mdb_walk("devinfo", (mdb_walk_cb_t)m2d_walk_dinfo, name) == -1) { 1227*0Sstevel@tonic-gate mdb_warn("couldn't walk devinfo"); 1228*0Sstevel@tonic-gate return (DCMD_ERR); 1229*0Sstevel@tonic-gate } 1230*0Sstevel@tonic-gate 1231*0Sstevel@tonic-gate return (DCMD_OK); 1232*0Sstevel@tonic-gate } 1233*0Sstevel@tonic-gate 1234*0Sstevel@tonic-gate static int 1235*0Sstevel@tonic-gate major_to_addr(major_t major, uintptr_t *vaddr) 1236*0Sstevel@tonic-gate { 1237*0Sstevel@tonic-gate uint_t devcnt; 1238*0Sstevel@tonic-gate uintptr_t devnamesp; 1239*0Sstevel@tonic-gate 1240*0Sstevel@tonic-gate if (mdb_readvar(&devcnt, "devcnt") == -1) { 1241*0Sstevel@tonic-gate mdb_warn("failed to read 'devcnt'"); 1242*0Sstevel@tonic-gate return (-1); 1243*0Sstevel@tonic-gate } 1244*0Sstevel@tonic-gate 1245*0Sstevel@tonic-gate if (mdb_readvar(&devnamesp, "devnamesp") == -1) { 1246*0Sstevel@tonic-gate mdb_warn("failed to read 'devnamesp'"); 1247*0Sstevel@tonic-gate return (-1); 1248*0Sstevel@tonic-gate } 1249*0Sstevel@tonic-gate 1250*0Sstevel@tonic-gate if (major >= devcnt) { 1251*0Sstevel@tonic-gate mdb_warn("%x is out of range [0x0-0x%x]\n", major, devcnt - 1); 1252*0Sstevel@tonic-gate return (-1); 1253*0Sstevel@tonic-gate } 1254*0Sstevel@tonic-gate 1255*0Sstevel@tonic-gate *vaddr = devnamesp + (major * sizeof (struct devnames)); 1256*0Sstevel@tonic-gate return (0); 1257*0Sstevel@tonic-gate } 1258*0Sstevel@tonic-gate 1259*0Sstevel@tonic-gate /*ARGSUSED*/ 1260*0Sstevel@tonic-gate int 1261*0Sstevel@tonic-gate devnames(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1262*0Sstevel@tonic-gate { 1263*0Sstevel@tonic-gate static const mdb_bitmask_t dn_flag_bits[] = { 1264*0Sstevel@tonic-gate { "DN_CONF_PARSED", DN_CONF_PARSED, DN_CONF_PARSED }, 1265*0Sstevel@tonic-gate { "DN_DRIVER_BUSY", DN_DRIVER_BUSY, DN_DRIVER_BUSY }, 1266*0Sstevel@tonic-gate { "DN_DRIVER_HELD", DN_DRIVER_HELD, DN_DRIVER_HELD }, 1267*0Sstevel@tonic-gate { "DN_TAKEN_GETUDEV", DN_TAKEN_GETUDEV, DN_TAKEN_GETUDEV }, 1268*0Sstevel@tonic-gate { "DN_DRIVER_REMOVED", DN_DRIVER_REMOVED, DN_DRIVER_REMOVED}, 1269*0Sstevel@tonic-gate { "DN_FORCE_ATTACH", DN_FORCE_ATTACH, DN_FORCE_ATTACH}, 1270*0Sstevel@tonic-gate { "DN_LEAF_DRIVER", DN_LEAF_DRIVER, DN_LEAF_DRIVER}, 1271*0Sstevel@tonic-gate { "DN_NETWORK_DRIVER", DN_NETWORK_DRIVER, DN_NETWORK_DRIVER}, 1272*0Sstevel@tonic-gate { "DN_NO_AUTODETACH", DN_NO_AUTODETACH, DN_NO_AUTODETACH }, 1273*0Sstevel@tonic-gate { NULL, 0, 0 } 1274*0Sstevel@tonic-gate }; 1275*0Sstevel@tonic-gate 1276*0Sstevel@tonic-gate const mdb_arg_t *argp = NULL; 1277*0Sstevel@tonic-gate uint_t opt_v = FALSE, opt_m = FALSE; 1278*0Sstevel@tonic-gate major_t major; 1279*0Sstevel@tonic-gate size_t i; 1280*0Sstevel@tonic-gate 1281*0Sstevel@tonic-gate char name[MODMAXNAMELEN + 1]; 1282*0Sstevel@tonic-gate struct devnames dn; 1283*0Sstevel@tonic-gate 1284*0Sstevel@tonic-gate if ((i = mdb_getopts(argc, argv, 1285*0Sstevel@tonic-gate 'm', MDB_OPT_SETBITS, TRUE, &opt_m, 1286*0Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, TRUE, &opt_v, 1287*0Sstevel@tonic-gate NULL)) != argc) { 1288*0Sstevel@tonic-gate if (argc - i > 1) 1289*0Sstevel@tonic-gate return (DCMD_USAGE); 1290*0Sstevel@tonic-gate argp = &argv[i]; 1291*0Sstevel@tonic-gate } 1292*0Sstevel@tonic-gate 1293*0Sstevel@tonic-gate if (opt_m) { 1294*0Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) 1295*0Sstevel@tonic-gate return (DCMD_USAGE); 1296*0Sstevel@tonic-gate 1297*0Sstevel@tonic-gate if (major_to_addr(addr, &addr) == -1) 1298*0Sstevel@tonic-gate return (DCMD_ERR); 1299*0Sstevel@tonic-gate 1300*0Sstevel@tonic-gate } else if (!(flags & DCMD_ADDRSPEC)) { 1301*0Sstevel@tonic-gate if (argp == NULL) { 1302*0Sstevel@tonic-gate if (mdb_walk_dcmd("devnames", "devnames", argc, argv)) { 1303*0Sstevel@tonic-gate mdb_warn("failed to walk devnames"); 1304*0Sstevel@tonic-gate return (DCMD_ERR); 1305*0Sstevel@tonic-gate } 1306*0Sstevel@tonic-gate return (DCMD_OK); 1307*0Sstevel@tonic-gate } 1308*0Sstevel@tonic-gate 1309*0Sstevel@tonic-gate if (argp->a_type == MDB_TYPE_IMMEDIATE) 1310*0Sstevel@tonic-gate major = (major_t)argp->a_un.a_val; 1311*0Sstevel@tonic-gate else 1312*0Sstevel@tonic-gate major = (major_t)mdb_strtoull(argp->a_un.a_str); 1313*0Sstevel@tonic-gate 1314*0Sstevel@tonic-gate if (major_to_addr(major, &addr) == -1) 1315*0Sstevel@tonic-gate return (DCMD_ERR); 1316*0Sstevel@tonic-gate } 1317*0Sstevel@tonic-gate 1318*0Sstevel@tonic-gate if (mdb_vread(&dn, sizeof (struct devnames), addr) == -1) { 1319*0Sstevel@tonic-gate mdb_warn("failed to read devnames struct at %p", addr); 1320*0Sstevel@tonic-gate return (DCMD_ERR); 1321*0Sstevel@tonic-gate } 1322*0Sstevel@tonic-gate 1323*0Sstevel@tonic-gate if (DCMD_HDRSPEC(flags)) { 1324*0Sstevel@tonic-gate if (opt_v) 1325*0Sstevel@tonic-gate mdb_printf("%<u>%-16s%</u>\n", "NAME"); 1326*0Sstevel@tonic-gate else 1327*0Sstevel@tonic-gate mdb_printf("%<u>%-16s %-?s%</u>\n", "NAME", "DN_HEAD"); 1328*0Sstevel@tonic-gate } 1329*0Sstevel@tonic-gate 1330*0Sstevel@tonic-gate if ((flags & DCMD_LOOP) && (dn.dn_name == NULL)) 1331*0Sstevel@tonic-gate return (DCMD_OK); /* Skip empty slots if we're printing table */ 1332*0Sstevel@tonic-gate 1333*0Sstevel@tonic-gate if (mdb_readstr(name, sizeof (name), (uintptr_t)dn.dn_name) == -1) 1334*0Sstevel@tonic-gate (void) mdb_snprintf(name, sizeof (name), "0x%p", dn.dn_name); 1335*0Sstevel@tonic-gate 1336*0Sstevel@tonic-gate if (opt_v) { 1337*0Sstevel@tonic-gate ddi_prop_list_t prop_list; 1338*0Sstevel@tonic-gate mdb_printf("%<b>%-16s%</b>\n", name); 1339*0Sstevel@tonic-gate mdb_inc_indent(2); 1340*0Sstevel@tonic-gate 1341*0Sstevel@tonic-gate mdb_printf(" flags %b\n", dn.dn_flags, dn_flag_bits); 1342*0Sstevel@tonic-gate mdb_printf(" pl %p\n", (void *)dn.dn_pl); 1343*0Sstevel@tonic-gate mdb_printf(" head %p\n", dn.dn_head); 1344*0Sstevel@tonic-gate mdb_printf(" instance %d\n", dn.dn_instance); 1345*0Sstevel@tonic-gate mdb_printf(" inlist %p\n", dn.dn_inlist); 1346*0Sstevel@tonic-gate mdb_printf("global_prop_ptr %p\n", dn.dn_global_prop_ptr); 1347*0Sstevel@tonic-gate if (mdb_vread(&prop_list, sizeof (ddi_prop_list_t), 1348*0Sstevel@tonic-gate (uintptr_t)dn.dn_global_prop_ptr) != -1) { 1349*0Sstevel@tonic-gate devinfo_print_props(NULL, prop_list.prop_list); 1350*0Sstevel@tonic-gate } 1351*0Sstevel@tonic-gate 1352*0Sstevel@tonic-gate mdb_dec_indent(2); 1353*0Sstevel@tonic-gate } else 1354*0Sstevel@tonic-gate mdb_printf("%-16s %-?p\n", name, dn.dn_head); 1355*0Sstevel@tonic-gate 1356*0Sstevel@tonic-gate return (DCMD_OK); 1357*0Sstevel@tonic-gate } 1358*0Sstevel@tonic-gate 1359*0Sstevel@tonic-gate /*ARGSUSED*/ 1360*0Sstevel@tonic-gate int 1361*0Sstevel@tonic-gate name2major(uintptr_t vaddr, uint_t flags, int argc, const mdb_arg_t *argv) 1362*0Sstevel@tonic-gate { 1363*0Sstevel@tonic-gate major_t major; 1364*0Sstevel@tonic-gate 1365*0Sstevel@tonic-gate if (flags & DCMD_ADDRSPEC) 1366*0Sstevel@tonic-gate return (DCMD_USAGE); 1367*0Sstevel@tonic-gate 1368*0Sstevel@tonic-gate if (argc != 1 || argv->a_type != MDB_TYPE_STRING) 1369*0Sstevel@tonic-gate return (DCMD_USAGE); 1370*0Sstevel@tonic-gate 1371*0Sstevel@tonic-gate if (mdb_name_to_major(argv->a_un.a_str, &major) != 0) { 1372*0Sstevel@tonic-gate mdb_warn("failed to convert name to major number\n"); 1373*0Sstevel@tonic-gate return (DCMD_ERR); 1374*0Sstevel@tonic-gate } 1375*0Sstevel@tonic-gate 1376*0Sstevel@tonic-gate mdb_printf("0x%x\n", major); 1377*0Sstevel@tonic-gate return (DCMD_OK); 1378*0Sstevel@tonic-gate } 1379*0Sstevel@tonic-gate 1380*0Sstevel@tonic-gate /* 1381*0Sstevel@tonic-gate * Get a numerical argument of a dcmd from addr if an address is specified 1382*0Sstevel@tonic-gate * or from argv if no address is specified. Return the argument in ret. 1383*0Sstevel@tonic-gate */ 1384*0Sstevel@tonic-gate static int 1385*0Sstevel@tonic-gate getarg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv, 1386*0Sstevel@tonic-gate uintptr_t *ret) 1387*0Sstevel@tonic-gate { 1388*0Sstevel@tonic-gate if (argc == 0 && (flags & DCMD_ADDRSPEC)) { 1389*0Sstevel@tonic-gate *ret = addr; 1390*0Sstevel@tonic-gate 1391*0Sstevel@tonic-gate } else if (argc == 1 && !(flags & DCMD_ADDRSPEC)) { 1392*0Sstevel@tonic-gate *ret = (argv[0].a_type == MDB_TYPE_IMMEDIATE) ? 1393*0Sstevel@tonic-gate (uintptr_t)argv[0].a_un.a_val : 1394*0Sstevel@tonic-gate (uintptr_t)mdb_strtoull(argv->a_un.a_str); 1395*0Sstevel@tonic-gate 1396*0Sstevel@tonic-gate } else { 1397*0Sstevel@tonic-gate return (-1); 1398*0Sstevel@tonic-gate } 1399*0Sstevel@tonic-gate 1400*0Sstevel@tonic-gate return (0); 1401*0Sstevel@tonic-gate } 1402*0Sstevel@tonic-gate 1403*0Sstevel@tonic-gate /*ARGSUSED*/ 1404*0Sstevel@tonic-gate int 1405*0Sstevel@tonic-gate major2name(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1406*0Sstevel@tonic-gate { 1407*0Sstevel@tonic-gate uintptr_t major; 1408*0Sstevel@tonic-gate const char *name; 1409*0Sstevel@tonic-gate 1410*0Sstevel@tonic-gate if (getarg(addr, flags, argc, argv, &major) < 0) 1411*0Sstevel@tonic-gate return (DCMD_USAGE); 1412*0Sstevel@tonic-gate 1413*0Sstevel@tonic-gate if ((name = mdb_major_to_name((major_t)major)) == NULL) { 1414*0Sstevel@tonic-gate mdb_warn("failed to convert major number to name\n"); 1415*0Sstevel@tonic-gate return (DCMD_ERR); 1416*0Sstevel@tonic-gate } 1417*0Sstevel@tonic-gate 1418*0Sstevel@tonic-gate mdb_printf("%s\n", name); 1419*0Sstevel@tonic-gate return (DCMD_OK); 1420*0Sstevel@tonic-gate } 1421*0Sstevel@tonic-gate 1422*0Sstevel@tonic-gate /*ARGSUSED*/ 1423*0Sstevel@tonic-gate int 1424*0Sstevel@tonic-gate dev2major(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1425*0Sstevel@tonic-gate { 1426*0Sstevel@tonic-gate uintptr_t dev; 1427*0Sstevel@tonic-gate 1428*0Sstevel@tonic-gate if (getarg(addr, flags, argc, argv, &dev) < 0) 1429*0Sstevel@tonic-gate return (DCMD_USAGE); 1430*0Sstevel@tonic-gate 1431*0Sstevel@tonic-gate if (flags & DCMD_PIPE_OUT) 1432*0Sstevel@tonic-gate mdb_printf("%x\n", getmajor(dev)); 1433*0Sstevel@tonic-gate else 1434*0Sstevel@tonic-gate mdb_printf("0x%x (0t%d)\n", getmajor(dev), getmajor(dev)); 1435*0Sstevel@tonic-gate 1436*0Sstevel@tonic-gate return (DCMD_OK); 1437*0Sstevel@tonic-gate } 1438*0Sstevel@tonic-gate 1439*0Sstevel@tonic-gate /*ARGSUSED*/ 1440*0Sstevel@tonic-gate int 1441*0Sstevel@tonic-gate dev2minor(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1442*0Sstevel@tonic-gate { 1443*0Sstevel@tonic-gate uintptr_t dev; 1444*0Sstevel@tonic-gate 1445*0Sstevel@tonic-gate if (getarg(addr, flags, argc, argv, &dev) < 0) 1446*0Sstevel@tonic-gate return (DCMD_USAGE); 1447*0Sstevel@tonic-gate 1448*0Sstevel@tonic-gate if (flags & DCMD_PIPE_OUT) 1449*0Sstevel@tonic-gate mdb_printf("%x\n", getminor(dev)); 1450*0Sstevel@tonic-gate else 1451*0Sstevel@tonic-gate mdb_printf("0x%x (0t%d)\n", getminor(dev), getminor(dev)); 1452*0Sstevel@tonic-gate 1453*0Sstevel@tonic-gate return (DCMD_OK); 1454*0Sstevel@tonic-gate } 1455*0Sstevel@tonic-gate 1456*0Sstevel@tonic-gate /*ARGSUSED*/ 1457*0Sstevel@tonic-gate int 1458*0Sstevel@tonic-gate devt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1459*0Sstevel@tonic-gate { 1460*0Sstevel@tonic-gate uintptr_t dev; 1461*0Sstevel@tonic-gate 1462*0Sstevel@tonic-gate if (getarg(addr, flags, argc, argv, &dev) < 0) 1463*0Sstevel@tonic-gate return (DCMD_USAGE); 1464*0Sstevel@tonic-gate 1465*0Sstevel@tonic-gate if (DCMD_HDRSPEC(flags)) { 1466*0Sstevel@tonic-gate mdb_printf("%<u>%10s%</u> %<u>%10s%</u>\n", "MAJOR", 1467*0Sstevel@tonic-gate "MINOR"); 1468*0Sstevel@tonic-gate } 1469*0Sstevel@tonic-gate 1470*0Sstevel@tonic-gate mdb_printf("%10d %10d\n", getmajor(dev), getminor(dev)); 1471*0Sstevel@tonic-gate 1472*0Sstevel@tonic-gate return (DCMD_OK); 1473*0Sstevel@tonic-gate } 1474*0Sstevel@tonic-gate 1475*0Sstevel@tonic-gate /*ARGSUSED*/ 1476*0Sstevel@tonic-gate int 1477*0Sstevel@tonic-gate softstate(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1478*0Sstevel@tonic-gate { 1479*0Sstevel@tonic-gate uintptr_t statep; 1480*0Sstevel@tonic-gate int instance; 1481*0Sstevel@tonic-gate 1482*0Sstevel@tonic-gate 1483*0Sstevel@tonic-gate if (argc != 1) { 1484*0Sstevel@tonic-gate return (DCMD_USAGE); 1485*0Sstevel@tonic-gate } 1486*0Sstevel@tonic-gate 1487*0Sstevel@tonic-gate if (argv[0].a_type == MDB_TYPE_IMMEDIATE) 1488*0Sstevel@tonic-gate instance = argv[0].a_un.a_val; 1489*0Sstevel@tonic-gate else 1490*0Sstevel@tonic-gate instance = mdb_strtoull(argv->a_un.a_str); 1491*0Sstevel@tonic-gate 1492*0Sstevel@tonic-gate if (mdb_get_soft_state_byaddr(addr, instance, &statep, NULL, 0) == -1) { 1493*0Sstevel@tonic-gate if (errno == ENOENT) { 1494*0Sstevel@tonic-gate mdb_warn("instance %d unused\n", instance); 1495*0Sstevel@tonic-gate } else { 1496*0Sstevel@tonic-gate mdb_warn("couldn't determine softstate for " 1497*0Sstevel@tonic-gate "instance %d", instance); 1498*0Sstevel@tonic-gate } 1499*0Sstevel@tonic-gate 1500*0Sstevel@tonic-gate return (DCMD_ERR); 1501*0Sstevel@tonic-gate } 1502*0Sstevel@tonic-gate 1503*0Sstevel@tonic-gate mdb_printf("%p\n", statep); 1504*0Sstevel@tonic-gate return (DCMD_OK); 1505*0Sstevel@tonic-gate } 1506*0Sstevel@tonic-gate 1507*0Sstevel@tonic-gate /* 1508*0Sstevel@tonic-gate * Walker for all possible pointers to a driver state struct in an 1509*0Sstevel@tonic-gate * i_ddi_soft_state instance chain. Returns all non-NULL pointers. 1510*0Sstevel@tonic-gate */ 1511*0Sstevel@tonic-gate typedef struct soft_state_walk { 1512*0Sstevel@tonic-gate struct i_ddi_soft_state ssw_ss; /* Local copy of i_ddi_soft_state */ 1513*0Sstevel@tonic-gate void **ssw_pointers; /* to driver state structs */ 1514*0Sstevel@tonic-gate uint_t ssw_index; /* array entry we're using */ 1515*0Sstevel@tonic-gate } soft_state_walk_t; 1516*0Sstevel@tonic-gate 1517*0Sstevel@tonic-gate int 1518*0Sstevel@tonic-gate soft_state_walk_init(mdb_walk_state_t *wsp) 1519*0Sstevel@tonic-gate { 1520*0Sstevel@tonic-gate soft_state_walk_t *sst; 1521*0Sstevel@tonic-gate 1522*0Sstevel@tonic-gate 1523*0Sstevel@tonic-gate if (wsp->walk_addr == NULL) 1524*0Sstevel@tonic-gate return (WALK_DONE); 1525*0Sstevel@tonic-gate 1526*0Sstevel@tonic-gate sst = mdb_zalloc(sizeof (soft_state_walk_t), UM_SLEEP|UM_GC); 1527*0Sstevel@tonic-gate wsp->walk_data = sst; 1528*0Sstevel@tonic-gate 1529*0Sstevel@tonic-gate 1530*0Sstevel@tonic-gate if (mdb_vread(&(sst->ssw_ss), sizeof (sst->ssw_ss), wsp->walk_addr) != 1531*0Sstevel@tonic-gate sizeof (sst->ssw_ss)) { 1532*0Sstevel@tonic-gate mdb_warn("failed to read i_ddi_soft_state at %p", 1533*0Sstevel@tonic-gate wsp->walk_addr); 1534*0Sstevel@tonic-gate return (WALK_ERR); 1535*0Sstevel@tonic-gate } 1536*0Sstevel@tonic-gate 1537*0Sstevel@tonic-gate 1538*0Sstevel@tonic-gate /* Read array of pointers to state structs into local storage. */ 1539*0Sstevel@tonic-gate sst->ssw_pointers = mdb_alloc((sst->ssw_ss.n_items * sizeof (void *)), 1540*0Sstevel@tonic-gate UM_SLEEP|UM_GC); 1541*0Sstevel@tonic-gate 1542*0Sstevel@tonic-gate if (mdb_vread(sst->ssw_pointers, (sst->ssw_ss.n_items * 1543*0Sstevel@tonic-gate sizeof (void *)), (uintptr_t)sst->ssw_ss.array) != 1544*0Sstevel@tonic-gate (sst->ssw_ss.n_items * sizeof (void *))) { 1545*0Sstevel@tonic-gate mdb_warn("failed to read i_ddi_soft_state at %p", 1546*0Sstevel@tonic-gate wsp->walk_addr); 1547*0Sstevel@tonic-gate return (WALK_ERR); 1548*0Sstevel@tonic-gate } 1549*0Sstevel@tonic-gate 1550*0Sstevel@tonic-gate sst->ssw_index = 0; 1551*0Sstevel@tonic-gate 1552*0Sstevel@tonic-gate return (WALK_NEXT); 1553*0Sstevel@tonic-gate } 1554*0Sstevel@tonic-gate 1555*0Sstevel@tonic-gate int 1556*0Sstevel@tonic-gate soft_state_walk_step(mdb_walk_state_t *wsp) 1557*0Sstevel@tonic-gate { 1558*0Sstevel@tonic-gate soft_state_walk_t *sst = (soft_state_walk_t *)wsp->walk_data; 1559*0Sstevel@tonic-gate int status = WALK_NEXT; 1560*0Sstevel@tonic-gate 1561*0Sstevel@tonic-gate 1562*0Sstevel@tonic-gate /* 1563*0Sstevel@tonic-gate * If the entry indexed has a valid pointer to a soft state struct, 1564*0Sstevel@tonic-gate * invoke caller's callback func. 1565*0Sstevel@tonic-gate */ 1566*0Sstevel@tonic-gate if (sst->ssw_pointers[sst->ssw_index] != NULL) { 1567*0Sstevel@tonic-gate status = wsp->walk_callback( 1568*0Sstevel@tonic-gate (uintptr_t)(sst->ssw_pointers[sst->ssw_index]), NULL, 1569*0Sstevel@tonic-gate wsp->walk_cbdata); 1570*0Sstevel@tonic-gate } 1571*0Sstevel@tonic-gate 1572*0Sstevel@tonic-gate sst->ssw_index += 1; 1573*0Sstevel@tonic-gate 1574*0Sstevel@tonic-gate if (sst->ssw_index == sst->ssw_ss.n_items) 1575*0Sstevel@tonic-gate return (WALK_DONE); 1576*0Sstevel@tonic-gate 1577*0Sstevel@tonic-gate return (status); 1578*0Sstevel@tonic-gate } 1579*0Sstevel@tonic-gate 1580*0Sstevel@tonic-gate int 1581*0Sstevel@tonic-gate soft_state_all_walk_step(mdb_walk_state_t *wsp) 1582*0Sstevel@tonic-gate { 1583*0Sstevel@tonic-gate soft_state_walk_t *sst = (soft_state_walk_t *)wsp->walk_data; 1584*0Sstevel@tonic-gate int status = WALK_NEXT; 1585*0Sstevel@tonic-gate 1586*0Sstevel@tonic-gate 1587*0Sstevel@tonic-gate status = wsp->walk_callback( 1588*0Sstevel@tonic-gate (uintptr_t)(sst->ssw_pointers[sst->ssw_index]), NULL, 1589*0Sstevel@tonic-gate wsp->walk_cbdata); 1590*0Sstevel@tonic-gate 1591*0Sstevel@tonic-gate sst->ssw_index += 1; 1592*0Sstevel@tonic-gate 1593*0Sstevel@tonic-gate if (sst->ssw_index == sst->ssw_ss.n_items) 1594*0Sstevel@tonic-gate return (WALK_DONE); 1595*0Sstevel@tonic-gate 1596*0Sstevel@tonic-gate return (status); 1597*0Sstevel@tonic-gate } 1598*0Sstevel@tonic-gate 1599*0Sstevel@tonic-gate /*ARGSUSED*/ 1600*0Sstevel@tonic-gate int 1601*0Sstevel@tonic-gate devbindings(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1602*0Sstevel@tonic-gate { 1603*0Sstevel@tonic-gate const mdb_arg_t *arg; 1604*0Sstevel@tonic-gate struct devnames dn; 1605*0Sstevel@tonic-gate uintptr_t dn_addr; 1606*0Sstevel@tonic-gate major_t major; 1607*0Sstevel@tonic-gate 1608*0Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC) && argc < 1) 1609*0Sstevel@tonic-gate return (DCMD_USAGE); 1610*0Sstevel@tonic-gate 1611*0Sstevel@tonic-gate if (flags & DCMD_ADDRSPEC) { 1612*0Sstevel@tonic-gate /* 1613*0Sstevel@tonic-gate * If there's an address, then it's a major number 1614*0Sstevel@tonic-gate */ 1615*0Sstevel@tonic-gate major = addr; 1616*0Sstevel@tonic-gate } else { 1617*0Sstevel@tonic-gate /* 1618*0Sstevel@tonic-gate * We interpret the last argument. Any other arguments are 1619*0Sstevel@tonic-gate * forwarded to "devinfo" 1620*0Sstevel@tonic-gate */ 1621*0Sstevel@tonic-gate arg = &argv[argc - 1]; 1622*0Sstevel@tonic-gate argc--; 1623*0Sstevel@tonic-gate 1624*0Sstevel@tonic-gate if (arg->a_type == MDB_TYPE_IMMEDIATE) { 1625*0Sstevel@tonic-gate major = (uintptr_t)arg->a_un.a_val; 1626*0Sstevel@tonic-gate 1627*0Sstevel@tonic-gate } else if (arg->a_un.a_str[0] == '-') { 1628*0Sstevel@tonic-gate /* the argument shouldn't be an option */ 1629*0Sstevel@tonic-gate return (DCMD_USAGE); 1630*0Sstevel@tonic-gate 1631*0Sstevel@tonic-gate } else if (isdigit(arg->a_un.a_str[0])) { 1632*0Sstevel@tonic-gate major = (uintptr_t)mdb_strtoull(arg->a_un.a_str); 1633*0Sstevel@tonic-gate 1634*0Sstevel@tonic-gate } else { 1635*0Sstevel@tonic-gate if (mdb_name_to_major(arg->a_un.a_str, &major) != 0) { 1636*0Sstevel@tonic-gate mdb_warn("failed to get major number for %s\n", 1637*0Sstevel@tonic-gate arg->a_un.a_str); 1638*0Sstevel@tonic-gate return (DCMD_ERR); 1639*0Sstevel@tonic-gate } 1640*0Sstevel@tonic-gate } 1641*0Sstevel@tonic-gate } 1642*0Sstevel@tonic-gate 1643*0Sstevel@tonic-gate if (major_to_addr(major, &dn_addr) != 0) 1644*0Sstevel@tonic-gate return (DCMD_ERR); 1645*0Sstevel@tonic-gate 1646*0Sstevel@tonic-gate if (mdb_vread(&dn, sizeof (struct devnames), dn_addr) == -1) { 1647*0Sstevel@tonic-gate mdb_warn("couldn't read devnames array at %p", dn_addr); 1648*0Sstevel@tonic-gate return (DCMD_ERR); 1649*0Sstevel@tonic-gate } 1650*0Sstevel@tonic-gate 1651*0Sstevel@tonic-gate if (mdb_pwalk_dcmd("devi_next", "devinfo", argc, argv, 1652*0Sstevel@tonic-gate (uintptr_t)dn.dn_head) != 0) { 1653*0Sstevel@tonic-gate mdb_warn("couldn't walk the devinfo chain at %p", dn.dn_head); 1654*0Sstevel@tonic-gate return (DCMD_ERR); 1655*0Sstevel@tonic-gate } 1656*0Sstevel@tonic-gate 1657*0Sstevel@tonic-gate return (DCMD_OK); 1658*0Sstevel@tonic-gate } 1659*0Sstevel@tonic-gate 1660*0Sstevel@tonic-gate /* 1661*0Sstevel@tonic-gate * walk binding hashtable (as of of driver names (e.g., mb_hashtab)) 1662*0Sstevel@tonic-gate */ 1663*0Sstevel@tonic-gate int 1664*0Sstevel@tonic-gate binding_hash_walk_init(mdb_walk_state_t *wsp) 1665*0Sstevel@tonic-gate { 1666*0Sstevel@tonic-gate if (wsp->walk_addr == NULL) 1667*0Sstevel@tonic-gate return (WALK_ERR); 1668*0Sstevel@tonic-gate 1669*0Sstevel@tonic-gate wsp->walk_data = mdb_alloc(sizeof (void *) * MOD_BIND_HASHSIZE, 1670*0Sstevel@tonic-gate UM_SLEEP|UM_GC); 1671*0Sstevel@tonic-gate if (mdb_vread(wsp->walk_data, sizeof (void *) * MOD_BIND_HASHSIZE, 1672*0Sstevel@tonic-gate wsp->walk_addr) == -1) { 1673*0Sstevel@tonic-gate mdb_warn("failed to read mb_hashtab"); 1674*0Sstevel@tonic-gate return (WALK_ERR); 1675*0Sstevel@tonic-gate } 1676*0Sstevel@tonic-gate 1677*0Sstevel@tonic-gate wsp->walk_arg = 0; /* index into mb_hashtab array to start */ 1678*0Sstevel@tonic-gate 1679*0Sstevel@tonic-gate return (WALK_NEXT); 1680*0Sstevel@tonic-gate } 1681*0Sstevel@tonic-gate 1682*0Sstevel@tonic-gate int 1683*0Sstevel@tonic-gate binding_hash_walk_step(mdb_walk_state_t *wsp) 1684*0Sstevel@tonic-gate { 1685*0Sstevel@tonic-gate int status; 1686*0Sstevel@tonic-gate uintptr_t bind_p; 1687*0Sstevel@tonic-gate struct bind bind; 1688*0Sstevel@tonic-gate 1689*0Sstevel@tonic-gate 1690*0Sstevel@tonic-gate /* 1691*0Sstevel@tonic-gate * Walk the singly-linked list of struct bind 1692*0Sstevel@tonic-gate */ 1693*0Sstevel@tonic-gate bind_p = ((uintptr_t *)wsp->walk_data)[(ulong_t)wsp->walk_arg]; 1694*0Sstevel@tonic-gate while (bind_p != NULL) { 1695*0Sstevel@tonic-gate 1696*0Sstevel@tonic-gate if (mdb_vread(&bind, sizeof (bind), bind_p) == -1) { 1697*0Sstevel@tonic-gate mdb_warn("failed to read bind struct at %p", 1698*0Sstevel@tonic-gate wsp->walk_addr); 1699*0Sstevel@tonic-gate return (WALK_ERR); 1700*0Sstevel@tonic-gate } 1701*0Sstevel@tonic-gate 1702*0Sstevel@tonic-gate if ((status = wsp->walk_callback(bind_p, &bind, 1703*0Sstevel@tonic-gate wsp->walk_cbdata)) != WALK_NEXT) { 1704*0Sstevel@tonic-gate return (status); 1705*0Sstevel@tonic-gate } 1706*0Sstevel@tonic-gate 1707*0Sstevel@tonic-gate bind_p = (uintptr_t)bind.b_next; 1708*0Sstevel@tonic-gate } 1709*0Sstevel@tonic-gate 1710*0Sstevel@tonic-gate wsp->walk_arg = (void *)((char *)wsp->walk_arg + 1); 1711*0Sstevel@tonic-gate 1712*0Sstevel@tonic-gate if (wsp->walk_arg == (void *)(MOD_BIND_HASHSIZE - 1)) 1713*0Sstevel@tonic-gate return (WALK_DONE); 1714*0Sstevel@tonic-gate 1715*0Sstevel@tonic-gate return (WALK_NEXT); 1716*0Sstevel@tonic-gate } 1717*0Sstevel@tonic-gate 1718*0Sstevel@tonic-gate /*ARGSUSED*/ 1719*0Sstevel@tonic-gate int 1720*0Sstevel@tonic-gate binding_hash_entry(uintptr_t addr, uint_t flags, int argc, 1721*0Sstevel@tonic-gate const mdb_arg_t *argv) 1722*0Sstevel@tonic-gate { 1723*0Sstevel@tonic-gate struct bind bind; 1724*0Sstevel@tonic-gate /* Arbitrary lengths based on output format below */ 1725*0Sstevel@tonic-gate char name[25] = "???"; 1726*0Sstevel@tonic-gate char bind_name[32] = "<null>"; 1727*0Sstevel@tonic-gate 1728*0Sstevel@tonic-gate 1729*0Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) == NULL) 1730*0Sstevel@tonic-gate return (DCMD_USAGE); 1731*0Sstevel@tonic-gate 1732*0Sstevel@tonic-gate /* Allow null addresses to be passed (as from a walker) */ 1733*0Sstevel@tonic-gate if (addr == NULL) 1734*0Sstevel@tonic-gate return (DCMD_OK); 1735*0Sstevel@tonic-gate 1736*0Sstevel@tonic-gate if (mdb_vread(&bind, sizeof (bind), addr) == -1) { 1737*0Sstevel@tonic-gate mdb_warn("failed to read struct bind at %p", addr); 1738*0Sstevel@tonic-gate return (DCMD_ERR); 1739*0Sstevel@tonic-gate } 1740*0Sstevel@tonic-gate 1741*0Sstevel@tonic-gate if (DCMD_HDRSPEC(flags)) { 1742*0Sstevel@tonic-gate mdb_printf("%<u>%-32s %-5s %-?s%</u>\n", 1743*0Sstevel@tonic-gate "NAME", "MAJOR", "NEXT"); 1744*0Sstevel@tonic-gate } 1745*0Sstevel@tonic-gate 1746*0Sstevel@tonic-gate if (mdb_readstr(name, sizeof (name), (uintptr_t)bind.b_name) == -1) 1747*0Sstevel@tonic-gate mdb_warn("failed to read 'name'"); 1748*0Sstevel@tonic-gate 1749*0Sstevel@tonic-gate /* There may be no binding name for a driver, so this may fail */ 1750*0Sstevel@tonic-gate (void) mdb_readstr(bind_name, sizeof (bind_name), 1751*0Sstevel@tonic-gate (uintptr_t)bind.b_bind_name); 1752*0Sstevel@tonic-gate 1753*0Sstevel@tonic-gate mdb_printf("%-32s %3d %?p\n", name, bind.b_num, bind.b_next); 1754*0Sstevel@tonic-gate 1755*0Sstevel@tonic-gate return (DCMD_OK); 1756*0Sstevel@tonic-gate } 1757*0Sstevel@tonic-gate 1758*0Sstevel@tonic-gate typedef struct devinfo_audit_log_walk_data { 1759*0Sstevel@tonic-gate devinfo_audit_t dil_buf; /* buffer of last entry */ 1760*0Sstevel@tonic-gate uintptr_t dil_base; /* starting address of log buffer */ 1761*0Sstevel@tonic-gate int dil_max; /* maximum index */ 1762*0Sstevel@tonic-gate int dil_start; /* starting index */ 1763*0Sstevel@tonic-gate int dil_index; /* current walking index */ 1764*0Sstevel@tonic-gate } devinfo_audit_log_walk_data_t; 1765*0Sstevel@tonic-gate 1766*0Sstevel@tonic-gate int 1767*0Sstevel@tonic-gate devinfo_audit_log_walk_init(mdb_walk_state_t *wsp) 1768*0Sstevel@tonic-gate { 1769*0Sstevel@tonic-gate devinfo_log_header_t header; 1770*0Sstevel@tonic-gate devinfo_audit_log_walk_data_t *dil; 1771*0Sstevel@tonic-gate uintptr_t devinfo_audit_log; 1772*0Sstevel@tonic-gate 1773*0Sstevel@tonic-gate /* read in devinfo_log_header structure */ 1774*0Sstevel@tonic-gate if (mdb_readvar(&devinfo_audit_log, "devinfo_audit_log") == -1) { 1775*0Sstevel@tonic-gate mdb_warn("failed to read 'devinfo_audit_log'"); 1776*0Sstevel@tonic-gate return (WALK_ERR); 1777*0Sstevel@tonic-gate } 1778*0Sstevel@tonic-gate 1779*0Sstevel@tonic-gate if (mdb_vread(&header, sizeof (devinfo_log_header_t), 1780*0Sstevel@tonic-gate devinfo_audit_log) == -1) { 1781*0Sstevel@tonic-gate mdb_warn("couldn't read devinfo_log_header at %p", 1782*0Sstevel@tonic-gate devinfo_audit_log); 1783*0Sstevel@tonic-gate return (WALK_ERR); 1784*0Sstevel@tonic-gate } 1785*0Sstevel@tonic-gate 1786*0Sstevel@tonic-gate dil = mdb_zalloc(sizeof (devinfo_audit_log_walk_data_t), UM_SLEEP); 1787*0Sstevel@tonic-gate wsp->walk_data = dil; 1788*0Sstevel@tonic-gate 1789*0Sstevel@tonic-gate dil->dil_start = dil->dil_index = header.dh_curr; 1790*0Sstevel@tonic-gate dil->dil_max = header.dh_max; 1791*0Sstevel@tonic-gate if (dil->dil_start < 0) /* no log entries */ 1792*0Sstevel@tonic-gate return (WALK_DONE); 1793*0Sstevel@tonic-gate 1794*0Sstevel@tonic-gate dil->dil_base = devinfo_audit_log + 1795*0Sstevel@tonic-gate offsetof(devinfo_log_header_t, dh_entry); 1796*0Sstevel@tonic-gate wsp->walk_addr = dil->dil_base + 1797*0Sstevel@tonic-gate dil->dil_index * sizeof (devinfo_audit_t); 1798*0Sstevel@tonic-gate 1799*0Sstevel@tonic-gate return (WALK_NEXT); 1800*0Sstevel@tonic-gate } 1801*0Sstevel@tonic-gate 1802*0Sstevel@tonic-gate int 1803*0Sstevel@tonic-gate devinfo_audit_log_walk_step(mdb_walk_state_t *wsp) 1804*0Sstevel@tonic-gate { 1805*0Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr; 1806*0Sstevel@tonic-gate devinfo_audit_log_walk_data_t *dil = wsp->walk_data; 1807*0Sstevel@tonic-gate devinfo_audit_t *da = &dil->dil_buf; 1808*0Sstevel@tonic-gate int status = WALK_NEXT; 1809*0Sstevel@tonic-gate 1810*0Sstevel@tonic-gate /* read in current entry and invoke callback */ 1811*0Sstevel@tonic-gate if (addr == NULL) 1812*0Sstevel@tonic-gate return (WALK_DONE); 1813*0Sstevel@tonic-gate 1814*0Sstevel@tonic-gate if (mdb_vread(&dil->dil_buf, sizeof (devinfo_audit_t), addr) == -1) { 1815*0Sstevel@tonic-gate mdb_warn("failed to read devinfo_audit at %p", addr); 1816*0Sstevel@tonic-gate status = WALK_DONE; 1817*0Sstevel@tonic-gate } 1818*0Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, da, wsp->walk_cbdata); 1819*0Sstevel@tonic-gate 1820*0Sstevel@tonic-gate /* step to the previous log entry in time */ 1821*0Sstevel@tonic-gate if (--dil->dil_index < 0) 1822*0Sstevel@tonic-gate dil->dil_index += dil->dil_max; 1823*0Sstevel@tonic-gate if (dil->dil_index == dil->dil_start) { 1824*0Sstevel@tonic-gate wsp->walk_addr = NULL; 1825*0Sstevel@tonic-gate return (WALK_DONE); 1826*0Sstevel@tonic-gate } 1827*0Sstevel@tonic-gate 1828*0Sstevel@tonic-gate wsp->walk_addr = dil->dil_base + 1829*0Sstevel@tonic-gate dil->dil_index * sizeof (devinfo_audit_t); 1830*0Sstevel@tonic-gate return (status); 1831*0Sstevel@tonic-gate } 1832*0Sstevel@tonic-gate 1833*0Sstevel@tonic-gate void 1834*0Sstevel@tonic-gate devinfo_audit_log_walk_fini(mdb_walk_state_t *wsp) 1835*0Sstevel@tonic-gate { 1836*0Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (devinfo_audit_log_walk_data_t)); 1837*0Sstevel@tonic-gate } 1838*0Sstevel@tonic-gate 1839*0Sstevel@tonic-gate /* 1840*0Sstevel@tonic-gate * display devinfo_audit_t stack trace 1841*0Sstevel@tonic-gate */ 1842*0Sstevel@tonic-gate /*ARGSUSED*/ 1843*0Sstevel@tonic-gate int 1844*0Sstevel@tonic-gate devinfo_audit(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1845*0Sstevel@tonic-gate { 1846*0Sstevel@tonic-gate uint_t verbose = FALSE; 1847*0Sstevel@tonic-gate devinfo_audit_t da; 1848*0Sstevel@tonic-gate int i, depth; 1849*0Sstevel@tonic-gate 1850*0Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) == 0) 1851*0Sstevel@tonic-gate return (DCMD_USAGE); 1852*0Sstevel@tonic-gate 1853*0Sstevel@tonic-gate if (mdb_getopts(argc, argv, 1854*0Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc) 1855*0Sstevel@tonic-gate return (DCMD_USAGE); 1856*0Sstevel@tonic-gate 1857*0Sstevel@tonic-gate if (DCMD_HDRSPEC(flags)) { 1858*0Sstevel@tonic-gate mdb_printf(" %-?s %16s %-?s %-?s %5s\n", 1859*0Sstevel@tonic-gate "AUDIT", "TIMESTAMP", "THREAD", "DEVINFO", "STATE"); 1860*0Sstevel@tonic-gate } 1861*0Sstevel@tonic-gate 1862*0Sstevel@tonic-gate if (mdb_vread(&da, sizeof (da), addr) == -1) { 1863*0Sstevel@tonic-gate mdb_warn("couldn't read devinfo_audit at %p", addr); 1864*0Sstevel@tonic-gate return (DCMD_ERR); 1865*0Sstevel@tonic-gate } 1866*0Sstevel@tonic-gate 1867*0Sstevel@tonic-gate mdb_printf(" %0?p %16llx %0?p %0?p %s\n", 1868*0Sstevel@tonic-gate addr, da.da_timestamp, da.da_thread, da.da_devinfo, 1869*0Sstevel@tonic-gate di_state[MIN(da.da_node_state + 1, DI_STATE_MAX)]); 1870*0Sstevel@tonic-gate 1871*0Sstevel@tonic-gate if (!verbose) 1872*0Sstevel@tonic-gate return (DCMD_OK); 1873*0Sstevel@tonic-gate 1874*0Sstevel@tonic-gate mdb_inc_indent(4); 1875*0Sstevel@tonic-gate 1876*0Sstevel@tonic-gate /* 1877*0Sstevel@tonic-gate * Guard against bogus da_depth in case the devinfo_audit_t 1878*0Sstevel@tonic-gate * is corrupt or the address does not really refer to a 1879*0Sstevel@tonic-gate * devinfo_audit_t. 1880*0Sstevel@tonic-gate */ 1881*0Sstevel@tonic-gate depth = MIN(da.da_depth, DDI_STACK_DEPTH); 1882*0Sstevel@tonic-gate 1883*0Sstevel@tonic-gate for (i = 0; i < depth; i++) 1884*0Sstevel@tonic-gate mdb_printf("%a\n", da.da_stack[i]); 1885*0Sstevel@tonic-gate 1886*0Sstevel@tonic-gate mdb_printf("\n"); 1887*0Sstevel@tonic-gate mdb_dec_indent(4); 1888*0Sstevel@tonic-gate 1889*0Sstevel@tonic-gate return (DCMD_OK); 1890*0Sstevel@tonic-gate } 1891*0Sstevel@tonic-gate 1892*0Sstevel@tonic-gate int 1893*0Sstevel@tonic-gate devinfo_audit_log(uintptr_t addr, uint_t flags, int argc, 1894*0Sstevel@tonic-gate const mdb_arg_t *argv) 1895*0Sstevel@tonic-gate { 1896*0Sstevel@tonic-gate if (flags & DCMD_ADDRSPEC) 1897*0Sstevel@tonic-gate return (devinfo_audit(addr, flags, argc, argv)); 1898*0Sstevel@tonic-gate 1899*0Sstevel@tonic-gate (void) mdb_walk_dcmd("devinfo_audit_log", "devinfo_audit", argc, argv); 1900*0Sstevel@tonic-gate return (DCMD_OK); 1901*0Sstevel@tonic-gate } 1902*0Sstevel@tonic-gate 1903*0Sstevel@tonic-gate typedef struct devinfo_audit_node_walk_data { 1904*0Sstevel@tonic-gate devinfo_audit_t dih_buf; /* buffer of last entry */ 1905*0Sstevel@tonic-gate uintptr_t dih_dip; /* address of dev_info */ 1906*0Sstevel@tonic-gate int dih_on_devinfo; /* devi_audit on dev_info struct */ 1907*0Sstevel@tonic-gate } devinfo_audit_node_walk_data_t; 1908*0Sstevel@tonic-gate 1909*0Sstevel@tonic-gate int 1910*0Sstevel@tonic-gate devinfo_audit_node_walk_init(mdb_walk_state_t *wsp) 1911*0Sstevel@tonic-gate { 1912*0Sstevel@tonic-gate devinfo_audit_node_walk_data_t *dih; 1913*0Sstevel@tonic-gate devinfo_audit_t *da; 1914*0Sstevel@tonic-gate struct dev_info devi; 1915*0Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr; 1916*0Sstevel@tonic-gate 1917*0Sstevel@tonic-gate /* read in devinfo structure */ 1918*0Sstevel@tonic-gate if (mdb_vread(&devi, sizeof (struct dev_info), addr) == -1) { 1919*0Sstevel@tonic-gate mdb_warn("couldn't read dev_info at %p", addr); 1920*0Sstevel@tonic-gate return (WALK_ERR); 1921*0Sstevel@tonic-gate } 1922*0Sstevel@tonic-gate 1923*0Sstevel@tonic-gate dih = mdb_zalloc(sizeof (devinfo_audit_node_walk_data_t), UM_SLEEP); 1924*0Sstevel@tonic-gate wsp->walk_data = dih; 1925*0Sstevel@tonic-gate da = &dih->dih_buf; 1926*0Sstevel@tonic-gate 1927*0Sstevel@tonic-gate /* read in devi_audit structure */ 1928*0Sstevel@tonic-gate if (mdb_vread(da, sizeof (devinfo_audit_t), (uintptr_t)devi.devi_audit) 1929*0Sstevel@tonic-gate == -1) { 1930*0Sstevel@tonic-gate mdb_warn("couldn't read devi_audit at %p", devi.devi_audit); 1931*0Sstevel@tonic-gate return (WALK_ERR); 1932*0Sstevel@tonic-gate } 1933*0Sstevel@tonic-gate dih->dih_dip = addr; 1934*0Sstevel@tonic-gate dih->dih_on_devinfo = 1; 1935*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)devi.devi_audit; 1936*0Sstevel@tonic-gate 1937*0Sstevel@tonic-gate return (WALK_NEXT); 1938*0Sstevel@tonic-gate } 1939*0Sstevel@tonic-gate 1940*0Sstevel@tonic-gate int 1941*0Sstevel@tonic-gate devinfo_audit_node_walk_step(mdb_walk_state_t *wsp) 1942*0Sstevel@tonic-gate { 1943*0Sstevel@tonic-gate uintptr_t addr; 1944*0Sstevel@tonic-gate devinfo_audit_node_walk_data_t *dih = wsp->walk_data; 1945*0Sstevel@tonic-gate devinfo_audit_t *da = &dih->dih_buf; 1946*0Sstevel@tonic-gate 1947*0Sstevel@tonic-gate if (wsp->walk_addr == NULL) 1948*0Sstevel@tonic-gate return (WALK_DONE); 1949*0Sstevel@tonic-gate (void) wsp->walk_callback(wsp->walk_addr, NULL, wsp->walk_cbdata); 1950*0Sstevel@tonic-gate 1951*0Sstevel@tonic-gate skip: 1952*0Sstevel@tonic-gate /* read in previous entry */ 1953*0Sstevel@tonic-gate if ((addr = (uintptr_t)da->da_lastlog) == 0) 1954*0Sstevel@tonic-gate return (WALK_DONE); 1955*0Sstevel@tonic-gate 1956*0Sstevel@tonic-gate if (mdb_vread(&dih->dih_buf, sizeof (devinfo_audit_t), addr) == -1) { 1957*0Sstevel@tonic-gate mdb_warn("failed to read devinfo_audit at %p", addr); 1958*0Sstevel@tonic-gate return (WALK_DONE); 1959*0Sstevel@tonic-gate } 1960*0Sstevel@tonic-gate 1961*0Sstevel@tonic-gate /* check if last log was over-written */ 1962*0Sstevel@tonic-gate if ((uintptr_t)da->da_devinfo != dih->dih_dip) 1963*0Sstevel@tonic-gate return (WALK_DONE); 1964*0Sstevel@tonic-gate 1965*0Sstevel@tonic-gate /* 1966*0Sstevel@tonic-gate * skip the first common log entry, which is a duplicate of 1967*0Sstevel@tonic-gate * the devi_audit buffer on the dev_info structure 1968*0Sstevel@tonic-gate */ 1969*0Sstevel@tonic-gate if (dih->dih_on_devinfo) { 1970*0Sstevel@tonic-gate dih->dih_on_devinfo = 0; 1971*0Sstevel@tonic-gate goto skip; 1972*0Sstevel@tonic-gate } 1973*0Sstevel@tonic-gate wsp->walk_addr = addr; 1974*0Sstevel@tonic-gate 1975*0Sstevel@tonic-gate return (WALK_NEXT); 1976*0Sstevel@tonic-gate } 1977*0Sstevel@tonic-gate 1978*0Sstevel@tonic-gate void 1979*0Sstevel@tonic-gate devinfo_audit_node_walk_fini(mdb_walk_state_t *wsp) 1980*0Sstevel@tonic-gate { 1981*0Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (devinfo_audit_node_walk_data_t)); 1982*0Sstevel@tonic-gate } 1983*0Sstevel@tonic-gate 1984*0Sstevel@tonic-gate int 1985*0Sstevel@tonic-gate devinfo_audit_node(uintptr_t addr, uint_t flags, int argc, 1986*0Sstevel@tonic-gate const mdb_arg_t *argv) 1987*0Sstevel@tonic-gate { 1988*0Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) 1989*0Sstevel@tonic-gate return (DCMD_USAGE); 1990*0Sstevel@tonic-gate 1991*0Sstevel@tonic-gate (void) mdb_pwalk_dcmd("devinfo_audit_node", "devinfo_audit", 1992*0Sstevel@tonic-gate argc, argv, addr); 1993*0Sstevel@tonic-gate return (DCMD_OK); 1994*0Sstevel@tonic-gate } 1995*0Sstevel@tonic-gate 1996*0Sstevel@tonic-gate /* 1997*0Sstevel@tonic-gate * mdb support for per-devinfo fault management data 1998*0Sstevel@tonic-gate */ 1999*0Sstevel@tonic-gate /*ARGSUSED*/ 2000*0Sstevel@tonic-gate int 2001*0Sstevel@tonic-gate devinfo_fm(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2002*0Sstevel@tonic-gate { 2003*0Sstevel@tonic-gate struct dev_info devi; 2004*0Sstevel@tonic-gate struct i_ddi_fmhdl fhdl; 2005*0Sstevel@tonic-gate 2006*0Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) == 0) 2007*0Sstevel@tonic-gate return (DCMD_USAGE); 2008*0Sstevel@tonic-gate 2009*0Sstevel@tonic-gate if (DCMD_HDRSPEC(flags)) { 2010*0Sstevel@tonic-gate mdb_printf("%<u>%-11s IPL CAPS DROP FMCFULL FMCGREW ACCERR " 2011*0Sstevel@tonic-gate "DMAERR %11s %11s%</u>\n", "ADDR", "DMACACHE", "ACCCACHE"); 2012*0Sstevel@tonic-gate } 2013*0Sstevel@tonic-gate 2014*0Sstevel@tonic-gate if (mdb_vread(&devi, sizeof (devi), addr) == -1) { 2015*0Sstevel@tonic-gate mdb_warn("failed to read devinfo struct at %p", addr); 2016*0Sstevel@tonic-gate return (DCMD_ERR); 2017*0Sstevel@tonic-gate } 2018*0Sstevel@tonic-gate 2019*0Sstevel@tonic-gate if (mdb_vread(&fhdl, sizeof (fhdl), (uintptr_t)devi.devi_fmhdl) == -1) { 2020*0Sstevel@tonic-gate mdb_warn("failed to read devinfo fm struct at %p", 2021*0Sstevel@tonic-gate (uintptr_t)devi.devi_fmhdl); 2022*0Sstevel@tonic-gate return (DCMD_ERR); 2023*0Sstevel@tonic-gate } 2024*0Sstevel@tonic-gate 2025*0Sstevel@tonic-gate mdb_printf("%-11p %3u %c%c%c%c %4llu %7llu %7llu %6llu %6llu %11p " 2026*0Sstevel@tonic-gate "%11p\n", 2027*0Sstevel@tonic-gate (uintptr_t)devi.devi_fmhdl, fhdl.fh_ibc, 2028*0Sstevel@tonic-gate (DDI_FM_EREPORT_CAP(fhdl.fh_cap) ? 'E' : '-'), 2029*0Sstevel@tonic-gate (DDI_FM_ERRCB_CAP(fhdl.fh_cap) ? 'C' : '-'), 2030*0Sstevel@tonic-gate (DDI_FM_ACC_ERR_CAP(fhdl.fh_cap) ? 'A' : '-'), 2031*0Sstevel@tonic-gate (DDI_FM_DMA_ERR_CAP(fhdl.fh_cap) ? 'D' : '-'), 2032*0Sstevel@tonic-gate fhdl.fh_kstat.fek_erpt_dropped.value.ui64, 2033*0Sstevel@tonic-gate fhdl.fh_kstat.fek_fmc_full.value.ui64, 2034*0Sstevel@tonic-gate fhdl.fh_kstat.fek_fmc_grew.value.ui64, 2035*0Sstevel@tonic-gate fhdl.fh_kstat.fek_acc_err.value.ui64, 2036*0Sstevel@tonic-gate fhdl.fh_kstat.fek_dma_err.value.ui64, 2037*0Sstevel@tonic-gate fhdl.fh_dma_cache, fhdl.fh_acc_cache); 2038*0Sstevel@tonic-gate 2039*0Sstevel@tonic-gate 2040*0Sstevel@tonic-gate return (DCMD_OK); 2041*0Sstevel@tonic-gate } 2042*0Sstevel@tonic-gate 2043*0Sstevel@tonic-gate /*ARGSUSED*/ 2044*0Sstevel@tonic-gate int 2045*0Sstevel@tonic-gate devinfo_fmce(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2046*0Sstevel@tonic-gate { 2047*0Sstevel@tonic-gate struct i_ddi_fmc_entry fce; 2048*0Sstevel@tonic-gate 2049*0Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) == 0) 2050*0Sstevel@tonic-gate return (DCMD_USAGE); 2051*0Sstevel@tonic-gate 2052*0Sstevel@tonic-gate if (DCMD_HDRSPEC(flags)) { 2053*0Sstevel@tonic-gate mdb_printf("%<u>%-11s %11s %11s%</u>\n", "ADDR", 2054*0Sstevel@tonic-gate "RESOURCE", "BUS_SPECIFIC"); 2055*0Sstevel@tonic-gate } 2056*0Sstevel@tonic-gate 2057*0Sstevel@tonic-gate if (mdb_vread(&fce, sizeof (fce), addr) == -1) { 2058*0Sstevel@tonic-gate mdb_warn("failed to read fm cache struct at %p", addr); 2059*0Sstevel@tonic-gate return (DCMD_ERR); 2060*0Sstevel@tonic-gate } 2061*0Sstevel@tonic-gate 2062*0Sstevel@tonic-gate mdb_printf("%-11p %11p %11p\n", 2063*0Sstevel@tonic-gate (uintptr_t)addr, fce.fce_resource, fce.fce_bus_specific); 2064*0Sstevel@tonic-gate 2065*0Sstevel@tonic-gate 2066*0Sstevel@tonic-gate return (DCMD_OK); 2067*0Sstevel@tonic-gate } 2068*0Sstevel@tonic-gate 2069*0Sstevel@tonic-gate int 2070*0Sstevel@tonic-gate devinfo_fmc_walk_init(mdb_walk_state_t *wsp) 2071*0Sstevel@tonic-gate { 2072*0Sstevel@tonic-gate struct i_ddi_fmc fec; 2073*0Sstevel@tonic-gate struct i_ddi_fmc_entry fe; 2074*0Sstevel@tonic-gate 2075*0Sstevel@tonic-gate if (wsp->walk_addr == NULL) 2076*0Sstevel@tonic-gate return (WALK_ERR); 2077*0Sstevel@tonic-gate 2078*0Sstevel@tonic-gate if (mdb_vread(&fec, sizeof (fec), wsp->walk_addr) == -1) { 2079*0Sstevel@tonic-gate mdb_warn("failed to read fm cache at %p", wsp->walk_addr); 2080*0Sstevel@tonic-gate return (WALK_ERR); 2081*0Sstevel@tonic-gate } 2082*0Sstevel@tonic-gate 2083*0Sstevel@tonic-gate if (fec.fc_active == NULL) 2084*0Sstevel@tonic-gate return (WALK_DONE); 2085*0Sstevel@tonic-gate 2086*0Sstevel@tonic-gate if (mdb_vread(&fe, sizeof (fe), (uintptr_t)fec.fc_active) == -1) { 2087*0Sstevel@tonic-gate mdb_warn("failed to read active fm cache list at %p", 2088*0Sstevel@tonic-gate fec.fc_active); 2089*0Sstevel@tonic-gate return (WALK_ERR); 2090*0Sstevel@tonic-gate } 2091*0Sstevel@tonic-gate 2092*0Sstevel@tonic-gate wsp->walk_data = fe.fce_next; 2093*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)fe.fce_next; 2094*0Sstevel@tonic-gate return (WALK_NEXT); 2095*0Sstevel@tonic-gate } 2096*0Sstevel@tonic-gate 2097*0Sstevel@tonic-gate int 2098*0Sstevel@tonic-gate devinfo_fmc_walk_step(mdb_walk_state_t *wsp) 2099*0Sstevel@tonic-gate { 2100*0Sstevel@tonic-gate int status; 2101*0Sstevel@tonic-gate struct i_ddi_fmc_entry fe; 2102*0Sstevel@tonic-gate 2103*0Sstevel@tonic-gate if (mdb_vread(&fe, sizeof (fe), wsp->walk_addr) == -1) { 2104*0Sstevel@tonic-gate mdb_warn("failed to read active fm cache entry at %p", 2105*0Sstevel@tonic-gate wsp->walk_addr); 2106*0Sstevel@tonic-gate return (WALK_DONE); 2107*0Sstevel@tonic-gate } 2108*0Sstevel@tonic-gate 2109*0Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, &fe, wsp->walk_cbdata); 2110*0Sstevel@tonic-gate 2111*0Sstevel@tonic-gate if (fe.fce_next == NULL) 2112*0Sstevel@tonic-gate return (WALK_DONE); 2113*0Sstevel@tonic-gate 2114*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)fe.fce_next; 2115*0Sstevel@tonic-gate return (status); 2116*0Sstevel@tonic-gate } 2117*0Sstevel@tonic-gate 2118*0Sstevel@tonic-gate int 2119*0Sstevel@tonic-gate minornode_walk_init(mdb_walk_state_t *wsp) 2120*0Sstevel@tonic-gate { 2121*0Sstevel@tonic-gate struct dev_info di; 2122*0Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr; 2123*0Sstevel@tonic-gate 2124*0Sstevel@tonic-gate if (addr == NULL) { 2125*0Sstevel@tonic-gate mdb_warn("a dev_info struct address must be provided\n"); 2126*0Sstevel@tonic-gate return (WALK_ERR); 2127*0Sstevel@tonic-gate } 2128*0Sstevel@tonic-gate 2129*0Sstevel@tonic-gate if (mdb_vread(&di, sizeof (di), wsp->walk_addr) == -1) { 2130*0Sstevel@tonic-gate mdb_warn("failed to read dev_info struct at %p", addr); 2131*0Sstevel@tonic-gate return (WALK_ERR); 2132*0Sstevel@tonic-gate } 2133*0Sstevel@tonic-gate 2134*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)di.devi_minor; 2135*0Sstevel@tonic-gate return (WALK_NEXT); 2136*0Sstevel@tonic-gate } 2137*0Sstevel@tonic-gate 2138*0Sstevel@tonic-gate int 2139*0Sstevel@tonic-gate minornode_walk_step(mdb_walk_state_t *wsp) 2140*0Sstevel@tonic-gate { 2141*0Sstevel@tonic-gate struct ddi_minor_data md; 2142*0Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr; 2143*0Sstevel@tonic-gate 2144*0Sstevel@tonic-gate if (addr == NULL) 2145*0Sstevel@tonic-gate return (WALK_DONE); 2146*0Sstevel@tonic-gate 2147*0Sstevel@tonic-gate if (mdb_vread(&md, sizeof (md), addr) == -1) { 2148*0Sstevel@tonic-gate mdb_warn("failed to read dev_info struct at %p", addr); 2149*0Sstevel@tonic-gate return (WALK_DONE); 2150*0Sstevel@tonic-gate } 2151*0Sstevel@tonic-gate 2152*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)md.next; 2153*0Sstevel@tonic-gate return (wsp->walk_callback(addr, &md, wsp->walk_cbdata)); 2154*0Sstevel@tonic-gate } 2155*0Sstevel@tonic-gate 2156*0Sstevel@tonic-gate static const char *const md_type[] = { 2157*0Sstevel@tonic-gate "DDI_MINOR", 2158*0Sstevel@tonic-gate "DDI_ALIAS", 2159*0Sstevel@tonic-gate "DDI_DEFAULT", 2160*0Sstevel@tonic-gate "DDI_I_PATH", 2161*0Sstevel@tonic-gate "?" 2162*0Sstevel@tonic-gate }; 2163*0Sstevel@tonic-gate 2164*0Sstevel@tonic-gate #define MD_TYPE_MAX ((sizeof (md_type) / sizeof (char *)) - 1) 2165*0Sstevel@tonic-gate 2166*0Sstevel@tonic-gate /*ARGSUSED*/ 2167*0Sstevel@tonic-gate static int 2168*0Sstevel@tonic-gate print_minornode(uintptr_t addr, const void *arg, void *data) 2169*0Sstevel@tonic-gate { 2170*0Sstevel@tonic-gate char name[128]; 2171*0Sstevel@tonic-gate char nodetype[128]; 2172*0Sstevel@tonic-gate char *spectype; 2173*0Sstevel@tonic-gate struct ddi_minor_data *mdp = (struct ddi_minor_data *)arg; 2174*0Sstevel@tonic-gate 2175*0Sstevel@tonic-gate if (mdb_readstr(name, sizeof (name), (uintptr_t)mdp->ddm_name) == -1) 2176*0Sstevel@tonic-gate *name = '\0'; 2177*0Sstevel@tonic-gate 2178*0Sstevel@tonic-gate if (mdb_readstr(nodetype, sizeof (nodetype), 2179*0Sstevel@tonic-gate (uintptr_t)mdp->ddm_node_type) == -1) 2180*0Sstevel@tonic-gate *nodetype = '\0'; 2181*0Sstevel@tonic-gate 2182*0Sstevel@tonic-gate switch (mdp->ddm_spec_type) { 2183*0Sstevel@tonic-gate case S_IFCHR: spectype = "c"; break; 2184*0Sstevel@tonic-gate case S_IFBLK: spectype = "b"; break; 2185*0Sstevel@tonic-gate default: spectype = "?"; break; 2186*0Sstevel@tonic-gate } 2187*0Sstevel@tonic-gate 2188*0Sstevel@tonic-gate mdb_printf("%?p %16lx %-4s %-11s %-10s %s\n", 2189*0Sstevel@tonic-gate addr, mdp->ddm_dev, spectype, md_type[MIN(mdp->type, MD_TYPE_MAX)], 2190*0Sstevel@tonic-gate name, nodetype); 2191*0Sstevel@tonic-gate 2192*0Sstevel@tonic-gate return (WALK_NEXT); 2193*0Sstevel@tonic-gate } 2194*0Sstevel@tonic-gate 2195*0Sstevel@tonic-gate /*ARGSUSED*/ 2196*0Sstevel@tonic-gate int 2197*0Sstevel@tonic-gate minornodes(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2198*0Sstevel@tonic-gate { 2199*0Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC) || argc != 0) 2200*0Sstevel@tonic-gate return (DCMD_USAGE); 2201*0Sstevel@tonic-gate 2202*0Sstevel@tonic-gate if (DCMD_HDRSPEC(flags)) 2203*0Sstevel@tonic-gate mdb_printf("%<u>%?s %16s %-4s %-11s %-10s %-16s%</u>\n", 2204*0Sstevel@tonic-gate "ADDR", "DEV", "SPEC", "TYPE", "NAME", "NODETYPE"); 2205*0Sstevel@tonic-gate 2206*0Sstevel@tonic-gate if (mdb_pwalk("minornode", print_minornode, NULL, addr) == -1) { 2207*0Sstevel@tonic-gate mdb_warn("can't walk minornode"); 2208*0Sstevel@tonic-gate return (DCMD_ERR); 2209*0Sstevel@tonic-gate } 2210*0Sstevel@tonic-gate 2211*0Sstevel@tonic-gate return (DCMD_OK); 2212*0Sstevel@tonic-gate } 2213