xref: /onnv-gate/usr/src/cmd/mdb/common/modules/genunix/mdi.c (revision 2577:630a8010260c)
1*2577Sramat /*
2*2577Sramat  * CDDL HEADER START
3*2577Sramat  *
4*2577Sramat  * The contents of this file are subject to the terms of the
5*2577Sramat  * Common Development and Distribution License (the "License").
6*2577Sramat  * You may not use this file except in compliance with the License.
7*2577Sramat  *
8*2577Sramat  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*2577Sramat  * or http://www.opensolaris.org/os/licensing.
10*2577Sramat  * See the License for the specific language governing permissions
11*2577Sramat  * and limitations under the License.
12*2577Sramat  *
13*2577Sramat  * When distributing Covered Code, include this CDDL HEADER in each
14*2577Sramat  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*2577Sramat  * If applicable, add the following below this CDDL HEADER, with the
16*2577Sramat  * fields enclosed by brackets "[]" replaced with your own identifying
17*2577Sramat  * information: Portions Copyright [yyyy] [name of copyright owner]
18*2577Sramat  *
19*2577Sramat  * CDDL HEADER END
20*2577Sramat  */
21*2577Sramat /*
22*2577Sramat  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*2577Sramat  * Use is subject to license terms.
24*2577Sramat  */
25*2577Sramat 
26*2577Sramat #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*2577Sramat 
28*2577Sramat #include <sys/kmem.h>
29*2577Sramat #include <sys/proc.h>
30*2577Sramat #include <sys/time.h>
31*2577Sramat #include <sys/conf.h>
32*2577Sramat #include <sys/file.h>
33*2577Sramat #include <sys/ddi.h>
34*2577Sramat #include <sys/ddi_impldefs.h>
35*2577Sramat #include <sys/modctl.h>
36*2577Sramat #include <sys/sunddi.h>
37*2577Sramat #include <sys/scsi/scsi.h>
38*2577Sramat #include <sys/scsi/impl/scsi_reset_notify.h>
39*2577Sramat #include <sys/sunmdi.h>
40*2577Sramat #include <sys/mdi_impldefs.h>
41*2577Sramat #include <sys/scsi/adapters/scsi_vhci.h>
42*2577Sramat #include <sys/scsi/scsi_types.h>
43*2577Sramat #include <sys/disp.h>
44*2577Sramat #include <sys/types.h>
45*2577Sramat #include <sys/mdb_modapi.h>
46*2577Sramat #include "mdi.h"
47*2577Sramat 
48*2577Sramat #define	FT(var, typ)	(*((typ *)(&(var))))
49*2577Sramat 
50*2577Sramat /* Utils */
51*2577Sramat static int get_mdbstr(uintptr_t addr, char *name);
52*2577Sramat static void dump_flags(unsigned long long flags, char **strings);
53*2577Sramat static void dump_mutex(kmutex_t m, char *name);
54*2577Sramat static void dump_condvar(kcondvar_t c, char *name);
55*2577Sramat static void dump_string(uintptr_t addr, char *name);
56*2577Sramat static void dump_state_str(char *name, uintptr_t addr, char **strings);
57*2577Sramat 
58*2577Sramat static int mpxio_walk_cb(uintptr_t addr, const void *data, void *cbdata);
59*2577Sramat 
60*2577Sramat static char *client_lb_str[] =
61*2577Sramat {
62*2577Sramat 	"NONE",
63*2577Sramat 	"RR",
64*2577Sramat 	"LBA",
65*2577Sramat 	NULL
66*2577Sramat };
67*2577Sramat 
68*2577Sramat static char *mdi_pathinfo_states[] =
69*2577Sramat {
70*2577Sramat 	"MDI_PATHINFO_STATE_INIT",
71*2577Sramat 	"MDI_PATHINFO_STATE_ONLINE",
72*2577Sramat 	"MDI_PATHINFO_STATE_STANDBY",
73*2577Sramat 	"MDI_PATHINFO_STATE_FAULT",
74*2577Sramat 	"MDI_PATHINFO_STATE_OFFLINE",
75*2577Sramat 	NULL
76*2577Sramat };
77*2577Sramat 
78*2577Sramat static char *mdi_pathinfo_ext_states[] =
79*2577Sramat {
80*2577Sramat 	"MDI_PATHINFO_STATE_USER_DISABLE",
81*2577Sramat 	"MDI_PATHINFO_STATE_DRV_DISABLE",
82*2577Sramat 	"MDI_PATHINFO_STATE_DRV_DISABLE_TRANSIENT",
83*2577Sramat 	NULL
84*2577Sramat };
85*2577Sramat 
86*2577Sramat static char *mdi_phci_flags[] =
87*2577Sramat {
88*2577Sramat 	"MDI_PHCI_FLAGS_OFFLINE",
89*2577Sramat 	"MDI_PHCI_FLAGS_SUSPEND",
90*2577Sramat 	"MDI_PHCI_FLAGS_POWER_DOWN",
91*2577Sramat 	"MDI_PHCI_FLAGS_DETACH",
92*2577Sramat 	"MDI_PHCI_FLAGS_USER_DISABLE",
93*2577Sramat 	"MDI_PHCI_FLAGS_D_DISABLE",
94*2577Sramat 	"MDI_PHCI_FLAGS_D_DISABLE_TRANS",
95*2577Sramat 	"MDI_PHCI_FLAGS_POWER_TRANSITION",
96*2577Sramat 	NULL
97*2577Sramat };
98*2577Sramat 
99*2577Sramat static uintptr_t firstaddr = 0;
100*2577Sramat static char mdipathinfo_cb_str[] = "::print struct mdi_pathinfo";
101*2577Sramat static char mdiphci_cb_str[] = "::print struct mdi_phci";
102*2577Sramat 
103*2577Sramat /*
104*2577Sramat  * mdipi()
105*2577Sramat  *
106*2577Sramat  * Given a path, dump mdi_pathinfo struct and detailed pi_prop list.
107*2577Sramat  */
108*2577Sramat /* ARGSUSED */
109*2577Sramat int
mdipi(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)110*2577Sramat mdipi(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
111*2577Sramat {
112*2577Sramat 	struct mdi_pathinfo	value;
113*2577Sramat 
114*2577Sramat 	if (!(flags & DCMD_ADDRSPEC)) {
115*2577Sramat 		mdb_warn("mdipi: requires an address");
116*2577Sramat 		return (DCMD_ERR);
117*2577Sramat 	}
118*2577Sramat 
119*2577Sramat 	if (mdb_vread(&value, sizeof (struct mdi_pathinfo), addr) !=
120*2577Sramat 	    sizeof (struct mdi_pathinfo)) {
121*2577Sramat 		mdb_warn("mdipi: Failed read on %l#r\n", addr);
122*2577Sramat 		return (DCMD_ERR);
123*2577Sramat 	}
124*2577Sramat 	mdb_printf("------------- mdi_pathinfo @ %#lr ----------\n", addr);
125*2577Sramat 
126*2577Sramat 	dump_string((uintptr_t)value.pi_addr, "PWWN,LUN (pi_addr)");
127*2577Sramat 
128*2577Sramat 	mdb_printf("\n");
129*2577Sramat 	mdb_printf("pi_client: %25l#r::print struct mdi_client\n",
130*2577Sramat 	    value.pi_client);
131*2577Sramat 	mdb_printf("pi_phci: %27l#r::print struct mdi_phci\n", value.pi_phci);
132*2577Sramat 	mdb_printf("pi_pprivate: %23l#r\n", value.pi_pprivate);
133*2577Sramat 	mdb_printf("pi_client_link: %20l#r::print struct mdi_pathinfo\n",
134*2577Sramat 	    value.pi_client_link);
135*2577Sramat 	mdb_printf("pi_phci_link: %22l#r::print struct mdi_pathinfo\n",
136*2577Sramat 	    value.pi_phci_link);
137*2577Sramat 	mdb_printf("pi_prop: %27l#r::print struct nv_list\n", value.pi_prop);
138*2577Sramat 
139*2577Sramat 	mdiprops((uintptr_t)value.pi_prop, flags, 0, NULL);
140*2577Sramat 
141*2577Sramat 	mdb_printf("\n");
142*2577Sramat 	dump_state_str("Pathinfo State (pi_state)        ",
143*2577Sramat 	    MDI_PI_STATE(&value), mdi_pathinfo_states);
144*2577Sramat 	if (MDI_PI_IS_TRANSIENT(&value)) {
145*2577Sramat 		mdb_printf("Pathinfo State is TRANSIENT\n");
146*2577Sramat 	}
147*2577Sramat 	if (MDI_PI_EXT_STATE(&value)) {
148*2577Sramat 		mdb_printf("      Extended (pi_state)        : ");
149*2577Sramat 		/*
150*2577Sramat 		 * Need to shift right 20 bits to match mdi_pathinfo_ext_states
151*2577Sramat 		 * array.
152*2577Sramat 		 */
153*2577Sramat 		dump_flags((unsigned long long)MDI_PI_EXT_STATE(&value) >> 20,
154*2577Sramat 		    mdi_pathinfo_ext_states);
155*2577Sramat 	}
156*2577Sramat 	dump_state_str("Old Pathinfo State (pi_old_state)",
157*2577Sramat 	    MDI_PI_OLD_STATE(&value), mdi_pathinfo_states);
158*2577Sramat 	if (MDI_PI_OLD_EXT_STATE(&value)) {
159*2577Sramat 		mdb_printf("      Extended (pi_old_state)    : ");
160*2577Sramat 		/*
161*2577Sramat 		 * Need to shift right 20 bits to match mdi_pathinfo_ext_states
162*2577Sramat 		 * array.
163*2577Sramat 		 */
164*2577Sramat 		dump_flags((unsigned long long)MDI_PI_OLD_EXT_STATE(&value)
165*2577Sramat 		>> 20, mdi_pathinfo_ext_states);
166*2577Sramat 	}
167*2577Sramat 	dump_mutex(value.pi_mutex, "per-path mutex (pi_mutex):");
168*2577Sramat 	dump_condvar(value.pi_state_cv, "Path state (pi_state_cv)");
169*2577Sramat 
170*2577Sramat 	mdb_printf("\n");
171*2577Sramat 	mdb_printf("pi_ref_cnt: %d\n", value.pi_ref_cnt);
172*2577Sramat 	dump_condvar(value.pi_ref_cv, "pi_ref_cv");
173*2577Sramat 
174*2577Sramat 	mdb_printf("\n");
175*2577Sramat 	mdb_printf("pi_kstats: %25l#r::print struct mdi_pi_kstats\n",
176*2577Sramat 	    value.pi_kstats);
177*2577Sramat 	mdb_printf("pi_cprivate UNUSED: %16l#r \n", value.pi_cprivate);
178*2577Sramat 
179*2577Sramat 	return (DCMD_OK);
180*2577Sramat }
181*2577Sramat 
182*2577Sramat /*
183*2577Sramat  * mdiprops()
184*2577Sramat  *
185*2577Sramat  * Given a pi_prop, dump the pi_prop list.
186*2577Sramat  */
187*2577Sramat /* ARGSUSED */
188*2577Sramat int
mdiprops(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)189*2577Sramat mdiprops(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
190*2577Sramat {
191*2577Sramat 	if (!(flags & DCMD_ADDRSPEC)) {
192*2577Sramat 		mdb_warn("mdiprops: requires an address");
193*2577Sramat 		return (DCMD_ERR);
194*2577Sramat 	}
195*2577Sramat 
196*2577Sramat 	mdb_printf("\tnvpairs @ %#lr:\n", addr);
197*2577Sramat 	mdb_pwalk_dcmd("nvpair", "nvpair", argc, argv, addr);
198*2577Sramat 	mdb_printf("\n");
199*2577Sramat 
200*2577Sramat 	return (DCMD_OK);
201*2577Sramat }
202*2577Sramat 
203*2577Sramat /*
204*2577Sramat  * mdiphci()
205*2577Sramat  *
206*2577Sramat  * Given a phci, dump mdi_phci struct.
207*2577Sramat  */
208*2577Sramat /* ARGSUSED */
209*2577Sramat int
mdiphci(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)210*2577Sramat mdiphci(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
211*2577Sramat {
212*2577Sramat 	struct mdi_phci value;
213*2577Sramat 
214*2577Sramat 	if (!(flags & DCMD_ADDRSPEC)) {
215*2577Sramat 		mdb_warn("mdiphci: requires an address");
216*2577Sramat 		return (DCMD_ERR);
217*2577Sramat 	}
218*2577Sramat 
219*2577Sramat 	if (mdb_vread(&value, sizeof (struct mdi_phci), addr) !=
220*2577Sramat 	    sizeof (struct mdi_phci)) {
221*2577Sramat 		mdb_warn("mdiphci: Failed read on %l#r\n", addr);
222*2577Sramat 		return (DCMD_ERR);
223*2577Sramat 	}
224*2577Sramat 	mdb_printf("---------------- mdi_phci @ %#lr ----------\n", addr);
225*2577Sramat 
226*2577Sramat 	mdb_printf("ph_next: %27l#r::print struct mdi_phci\n", value.ph_next);
227*2577Sramat 	mdb_printf("ph_prev: %27l#r::print struct mdi_phci\n", value.ph_prev);
228*2577Sramat 	mdb_printf("ph_vhci: %27l#r::print struct mdi_vhci\n", value.ph_vhci);
229*2577Sramat 	mdb_printf("ph_dip: %28l#r::print struct dev_info\n", value.ph_dip);
230*2577Sramat 	mdb_printf("\nph_path_head: %22l#r::print struct mdi_pathinfo\n",
231*2577Sramat 	    value.ph_path_head);
232*2577Sramat 	mdb_printf("ph_path_tail: %22l#r::print struct mdi_pathinfo\n",
233*2577Sramat 	    value.ph_path_tail);
234*2577Sramat 	mdb_printf("ph_path_count: %21d\n", value.ph_path_count);
235*2577Sramat 	mdb_printf("List of paths:\n");
236*2577Sramat 	mdb_pwalk("mdipi_phci_list", (mdb_walk_cb_t)mpxio_walk_cb,
237*2577Sramat 			mdipathinfo_cb_str, (uintptr_t)value.ph_path_head);
238*2577Sramat 
239*2577Sramat 	mdb_printf("\n");
240*2577Sramat 	mdb_printf("ph_flags: %26d\n", value.ph_flags);
241*2577Sramat 	if (value.ph_flags) {
242*2577Sramat 		dump_flags((unsigned long long)value.ph_flags, mdi_phci_flags);
243*2577Sramat 	}
244*2577Sramat 	dump_mutex(value.ph_mutex, "per-pHCI mutex (ph_mutex):");
245*2577Sramat 	dump_condvar(value.ph_unstable_cv,
246*2577Sramat 	    "Paths in transient state (ph_unstable_cv)");
247*2577Sramat 	mdb_printf("ph_unstable: %23d\n", value.ph_unstable);
248*2577Sramat 
249*2577Sramat 	return (DCMD_OK);
250*2577Sramat }
251*2577Sramat 
252*2577Sramat /*
253*2577Sramat  * mdivhci()
254*2577Sramat  *
255*2577Sramat  * Given a vhci, dump mdi_vhci struct and list all phcis.
256*2577Sramat  */
257*2577Sramat /* ARGSUSED */
258*2577Sramat int
mdivhci(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)259*2577Sramat mdivhci(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
260*2577Sramat {
261*2577Sramat 	struct mdi_vhci value;
262*2577Sramat 
263*2577Sramat 	if (!(flags & DCMD_ADDRSPEC)) {
264*2577Sramat 		mdb_warn("mdivhci: requires an address");
265*2577Sramat 		return (DCMD_ERR);
266*2577Sramat 	}
267*2577Sramat 
268*2577Sramat 	if (mdb_vread(&value, sizeof (struct mdi_vhci), addr) !=
269*2577Sramat 	    sizeof (struct mdi_vhci)) {
270*2577Sramat 		mdb_warn("mdivhci: Failed read on %l#r\n", addr);
271*2577Sramat 		return (DCMD_ERR);
272*2577Sramat 	}
273*2577Sramat 	mdb_printf("----------------- mdi_vhci @ %#lr ----------\n", addr);
274*2577Sramat 
275*2577Sramat 	dump_string((uintptr_t)value.vh_class, "Class name (vh_class)");
276*2577Sramat 	mdb_printf("vh_refcnt: %19d\n", value.vh_refcnt);
277*2577Sramat 	mdb_printf("vh_dip: %28l#r::print struct dev_info\n", value.vh_dip);
278*2577Sramat 	mdb_printf("vh_next: %27l#r::print struct mdi_vhci\n", value.vh_next);
279*2577Sramat 	mdb_printf("vh_prev: %27l#r::print struct mdi_vhci\n", value.vh_prev);
280*2577Sramat 	dump_state_str("Load Balance (vh_lb)", value.vh_lb, client_lb_str);
281*2577Sramat 	mdb_printf("vh_ops: %28l#r::print struct mdi_vhci_ops\n",
282*2577Sramat 	    value.vh_ops);
283*2577Sramat 
284*2577Sramat 	dump_mutex(value.vh_phci_mutex, "phci mutex (vh_phci_mutex):");
285*2577Sramat 	mdb_printf("vh_phci_count: %21d\n", value.vh_phci_count);
286*2577Sramat 	mdb_printf("\nvh_phci_head: %22l#r::print struct mdi_phci\n",
287*2577Sramat 	    value.vh_phci_head);
288*2577Sramat 	mdb_printf("vh_phci_tail: %22l#r::print struct mdi_phci\n",
289*2577Sramat 	    value.vh_phci_tail);
290*2577Sramat 
291*2577Sramat 	dump_mutex(value.vh_phci_mutex, "client mutex (vh_client_mutex):");
292*2577Sramat 	mdb_printf("vh_client_count: %19d\n", value.vh_client_count);
293*2577Sramat 	mdb_printf("vh_client_table: %19l#r::print struct client_hash\n",
294*2577Sramat 	    value.vh_client_table);
295*2577Sramat 
296*2577Sramat 	mdb_printf("List of pHCIs:\n");
297*2577Sramat 	mdb_pwalk("mdiphci_list", (mdb_walk_cb_t)mpxio_walk_cb,
298*2577Sramat 			mdiphci_cb_str, (uintptr_t)value.vh_phci_head);
299*2577Sramat 	mdb_printf("\n");
300*2577Sramat 	return (DCMD_OK);
301*2577Sramat }
302*2577Sramat 
303*2577Sramat /* mdi_pathinfo client walker */
304*2577Sramat 
305*2577Sramat /* ARGUSED */
306*2577Sramat int
mdi_pi_client_link_walk_init(mdb_walk_state_t * wsp)307*2577Sramat mdi_pi_client_link_walk_init(mdb_walk_state_t *wsp)
308*2577Sramat {
309*2577Sramat 	if (wsp->walk_addr == NULL) {
310*2577Sramat 		mdb_warn("Address is required");
311*2577Sramat 		return (WALK_ERR);
312*2577Sramat 	}
313*2577Sramat 	wsp->walk_data = mdb_alloc(sizeof (struct mdi_pathinfo), UM_SLEEP);
314*2577Sramat 	firstaddr = wsp->walk_addr;
315*2577Sramat 	return (WALK_NEXT);
316*2577Sramat }
317*2577Sramat 
318*2577Sramat /* ARGUSED */
319*2577Sramat int
mdi_pi_client_link_walk_step(mdb_walk_state_t * wsp)320*2577Sramat mdi_pi_client_link_walk_step(mdb_walk_state_t *wsp)
321*2577Sramat {
322*2577Sramat 	int 		status = 0;
323*2577Sramat 	static int	counts = 0;
324*2577Sramat 
325*2577Sramat 	if (firstaddr == wsp->walk_addr && counts != 0) {
326*2577Sramat 		counts = 0;
327*2577Sramat 		return (WALK_DONE);
328*2577Sramat 	}
329*2577Sramat 	if (wsp->walk_addr == NULL) {
330*2577Sramat 		counts = 0;
331*2577Sramat 		return (WALK_DONE);
332*2577Sramat 	}
333*2577Sramat 	if (mdb_vread(wsp->walk_data, sizeof (struct mdi_pathinfo),
334*2577Sramat 	    wsp->walk_addr) == -1) {
335*2577Sramat 		mdb_warn("failed to read mdi_pathinfo at %p", wsp->walk_addr);
336*2577Sramat 		return (WALK_DONE);
337*2577Sramat 	}
338*2577Sramat 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
339*2577Sramat 	    wsp->walk_cbdata);
340*2577Sramat 	wsp->walk_addr = (uintptr_t)
341*2577Sramat 	    (((struct mdi_pathinfo *)wsp->walk_data)->pi_client_link);
342*2577Sramat 	counts++;
343*2577Sramat 	return (status);
344*2577Sramat }
345*2577Sramat 
346*2577Sramat /* ARGUSED */
347*2577Sramat void
mdi_pi_client_link_walk_fini(mdb_walk_state_t * wsp)348*2577Sramat mdi_pi_client_link_walk_fini(mdb_walk_state_t *wsp)
349*2577Sramat {
350*2577Sramat 	mdb_free(wsp->walk_data, sizeof (struct mdi_pathinfo));
351*2577Sramat }
352*2577Sramat 
353*2577Sramat /*
354*2577Sramat  * mdiclient_paths()
355*2577Sramat  *
356*2577Sramat  * Given a path, walk through mdi_pathinfo client links.
357*2577Sramat  */
358*2577Sramat /* ARGUSED */
359*2577Sramat int
mdiclient_paths(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)360*2577Sramat mdiclient_paths(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
361*2577Sramat {
362*2577Sramat 	int status;
363*2577Sramat 	if (argc != 0)
364*2577Sramat 		return (DCMD_USAGE);
365*2577Sramat 
366*2577Sramat 	if (!(flags & DCMD_ADDRSPEC)) {
367*2577Sramat 		mdb_warn("Address needs to be specified");
368*2577Sramat 		return (DCMD_ERR);
369*2577Sramat 	}
370*2577Sramat 	status =
371*2577Sramat 	    mdb_pwalk_dcmd("mdipi_client_list", "mdipi", argc, argv, addr);
372*2577Sramat 	return (status);
373*2577Sramat }
374*2577Sramat 
375*2577Sramat /* mdi_pathinfo phci walker */
376*2577Sramat int
mdi_pi_phci_link_walk_init(mdb_walk_state_t * wsp)377*2577Sramat mdi_pi_phci_link_walk_init(mdb_walk_state_t *wsp)
378*2577Sramat {
379*2577Sramat 	if (wsp->walk_addr == NULL) {
380*2577Sramat 		mdb_warn("Address is required");
381*2577Sramat 		return (WALK_ERR);
382*2577Sramat 	}
383*2577Sramat 	wsp->walk_data = mdb_alloc(sizeof (struct mdi_pathinfo), UM_SLEEP);
384*2577Sramat 	firstaddr = wsp->walk_addr;
385*2577Sramat 	return (WALK_NEXT);
386*2577Sramat }
387*2577Sramat 
388*2577Sramat int
mdi_pi_phci_link_walk_step(mdb_walk_state_t * wsp)389*2577Sramat mdi_pi_phci_link_walk_step(mdb_walk_state_t *wsp)
390*2577Sramat {
391*2577Sramat 	int status;
392*2577Sramat 	static int	counts = 0;
393*2577Sramat 
394*2577Sramat 	if (firstaddr == wsp->walk_addr && counts != 0) {
395*2577Sramat 		counts = 0;
396*2577Sramat 		return (WALK_DONE);
397*2577Sramat 	}
398*2577Sramat 	if (wsp->walk_addr == NULL) {
399*2577Sramat 		counts = 0;
400*2577Sramat 		return (WALK_DONE);
401*2577Sramat 	}
402*2577Sramat 	if (mdb_vread(wsp->walk_data, sizeof (struct mdi_pathinfo),
403*2577Sramat 	    wsp->walk_addr) == -1) {
404*2577Sramat 		mdb_warn("failed to read mdi_pathinfo at %p", wsp->walk_addr);
405*2577Sramat 		return (WALK_DONE);
406*2577Sramat 	}
407*2577Sramat 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
408*2577Sramat 	    wsp->walk_cbdata);
409*2577Sramat 	wsp->walk_addr = (uintptr_t)
410*2577Sramat 	    (((struct mdi_pathinfo *)wsp->walk_data)->pi_phci_link);
411*2577Sramat 	counts++;
412*2577Sramat 	return (status);
413*2577Sramat }
414*2577Sramat 
415*2577Sramat void
mdi_pi_phci_link_walk_fini(mdb_walk_state_t * wsp)416*2577Sramat mdi_pi_phci_link_walk_fini(mdb_walk_state_t *wsp)
417*2577Sramat {
418*2577Sramat 	mdb_free(wsp->walk_data, sizeof (struct mdi_pathinfo));
419*2577Sramat }
420*2577Sramat 
421*2577Sramat /*
422*2577Sramat  * mdiphci_paths()
423*2577Sramat  *
424*2577Sramat  * Given a path, walk through mdi_pathinfo phci links.
425*2577Sramat  */
426*2577Sramat int
mdiphci_paths(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)427*2577Sramat mdiphci_paths(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
428*2577Sramat {
429*2577Sramat 	int status;
430*2577Sramat 	if (argc != 0)
431*2577Sramat 		return (DCMD_USAGE);
432*2577Sramat 
433*2577Sramat 	if (!(flags & DCMD_ADDRSPEC)) {
434*2577Sramat 		mdb_warn("Address needs to be specified");
435*2577Sramat 		return (DCMD_ERR);
436*2577Sramat 	}
437*2577Sramat 	status =
438*2577Sramat 	    mdb_pwalk_dcmd("mdipi_phci_list", "mdipi", argc, argv, addr);
439*2577Sramat 	return (status);
440*2577Sramat }
441*2577Sramat 
442*2577Sramat /* mdi_phci walker */
443*2577Sramat int
mdi_phci_ph_next_walk_init(mdb_walk_state_t * wsp)444*2577Sramat mdi_phci_ph_next_walk_init(mdb_walk_state_t *wsp)
445*2577Sramat {
446*2577Sramat 	if (wsp->walk_addr == NULL) {
447*2577Sramat 		mdb_warn("Address is required");
448*2577Sramat 		return (WALK_ERR);
449*2577Sramat 	}
450*2577Sramat 	wsp->walk_data = mdb_alloc(sizeof (struct mdi_phci), UM_SLEEP);
451*2577Sramat 	firstaddr = wsp->walk_addr;
452*2577Sramat 	return (WALK_NEXT);
453*2577Sramat }
454*2577Sramat 
455*2577Sramat int
mdi_phci_ph_next_walk_step(mdb_walk_state_t * wsp)456*2577Sramat mdi_phci_ph_next_walk_step(mdb_walk_state_t *wsp)
457*2577Sramat {
458*2577Sramat 	int status;
459*2577Sramat 	static int counts = 0;
460*2577Sramat 
461*2577Sramat 	if (firstaddr == wsp->walk_addr && counts != 0) {
462*2577Sramat 		counts = 0;
463*2577Sramat 		return (WALK_DONE);
464*2577Sramat 	}
465*2577Sramat 	if (wsp->walk_addr == NULL) {
466*2577Sramat 		counts = 0;
467*2577Sramat 		return (WALK_DONE);
468*2577Sramat 	}
469*2577Sramat 	if (mdb_vread(wsp->walk_data, sizeof (struct mdi_phci), wsp->walk_addr)
470*2577Sramat 	    == -1) {
471*2577Sramat 		mdb_warn("failed to read mdi_phci at %p", wsp->walk_addr);
472*2577Sramat 		return (WALK_DONE);
473*2577Sramat 	}
474*2577Sramat 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
475*2577Sramat 	    wsp->walk_cbdata);
476*2577Sramat 	wsp->walk_addr = (uintptr_t)
477*2577Sramat 	    (((struct mdi_phci *)wsp->walk_data)->ph_next);
478*2577Sramat 	counts++;
479*2577Sramat 	return (status);
480*2577Sramat }
481*2577Sramat 
482*2577Sramat void
mdi_phci_ph_next_walk_fini(mdb_walk_state_t * wsp)483*2577Sramat mdi_phci_ph_next_walk_fini(mdb_walk_state_t *wsp)
484*2577Sramat {
485*2577Sramat 	mdb_free(wsp->walk_data, sizeof (struct mdi_phci));
486*2577Sramat }
487*2577Sramat 
488*2577Sramat /*
489*2577Sramat  * mdiphcis()
490*2577Sramat  *
491*2577Sramat  * Given a phci, walk through mdi_phci ph_next links.
492*2577Sramat  */
493*2577Sramat int
mdiphcis(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)494*2577Sramat mdiphcis(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
495*2577Sramat {
496*2577Sramat 	int status;
497*2577Sramat 	if (argc != 0)
498*2577Sramat 		return (DCMD_USAGE);
499*2577Sramat 
500*2577Sramat 	if (!(flags & DCMD_ADDRSPEC)) {
501*2577Sramat 		mdb_warn("Address needs to be specified");
502*2577Sramat 		return (DCMD_ERR);
503*2577Sramat 	}
504*2577Sramat 	status =
505*2577Sramat 	    mdb_pwalk_dcmd("mdiphci_list", "mdiphci", argc, argv, addr);
506*2577Sramat 	return (status);
507*2577Sramat }
508*2577Sramat 
509*2577Sramat /*
510*2577Sramat  * Print the flag name by comparing flags to the mask variable.
511*2577Sramat  */
512*2577Sramat static void
dump_flags(unsigned long long flags,char ** strings)513*2577Sramat dump_flags(unsigned long long flags, char **strings)
514*2577Sramat {
515*2577Sramat 	int i, linel = 8, first = 1;
516*2577Sramat 	unsigned long long mask = 1;
517*2577Sramat 
518*2577Sramat 	for (i = 0; i < 64; i++) {
519*2577Sramat 		if (strings[i] == NULL)
520*2577Sramat 			break;
521*2577Sramat 		if (flags & mask) {
522*2577Sramat 			if (!first) {
523*2577Sramat 				mdb_printf(" | ");
524*2577Sramat 			} else {
525*2577Sramat 				first = 0;
526*2577Sramat 			}
527*2577Sramat 			/* make output pretty */
528*2577Sramat 			linel += strlen(strings[i]) + 3;
529*2577Sramat 			if (linel > 80) {
530*2577Sramat 				mdb_printf("\n\t");
531*2577Sramat 				linel = strlen(strings[i]) + 1 + 8;
532*2577Sramat 			}
533*2577Sramat 			mdb_printf("%s", strings[i]);
534*2577Sramat 		}
535*2577Sramat 		mask <<= 1;
536*2577Sramat 	}
537*2577Sramat 	mdb_printf("\n");
538*2577Sramat }
539*2577Sramat 
540*2577Sramat static void
dump_mutex(kmutex_t m,char * name)541*2577Sramat dump_mutex(kmutex_t m, char *name)
542*2577Sramat {
543*2577Sramat 	mdb_printf("%s is%s held\n", name, FT(m, uint64_t) == 0 ? " not" : "");
544*2577Sramat }
545*2577Sramat 
546*2577Sramat static void
dump_condvar(kcondvar_t c,char * name)547*2577Sramat dump_condvar(kcondvar_t c, char *name)
548*2577Sramat {
549*2577Sramat 	mdb_printf("Threads sleeping on %s = %d\n", name, (int)FT(c, ushort_t));
550*2577Sramat }
551*2577Sramat 
552*2577Sramat static int
get_mdbstr(uintptr_t addr,char * string_val)553*2577Sramat get_mdbstr(uintptr_t addr, char *string_val)
554*2577Sramat {
555*2577Sramat 	if (mdb_readstr(string_val, MAXNAMELEN, addr) == -1) {
556*2577Sramat 		mdb_warn("Error Reading String from %l#r\n", addr);
557*2577Sramat 		return (1);
558*2577Sramat 	}
559*2577Sramat 
560*2577Sramat 	return (0);
561*2577Sramat }
562*2577Sramat 
563*2577Sramat static void
dump_string(uintptr_t addr,char * name)564*2577Sramat dump_string(uintptr_t addr, char *name)
565*2577Sramat {
566*2577Sramat 	char string_val[MAXNAMELEN];
567*2577Sramat 
568*2577Sramat 	if (get_mdbstr(addr, string_val)) {
569*2577Sramat 		return;
570*2577Sramat 	}
571*2577Sramat 	mdb_printf("%s: %s (%l#r)\n", name, string_val, addr);
572*2577Sramat }
573*2577Sramat 
574*2577Sramat static void
dump_state_str(char * name,uintptr_t addr,char ** strings)575*2577Sramat dump_state_str(char *name, uintptr_t addr, char **strings)
576*2577Sramat {
577*2577Sramat 	mdb_printf("%s: %s (%l#r)\n", name, strings[(unsigned long)addr], addr);
578*2577Sramat }
579*2577Sramat 
580*2577Sramat /* ARGSUSED */
581*2577Sramat static int
mpxio_walk_cb(uintptr_t addr,const void * data,void * cbdata)582*2577Sramat mpxio_walk_cb(uintptr_t addr, const void *data, void *cbdata)
583*2577Sramat {
584*2577Sramat 	mdb_printf("%t%l#r%s\n", addr, (char *)cbdata);
585*2577Sramat 	return (0);
586*2577Sramat }
587