xref: /illumos-gate/usr/src/cmd/mdb/common/modules/genunix/streams.c (revision 88d6421c15f1c4daea9c8128e715662091258054)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5ca9327a6Smeem  * Common Development and Distribution License (the "License").
6ca9327a6Smeem  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22a45f3f93Smeem  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
26*88d6421cSAndy Fiddaman /*
27*88d6421cSAndy Fiddaman  * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
28*88d6421cSAndy Fiddaman  */
29*88d6421cSAndy Fiddaman 
307c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
317c478bd9Sstevel@tonic-gate #include <mdb/mdb_ks.h>
327c478bd9Sstevel@tonic-gate 
33a45f3f93Smeem #include <ctype.h>
347c478bd9Sstevel@tonic-gate #include <sys/types.h>
357c478bd9Sstevel@tonic-gate #include <sys/strsubr.h>
367c478bd9Sstevel@tonic-gate #include <sys/stream.h>
377c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
387c478bd9Sstevel@tonic-gate #include <sys/strft.h>
397c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
407c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #include "streams.h"
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate typedef struct str_flags {
457c478bd9Sstevel@tonic-gate 	uint_t strf_flag;
467c478bd9Sstevel@tonic-gate 	const char *strf_name;
477c478bd9Sstevel@tonic-gate 	const char *strf_descr;
487c478bd9Sstevel@tonic-gate } strflags_t;
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate typedef struct str_types {
517c478bd9Sstevel@tonic-gate 	const char *strt_name;
527c478bd9Sstevel@tonic-gate 	int strt_value;
537c478bd9Sstevel@tonic-gate 	const char *strt_descr;
547c478bd9Sstevel@tonic-gate } strtypes_t;
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate typedef struct ftblk_data {
577c478bd9Sstevel@tonic-gate 	ftblk_t ft_data;	/* Copy of ftblk */
587c478bd9Sstevel@tonic-gate 	int	ft_ix;		/* Index in event list */
597c478bd9Sstevel@tonic-gate 	boolean_t ft_in_evlist;	/* Iterating through evlist */
607c478bd9Sstevel@tonic-gate } ftblkdata_t;
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate typedef void qprint_func(queue_t *, queue_t *);
637c478bd9Sstevel@tonic-gate typedef void sdprint_func(stdata_t *, stdata_t *);
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate #define	SF(flag)	flag, #flag
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate /*
687c478bd9Sstevel@tonic-gate  * Queue flags
697c478bd9Sstevel@tonic-gate  */
707c478bd9Sstevel@tonic-gate static const strflags_t qf[] = {
717c478bd9Sstevel@tonic-gate 	{ SF(QENAB),		"Queue is already enabled to run"	},
727c478bd9Sstevel@tonic-gate 	{ SF(QWANTR),		"Someone wants to read Q"		},
737c478bd9Sstevel@tonic-gate 	{ SF(QWANTW),		"Someone wants to write Q"		},
747c478bd9Sstevel@tonic-gate 	{ SF(QFULL),		"Q is considered full"			},
757c478bd9Sstevel@tonic-gate 	{ SF(QREADR),		"This is the reader (first) Q"		},
767c478bd9Sstevel@tonic-gate 	{ SF(QUSE),		"This queue in use (allocation)"	},
777c478bd9Sstevel@tonic-gate 	{ SF(QNOENB),		"Don't enable Q via putq"		},
787c478bd9Sstevel@tonic-gate 	{ SF(QWANTRMQSYNC),	"Want to remove sync stream Q"		},
797c478bd9Sstevel@tonic-gate 	{ SF(QBACK),		"queue has been back-enabled"		},
807c478bd9Sstevel@tonic-gate 	{ SF(0x00000200),	"unused (was QHLIST)"			},
817c478bd9Sstevel@tonic-gate 	{ SF(0x00000400),	"unused (was QUNSAFE)"			},
827c478bd9Sstevel@tonic-gate 	{ SF(QPAIR),		"per queue-pair syncq"			},
837c478bd9Sstevel@tonic-gate 	{ SF(QPERQ),		"per queue-instance syncq"		},
847c478bd9Sstevel@tonic-gate 	{ SF(QPERMOD),		"per module syncq"			},
857c478bd9Sstevel@tonic-gate 	{ SF(QMTSAFE),		"stream module is MT-safe"		},
867c478bd9Sstevel@tonic-gate 	{ SF(QMTOUTPERIM),	"Has outer perimeter"			},
877c478bd9Sstevel@tonic-gate 	{ SF(QINSERVICE),	"service routine executing"		},
887c478bd9Sstevel@tonic-gate 	{ SF(QWCLOSE),		"will not be enabled"			},
897c478bd9Sstevel@tonic-gate 	{ SF(QEND),		"last queue in stream"			},
907c478bd9Sstevel@tonic-gate 	{ SF(QWANTWSYNC),	"Streamhead wants to write Q"		},
917c478bd9Sstevel@tonic-gate 	{ SF(QSYNCSTR),		"Q supports Synchronous STREAMS"	},
927c478bd9Sstevel@tonic-gate 	{ SF(QISDRV),		"the Queue is attached to a driver"	},
937c478bd9Sstevel@tonic-gate 	{ SF(0x00400000),	"unused (was QHOT)"			},
947c478bd9Sstevel@tonic-gate 	{ SF(0x00800000),	"unused (was QNEXTHOT)"			},
957c478bd9Sstevel@tonic-gate 	{ SF(0x01000000),	"unused (was _QNEXTLESS)"		},
967c478bd9Sstevel@tonic-gate 	{ SF(0x02000000),	"unused"				},
977c478bd9Sstevel@tonic-gate 	{ SF(_QINSERTING),	"module is inserted with _I_INSERT"	},
987c478bd9Sstevel@tonic-gate 	{ SF(_QREMOVING)	"module is removed with _I_REMOVE"	},
997c478bd9Sstevel@tonic-gate 	{ SF(_QASSOCIATED),	"queue is associated with a device"	},
100595aa6e4Smeem 	{ 0, NULL,		NULL					}
1017c478bd9Sstevel@tonic-gate };
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate /*
1047c478bd9Sstevel@tonic-gate  * Syncq flags
1057c478bd9Sstevel@tonic-gate  */
1067c478bd9Sstevel@tonic-gate static const struct str_flags sqf[] = {
1077c478bd9Sstevel@tonic-gate 	{ SF(SQ_EXCL),		"Exclusive access to inner perimeter"	},
1087c478bd9Sstevel@tonic-gate 	{ SF(SQ_BLOCKED),	"qprocsoff in progress"			},
1097c478bd9Sstevel@tonic-gate 	{ SF(SQ_FROZEN),	"freezestr in progress"			},
1107c478bd9Sstevel@tonic-gate 	{ SF(SQ_WRITER),	"qwriter(OUTER) pending or running"	},
1117c478bd9Sstevel@tonic-gate 	{ SF(SQ_MESSAGES),	"There are messages on syncq"		},
1127c478bd9Sstevel@tonic-gate 	{ SF(SQ_WANTWAKEUP)	"Thread waiting on sq_wait"		},
1137c478bd9Sstevel@tonic-gate 	{ SF(SQ_WANTEXWAKEUP),	"Thread waiting on sq_exwait"		},
1147c478bd9Sstevel@tonic-gate 	{ SF(SQ_EVENTS),	"There are events on syncq"		},
115595aa6e4Smeem 	{ 0, NULL,		NULL					}
1167c478bd9Sstevel@tonic-gate };
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate /*
1197c478bd9Sstevel@tonic-gate  * Syncq types
1207c478bd9Sstevel@tonic-gate  */
1217c478bd9Sstevel@tonic-gate static const struct str_flags sqt[] = {
1227c478bd9Sstevel@tonic-gate 	{ SF(SQ_CIPUT),		"Concurrent inner put procedure"	},
1237c478bd9Sstevel@tonic-gate 	{ SF(SQ_CISVC),		"Concurrent inner svc procedure"	},
1247c478bd9Sstevel@tonic-gate 	{ SF(SQ_CIOC),		"Concurrent inner open/close"		},
1257c478bd9Sstevel@tonic-gate 	{ SF(SQ_CICB),		"Concurrent inner callback"		},
1267c478bd9Sstevel@tonic-gate 	{ SF(SQ_COPUT),		"Concurrent outer put procedure"	},
1277c478bd9Sstevel@tonic-gate 	{ SF(SQ_COSVC),		"Concurrent outer svc procedure"	},
1287c478bd9Sstevel@tonic-gate 	{ SF(SQ_COOC),		"Concurrent outer open/close"		},
1297c478bd9Sstevel@tonic-gate 	{ SF(SQ_COCB),		"Concurrent outer callback"		},
130595aa6e4Smeem 	{ 0, NULL,		NULL					}
1317c478bd9Sstevel@tonic-gate };
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate /*
1347c478bd9Sstevel@tonic-gate  * Stdata flags
1357c478bd9Sstevel@tonic-gate  */
1367c478bd9Sstevel@tonic-gate static const struct str_flags stdf[] = {
1377c478bd9Sstevel@tonic-gate 	{ SF(IOCWAIT),		"someone is doing an ioctl"		},
1387c478bd9Sstevel@tonic-gate 	{ SF(RSLEEP),		"someone wants to read/recv msg"	},
1397c478bd9Sstevel@tonic-gate 	{ SF(WSLEEP),		"someone wants to write"		},
1407c478bd9Sstevel@tonic-gate 	{ SF(STRPRI),		"an M_PCPROTO is at stream head"	},
1417c478bd9Sstevel@tonic-gate 	{ SF(STRHUP),		"device has vanished"			},
1427c478bd9Sstevel@tonic-gate 	{ SF(STWOPEN),		"waiting for 1st open"			},
1437c478bd9Sstevel@tonic-gate 	{ SF(STPLEX),		"stream is being multiplexed"		},
1447c478bd9Sstevel@tonic-gate 	{ SF(STRISTTY),		"stream is a terminal"			},
1457c478bd9Sstevel@tonic-gate 	{ SF(STRGETINPROG),	"(k)strgetmsg is running"		},
1467c478bd9Sstevel@tonic-gate 	{ SF(IOCWAITNE),	"STR_NOERROR ioctl running"		},
1477c478bd9Sstevel@tonic-gate 	{ SF(STRDERR),		"fatal read error from M_ERROR"		},
1487c478bd9Sstevel@tonic-gate 	{ SF(STWRERR),		"fatal write error from M_ERROR"	},
1497c478bd9Sstevel@tonic-gate 	{ SF(STRDERRNONPERSIST), "nonpersistent read errors"		},
1507c478bd9Sstevel@tonic-gate 	{ SF(STWRERRNONPERSIST), "nonpersistent write errors"		},
1517c478bd9Sstevel@tonic-gate 	{ SF(STRCLOSE),		"wait for a close to complete"		},
1527c478bd9Sstevel@tonic-gate 	{ SF(SNDMREAD),		"used for read notification"		},
1537c478bd9Sstevel@tonic-gate 	{ SF(OLDNDELAY),	"use old NDELAY TTY semantics"		},
154*88d6421cSAndy Fiddaman 	{ SF(STRXPG4TTY),	"Use XPG4 TTY semantics"		},
1557c478bd9Sstevel@tonic-gate 	{ SF(0x00040000),	"unused"				},
1567c478bd9Sstevel@tonic-gate 	{ SF(STRTOSTOP),	"block background writes"		},
157ca9327a6Smeem 	{ SF(STRCMDWAIT),	"someone is doing an _I_CMD"		},
1587c478bd9Sstevel@tonic-gate 	{ SF(0x00200000),	"unused"				},
1597c478bd9Sstevel@tonic-gate 	{ SF(STRMOUNT),		"stream is mounted"			},
1607c478bd9Sstevel@tonic-gate 	{ SF(STRNOTATMARK),	"Not at mark (when empty read q)"	},
1617c478bd9Sstevel@tonic-gate 	{ SF(STRDELIM),		"generate delimited messages"		},
1627c478bd9Sstevel@tonic-gate 	{ SF(STRATMARK),	"at mark (due to MSGMARKNEXT)"		},
1637c478bd9Sstevel@tonic-gate 	{ SF(STZCNOTIFY),	"wait for zerocopy mblk to be acked"	},
1647c478bd9Sstevel@tonic-gate 	{ SF(STRPLUMB),		"stream plumbing changes in progress"	},
1657c478bd9Sstevel@tonic-gate 	{ SF(STREOF),		"End-of-file indication"		},
1667c478bd9Sstevel@tonic-gate 	{ SF(STREOPENFAIL),	"re-open has failed"			},
1677c478bd9Sstevel@tonic-gate 	{ SF(STRMATE),		"this stream is a mate"			},
1687c478bd9Sstevel@tonic-gate 	{ SF(STRHASLINKS),	"there are I_LINKs under this stream"	},
169595aa6e4Smeem 	{ 0, NULL,		NULL					}
1707c478bd9Sstevel@tonic-gate };
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate static const struct str_flags mbf[] = {
1737c478bd9Sstevel@tonic-gate 	{ SF(MSGMARK),		"last byte of message is marked"	},
1747c478bd9Sstevel@tonic-gate 	{ SF(MSGNOLOOP),	"don't loop message to write side"	},
1757c478bd9Sstevel@tonic-gate 	{ SF(MSGDELIM),		"message is delimited"			},
1767c478bd9Sstevel@tonic-gate 	{ SF(0x08),		"unused"				},
1777c478bd9Sstevel@tonic-gate 	{ SF(MSGMARKNEXT),	"Private: b_next's first byte marked"	},
1787c478bd9Sstevel@tonic-gate 	{ SF(MSGNOTMARKNEXT),	"Private: ... not marked"		},
179595aa6e4Smeem 	{ 0, NULL,		NULL					}
1807c478bd9Sstevel@tonic-gate };
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate #define	M_DATA_T 0xff
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate static const strtypes_t mbt[] = {
1857c478bd9Sstevel@tonic-gate 	{ "M_DATA",	M_DATA_T,	"regular data"			},
1867c478bd9Sstevel@tonic-gate 	{ "M_PROTO",	M_PROTO,	"protocol control"		},
1877c478bd9Sstevel@tonic-gate 	{ "M_MULTIDATA", M_MULTIDATA,	"multidata"			},
1887c478bd9Sstevel@tonic-gate 	{ "M_BREAK",	M_BREAK,	"line break"			},
1897c478bd9Sstevel@tonic-gate 	{ "M_PASSFP",	M_PASSFP,	"pass file pointer"		},
1907c478bd9Sstevel@tonic-gate 	{ "M_EVENT",	M_EVENT,	"Obsoleted: do not use"		},
1917c478bd9Sstevel@tonic-gate 	{ "M_SIG",	M_SIG,		"generate process signal"	},
1927c478bd9Sstevel@tonic-gate 	{ "M_DELAY",	M_DELAY,	"real-time xmit delay"		},
1937c478bd9Sstevel@tonic-gate 	{ "M_CTL",	M_CTL,		"device-specific control message" },
1947c478bd9Sstevel@tonic-gate 	{ "M_IOCTL",	M_IOCTL,	"ioctl; set/get params"		},
1957c478bd9Sstevel@tonic-gate 	{ "M_SETOPTS",	M_SETOPTS,	"set stream head options"	},
1967c478bd9Sstevel@tonic-gate 	{ "M_RSE",	M_RSE,		"reserved for RSE use only"	},
1977c478bd9Sstevel@tonic-gate 	{ "M_IOCACK",	M_IOCACK,	"acknowledge ioctl"		},
1987c478bd9Sstevel@tonic-gate 	{ "M_IOCNAK",	M_IOCNAK,	"negative ioctl acknowledge"	},
1997c478bd9Sstevel@tonic-gate 	{ "M_PCPROTO",	M_PCPROTO,	"priority proto message"	},
2007c478bd9Sstevel@tonic-gate 	{ "M_PCSIG",	M_PCSIG,	"generate process signal"	},
2017c478bd9Sstevel@tonic-gate 	{ "M_READ",	M_READ,		"generate read notification"	},
2027c478bd9Sstevel@tonic-gate 	{ "M_FLUSH",	M_FLUSH,	"flush your queues"		},
2037c478bd9Sstevel@tonic-gate 	{ "M_STOP",	M_STOP,		"stop transmission immediately" },
2047c478bd9Sstevel@tonic-gate 	{ "M_START",	M_START,	"restart transmission after stop" },
2057c478bd9Sstevel@tonic-gate 	{ "M_HANGUP",	M_HANGUP,	"line disconnect"		},
2067c478bd9Sstevel@tonic-gate 	{ "M_ERROR",	M_ERROR,	"send error to stream head"	},
2077c478bd9Sstevel@tonic-gate 	{ "M_COPYIN",	M_COPYIN,	"request to copyin data"	},
2087c478bd9Sstevel@tonic-gate 	{ "M_COPYOUT",	M_COPYOUT,	"request to copyout data"	},
2097c478bd9Sstevel@tonic-gate 	{ "M_IOCDATA",	M_IOCDATA,	"response to M_COPYIN and M_COPYOUT" },
2107c478bd9Sstevel@tonic-gate 	{ "M_PCRSE",	M_PCRSE,	"reserved for RSE use only"	},
2117c478bd9Sstevel@tonic-gate 	{ "M_STOPI",	M_STOPI,	"stop reception immediately"	},
2127c478bd9Sstevel@tonic-gate 	{ "M_STARTI",	M_STARTI,	"restart reception after stop"	},
2137c478bd9Sstevel@tonic-gate 	{ "M_PCEVENT",	M_PCEVENT,	"Obsoleted: do not use"		},
2147c478bd9Sstevel@tonic-gate 	{ "M_UNHANGUP",	M_UNHANGUP,	"line reconnect"		},
215ca9327a6Smeem 	{ "M_CMD",	M_CMD,		"out-of-band ioctl command"	},
216595aa6e4Smeem 	{ NULL,		0,		NULL				}
2177c478bd9Sstevel@tonic-gate };
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate /* Allocation flow trace events, starting from 0 */
2207c478bd9Sstevel@tonic-gate static const char *ftev_alloc[] = {
221a45f3f93Smeem /* 0 */	"allocb",
222a45f3f93Smeem /* 1 */	"esballoc",
223a45f3f93Smeem /* 2 */	"desballoc",
224a45f3f93Smeem /* 3 */	"esballoca",
225a45f3f93Smeem /* 4 */	"desballoca",
226a45f3f93Smeem /* 5 */	"allocbig",
227a45f3f93Smeem /* 6 */	"allocbw",
228a45f3f93Smeem /* 7 */	"bcallocb",
229a45f3f93Smeem /* 8 */	"freeb",
230a45f3f93Smeem /* 9 */	"dupb",
231a45f3f93Smeem /* A */	"copyb",
2327c478bd9Sstevel@tonic-gate };
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate #define	FTEV_PROC_START FTEV_PUT
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate /* Procedures recorded by flow tracing, starting from 0x100 */
2377c478bd9Sstevel@tonic-gate static const char *ftev_proc[] = {
238a45f3f93Smeem /* 100 */	"put",
239a45f3f93Smeem /* 101 */	"0x101",
240a45f3f93Smeem /* 102 */	"0x102",
241a45f3f93Smeem /* 103 */	"0x103",
242a45f3f93Smeem /* 104 */	"0x104",
243a45f3f93Smeem /* 105 */	"putq",
244a45f3f93Smeem /* 106 */	"getq",
245a45f3f93Smeem /* 107 */	"rmvq",
246a45f3f93Smeem /* 108 */	"insq",
247a45f3f93Smeem /* 109 */	"putbq",
248a45f3f93Smeem /* 10A */	"flushq",
249a45f3f93Smeem /* 10B */	"0x10b",
250a45f3f93Smeem /* 10C */	"0x10c",
251a45f3f93Smeem /* 10D */	"putnext",
252a45f3f93Smeem /* 10E */	"rwnext",
2537c478bd9Sstevel@tonic-gate };
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate static const char *db_control_types[] = {
2567c478bd9Sstevel@tonic-gate /* 00 */	"data",
2577c478bd9Sstevel@tonic-gate /* 01 */	"proto",
2587c478bd9Sstevel@tonic-gate /* 02 */	"multidata",
259a45f3f93Smeem /* 03 */	"0x03",
260a45f3f93Smeem /* 04 */	"0x04",
261a45f3f93Smeem /* 05 */	"0x05",
262a45f3f93Smeem /* 06 */	"0x06",
263a45f3f93Smeem /* 07 */	"0x07",
2647c478bd9Sstevel@tonic-gate /* 08 */	"break",
2657c478bd9Sstevel@tonic-gate /* 09 */	"passfp",
2667c478bd9Sstevel@tonic-gate /* 0a */	"event",
2677c478bd9Sstevel@tonic-gate /* 0b */	"sig",
2687c478bd9Sstevel@tonic-gate /* 0c */	"delay",
2697c478bd9Sstevel@tonic-gate /* 0d */	"ctl",
2707c478bd9Sstevel@tonic-gate /* 0e */	"ioctl",
2717c478bd9Sstevel@tonic-gate /* 0f */	"unused",
2727c478bd9Sstevel@tonic-gate /* 10 */	"setopts",
2737c478bd9Sstevel@tonic-gate /* 11 */	"rse",
2747c478bd9Sstevel@tonic-gate };
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate static const char *db_control_hipri_types[] = {
2777c478bd9Sstevel@tonic-gate /* 81 */	"iocack",
2787c478bd9Sstevel@tonic-gate /* 82 */	"iocnak",
2797c478bd9Sstevel@tonic-gate /* 83 */	"pcproto",
2807c478bd9Sstevel@tonic-gate /* 84 */	"pcsig",
2817c478bd9Sstevel@tonic-gate /* 85 */	"read",
2827c478bd9Sstevel@tonic-gate /* 86 */	"flush",
2837c478bd9Sstevel@tonic-gate /* 87 */	"stop",
2847c478bd9Sstevel@tonic-gate /* 88 */	"start",
2857c478bd9Sstevel@tonic-gate /* 89 */	"hangup",
2867c478bd9Sstevel@tonic-gate /* 8a */	"error",
2877c478bd9Sstevel@tonic-gate /* 8b */	"copyin",
2887c478bd9Sstevel@tonic-gate /* 8c */	"copyout",
2897c478bd9Sstevel@tonic-gate /* 8d */	"iocdata",
2907c478bd9Sstevel@tonic-gate /* 8e */	"pcrse",
2917c478bd9Sstevel@tonic-gate /* 8f */	"stopi",
2927c478bd9Sstevel@tonic-gate /* 90 */	"starti",
2937c478bd9Sstevel@tonic-gate /* 91 */	"pcevent",
2947c478bd9Sstevel@tonic-gate /* 92 */	"unhangup",
295a45f3f93Smeem /* 93 */	"cmd",
2967c478bd9Sstevel@tonic-gate };
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate #define	A_SIZE(a) (sizeof (a) / sizeof (a[0]))
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate static void ft_printevent(ushort_t);
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate static int
streams_parse_flag(const strflags_t ftable[],const char * arg,uint32_t * flag)3037c478bd9Sstevel@tonic-gate streams_parse_flag(const strflags_t ftable[], const char *arg, uint32_t *flag)
3047c478bd9Sstevel@tonic-gate {
3057c478bd9Sstevel@tonic-gate 	int i;
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 	for (i = 0; ftable[i].strf_name != NULL; i++) {
3087c478bd9Sstevel@tonic-gate 		if (strcasecmp(arg, ftable[i].strf_name) == 0) {
3097c478bd9Sstevel@tonic-gate 			*flag |= (1 << i);
3107c478bd9Sstevel@tonic-gate 			return (0);
3117c478bd9Sstevel@tonic-gate 		}
3127c478bd9Sstevel@tonic-gate 	}
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	return (-1);
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate static void
streams_flag_usage(const strflags_t ftable[])3187c478bd9Sstevel@tonic-gate streams_flag_usage(const strflags_t ftable[])
3197c478bd9Sstevel@tonic-gate {
3207c478bd9Sstevel@tonic-gate 	int i;
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	for (i = 0; ftable[i].strf_name != NULL; i++)
3237c478bd9Sstevel@tonic-gate 		mdb_printf("%-14s %s\n",
3247c478bd9Sstevel@tonic-gate 		    ftable[i].strf_name, ftable[i].strf_descr);
3257c478bd9Sstevel@tonic-gate }
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate static int
streams_parse_type(const strtypes_t ftable[],const char * arg,uint32_t * flag)3287c478bd9Sstevel@tonic-gate streams_parse_type(const strtypes_t ftable[], const char *arg, uint32_t *flag)
3297c478bd9Sstevel@tonic-gate {
3307c478bd9Sstevel@tonic-gate 	int i;
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 	for (i = 0; ftable[i].strt_name != NULL; i++) {
3337c478bd9Sstevel@tonic-gate 		if (strcasecmp(arg, ftable[i].strt_name) == 0) {
3347c478bd9Sstevel@tonic-gate 			*flag = ftable[i].strt_value;
3357c478bd9Sstevel@tonic-gate 			return (0);
3367c478bd9Sstevel@tonic-gate 		}
3377c478bd9Sstevel@tonic-gate 	}
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	return (-1);
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate static void
streams_type_usage(const strtypes_t ftable[])3437c478bd9Sstevel@tonic-gate streams_type_usage(const strtypes_t ftable[])
3447c478bd9Sstevel@tonic-gate {
3457c478bd9Sstevel@tonic-gate 	int i;
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	for (i = 0; ftable[i].strt_name != NULL; i++)
3487c478bd9Sstevel@tonic-gate 		mdb_printf("%-12s %s\n",
3497c478bd9Sstevel@tonic-gate 		    ftable[i].strt_name, ftable[i].strt_descr);
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate int
queue(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)3537c478bd9Sstevel@tonic-gate queue(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3547c478bd9Sstevel@tonic-gate {
3557c478bd9Sstevel@tonic-gate 	const int QUEUE_FLGDELT = (int)(sizeof (uintptr_t) * 2 + 15);
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 	char name[MODMAXNAMELEN];
3587c478bd9Sstevel@tonic-gate 	int nblks = 0;
3597c478bd9Sstevel@tonic-gate 	uintptr_t maddr;
3607c478bd9Sstevel@tonic-gate 	mblk_t mblk;
3617c478bd9Sstevel@tonic-gate 	queue_t q;
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	const char *mod = NULL, *flag = NULL, *not_flag = NULL;
3647c478bd9Sstevel@tonic-gate 	uint_t quiet = FALSE;
3657c478bd9Sstevel@tonic-gate 	uint_t verbose = FALSE;
3667c478bd9Sstevel@tonic-gate 	uint32_t mask = 0, not_mask = 0;
3677c478bd9Sstevel@tonic-gate 	uintptr_t syncq = 0;
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
3707c478bd9Sstevel@tonic-gate 		if (mdb_walk_dcmd("genunix`queue_cache", "genunix`queue",
3717c478bd9Sstevel@tonic-gate 		    argc, argv) == -1) {
3727c478bd9Sstevel@tonic-gate 			mdb_warn("failed to walk queue cache");
3737c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
3747c478bd9Sstevel@tonic-gate 		}
3757c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
3767c478bd9Sstevel@tonic-gate 	}
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	if (flags & DCMD_PIPE_OUT)
3797c478bd9Sstevel@tonic-gate 		quiet = TRUE;
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
3827c478bd9Sstevel@tonic-gate 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
3837c478bd9Sstevel@tonic-gate 	    'q', MDB_OPT_SETBITS, TRUE, &quiet,
3847c478bd9Sstevel@tonic-gate 	    'm', MDB_OPT_STR, &mod,
3857c478bd9Sstevel@tonic-gate 	    'f', MDB_OPT_STR, &flag,
3867c478bd9Sstevel@tonic-gate 	    'F', MDB_OPT_STR, &not_flag,
3877c478bd9Sstevel@tonic-gate 	    's', MDB_OPT_UINTPTR, &syncq,
3887c478bd9Sstevel@tonic-gate 	    NULL) != argc)
3897c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 	/*
3927c478bd9Sstevel@tonic-gate 	 * If any of the filtering flags is specified, don't print anything
3937c478bd9Sstevel@tonic-gate 	 * except the matching pointer.
3947c478bd9Sstevel@tonic-gate 	 */
395892ad162SToomas Soome 	if (flag != NULL || not_flag != NULL || mod != NULL || syncq != 0)
3967c478bd9Sstevel@tonic-gate 		quiet = TRUE;
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags) && !quiet) {
3997c478bd9Sstevel@tonic-gate 		mdb_printf("%?s %-13s %6s %4s\n",
4007c478bd9Sstevel@tonic-gate 		    "ADDR", "MODULE", "FLAGS", "NBLK");
4017c478bd9Sstevel@tonic-gate 	}
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	if (flag != NULL && streams_parse_flag(qf, flag, &mask) == -1) {
4047c478bd9Sstevel@tonic-gate 		mdb_warn("unrecognized queue flag '%s'\n", flag);
4057c478bd9Sstevel@tonic-gate 		streams_flag_usage(qf);
4067c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
4077c478bd9Sstevel@tonic-gate 	}
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	if (not_flag != NULL &&
4107c478bd9Sstevel@tonic-gate 	    streams_parse_flag(qf, not_flag, &not_mask) == -1) {
4117c478bd9Sstevel@tonic-gate 		mdb_warn("unrecognized queue flag '%s'\n", flag);
4127c478bd9Sstevel@tonic-gate 		streams_flag_usage(qf);
4137c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
4147c478bd9Sstevel@tonic-gate 	}
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 	if (mdb_vread(&q, sizeof (q), addr) == -1) {
4177c478bd9Sstevel@tonic-gate 		mdb_warn("couldn't read queue at %p", addr);
4187c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
4197c478bd9Sstevel@tonic-gate 	}
4207c478bd9Sstevel@tonic-gate 
421892ad162SToomas Soome 	for (maddr = (uintptr_t)q.q_first; maddr != 0; nblks++) {
4227c478bd9Sstevel@tonic-gate 		if (mdb_vread(&mblk, sizeof (mblk), maddr) == -1) {
4237c478bd9Sstevel@tonic-gate 			mdb_warn("couldn't read mblk %p for queue %p",
4247c478bd9Sstevel@tonic-gate 			    maddr, addr);
4257c478bd9Sstevel@tonic-gate 			break;
4267c478bd9Sstevel@tonic-gate 		}
4277c478bd9Sstevel@tonic-gate 		maddr = (uintptr_t)mblk.b_next;
4287c478bd9Sstevel@tonic-gate 	}
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	(void) mdb_qname(&q, name, sizeof (name));
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	/*
4337c478bd9Sstevel@tonic-gate 	 * If queue doesn't pass filtering criteria, don't print anything and
4347c478bd9Sstevel@tonic-gate 	 * just return.
4357c478bd9Sstevel@tonic-gate 	 */
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 	if (mod != NULL && strcmp(mod, name) != 0)
4387c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	if (mask != 0 && !(q.q_flag & mask))
4417c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	if (not_mask != 0 && (q.q_flag & not_mask))
4447c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	if (syncq != 0 && q.q_syncq != (syncq_t *)syncq)
4477c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	/*
4507c478bd9Sstevel@tonic-gate 	 * Options are specified for filtering, so If any option is specified on
4517c478bd9Sstevel@tonic-gate 	 * the command line, just print address and exit.
4527c478bd9Sstevel@tonic-gate 	 */
4537c478bd9Sstevel@tonic-gate 	if (quiet) {
4547c478bd9Sstevel@tonic-gate 		mdb_printf("%0?p\n", addr);
4557c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
4567c478bd9Sstevel@tonic-gate 	}
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	mdb_printf("%0?p %-13s %06x %4d %0?p\n",
4597c478bd9Sstevel@tonic-gate 	    addr, name, q.q_flag, nblks, q.q_first);
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 	if (verbose) {
4627c478bd9Sstevel@tonic-gate 		int i, arm = 0;
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 		for (i = 0; qf[i].strf_name != NULL; i++) {
4657c478bd9Sstevel@tonic-gate 			if (!(q.q_flag & (1 << i)))
4667c478bd9Sstevel@tonic-gate 				continue;
4677c478bd9Sstevel@tonic-gate 			if (!arm) {
4687c478bd9Sstevel@tonic-gate 				mdb_printf("%*s|\n%*s+-->  ",
4697c478bd9Sstevel@tonic-gate 				    QUEUE_FLGDELT, "", QUEUE_FLGDELT, "");
4707c478bd9Sstevel@tonic-gate 				arm = 1;
4717c478bd9Sstevel@tonic-gate 			} else
4727c478bd9Sstevel@tonic-gate 				mdb_printf("%*s      ", QUEUE_FLGDELT, "");
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 			mdb_printf("%-12s %s\n",
4757c478bd9Sstevel@tonic-gate 			    qf[i].strf_name, qf[i].strf_descr);
4767c478bd9Sstevel@tonic-gate 		}
4777c478bd9Sstevel@tonic-gate 	}
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
4807c478bd9Sstevel@tonic-gate }
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate int
syncq(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)4837c478bd9Sstevel@tonic-gate syncq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
4847c478bd9Sstevel@tonic-gate {
4857c478bd9Sstevel@tonic-gate 	const int SYNC_FLGDELT = (int)(sizeof (uintptr_t) * 2 + 1);
4867c478bd9Sstevel@tonic-gate 	const int SYNC_TYPDELT = (int)(sizeof (uintptr_t) * 2 + 5);
4877c478bd9Sstevel@tonic-gate 	syncq_t sq;
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 	const char *flag = NULL, *not_flag = NULL;
4907c478bd9Sstevel@tonic-gate 	const char *typ = NULL, *not_typ = NULL;
4917c478bd9Sstevel@tonic-gate 	uint_t verbose = FALSE;
4927c478bd9Sstevel@tonic-gate 	uint_t quiet = FALSE;
4937c478bd9Sstevel@tonic-gate 	uint32_t mask = 0, not_mask = 0;
4947c478bd9Sstevel@tonic-gate 	uint32_t tmask = 0, not_tmask = 0;
4957c478bd9Sstevel@tonic-gate 	uint8_t sqtype = 0;
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
4987c478bd9Sstevel@tonic-gate 		if (mdb_walk_dcmd("genunix`syncq_cache", "genunix`syncq",
4997c478bd9Sstevel@tonic-gate 		    argc, argv) == -1) {
5007c478bd9Sstevel@tonic-gate 			mdb_warn("failed to walk syncq cache");
5017c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
5027c478bd9Sstevel@tonic-gate 		}
5037c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
5047c478bd9Sstevel@tonic-gate 	}
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 	if (flags & DCMD_PIPE_OUT)
5077c478bd9Sstevel@tonic-gate 		quiet = TRUE;
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
5107c478bd9Sstevel@tonic-gate 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
5117c478bd9Sstevel@tonic-gate 	    'q', MDB_OPT_SETBITS, TRUE, &quiet,
5127c478bd9Sstevel@tonic-gate 	    'f', MDB_OPT_STR, &flag,
5137c478bd9Sstevel@tonic-gate 	    'F', MDB_OPT_STR, &not_flag,
5147c478bd9Sstevel@tonic-gate 	    't', MDB_OPT_STR, &typ,
5157c478bd9Sstevel@tonic-gate 	    'T', MDB_OPT_STR, &not_typ,
5167c478bd9Sstevel@tonic-gate 	    NULL) != argc)
5177c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 	/*
5207c478bd9Sstevel@tonic-gate 	 * If any of the filtering flags is specified, don't print anything
5217c478bd9Sstevel@tonic-gate 	 * except the matching pointer.
5227c478bd9Sstevel@tonic-gate 	 */
5237c478bd9Sstevel@tonic-gate 	if (flag != NULL || not_flag != NULL || typ != NULL || not_typ != NULL)
5247c478bd9Sstevel@tonic-gate 		quiet = TRUE;
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags) && !quiet) {
5277c478bd9Sstevel@tonic-gate 		mdb_printf("%?s %s %s %s %s %?s %s %s\n",
5287c478bd9Sstevel@tonic-gate 		    "ADDR", "FLG", "TYP", "CNT", "NQS", "OUTER", "SF", "PRI");
5297c478bd9Sstevel@tonic-gate 	}
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 	if (flag != NULL && streams_parse_flag(sqf, flag, &mask) == -1) {
5327c478bd9Sstevel@tonic-gate 		mdb_warn("unrecognized syncq flag '%s'\n", flag);
5337c478bd9Sstevel@tonic-gate 		streams_flag_usage(sqf);
5347c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
5357c478bd9Sstevel@tonic-gate 	}
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	if (typ != NULL && streams_parse_flag(sqt, typ, &tmask) == -1) {
5387c478bd9Sstevel@tonic-gate 		mdb_warn("unrecognized syncq type '%s'\n", typ);
5397c478bd9Sstevel@tonic-gate 		streams_flag_usage(sqt);
5407c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
5417c478bd9Sstevel@tonic-gate 	}
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 	if (not_flag != NULL && streams_parse_flag(sqf, not_flag, &not_mask)
5447c478bd9Sstevel@tonic-gate 	    == -1) {
5457c478bd9Sstevel@tonic-gate 		mdb_warn("unrecognized syncq flag '%s'\n", not_flag);
5467c478bd9Sstevel@tonic-gate 		streams_flag_usage(sqf);
5477c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
5487c478bd9Sstevel@tonic-gate 	}
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	if (not_typ != NULL && streams_parse_flag(sqt, not_typ, &not_tmask)
5517c478bd9Sstevel@tonic-gate 	    == -1) {
5527c478bd9Sstevel@tonic-gate 		mdb_warn("unrecognized syncq type '%s'\n", not_typ);
5537c478bd9Sstevel@tonic-gate 		streams_flag_usage(sqt);
5547c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
5557c478bd9Sstevel@tonic-gate 	}
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate 	if (mdb_vread(&sq, sizeof (sq), addr) == -1) {
5587c478bd9Sstevel@tonic-gate 		mdb_warn("couldn't read syncq at %p", addr);
5597c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
5607c478bd9Sstevel@tonic-gate 	}
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate 	if (mask != 0 && !(sq.sq_flags & mask))
5637c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 	if (not_mask != 0 && (sq.sq_flags & not_mask))
5667c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 	sqtype = (sq.sq_type >> 8) & 0xff;
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate 	if (tmask != 0 && !(sqtype & tmask))
5717c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate 	if (not_tmask != 0 && (sqtype & not_tmask))
5747c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 	/*
5777c478bd9Sstevel@tonic-gate 	 * Options are specified for filtering, so If any option is specified on
5787c478bd9Sstevel@tonic-gate 	 * the command line, just print address and exit.
5797c478bd9Sstevel@tonic-gate 	 */
5807c478bd9Sstevel@tonic-gate 	if (quiet) {
5817c478bd9Sstevel@tonic-gate 		mdb_printf("%0?p\n", addr);
5827c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
5837c478bd9Sstevel@tonic-gate 	}
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate 	mdb_printf("%0?p %02x  %02x  %-3u %-3u %0?p  %1x %-3d\n",
5867c478bd9Sstevel@tonic-gate 	    addr, sq.sq_flags & 0xff, sqtype, sq.sq_count,
5877c478bd9Sstevel@tonic-gate 	    sq.sq_nqueues, sq.sq_outer, sq.sq_svcflags, sq.sq_pri);
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 	if (verbose) {
5907c478bd9Sstevel@tonic-gate 		int i, arm = 0;
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 		for (i = 0; sqf[i].strf_name != NULL; i++) {
5937c478bd9Sstevel@tonic-gate 			if (!(sq.sq_flags & (1 << i)))
5947c478bd9Sstevel@tonic-gate 				continue;
5957c478bd9Sstevel@tonic-gate 			if (!arm) {
5967c478bd9Sstevel@tonic-gate 				mdb_printf("%*s|\n%*s+-->  ",
5977c478bd9Sstevel@tonic-gate 				    SYNC_FLGDELT, "", SYNC_FLGDELT, "");
5987c478bd9Sstevel@tonic-gate 				arm = 1;
5997c478bd9Sstevel@tonic-gate 			} else
6007c478bd9Sstevel@tonic-gate 				mdb_printf("%*s      ", SYNC_FLGDELT, "");
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 			mdb_printf("%-12s %s\n",
6037c478bd9Sstevel@tonic-gate 			    sqf[i].strf_name, sqf[i].strf_descr);
6047c478bd9Sstevel@tonic-gate 		}
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 		for (i = 0; sqt[i].strf_name != NULL; i++) {
6077c478bd9Sstevel@tonic-gate 			if (!(sqtype & (1 << i)))
6087c478bd9Sstevel@tonic-gate 				continue;
6097c478bd9Sstevel@tonic-gate 			if (!arm) {
6107c478bd9Sstevel@tonic-gate 				mdb_printf("%*s|\n%*s+-->  ",
6117c478bd9Sstevel@tonic-gate 				    SYNC_TYPDELT, "", SYNC_TYPDELT, "");
6127c478bd9Sstevel@tonic-gate 				arm = 1;
6137c478bd9Sstevel@tonic-gate 			} else
6147c478bd9Sstevel@tonic-gate 				mdb_printf("%*s      ", SYNC_TYPDELT, "");
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 			mdb_printf("%-12s %s\n",
6177c478bd9Sstevel@tonic-gate 			    sqt[i].strf_name, sqt[i].strf_descr);
6187c478bd9Sstevel@tonic-gate 		}
6197c478bd9Sstevel@tonic-gate 	}
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
6227c478bd9Sstevel@tonic-gate }
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate int
stdata(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)6257c478bd9Sstevel@tonic-gate stdata(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
6267c478bd9Sstevel@tonic-gate {
6277c478bd9Sstevel@tonic-gate 	const int STREAM_FLGDELT = (int)(sizeof (uintptr_t) * 2 + 10);
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 	stdata_t  sd;
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 	const char *flag = NULL, *not_flag = NULL;
6327c478bd9Sstevel@tonic-gate 	uint_t verbose = FALSE;
6337c478bd9Sstevel@tonic-gate 	uint_t quiet = FALSE;
6347c478bd9Sstevel@tonic-gate 	uint32_t mask = 0, not_mask = 0;
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
6377c478bd9Sstevel@tonic-gate 		if (mdb_walk_dcmd("genunix`stream_head_cache",
6387c478bd9Sstevel@tonic-gate 		    "genunix`stdata", argc, argv) == -1) {
6397c478bd9Sstevel@tonic-gate 			mdb_warn("failed to walk stream head cache");
6407c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
6417c478bd9Sstevel@tonic-gate 		}
6427c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
6437c478bd9Sstevel@tonic-gate 	}
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 	if (flags & DCMD_PIPE_OUT)
6467c478bd9Sstevel@tonic-gate 		quiet = TRUE;
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
6497c478bd9Sstevel@tonic-gate 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
6507c478bd9Sstevel@tonic-gate 	    'q', MDB_OPT_SETBITS, TRUE, &quiet,
6517c478bd9Sstevel@tonic-gate 	    'f', MDB_OPT_STR, &flag,
6527c478bd9Sstevel@tonic-gate 	    'F', MDB_OPT_STR, &not_flag,
6537c478bd9Sstevel@tonic-gate 	    NULL) != argc)
6547c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate 	/*
6577c478bd9Sstevel@tonic-gate 	 * If any of the filtering flags is specified, don't print anything
6587c478bd9Sstevel@tonic-gate 	 * except the matching pointer.
6597c478bd9Sstevel@tonic-gate 	 */
6607c478bd9Sstevel@tonic-gate 	if (flag != NULL || not_flag != NULL)
6617c478bd9Sstevel@tonic-gate 		quiet = TRUE;
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags) && !quiet) {
6647c478bd9Sstevel@tonic-gate 		mdb_printf("%?s %?s %8s %?s %s %s\n",
6657c478bd9Sstevel@tonic-gate 		    "ADDR", "WRQ", "FLAGS", "VNODE", "N/A", "REF");
6667c478bd9Sstevel@tonic-gate 	}
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 	if (flag != NULL && streams_parse_flag(stdf, flag, &mask) == -1) {
6697c478bd9Sstevel@tonic-gate 		mdb_warn("unrecognized stream flag '%s'\n", flag);
6707c478bd9Sstevel@tonic-gate 		streams_flag_usage(stdf);
6717c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
6727c478bd9Sstevel@tonic-gate 	}
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate 	if (not_flag != NULL &&
6757c478bd9Sstevel@tonic-gate 	    streams_parse_flag(stdf, not_flag, &not_mask) == -1) {
6767c478bd9Sstevel@tonic-gate 		mdb_warn("unrecognized stream flag '%s'\n", flag);
6777c478bd9Sstevel@tonic-gate 		streams_flag_usage(stdf);
6787c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
6797c478bd9Sstevel@tonic-gate 	}
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 	if (mdb_vread(&sd, sizeof (sd), addr) == -1) {
6827c478bd9Sstevel@tonic-gate 		mdb_warn("couldn't read stdata at %p", addr);
6837c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
6847c478bd9Sstevel@tonic-gate 	}
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 	/*
6877c478bd9Sstevel@tonic-gate 	 * If stream doesn't pass filtering criteria, don't print anything and
6887c478bd9Sstevel@tonic-gate 	 * just return.
6897c478bd9Sstevel@tonic-gate 	 */
6907c478bd9Sstevel@tonic-gate 
6917c478bd9Sstevel@tonic-gate 	if (mask != 0 && !(sd.sd_flag & mask))
6927c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 	if (not_mask != 0 && (sd.sd_flag & not_mask))
6957c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate 	/*
6987c478bd9Sstevel@tonic-gate 	 * Options are specified for filtering, so If any option is specified on
6997c478bd9Sstevel@tonic-gate 	 * the command line, just print address and exit.
7007c478bd9Sstevel@tonic-gate 	 */
7017c478bd9Sstevel@tonic-gate 	if (quiet) {
7027c478bd9Sstevel@tonic-gate 		mdb_printf("%0?p\n", addr);
7037c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
7047c478bd9Sstevel@tonic-gate 	}
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 	mdb_printf("%0?p %0?p %08x %0?p %d/%d %d\n",
7077c478bd9Sstevel@tonic-gate 	    addr, sd.sd_wrq, sd.sd_flag, sd.sd_vnode,
7087c478bd9Sstevel@tonic-gate 	    sd.sd_pushcnt, sd.sd_anchor, sd.sd_refcnt);
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate 	if (verbose) {
7117c478bd9Sstevel@tonic-gate 		int i, arm = 0;
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate 		for (i = 0; stdf[i].strf_name != NULL; i++) {
7147c478bd9Sstevel@tonic-gate 			if (!(sd.sd_flag & (1 << i)))
7157c478bd9Sstevel@tonic-gate 				continue;
7167c478bd9Sstevel@tonic-gate 			if (!arm) {
7177c478bd9Sstevel@tonic-gate 				mdb_printf("%*s|\n%*s+-->  ",
7187c478bd9Sstevel@tonic-gate 				    STREAM_FLGDELT, "", STREAM_FLGDELT, "");
7197c478bd9Sstevel@tonic-gate 				arm = 1;
7207c478bd9Sstevel@tonic-gate 			} else
7217c478bd9Sstevel@tonic-gate 				mdb_printf("%*s      ", STREAM_FLGDELT, "");
7227c478bd9Sstevel@tonic-gate 
7237c478bd9Sstevel@tonic-gate 			mdb_printf("%-12s %s\n",
7247c478bd9Sstevel@tonic-gate 			    stdf[i].strf_name, stdf[i].strf_descr);
7257c478bd9Sstevel@tonic-gate 		}
7267c478bd9Sstevel@tonic-gate 	}
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
7297c478bd9Sstevel@tonic-gate }
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7327c478bd9Sstevel@tonic-gate static void
qprint_syncq(queue_t * addr,queue_t * q)7337c478bd9Sstevel@tonic-gate qprint_syncq(queue_t *addr, queue_t *q)
7347c478bd9Sstevel@tonic-gate {
7357c478bd9Sstevel@tonic-gate 	mdb_printf("%p\n", q->q_syncq);
7367c478bd9Sstevel@tonic-gate }
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7397c478bd9Sstevel@tonic-gate static void
qprint_stream(queue_t * addr,queue_t * q)7407c478bd9Sstevel@tonic-gate qprint_stream(queue_t *addr, queue_t *q)
7417c478bd9Sstevel@tonic-gate {
7427c478bd9Sstevel@tonic-gate 	mdb_printf("%p\n", q->q_stream);
7437c478bd9Sstevel@tonic-gate }
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate static void
qprint_wrq(queue_t * addr,queue_t * q)7467c478bd9Sstevel@tonic-gate qprint_wrq(queue_t *addr, queue_t *q)
7477c478bd9Sstevel@tonic-gate {
7487c478bd9Sstevel@tonic-gate 	mdb_printf("%p\n", ((q)->q_flag & QREADR? (addr)+1: (addr)));
7497c478bd9Sstevel@tonic-gate }
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate static void
qprint_rdq(queue_t * addr,queue_t * q)7527c478bd9Sstevel@tonic-gate qprint_rdq(queue_t *addr, queue_t *q)
7537c478bd9Sstevel@tonic-gate {
7547c478bd9Sstevel@tonic-gate 	mdb_printf("%p\n", ((q)->q_flag & QREADR? (addr): (addr)-1));
7557c478bd9Sstevel@tonic-gate }
7567c478bd9Sstevel@tonic-gate 
7577c478bd9Sstevel@tonic-gate static void
qprint_otherq(queue_t * addr,queue_t * q)7587c478bd9Sstevel@tonic-gate qprint_otherq(queue_t *addr, queue_t *q)
7597c478bd9Sstevel@tonic-gate {
7607c478bd9Sstevel@tonic-gate 	mdb_printf("%p\n", ((q)->q_flag & QREADR? (addr)+1: (addr)-1));
7617c478bd9Sstevel@tonic-gate }
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate static int
q2x(uintptr_t addr,int argc,qprint_func prfunc)7647c478bd9Sstevel@tonic-gate q2x(uintptr_t addr, int argc, qprint_func prfunc)
7657c478bd9Sstevel@tonic-gate {
7667c478bd9Sstevel@tonic-gate 	queue_t q;
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate 	if (argc != 0)
7697c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate 	if (mdb_vread(&q, sizeof (q), addr) == -1) {
7727c478bd9Sstevel@tonic-gate 		mdb_warn("couldn't read queue at %p", addr);
7737c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
7747c478bd9Sstevel@tonic-gate 	}
7757c478bd9Sstevel@tonic-gate 
7767c478bd9Sstevel@tonic-gate 	prfunc((queue_t *)addr, &q);
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
7797c478bd9Sstevel@tonic-gate }
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7827c478bd9Sstevel@tonic-gate int
q2syncq(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)7837c478bd9Sstevel@tonic-gate q2syncq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
7847c478bd9Sstevel@tonic-gate {
7857c478bd9Sstevel@tonic-gate 	return (q2x(addr, argc, qprint_syncq));
7867c478bd9Sstevel@tonic-gate }
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7897c478bd9Sstevel@tonic-gate int
q2stream(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)7907c478bd9Sstevel@tonic-gate q2stream(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
7917c478bd9Sstevel@tonic-gate {
7927c478bd9Sstevel@tonic-gate 	return (q2x(addr, argc, qprint_stream));
7937c478bd9Sstevel@tonic-gate }
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7967c478bd9Sstevel@tonic-gate int
q2rdq(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)7977c478bd9Sstevel@tonic-gate q2rdq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
7987c478bd9Sstevel@tonic-gate {
7997c478bd9Sstevel@tonic-gate 	return (q2x(addr, argc, qprint_rdq));
8007c478bd9Sstevel@tonic-gate }
8017c478bd9Sstevel@tonic-gate 
8027c478bd9Sstevel@tonic-gate /*ARGSUSED*/
8037c478bd9Sstevel@tonic-gate int
q2wrq(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)8047c478bd9Sstevel@tonic-gate q2wrq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
8057c478bd9Sstevel@tonic-gate {
8067c478bd9Sstevel@tonic-gate 	return (q2x(addr, argc, qprint_wrq));
8077c478bd9Sstevel@tonic-gate }
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate /*ARGSUSED*/
8107c478bd9Sstevel@tonic-gate int
q2otherq(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)8117c478bd9Sstevel@tonic-gate q2otherq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
8127c478bd9Sstevel@tonic-gate {
8137c478bd9Sstevel@tonic-gate 	return (q2x(addr, argc, qprint_otherq));
8147c478bd9Sstevel@tonic-gate }
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate static int
sd2x(uintptr_t addr,int argc,sdprint_func prfunc)8177c478bd9Sstevel@tonic-gate sd2x(uintptr_t addr, int argc, sdprint_func prfunc)
8187c478bd9Sstevel@tonic-gate {
8197c478bd9Sstevel@tonic-gate 	stdata_t sd;
8207c478bd9Sstevel@tonic-gate 
8217c478bd9Sstevel@tonic-gate 	if (argc != 0)
8227c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate 	if (mdb_vread(&sd, sizeof (sd), addr) == -1) {
8257c478bd9Sstevel@tonic-gate 		mdb_warn("couldn't read stream head at %p", addr);
8267c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
8277c478bd9Sstevel@tonic-gate 	}
8287c478bd9Sstevel@tonic-gate 
8297c478bd9Sstevel@tonic-gate 	prfunc((stdata_t *)addr, &sd);
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
8327c478bd9Sstevel@tonic-gate }
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate /*ARGSUSED*/
8357c478bd9Sstevel@tonic-gate static void
sdprint_wrq(stdata_t * addr,stdata_t * sd)8367c478bd9Sstevel@tonic-gate sdprint_wrq(stdata_t *addr, stdata_t *sd)
8377c478bd9Sstevel@tonic-gate {
8387c478bd9Sstevel@tonic-gate 	mdb_printf("%p\n", sd->sd_wrq);
8397c478bd9Sstevel@tonic-gate }
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate static void
sdprint_mate(stdata_t * addr,stdata_t * sd)8427c478bd9Sstevel@tonic-gate sdprint_mate(stdata_t *addr, stdata_t *sd)
8437c478bd9Sstevel@tonic-gate {
8447c478bd9Sstevel@tonic-gate 	mdb_printf("%p\n", sd->sd_mate ? sd->sd_mate : addr);
8457c478bd9Sstevel@tonic-gate }
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate /*ARGSUSED*/
8487c478bd9Sstevel@tonic-gate int
str2mate(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)8497c478bd9Sstevel@tonic-gate str2mate(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
8507c478bd9Sstevel@tonic-gate {
8517c478bd9Sstevel@tonic-gate 	return (sd2x(addr, argc, sdprint_mate));
8527c478bd9Sstevel@tonic-gate }
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate /*ARGSUSED*/
8557c478bd9Sstevel@tonic-gate int
str2wrq(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)8567c478bd9Sstevel@tonic-gate str2wrq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
8577c478bd9Sstevel@tonic-gate {
8587c478bd9Sstevel@tonic-gate 	return (sd2x(addr, argc, sdprint_wrq));
8597c478bd9Sstevel@tonic-gate }
8607c478bd9Sstevel@tonic-gate 
8617c478bd9Sstevel@tonic-gate /*
8627c478bd9Sstevel@tonic-gate  * If this syncq is a part of the queue pair structure, find the queue for it.
8637c478bd9Sstevel@tonic-gate  */
8647c478bd9Sstevel@tonic-gate /*ARGSUSED*/
8657c478bd9Sstevel@tonic-gate int
syncq2q(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)8667c478bd9Sstevel@tonic-gate syncq2q(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
8677c478bd9Sstevel@tonic-gate {
8687c478bd9Sstevel@tonic-gate 	syncq_t sq;
8697c478bd9Sstevel@tonic-gate 	queue_t q;
8707c478bd9Sstevel@tonic-gate 	queue_t *qp;
8717c478bd9Sstevel@tonic-gate 
8727c478bd9Sstevel@tonic-gate 	if (argc != 0)
8737c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate 	if (mdb_vread(&sq, sizeof (sq), addr) == -1) {
8767c478bd9Sstevel@tonic-gate 		mdb_warn("couldn't read syncq at %p", addr);
8777c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
8787c478bd9Sstevel@tonic-gate 	}
8797c478bd9Sstevel@tonic-gate 
8807c478bd9Sstevel@tonic-gate 	/* Try to find its queue */
8817c478bd9Sstevel@tonic-gate 	qp = (queue_t *)addr - 2;
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate 	if ((mdb_vread(&q, sizeof (q), (uintptr_t)qp) == -1) ||
8847c478bd9Sstevel@tonic-gate 	    (q.q_syncq != (syncq_t *)addr)) {
8857c478bd9Sstevel@tonic-gate 		mdb_warn("syncq2q: %p is not part of any queue\n", addr);
8867c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
8877c478bd9Sstevel@tonic-gate 	} else
8887c478bd9Sstevel@tonic-gate 		mdb_printf("%p\n", qp);
8897c478bd9Sstevel@tonic-gate 
8907c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
8917c478bd9Sstevel@tonic-gate }
8927c478bd9Sstevel@tonic-gate 
8937c478bd9Sstevel@tonic-gate int
queue_walk_init(mdb_walk_state_t * wsp)8947c478bd9Sstevel@tonic-gate queue_walk_init(mdb_walk_state_t *wsp)
8957c478bd9Sstevel@tonic-gate {
896892ad162SToomas Soome 	if (wsp->walk_addr == 0 &&
8977c478bd9Sstevel@tonic-gate 	    mdb_readvar(&wsp->walk_addr, "qhead") == -1) {
8987c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read 'qhead'");
8997c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
9007c478bd9Sstevel@tonic-gate 	}
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate 	wsp->walk_data = mdb_alloc(sizeof (queue_t), UM_SLEEP);
9037c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
9047c478bd9Sstevel@tonic-gate }
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate int
queue_link_step(mdb_walk_state_t * wsp)9077c478bd9Sstevel@tonic-gate queue_link_step(mdb_walk_state_t *wsp)
9087c478bd9Sstevel@tonic-gate {
9097c478bd9Sstevel@tonic-gate 	int status;
9107c478bd9Sstevel@tonic-gate 
911892ad162SToomas Soome 	if (wsp->walk_addr == 0)
9127c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
9137c478bd9Sstevel@tonic-gate 
9147c478bd9Sstevel@tonic-gate 	if (mdb_vread(wsp->walk_data, sizeof (queue_t), wsp->walk_addr) == -1) {
9157c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read queue at %p", wsp->walk_addr);
9167c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
9177c478bd9Sstevel@tonic-gate 	}
9187c478bd9Sstevel@tonic-gate 
9197c478bd9Sstevel@tonic-gate 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
9207c478bd9Sstevel@tonic-gate 	    wsp->walk_cbdata);
9217c478bd9Sstevel@tonic-gate 
9227c478bd9Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)(((queue_t *)wsp->walk_data)->q_link);
9237c478bd9Sstevel@tonic-gate 	return (status);
9247c478bd9Sstevel@tonic-gate }
9257c478bd9Sstevel@tonic-gate 
9267c478bd9Sstevel@tonic-gate int
queue_next_step(mdb_walk_state_t * wsp)9277c478bd9Sstevel@tonic-gate queue_next_step(mdb_walk_state_t *wsp)
9287c478bd9Sstevel@tonic-gate {
9297c478bd9Sstevel@tonic-gate 	int status;
9307c478bd9Sstevel@tonic-gate 
931892ad162SToomas Soome 	if (wsp->walk_addr == 0)
9327c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate 	if (mdb_vread(wsp->walk_data, sizeof (queue_t), wsp->walk_addr) == -1) {
9357c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read queue at %p", wsp->walk_addr);
9367c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
9377c478bd9Sstevel@tonic-gate 	}
9387c478bd9Sstevel@tonic-gate 
9397c478bd9Sstevel@tonic-gate 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
9407c478bd9Sstevel@tonic-gate 	    wsp->walk_cbdata);
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)(((queue_t *)wsp->walk_data)->q_next);
9437c478bd9Sstevel@tonic-gate 	return (status);
9447c478bd9Sstevel@tonic-gate }
9457c478bd9Sstevel@tonic-gate 
9467c478bd9Sstevel@tonic-gate void
queue_walk_fini(mdb_walk_state_t * wsp)9477c478bd9Sstevel@tonic-gate queue_walk_fini(mdb_walk_state_t *wsp)
9487c478bd9Sstevel@tonic-gate {
9497c478bd9Sstevel@tonic-gate 	mdb_free(wsp->walk_data, sizeof (queue_t));
9507c478bd9Sstevel@tonic-gate }
9517c478bd9Sstevel@tonic-gate 
9527c478bd9Sstevel@tonic-gate int
str_walk_init(mdb_walk_state_t * wsp)9537c478bd9Sstevel@tonic-gate str_walk_init(mdb_walk_state_t *wsp)
9547c478bd9Sstevel@tonic-gate {
9557c478bd9Sstevel@tonic-gate 	stdata_t s;
9567c478bd9Sstevel@tonic-gate 
957892ad162SToomas Soome 	if (wsp->walk_addr == 0) {
9587c478bd9Sstevel@tonic-gate 		mdb_warn("walk must begin at address of stdata_t\n");
9597c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
9607c478bd9Sstevel@tonic-gate 	}
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate 	if (mdb_vread(&s, sizeof (s), wsp->walk_addr) == -1) {
9637c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read stdata at %p", wsp->walk_addr);
9647c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
9657c478bd9Sstevel@tonic-gate 	}
9667c478bd9Sstevel@tonic-gate 
9677c478bd9Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)s.sd_wrq;
9687c478bd9Sstevel@tonic-gate 	wsp->walk_data = mdb_alloc(sizeof (queue_t) * 2, UM_SLEEP);
9697c478bd9Sstevel@tonic-gate 
9707c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
9717c478bd9Sstevel@tonic-gate }
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate int
strr_walk_step(mdb_walk_state_t * wsp)9747c478bd9Sstevel@tonic-gate strr_walk_step(mdb_walk_state_t *wsp)
9757c478bd9Sstevel@tonic-gate {
9767c478bd9Sstevel@tonic-gate 	queue_t *rq = wsp->walk_data, *wq = rq + 1;
9777c478bd9Sstevel@tonic-gate 	int status;
9787c478bd9Sstevel@tonic-gate 
979892ad162SToomas Soome 	if (wsp->walk_addr == 0)
9807c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate 	if (mdb_vread(wsp->walk_data, sizeof (queue_t) * 2,
9837c478bd9Sstevel@tonic-gate 	    wsp->walk_addr - sizeof (queue_t)) == -1) {
9847c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read queue pair at %p",
9857c478bd9Sstevel@tonic-gate 		    wsp->walk_addr - sizeof (queue_t));
9867c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
9877c478bd9Sstevel@tonic-gate 	}
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate 	status = wsp->walk_callback(wsp->walk_addr - sizeof (queue_t),
9907c478bd9Sstevel@tonic-gate 	    rq, wsp->walk_cbdata);
9917c478bd9Sstevel@tonic-gate 
9927c478bd9Sstevel@tonic-gate 	if (wq->q_next != NULL)
9937c478bd9Sstevel@tonic-gate 		wsp->walk_addr = (uintptr_t)wq->q_next;
9947c478bd9Sstevel@tonic-gate 	else
9957c478bd9Sstevel@tonic-gate 		wsp->walk_addr = mdb_qwnext(wq);
9967c478bd9Sstevel@tonic-gate 
9977c478bd9Sstevel@tonic-gate 	return (status);
9987c478bd9Sstevel@tonic-gate }
9997c478bd9Sstevel@tonic-gate 
10007c478bd9Sstevel@tonic-gate int
strw_walk_step(mdb_walk_state_t * wsp)10017c478bd9Sstevel@tonic-gate strw_walk_step(mdb_walk_state_t *wsp)
10027c478bd9Sstevel@tonic-gate {
10037c478bd9Sstevel@tonic-gate 	queue_t *rq = wsp->walk_data, *wq = rq + 1;
10047c478bd9Sstevel@tonic-gate 	int status;
10057c478bd9Sstevel@tonic-gate 
1006892ad162SToomas Soome 	if (wsp->walk_addr == 0)
10077c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
10087c478bd9Sstevel@tonic-gate 
10097c478bd9Sstevel@tonic-gate 	if (mdb_vread(wsp->walk_data, sizeof (queue_t) * 2,
10107c478bd9Sstevel@tonic-gate 	    wsp->walk_addr - sizeof (queue_t)) == -1) {
10117c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read queue pair at %p",
10127c478bd9Sstevel@tonic-gate 		    wsp->walk_addr - sizeof (queue_t));
10137c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
10147c478bd9Sstevel@tonic-gate 	}
10157c478bd9Sstevel@tonic-gate 
10167c478bd9Sstevel@tonic-gate 	status = wsp->walk_callback(wsp->walk_addr, wq, wsp->walk_cbdata);
10177c478bd9Sstevel@tonic-gate 
10187c478bd9Sstevel@tonic-gate 	if (wq->q_next != NULL)
10197c478bd9Sstevel@tonic-gate 		wsp->walk_addr = (uintptr_t)wq->q_next;
10207c478bd9Sstevel@tonic-gate 	else
10217c478bd9Sstevel@tonic-gate 		wsp->walk_addr = mdb_qwnext(wq);
10227c478bd9Sstevel@tonic-gate 
10237c478bd9Sstevel@tonic-gate 	return (status);
10247c478bd9Sstevel@tonic-gate }
10257c478bd9Sstevel@tonic-gate 
10267c478bd9Sstevel@tonic-gate void
str_walk_fini(mdb_walk_state_t * wsp)10277c478bd9Sstevel@tonic-gate str_walk_fini(mdb_walk_state_t *wsp)
10287c478bd9Sstevel@tonic-gate {
10297c478bd9Sstevel@tonic-gate 	mdb_free(wsp->walk_data, sizeof (queue_t) * 2);
10307c478bd9Sstevel@tonic-gate }
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate static int
print_qpair(uintptr_t addr,const queue_t * q,uint_t * depth)10337c478bd9Sstevel@tonic-gate print_qpair(uintptr_t addr, const queue_t *q, uint_t *depth)
10347c478bd9Sstevel@tonic-gate {
10357c478bd9Sstevel@tonic-gate 	static const char box_lid[] =
10367c478bd9Sstevel@tonic-gate 	    "+-----------------------+-----------------------+\n";
10377c478bd9Sstevel@tonic-gate 	static const char box_sep[] =
10387c478bd9Sstevel@tonic-gate 	    "|                       |                       |\n";
10397c478bd9Sstevel@tonic-gate 
10407c478bd9Sstevel@tonic-gate 	char wname[32], rname[32], info1[256], *info2;
10417c478bd9Sstevel@tonic-gate 
10427c478bd9Sstevel@tonic-gate 	if (*depth != 0) {
10437c478bd9Sstevel@tonic-gate 		mdb_printf("            |                       ^\n");
10447c478bd9Sstevel@tonic-gate 		mdb_printf("            v                       |\n");
10457c478bd9Sstevel@tonic-gate 	} else
10467c478bd9Sstevel@tonic-gate 		mdb_printf("\n");
10477c478bd9Sstevel@tonic-gate 
10487c478bd9Sstevel@tonic-gate 	(void) mdb_qname(_WR(q), wname, sizeof (wname));
10497c478bd9Sstevel@tonic-gate 	(void) mdb_qname(_RD(q), rname, sizeof (rname));
10507c478bd9Sstevel@tonic-gate 
10517c478bd9Sstevel@tonic-gate 	mdb_qinfo(_WR(q), info1, sizeof (info1));
10527c478bd9Sstevel@tonic-gate 	if ((info2 = strchr(info1, '\n')) != NULL)
10537c478bd9Sstevel@tonic-gate 		*info2++ = '\0';
10547c478bd9Sstevel@tonic-gate 	else
10557c478bd9Sstevel@tonic-gate 		info2 = "";
10567c478bd9Sstevel@tonic-gate 
10577c478bd9Sstevel@tonic-gate 	mdb_printf(box_lid);
10587c478bd9Sstevel@tonic-gate 	mdb_printf("| 0x%-19p | 0x%-19p | %s\n",
10597c478bd9Sstevel@tonic-gate 	    addr, addr - sizeof (queue_t), info1);
10607c478bd9Sstevel@tonic-gate 
10617c478bd9Sstevel@tonic-gate 	mdb_printf("| %<b>%-21s%</b> | %<b>%-21s%</b> |", wname, rname);
10627c478bd9Sstevel@tonic-gate 	mdb_flush(); /* Account for buffered terminal sequences */
10637c478bd9Sstevel@tonic-gate 
10647c478bd9Sstevel@tonic-gate 	mdb_printf(" %s\n", info2);
10657c478bd9Sstevel@tonic-gate 	mdb_printf(box_sep);
10667c478bd9Sstevel@tonic-gate 
10677c478bd9Sstevel@tonic-gate 	mdb_qinfo(_RD(q), info1, sizeof (info1));
10687c478bd9Sstevel@tonic-gate 	if ((info2 = strchr(info1, '\n')) != NULL)
10697c478bd9Sstevel@tonic-gate 		*info2++ = '\0';
10707c478bd9Sstevel@tonic-gate 	else
10717c478bd9Sstevel@tonic-gate 		info2 = "";
10727c478bd9Sstevel@tonic-gate 
10737c478bd9Sstevel@tonic-gate 	mdb_printf("| cnt = 0t%-13lu | cnt = 0t%-13lu | %s\n",
10747c478bd9Sstevel@tonic-gate 	    _WR(q)->q_count, _RD(q)->q_count, info1);
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 	mdb_printf("| flg = 0x%08x      | flg = 0x%08x      | %s\n",
10777c478bd9Sstevel@tonic-gate 	    _WR(q)->q_flag, _RD(q)->q_flag, info2);
10787c478bd9Sstevel@tonic-gate 
10797c478bd9Sstevel@tonic-gate 	mdb_printf(box_lid);
10807c478bd9Sstevel@tonic-gate 	*depth += 1;
10817c478bd9Sstevel@tonic-gate 	return (0);
10827c478bd9Sstevel@tonic-gate }
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate /*ARGSUSED*/
10857c478bd9Sstevel@tonic-gate int
stream(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)10867c478bd9Sstevel@tonic-gate stream(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
10877c478bd9Sstevel@tonic-gate {
10887c478bd9Sstevel@tonic-gate 	uint_t d = 0;	/* Depth counter for print_qpair */
10897c478bd9Sstevel@tonic-gate 
10907c478bd9Sstevel@tonic-gate 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
10917c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate 	if (mdb_pwalk("writeq", (mdb_walk_cb_t)print_qpair, &d, addr) == -1) {
10947c478bd9Sstevel@tonic-gate 		mdb_warn("failed to walk writeq");
10957c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
10967c478bd9Sstevel@tonic-gate 	}
10977c478bd9Sstevel@tonic-gate 
10987c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
10997c478bd9Sstevel@tonic-gate }
11007c478bd9Sstevel@tonic-gate 
11017c478bd9Sstevel@tonic-gate int
mblk_walk_init(mdb_walk_state_t * wsp)11027c478bd9Sstevel@tonic-gate mblk_walk_init(mdb_walk_state_t *wsp)
11037c478bd9Sstevel@tonic-gate {
11047c478bd9Sstevel@tonic-gate 	wsp->walk_data = mdb_alloc(sizeof (mblk_t), UM_SLEEP);
11057c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
11067c478bd9Sstevel@tonic-gate }
11077c478bd9Sstevel@tonic-gate 
11087c478bd9Sstevel@tonic-gate int
b_cont_step(mdb_walk_state_t * wsp)11097c478bd9Sstevel@tonic-gate b_cont_step(mdb_walk_state_t *wsp)
11107c478bd9Sstevel@tonic-gate {
11117c478bd9Sstevel@tonic-gate 	int status;
11127c478bd9Sstevel@tonic-gate 
1113892ad162SToomas Soome 	if (wsp->walk_addr == 0)
11147c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
11157c478bd9Sstevel@tonic-gate 
11167c478bd9Sstevel@tonic-gate 	if (mdb_vread(wsp->walk_data, sizeof (mblk_t), wsp->walk_addr) == -1) {
11177c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read mblk at %p", wsp->walk_addr);
11187c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
11197c478bd9Sstevel@tonic-gate 	}
11207c478bd9Sstevel@tonic-gate 
11217c478bd9Sstevel@tonic-gate 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
11227c478bd9Sstevel@tonic-gate 	    wsp->walk_cbdata);
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)(((mblk_t *)wsp->walk_data)->b_cont);
11257c478bd9Sstevel@tonic-gate 	return (status);
11267c478bd9Sstevel@tonic-gate }
11277c478bd9Sstevel@tonic-gate 
11287c478bd9Sstevel@tonic-gate int
b_next_step(mdb_walk_state_t * wsp)11297c478bd9Sstevel@tonic-gate b_next_step(mdb_walk_state_t *wsp)
11307c478bd9Sstevel@tonic-gate {
11317c478bd9Sstevel@tonic-gate 	int status;
11327c478bd9Sstevel@tonic-gate 
1133892ad162SToomas Soome 	if (wsp->walk_addr == 0)
11347c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
11357c478bd9Sstevel@tonic-gate 
11367c478bd9Sstevel@tonic-gate 	if (mdb_vread(wsp->walk_data, sizeof (mblk_t), wsp->walk_addr) == -1) {
11377c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read mblk at %p", wsp->walk_addr);
11387c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
11397c478bd9Sstevel@tonic-gate 	}
11407c478bd9Sstevel@tonic-gate 
11417c478bd9Sstevel@tonic-gate 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
11427c478bd9Sstevel@tonic-gate 	    wsp->walk_cbdata);
11437c478bd9Sstevel@tonic-gate 
11447c478bd9Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)(((mblk_t *)wsp->walk_data)->b_next);
11457c478bd9Sstevel@tonic-gate 	return (status);
11467c478bd9Sstevel@tonic-gate }
11477c478bd9Sstevel@tonic-gate 
11487c478bd9Sstevel@tonic-gate void
mblk_walk_fini(mdb_walk_state_t * wsp)11497c478bd9Sstevel@tonic-gate mblk_walk_fini(mdb_walk_state_t *wsp)
11507c478bd9Sstevel@tonic-gate {
11517c478bd9Sstevel@tonic-gate 	mdb_free(wsp->walk_data, sizeof (mblk_t));
11527c478bd9Sstevel@tonic-gate }
11537c478bd9Sstevel@tonic-gate 
11547c478bd9Sstevel@tonic-gate /* ARGSUSED */
11557c478bd9Sstevel@tonic-gate int
mblk2dblk(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)11567c478bd9Sstevel@tonic-gate mblk2dblk(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
11577c478bd9Sstevel@tonic-gate {
11587c478bd9Sstevel@tonic-gate 	mblk_t mb;
11597c478bd9Sstevel@tonic-gate 
11607c478bd9Sstevel@tonic-gate 	if (argc != 0)
11617c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate 	if (mdb_vread(&mb, sizeof (mb), addr) == -1) {
11647c478bd9Sstevel@tonic-gate 		mdb_warn("couldn't read mblk at %p", addr);
11657c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
11667c478bd9Sstevel@tonic-gate 	}
11677c478bd9Sstevel@tonic-gate 
11687c478bd9Sstevel@tonic-gate 	mdb_printf("%p\n", mb.b_datap);
11697c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
11707c478bd9Sstevel@tonic-gate }
11717c478bd9Sstevel@tonic-gate 
11727c478bd9Sstevel@tonic-gate static void
mblk_error(int * error,uintptr_t addr,char * message)11737c478bd9Sstevel@tonic-gate mblk_error(int *error, uintptr_t addr, char *message)
11747c478bd9Sstevel@tonic-gate {
11757c478bd9Sstevel@tonic-gate 	if (!*error)
11767c478bd9Sstevel@tonic-gate 		mdb_printf("%?lx: ", addr);
11777c478bd9Sstevel@tonic-gate 	else
11787c478bd9Sstevel@tonic-gate 		mdb_printf(", ");
11797c478bd9Sstevel@tonic-gate 	mdb_printf("%s", message);
11807c478bd9Sstevel@tonic-gate 	*error = 1;
11817c478bd9Sstevel@tonic-gate }
11827c478bd9Sstevel@tonic-gate 
11837c478bd9Sstevel@tonic-gate int
mblk_verify(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)11847c478bd9Sstevel@tonic-gate mblk_verify(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
11857c478bd9Sstevel@tonic-gate {
11867c478bd9Sstevel@tonic-gate 	mblk_t	mb;
11877c478bd9Sstevel@tonic-gate 	dblk_t	db;
11887c478bd9Sstevel@tonic-gate 	int	error = 0;
11897c478bd9Sstevel@tonic-gate 
11907c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
11917c478bd9Sstevel@tonic-gate 		if (mdb_walk_dcmd("streams_mblk", "mblk_verify", argc, argv) ==
11927c478bd9Sstevel@tonic-gate 		    -1) {
11937c478bd9Sstevel@tonic-gate 			mdb_warn("can't walk mblk cache");
11947c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
11957c478bd9Sstevel@tonic-gate 		}
11967c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
11977c478bd9Sstevel@tonic-gate 	}
11987c478bd9Sstevel@tonic-gate 
11997c478bd9Sstevel@tonic-gate 	if (mdb_vread(&mb, sizeof (mblk_t), addr) == -1) {
12007c478bd9Sstevel@tonic-gate 		mdb_warn("can't read mblk_t at 0x%lx", addr);
12017c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
12027c478bd9Sstevel@tonic-gate 	}
12037c478bd9Sstevel@tonic-gate 
12047c478bd9Sstevel@tonic-gate 	if (mdb_vread(&db, sizeof (dblk_t), (uintptr_t)mb.b_datap) == -1) {
12057c478bd9Sstevel@tonic-gate 		mdb_warn("%?lx: invalid b_datap pointer\n", addr);
12067c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
12077c478bd9Sstevel@tonic-gate 	}
12087c478bd9Sstevel@tonic-gate 
12097c478bd9Sstevel@tonic-gate 	if (mb.b_rptr < db.db_base || mb.b_rptr > db.db_lim)
12107c478bd9Sstevel@tonic-gate 		mblk_error(&error, addr, "b_rptr out of range");
12117c478bd9Sstevel@tonic-gate 
12127c478bd9Sstevel@tonic-gate 	if (mb.b_wptr < db.db_base || mb.b_wptr > db.db_lim)
12137c478bd9Sstevel@tonic-gate 		mblk_error(&error, addr, "b_wptr out of range");
12147c478bd9Sstevel@tonic-gate 
12157c478bd9Sstevel@tonic-gate 	if (error)
12167c478bd9Sstevel@tonic-gate 		mdb_printf("\n");
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate 	return (error ? DCMD_ERR : DCMD_OK);
12197c478bd9Sstevel@tonic-gate }
12207c478bd9Sstevel@tonic-gate 
12217c478bd9Sstevel@tonic-gate int
mblk_prt(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)12227c478bd9Sstevel@tonic-gate mblk_prt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
12237c478bd9Sstevel@tonic-gate {
12247c478bd9Sstevel@tonic-gate 	const int MBLK_FLGDELT = (int)(sizeof (uintptr_t) * 2 + 15);
12257c478bd9Sstevel@tonic-gate 	mblk_t mblk;
12267c478bd9Sstevel@tonic-gate 	dblk_t dblk;
12277c478bd9Sstevel@tonic-gate 	int b_flag;
12287c478bd9Sstevel@tonic-gate 	int db_type;
12297c478bd9Sstevel@tonic-gate 	int mblklen;
12307c478bd9Sstevel@tonic-gate 	uint64_t len = ~0UL;
12317c478bd9Sstevel@tonic-gate 	uint64_t glen = ~0UL;
12327c478bd9Sstevel@tonic-gate 	uint64_t llen = ~0UL;
12337c478bd9Sstevel@tonic-gate 	uint64_t blen = ~0UL;
12347c478bd9Sstevel@tonic-gate 	const char *dbtype;
12357c478bd9Sstevel@tonic-gate 	const char *flag = NULL, *not_flag = NULL;
12367c478bd9Sstevel@tonic-gate 	const char *typ = NULL, *not_typ = NULL;
12377c478bd9Sstevel@tonic-gate 	uintptr_t  dbaddr = 0;
12387c478bd9Sstevel@tonic-gate 	uint32_t tmask = 0, not_tmask = 0;
12397c478bd9Sstevel@tonic-gate 	uint32_t mask = 0, not_mask = 0;
12407c478bd9Sstevel@tonic-gate 	uint_t quiet = FALSE;
12417c478bd9Sstevel@tonic-gate 	uint_t verbose = FALSE;
12427c478bd9Sstevel@tonic-gate 
12437c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
12447c478bd9Sstevel@tonic-gate 		if (mdb_walk_dcmd("genunix`streams_mblk", "genunix`mblk",
12457c478bd9Sstevel@tonic-gate 		    argc, argv) == -1) {
12467c478bd9Sstevel@tonic-gate 			mdb_warn("failed to walk mblk cache");
12477c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
12487c478bd9Sstevel@tonic-gate 		}
12497c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
12507c478bd9Sstevel@tonic-gate 	}
12517c478bd9Sstevel@tonic-gate 
12527c478bd9Sstevel@tonic-gate 	if (flags & DCMD_PIPE_OUT)
12537c478bd9Sstevel@tonic-gate 		quiet = TRUE;
12547c478bd9Sstevel@tonic-gate 
12557c478bd9Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
12567c478bd9Sstevel@tonic-gate 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
12577c478bd9Sstevel@tonic-gate 	    'q', MDB_OPT_SETBITS, TRUE, &quiet,
12587c478bd9Sstevel@tonic-gate 	    'f', MDB_OPT_STR, &flag,
12597c478bd9Sstevel@tonic-gate 	    'F', MDB_OPT_STR, &not_flag,
12607c478bd9Sstevel@tonic-gate 	    't', MDB_OPT_STR, &typ,
12617c478bd9Sstevel@tonic-gate 	    'T', MDB_OPT_STR, &not_typ,
12627c478bd9Sstevel@tonic-gate 	    'l', MDB_OPT_UINT64, &len,
12637c478bd9Sstevel@tonic-gate 	    'L', MDB_OPT_UINT64, &llen,
12647c478bd9Sstevel@tonic-gate 	    'G', MDB_OPT_UINT64, &glen,
12657c478bd9Sstevel@tonic-gate 	    'b', MDB_OPT_UINT64, &blen,
12667c478bd9Sstevel@tonic-gate 	    'd', MDB_OPT_UINTPTR, &dbaddr,
12677c478bd9Sstevel@tonic-gate 	    NULL) != argc)
12687c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
12697c478bd9Sstevel@tonic-gate 
12707c478bd9Sstevel@tonic-gate 	/*
12717c478bd9Sstevel@tonic-gate 	 * If any of the filtering flags is specified, don't print anything
12727c478bd9Sstevel@tonic-gate 	 * except the matching pointer.
12737c478bd9Sstevel@tonic-gate 	 */
12747c478bd9Sstevel@tonic-gate 	if ((flag != NULL) || (not_flag != NULL) || (typ != NULL) ||
12757c478bd9Sstevel@tonic-gate 	    (not_typ != NULL) || (len != ~0UL) || (glen != ~0UL) ||
12767c478bd9Sstevel@tonic-gate 	    (llen != ~0UL) || (blen != ~0UL) || (dbaddr != 0))
12777c478bd9Sstevel@tonic-gate 		quiet = TRUE;
12787c478bd9Sstevel@tonic-gate 
12797c478bd9Sstevel@tonic-gate 	if (flag != NULL && streams_parse_flag(mbf, flag, &mask) == -1) {
12807c478bd9Sstevel@tonic-gate 		mdb_warn("unrecognized mblk flag '%s'\n", flag);
12817c478bd9Sstevel@tonic-gate 		streams_flag_usage(mbf);
12827c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
12837c478bd9Sstevel@tonic-gate 	}
12847c478bd9Sstevel@tonic-gate 
12857c478bd9Sstevel@tonic-gate 	if (not_flag != NULL &&
12867c478bd9Sstevel@tonic-gate 	    streams_parse_flag(mbf, not_flag, &not_mask) == -1) {
12877c478bd9Sstevel@tonic-gate 		mdb_warn("unrecognized mblk flag '%s'\n", flag);
12887c478bd9Sstevel@tonic-gate 		streams_flag_usage(mbf);
12897c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
12907c478bd9Sstevel@tonic-gate 	}
12917c478bd9Sstevel@tonic-gate 
12927c478bd9Sstevel@tonic-gate 	if (typ != NULL && streams_parse_type(mbt, typ, &tmask) == -1) {
12937c478bd9Sstevel@tonic-gate 		mdb_warn("unrecognized dblk type '%s'\n", typ);
12947c478bd9Sstevel@tonic-gate 		streams_type_usage(mbt);
12957c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
12967c478bd9Sstevel@tonic-gate 	}
12977c478bd9Sstevel@tonic-gate 
12987c478bd9Sstevel@tonic-gate 	if (not_typ != NULL && streams_parse_type(mbt, not_typ, &not_tmask)
12997c478bd9Sstevel@tonic-gate 	    == -1) {
13007c478bd9Sstevel@tonic-gate 		mdb_warn("unrecognized dblk type '%s'\n", not_typ);
13017c478bd9Sstevel@tonic-gate 		streams_type_usage(mbt);
13027c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
13037c478bd9Sstevel@tonic-gate 	}
13047c478bd9Sstevel@tonic-gate 
13057c478bd9Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags) && !quiet) {
13067c478bd9Sstevel@tonic-gate 		mdb_printf("%?s %2s %-7s %-5s %-5s %?s %?s\n",
13077c478bd9Sstevel@tonic-gate 		    "ADDR", "FL", "TYPE", "LEN", "BLEN", "RPTR", "DBLK");
13087c478bd9Sstevel@tonic-gate 	}
13097c478bd9Sstevel@tonic-gate 
13107c478bd9Sstevel@tonic-gate 	if (mdb_vread(&mblk, sizeof (mblk), addr) == -1) {
13117c478bd9Sstevel@tonic-gate 		mdb_warn("couldn't read mblk at %p", addr);
13127c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
13137c478bd9Sstevel@tonic-gate 	}
13147c478bd9Sstevel@tonic-gate 	b_flag = mblk.b_flag;
13157c478bd9Sstevel@tonic-gate 
13167c478bd9Sstevel@tonic-gate 	if (mask != 0 && !(b_flag & mask))
13177c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
13187c478bd9Sstevel@tonic-gate 
13197c478bd9Sstevel@tonic-gate 	if (not_mask != 0 && (b_flag & not_mask))
13207c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
13217c478bd9Sstevel@tonic-gate 
13227c478bd9Sstevel@tonic-gate 	if (mdb_vread(&dblk, sizeof (dblk), (uintptr_t)(mblk.b_datap)) == -1) {
13237c478bd9Sstevel@tonic-gate 		mdb_warn("couldn't read dblk at %p/%p", addr, mblk.b_datap);
13247c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
13257c478bd9Sstevel@tonic-gate 	}
13267c478bd9Sstevel@tonic-gate 	db_type = dblk.db_type;
13277c478bd9Sstevel@tonic-gate 
13287c478bd9Sstevel@tonic-gate 	/* M_DATA is 0, so tmask has special value 0xff for it */
1329ca9327a6Smeem 	if (tmask != 0) {
1330ca9327a6Smeem 		if ((tmask == M_DATA_T && db_type != M_DATA) ||
1331ca9327a6Smeem 		    (tmask != M_DATA_T && db_type != tmask))
13327c478bd9Sstevel@tonic-gate 			return (DCMD_OK);
1333ca9327a6Smeem 	}
13347c478bd9Sstevel@tonic-gate 
1335ca9327a6Smeem 	if (not_tmask != 0) {
1336ca9327a6Smeem 		if ((not_tmask == M_DATA_T && db_type == M_DATA) ||
1337ca9327a6Smeem 		    (db_type == not_tmask))
13387c478bd9Sstevel@tonic-gate 			return (DCMD_OK);
1339ca9327a6Smeem 	}
13407c478bd9Sstevel@tonic-gate 
13417c478bd9Sstevel@tonic-gate 	if (dbaddr != 0 && (uintptr_t)mblk.b_datap != dbaddr)
13427c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
13437c478bd9Sstevel@tonic-gate 
13447c478bd9Sstevel@tonic-gate 	mblklen = MBLKL(&mblk);
13457c478bd9Sstevel@tonic-gate 
13467c478bd9Sstevel@tonic-gate 	if ((len != ~0UL) && (len != mblklen))
13477c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
13487c478bd9Sstevel@tonic-gate 
13497c478bd9Sstevel@tonic-gate 	if ((llen != ~0Ul) && (mblklen > (int)llen))
13507c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
13517c478bd9Sstevel@tonic-gate 
13527c478bd9Sstevel@tonic-gate 	if ((glen != ~0Ul) && (mblklen < (int)glen))
13537c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
13547c478bd9Sstevel@tonic-gate 
13557c478bd9Sstevel@tonic-gate 	if ((blen != ~0UL) && (blen != (dblk.db_lim - dblk.db_base)))
13567c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
13577c478bd9Sstevel@tonic-gate 
13587c478bd9Sstevel@tonic-gate 	/*
13597c478bd9Sstevel@tonic-gate 	 * Options are specified for filtering, so If any option is specified on
13607c478bd9Sstevel@tonic-gate 	 * the command line, just print address and exit.
13617c478bd9Sstevel@tonic-gate 	 */
13627c478bd9Sstevel@tonic-gate 	if (quiet) {
13637c478bd9Sstevel@tonic-gate 		mdb_printf("%0?p\n", addr);
13647c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
13657c478bd9Sstevel@tonic-gate 	}
13667c478bd9Sstevel@tonic-gate 
13677c478bd9Sstevel@tonic-gate 	/* Figure out symbolic DB_TYPE */
13687c478bd9Sstevel@tonic-gate 	if (db_type < A_SIZE(db_control_types)) {
13697c478bd9Sstevel@tonic-gate 		dbtype = db_control_types[db_type];
13707c478bd9Sstevel@tonic-gate 	} else {
13717c478bd9Sstevel@tonic-gate 		/*
13727c478bd9Sstevel@tonic-gate 		 * Must be a high-priority message -- adjust so that
13737c478bd9Sstevel@tonic-gate 		 * "QPCTL + 1" corresponds to db_control_hipri_types[0]
13747c478bd9Sstevel@tonic-gate 		 */
13757c478bd9Sstevel@tonic-gate 		db_type -= (QPCTL + 1);
13767c478bd9Sstevel@tonic-gate 		if (db_type >= 0 && db_type < A_SIZE(db_control_hipri_types))
13777c478bd9Sstevel@tonic-gate 			dbtype = db_control_hipri_types[db_type];
13787c478bd9Sstevel@tonic-gate 		else
13797c478bd9Sstevel@tonic-gate 			dbtype = "UNKNOWN";
13807c478bd9Sstevel@tonic-gate 	}
13817c478bd9Sstevel@tonic-gate 
13827c478bd9Sstevel@tonic-gate 	mdb_printf("%0?p %-2x %-7s %-5d %-5d %0?p %0?p\n",
13837c478bd9Sstevel@tonic-gate 	    addr, b_flag, dbtype, mblklen, dblk.db_lim - dblk.db_base,
13847c478bd9Sstevel@tonic-gate 	    mblk.b_rptr, mblk.b_datap);
13857c478bd9Sstevel@tonic-gate 
13867c478bd9Sstevel@tonic-gate 	if (verbose) {
13877c478bd9Sstevel@tonic-gate 		int i, arm = 0;
13887c478bd9Sstevel@tonic-gate 
13897c478bd9Sstevel@tonic-gate 		for (i = 0; mbf[i].strf_name != NULL; i++) {
13907c478bd9Sstevel@tonic-gate 			if (!(b_flag & (1 << i)))
13917c478bd9Sstevel@tonic-gate 				continue;
13927c478bd9Sstevel@tonic-gate 			if (!arm) {
13937c478bd9Sstevel@tonic-gate 				mdb_printf("%*s|\n%*s+-->  ",
13947c478bd9Sstevel@tonic-gate 				    MBLK_FLGDELT, "", MBLK_FLGDELT, "");
13957c478bd9Sstevel@tonic-gate 				arm = 1;
13967c478bd9Sstevel@tonic-gate 			} else
13977c478bd9Sstevel@tonic-gate 				mdb_printf("%*s      ", MBLK_FLGDELT, "");
13987c478bd9Sstevel@tonic-gate 
13997c478bd9Sstevel@tonic-gate 			mdb_printf("%-12s %s\n",
14007c478bd9Sstevel@tonic-gate 			    mbf[i].strf_name, mbf[i].strf_descr);
14017c478bd9Sstevel@tonic-gate 		}
14027c478bd9Sstevel@tonic-gate 	}
14037c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
14047c478bd9Sstevel@tonic-gate }
14057c478bd9Sstevel@tonic-gate 
14067c478bd9Sstevel@tonic-gate /*
14077c478bd9Sstevel@tonic-gate  * Streams flow trace walkers.
14087c478bd9Sstevel@tonic-gate  */
14097c478bd9Sstevel@tonic-gate 
14107c478bd9Sstevel@tonic-gate int
strftblk_walk_init(mdb_walk_state_t * wsp)14117c478bd9Sstevel@tonic-gate strftblk_walk_init(mdb_walk_state_t *wsp)
14127c478bd9Sstevel@tonic-gate {
14137c478bd9Sstevel@tonic-gate 	ftblkdata_t *ftd;
14147c478bd9Sstevel@tonic-gate 	dblk_t	db;
14157c478bd9Sstevel@tonic-gate 
14167c478bd9Sstevel@tonic-gate 	/* Get the dblock from the address */
14177c478bd9Sstevel@tonic-gate 	if (mdb_vread(&db, sizeof (dblk_t), wsp->walk_addr) == -1) {
14187c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read dblk at %p", wsp->walk_addr);
14197c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
14207c478bd9Sstevel@tonic-gate 	}
14217c478bd9Sstevel@tonic-gate 
14227c478bd9Sstevel@tonic-gate 	/* Is there any flow trace data? */
14237c478bd9Sstevel@tonic-gate 	if (db.db_fthdr == NULL) {
14247c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
14257c478bd9Sstevel@tonic-gate 	}
14267c478bd9Sstevel@tonic-gate 
14277c478bd9Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)((char *)db.db_fthdr +
14287c478bd9Sstevel@tonic-gate 	    offsetof(fthdr_t, first));
14297c478bd9Sstevel@tonic-gate 
14307c478bd9Sstevel@tonic-gate 	ftd = mdb_alloc(sizeof (ftblkdata_t), UM_SLEEP);
14317c478bd9Sstevel@tonic-gate 	ftd->ft_ix = 0;
14327c478bd9Sstevel@tonic-gate 	ftd->ft_in_evlist = B_FALSE;
14337c478bd9Sstevel@tonic-gate 	wsp->walk_data = ftd;
14347c478bd9Sstevel@tonic-gate 
14357c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
14367c478bd9Sstevel@tonic-gate }
14377c478bd9Sstevel@tonic-gate 
14387c478bd9Sstevel@tonic-gate int
strftblk_step(mdb_walk_state_t * wsp)14397c478bd9Sstevel@tonic-gate strftblk_step(mdb_walk_state_t *wsp)
14407c478bd9Sstevel@tonic-gate {
14417c478bd9Sstevel@tonic-gate 	ftblkdata_t *ftd;
14427c478bd9Sstevel@tonic-gate 	ftblk_t *ftbp;
14437c478bd9Sstevel@tonic-gate 	int status = WALK_NEXT;
14447c478bd9Sstevel@tonic-gate 
1445892ad162SToomas Soome 	if (wsp->walk_addr == 0)
14467c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
14477c478bd9Sstevel@tonic-gate 
14487c478bd9Sstevel@tonic-gate 	ftd = (ftblkdata_t *)wsp->walk_data;
14497c478bd9Sstevel@tonic-gate 	ftbp = &(ftd->ft_data);
14507c478bd9Sstevel@tonic-gate 
14517c478bd9Sstevel@tonic-gate 	if (! ftd->ft_in_evlist) {
14527c478bd9Sstevel@tonic-gate 		/* Read a new ft block */
14537c478bd9Sstevel@tonic-gate 		if (mdb_vread(ftbp, sizeof (ftblk_t),
14547c478bd9Sstevel@tonic-gate 		    wsp->walk_addr) == -1) {
14557c478bd9Sstevel@tonic-gate 			mdb_warn("failed to read ftblk at %p", wsp->walk_addr);
14567c478bd9Sstevel@tonic-gate 			return (WALK_ERR);
14577c478bd9Sstevel@tonic-gate 		}
14587c478bd9Sstevel@tonic-gate 		/*
14597c478bd9Sstevel@tonic-gate 		 * Check correctness of the index field.
14607c478bd9Sstevel@tonic-gate 		 */
14617c478bd9Sstevel@tonic-gate 		if (ftbp->ix < 0 || ftbp->ix > FTBLK_EVNTS) {
14627c478bd9Sstevel@tonic-gate 			mdb_warn("ftblk: incorrect index value %i\n", ftbp->ix);
14637c478bd9Sstevel@tonic-gate 			return (WALK_ERR);
14647c478bd9Sstevel@tonic-gate 		}
14657c478bd9Sstevel@tonic-gate 		ftd->ft_ix = 1;
14667c478bd9Sstevel@tonic-gate 		ftd->ft_in_evlist = B_TRUE;
14677c478bd9Sstevel@tonic-gate 	}
14687c478bd9Sstevel@tonic-gate 
14697c478bd9Sstevel@tonic-gate 	if (ftd->ft_ix > ftbp->ix) {
14707c478bd9Sstevel@tonic-gate 		ftd->ft_in_evlist = B_FALSE;
14717c478bd9Sstevel@tonic-gate 		/* End of event list reached - move to the next event block */
14727c478bd9Sstevel@tonic-gate 		wsp->walk_addr = (uintptr_t)ftbp->nxt;
14737c478bd9Sstevel@tonic-gate 	} else {
14747c478bd9Sstevel@tonic-gate 		/* Print event address */
14757c478bd9Sstevel@tonic-gate 		status = wsp->walk_callback((uintptr_t)((char *)wsp->walk_addr +
14767c478bd9Sstevel@tonic-gate 		    offsetof(ftblk_t, ev) +
14777c478bd9Sstevel@tonic-gate 		    (ftd->ft_ix - 1) * sizeof (struct ftevnt)),
14787c478bd9Sstevel@tonic-gate 		    wsp->walk_data, wsp->walk_cbdata);
14797c478bd9Sstevel@tonic-gate 		ftd->ft_ix++;
14807c478bd9Sstevel@tonic-gate 	}
14817c478bd9Sstevel@tonic-gate 
14827c478bd9Sstevel@tonic-gate 	return (status);
14837c478bd9Sstevel@tonic-gate }
14847c478bd9Sstevel@tonic-gate 
14857c478bd9Sstevel@tonic-gate void
strftblk_walk_fini(mdb_walk_state_t * wsp)14867c478bd9Sstevel@tonic-gate strftblk_walk_fini(mdb_walk_state_t *wsp)
14877c478bd9Sstevel@tonic-gate {
14887c478bd9Sstevel@tonic-gate 	mdb_free(wsp->walk_data, sizeof (ftblkdata_t));
14897c478bd9Sstevel@tonic-gate }
14907c478bd9Sstevel@tonic-gate 
1491a45f3f93Smeem static const char *
getqname(const void * nameptr,char * buf,uint_t bufsize)1492a45f3f93Smeem getqname(const void *nameptr, char *buf, uint_t bufsize)
1493a45f3f93Smeem {
1494a45f3f93Smeem 	char *cp;
1495a45f3f93Smeem 
1496a45f3f93Smeem 	if (mdb_readstr(buf, bufsize, (uintptr_t)nameptr) == -1)
1497a45f3f93Smeem 		goto fail;
1498a45f3f93Smeem 
1499a45f3f93Smeem 	/*
1500a45f3f93Smeem 	 * Sanity-check the name we read.  This is needed because the pointer
1501a45f3f93Smeem 	 * value may have been recycled for some other purpose in the kernel
1502a45f3f93Smeem 	 * (e.g., if the STREAMS module was unloaded).
1503a45f3f93Smeem 	 */
1504a45f3f93Smeem 	for (cp = buf; *cp != '\0'; cp++) {
1505a45f3f93Smeem 		if (!isprint(*cp))
1506a45f3f93Smeem 			goto fail;
1507a45f3f93Smeem 	}
1508a45f3f93Smeem 	return (buf);
1509a45f3f93Smeem fail:
1510a45f3f93Smeem 	return (strncpy(buf, "?", bufsize));
1511a45f3f93Smeem }
1512a45f3f93Smeem 
15137c478bd9Sstevel@tonic-gate /*ARGSUSED*/
15147c478bd9Sstevel@tonic-gate int
strftevent(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)15157c478bd9Sstevel@tonic-gate strftevent(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
15167c478bd9Sstevel@tonic-gate {
1517a45f3f93Smeem 	int i;
1518a45f3f93Smeem 	struct ftstk stk;
15197c478bd9Sstevel@tonic-gate 	struct ftevnt ev;
1520a45f3f93Smeem 	char name[FMNAMESZ + 1];
1521a45f3f93Smeem 	boolean_t havestk = B_FALSE;
15227c478bd9Sstevel@tonic-gate 
15237c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC))
15247c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
15257c478bd9Sstevel@tonic-gate 
15267c478bd9Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags)) {
1527a45f3f93Smeem 		mdb_printf("%?s %-18s %-9s %-18s %4s %s\n",
1528a45f3f93Smeem 		    "ADDR", "Q/CALLER", "QNEXT", "STACK", "DATA", "EVENT");
15297c478bd9Sstevel@tonic-gate 	}
15307c478bd9Sstevel@tonic-gate 
15317c478bd9Sstevel@tonic-gate 	if (mdb_vread(&ev, sizeof (ev), addr) == -1) {
1532a45f3f93Smeem 		mdb_warn("couldn't read struct ftevnt at %p", addr);
15337c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
15347c478bd9Sstevel@tonic-gate 	}
15357c478bd9Sstevel@tonic-gate 
1536a45f3f93Smeem 	mdb_printf("%0?p", addr);
15377c478bd9Sstevel@tonic-gate 
1538a45f3f93Smeem 	if (ev.evnt & FTEV_QMASK)
1539a45f3f93Smeem 		mdb_printf(" %-18s", getqname(ev.mid, name, sizeof (name)));
1540a45f3f93Smeem 	else
1541a45f3f93Smeem 		mdb_printf(" %-18a", ev.mid);
15427c478bd9Sstevel@tonic-gate 
1543a45f3f93Smeem 	if ((ev.evnt & FTEV_MASK) == FTEV_PUTNEXT)
1544a45f3f93Smeem 		mdb_printf(" %-9s", getqname(ev.midnext, name, sizeof (name)));
1545a45f3f93Smeem 	else
1546a45f3f93Smeem 		mdb_printf(" %-9s", "--");
1547a45f3f93Smeem 
1548a45f3f93Smeem 	if (ev.stk == NULL) {
1549a45f3f93Smeem 		mdb_printf(" %-18s", "--");
1550a45f3f93Smeem 	} else if (mdb_vread(&stk, sizeof (stk), (uintptr_t)ev.stk) == -1) {
1551a45f3f93Smeem 		mdb_printf(" %-18s", "?");
1552a45f3f93Smeem 	} else {
1553a45f3f93Smeem 		mdb_printf(" %-18a", stk.fs_stk[0]);
1554a45f3f93Smeem 		havestk = B_TRUE;
1555a45f3f93Smeem 	}
1556a45f3f93Smeem 
1557a45f3f93Smeem 	mdb_printf(" %4x", ev.data);
15587c478bd9Sstevel@tonic-gate 	ft_printevent(ev.evnt);
15597c478bd9Sstevel@tonic-gate 	mdb_printf("\n");
15607c478bd9Sstevel@tonic-gate 
1561a45f3f93Smeem 	if (havestk) {
1562a45f3f93Smeem 		for (i = 1; i < stk.fs_depth; i++) {
1563a45f3f93Smeem 			mdb_printf("%?s %-18s %-9s %-18a\n", "", "", "",
1564a45f3f93Smeem 			    stk.fs_stk[i]);
1565a45f3f93Smeem 		}
1566a45f3f93Smeem 	}
1567a45f3f93Smeem 
15687c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
15697c478bd9Sstevel@tonic-gate }
15707c478bd9Sstevel@tonic-gate 
15717c478bd9Sstevel@tonic-gate static void
ft_printevent(ushort_t ev)15727c478bd9Sstevel@tonic-gate ft_printevent(ushort_t ev)
15737c478bd9Sstevel@tonic-gate {
15747c478bd9Sstevel@tonic-gate 	ushort_t proc_ev = (ev & (FTEV_PROC_START | 0xFF)) - FTEV_PROC_START;
15757c478bd9Sstevel@tonic-gate 	ushort_t alloc_ev = ev & FTEV_CALLER;
15767c478bd9Sstevel@tonic-gate 
15777c478bd9Sstevel@tonic-gate 	/* Get event class first */
15787c478bd9Sstevel@tonic-gate 	if (ev & FTEV_PROC_START) {
15797c478bd9Sstevel@tonic-gate 		if (proc_ev >= A_SIZE(ftev_proc))
15807c478bd9Sstevel@tonic-gate 			mdb_printf(" undefined");
15817c478bd9Sstevel@tonic-gate 		else
15827c478bd9Sstevel@tonic-gate 			mdb_printf(" %s", ftev_proc[proc_ev]);
1583a45f3f93Smeem 	} else if (alloc_ev >= A_SIZE(ftev_alloc)) {
15847c478bd9Sstevel@tonic-gate 		mdb_printf(" undefined");
1585a45f3f93Smeem 	} else {
15867c478bd9Sstevel@tonic-gate 		mdb_printf(" %s", ftev_alloc[alloc_ev]);
1587a45f3f93Smeem 	}
15887c478bd9Sstevel@tonic-gate 
15897c478bd9Sstevel@tonic-gate 	/* Print event modifiers, if any */
1590a45f3f93Smeem 	if (ev & (FTEV_PS | FTEV_CS | FTEV_ISWR)) {
1591a45f3f93Smeem 		mdb_printf("|");
15927c478bd9Sstevel@tonic-gate 		if (ev & FTEV_ISWR)
1593a45f3f93Smeem 			mdb_printf("W");
1594a45f3f93Smeem 		if (ev & FTEV_CS)
1595a45f3f93Smeem 			mdb_printf("C");
1596a45f3f93Smeem 		if (ev & FTEV_PS)
1597a45f3f93Smeem 			mdb_printf("P");
1598a45f3f93Smeem 	}
15997c478bd9Sstevel@tonic-gate }
16007c478bd9Sstevel@tonic-gate 
16017c478bd9Sstevel@tonic-gate /*
16027c478bd9Sstevel@tonic-gate  * Help functions for STREAMS debugging facilities.
16037c478bd9Sstevel@tonic-gate  */
16047c478bd9Sstevel@tonic-gate void
queue_help(void)16057c478bd9Sstevel@tonic-gate queue_help(void)
16067c478bd9Sstevel@tonic-gate {
16077c478bd9Sstevel@tonic-gate 	mdb_printf("Print queue information for a given queue pointer.\n"
16087c478bd9Sstevel@tonic-gate 	    "\nWithout the address of a \"queue_t\" structure given, print "
16097c478bd9Sstevel@tonic-gate 	    "information about all\n"
16107c478bd9Sstevel@tonic-gate 	    "queues in the \"queue_cache\".\n\n"
16117c478bd9Sstevel@tonic-gate 	    "Options:\n"
16127c478bd9Sstevel@tonic-gate 	    "	-v:\t\tbe verbose - print symbolic flags falues\n"
16137c478bd9Sstevel@tonic-gate 	    "	-q:\t\tbe quiet - print queue pointer only\n"
16147c478bd9Sstevel@tonic-gate 	    "	-f flag:\tprint only queues with flag set\n"
16157c478bd9Sstevel@tonic-gate 	    "	-F flag:\tprint only queues with flag NOT set\n"
16167c478bd9Sstevel@tonic-gate 	    "	-m modname:\tprint only queues with specified module name\n"
16177c478bd9Sstevel@tonic-gate 	    "	-s syncq_addr:\tprint only queues which use specified syncq\n\n"
16187c478bd9Sstevel@tonic-gate 	    "Available conversions:\n"
16197c478bd9Sstevel@tonic-gate 	    "	q2rdq:		given a queue addr print read queue pointer\n"
16207c478bd9Sstevel@tonic-gate 	    "	q2wrq:		given a queue addr print write queue pointer\n"
16217c478bd9Sstevel@tonic-gate 	    "	q2otherq:	given a queue addr print other queue pointer\n"
16227c478bd9Sstevel@tonic-gate 	    "	q2syncq:	given a queue addr print syncq pointer"
16237c478bd9Sstevel@tonic-gate 	    " (::help syncq)\n"
16247c478bd9Sstevel@tonic-gate 	    "	q2stream:	given a queue addr print its stream pointer\n"
16257c478bd9Sstevel@tonic-gate 	    "\t\t(see ::help stream and ::help stdata)\n\n"
16267c478bd9Sstevel@tonic-gate 	    "To walk q_next pointer of the queue use\n"
16277c478bd9Sstevel@tonic-gate 	    "	queue_addr::walk qnext\n");
16287c478bd9Sstevel@tonic-gate }
16297c478bd9Sstevel@tonic-gate 
16307c478bd9Sstevel@tonic-gate void
syncq_help(void)16317c478bd9Sstevel@tonic-gate syncq_help(void)
16327c478bd9Sstevel@tonic-gate {
16337c478bd9Sstevel@tonic-gate 	mdb_printf("Print syncq information for a given syncq pointer.\n"
16347c478bd9Sstevel@tonic-gate 	    "\nWithout the address of a \"syncq_t\" structure given, print "
16357c478bd9Sstevel@tonic-gate 	    "information about all\n"
16367c478bd9Sstevel@tonic-gate 	    "syncqs in the \"syncq_cache\".\n\n"
16377c478bd9Sstevel@tonic-gate 	    "Options:\n"
16387c478bd9Sstevel@tonic-gate 	    "	-v:\t\tbe verbose - print symbolic flags falues\n"
16397c478bd9Sstevel@tonic-gate 	    "	-q:\t\tbe quiet - print syncq pointer only\n"
16407c478bd9Sstevel@tonic-gate 	    "	-f flag:\tprint only syncqs with flag set\n"
16417c478bd9Sstevel@tonic-gate 	    "	-F flag:\tprint only syncqs with flag NOT set\n"
16427c478bd9Sstevel@tonic-gate 	    "	-t type:\tprint only syncqs with specified type\n"
16437c478bd9Sstevel@tonic-gate 	    "	-T type:\tprint only syncqs with do NOT have specified type\n\n"
16447c478bd9Sstevel@tonic-gate 	    "Available conversions:\n"
16457c478bd9Sstevel@tonic-gate 	    "	syncq2q:\tgiven a syncq addr print queue address of the\n"
16467c478bd9Sstevel@tonic-gate 	    "\t\t\tenclosing queue, if it is part of a queue\n\n"
16477c478bd9Sstevel@tonic-gate 	    "See also: \"::help queue\" and \"::help stdata\"\n");
16487c478bd9Sstevel@tonic-gate }
16497c478bd9Sstevel@tonic-gate 
16507c478bd9Sstevel@tonic-gate void
stdata_help(void)16517c478bd9Sstevel@tonic-gate stdata_help(void)
16527c478bd9Sstevel@tonic-gate {
16537c478bd9Sstevel@tonic-gate 	mdb_printf("Print stdata information for a given stdata pointer.\n"
16547c478bd9Sstevel@tonic-gate 	    "\nWithout the address of a \"stdata_t\" structure given, print "
16557c478bd9Sstevel@tonic-gate 	    "information about all\n"
16567c478bd9Sstevel@tonic-gate 	    "stream head pointers from the \"stream_head_cache\".\n\n"
16577c478bd9Sstevel@tonic-gate 	    "Fields printed:\n"
16587c478bd9Sstevel@tonic-gate 	    "	ADDR:\tstream head address\n"
16597c478bd9Sstevel@tonic-gate 	    "	WRQ:\twrite queue pointer\n"
16607c478bd9Sstevel@tonic-gate 	    "	FLAGS:\tstream head flags (use -v to show in symbolic form)\n"
16617c478bd9Sstevel@tonic-gate 	    "	VNODE:\tstream vnode pointer\n"
16627c478bd9Sstevel@tonic-gate 	    "	N/A:\tpushcount and anchor positions\n"
16637c478bd9Sstevel@tonic-gate 	    "	REF:\tstream head reference counter\n\n"
16647c478bd9Sstevel@tonic-gate 	    "Options:\n"
16657c478bd9Sstevel@tonic-gate 	    "	-v:\t\tbe verbose - print symbolic flags falues\n"
16667c478bd9Sstevel@tonic-gate 	    "	-q:\t\tbe quiet - print stdata pointer only\n"
16677c478bd9Sstevel@tonic-gate 	    "	-f flag:\tprint only stdatas with flag set\n"
16687c478bd9Sstevel@tonic-gate 	    "	-F flag:\tprint only stdatas with flag NOT set\n\n"
16697c478bd9Sstevel@tonic-gate 	    "Available conversions:\n"
16707c478bd9Sstevel@tonic-gate 	    "	str2mate:\tgiven a stream head addr print its mate\n"
16717c478bd9Sstevel@tonic-gate 	    "	str2wrq:\tgiven a stream head addr print its write queue\n\n"
16727c478bd9Sstevel@tonic-gate 	    "See also: \"::help queue\" and \"::help syncq\"\n");
16737c478bd9Sstevel@tonic-gate }
16747c478bd9Sstevel@tonic-gate 
16757c478bd9Sstevel@tonic-gate void
mblk_help(void)16767c478bd9Sstevel@tonic-gate mblk_help(void)
16777c478bd9Sstevel@tonic-gate {
16787c478bd9Sstevel@tonic-gate 	mdb_printf("Print mblock information for a given mblk pointer.\n"
16797c478bd9Sstevel@tonic-gate 	    "Without the address, print information about all mblocks.\n\n"
16807c478bd9Sstevel@tonic-gate 	    "Fields printed:\n"
16817c478bd9Sstevel@tonic-gate 	    "	ADDR:\tmblk address\n"
16827c478bd9Sstevel@tonic-gate 	    "	FL:\tFlags\n"
16837c478bd9Sstevel@tonic-gate 	    "	TYPE:\tType of corresponding dblock\n"
16847c478bd9Sstevel@tonic-gate 	    "	LEN:\tData length as b_wptr - b_rptr\n"
16857c478bd9Sstevel@tonic-gate 	    "	BLEN:\tDblock space as db_lim - db_base\n"
16867c478bd9Sstevel@tonic-gate 	    "	RPTR:\tRead pointer\n"
16877c478bd9Sstevel@tonic-gate 	    "	DBLK:\tDblock pointer\n\n"
16887c478bd9Sstevel@tonic-gate 	    "Options:\n"
16897c478bd9Sstevel@tonic-gate 	    "	-v:\t\tbe verbose - print symbolic flags falues\n"
16907c478bd9Sstevel@tonic-gate 	    "	-q:\t\tbe quiet - print mblk pointer only\n"
16917c478bd9Sstevel@tonic-gate 	    "	-d dbaddr:\t\tprint mblks with specified dblk address\n"
16927c478bd9Sstevel@tonic-gate 	    "	-f flag:\tprint only mblks with flag set\n"
16937c478bd9Sstevel@tonic-gate 	    "	-F flag:\tprint only mblks with flag NOT set\n"
16947c478bd9Sstevel@tonic-gate 	    "	-t type:\tprint only mblks of specified db_type\n"
16957c478bd9Sstevel@tonic-gate 	    "	-T type:\tprint only mblks other then the specified db_type\n"
16967c478bd9Sstevel@tonic-gate 	    "	-l len:\t\ttprint only mblks with MBLKL == len\n"
16977c478bd9Sstevel@tonic-gate 	    "	-L len:\t\tprint only mblks with MBLKL <= len \n"
16987c478bd9Sstevel@tonic-gate 	    "	-G len:\t\tprint only mblks with MBLKL >= len \n"
16997c478bd9Sstevel@tonic-gate 	    "	-b len:\t\tprint only mblks with db_lim - db_base == len\n"
17007c478bd9Sstevel@tonic-gate 	    "\n");
17017c478bd9Sstevel@tonic-gate }
1702