xref: /titanic_44/usr/src/cmd/mdb/common/modules/nsctl/nsctl.c (revision 2d6b5ea734bb47d251c82670646fde46af15fd69)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <sys/types.h>
27 #include <sys/ksynch.h>
28 #include <sys/kmem.h>
29 #include <sys/errno.h>
30 #include <sys/ddi.h>
31 
32 #include <sys/mdb_modapi.h>
33 
34 #define	__NSC_GEN__
35 #include <sys/nsc_thread.h>
36 #include <sys/nsctl/nsc_dev.h>
37 #include <sys/nsctl/nsc_gen.h>
38 #include <sys/nsctl/nsc_mem.h>
39 #include <sys/nsctl/nsctl.h>
40 #include <sys/nsctl/nsc_disk.h>
41 
42 
43 /*
44  * Data struct for the complex walks.
45  */
46 
47 struct complex_args {
48 	int		argc;
49 	mdb_arg_t	*argv;
50 };
51 
52 
53 /*
54  * Bit definitions
55  */
56 
57 #define	NSC_RW_BITS	\
58 	{ "NSC_READ", NSC_READ, NSC_READ },	\
59 	{ "NSC_WRITE", NSC_WRITE, NSC_WRITE }
60 
61 
62 static const mdb_bitmask_t nsc_bhflag_bits[] = {
63 	NSC_RW_BITS,
64 	{ "NSC_PINNABLE", NSC_PINNABLE, NSC_PINNABLE },
65 	{ "NSC_NOBLOCK", NSC_NOBLOCK, NSC_NOBLOCK },
66 	{ "NSC_HALLOCATED", NSC_HALLOCATED, NSC_HALLOCATED },
67 	{ "NSC_HACTIVE", NSC_HACTIVE, NSC_HACTIVE },
68 	{ "NSC_BCOPY", NSC_BCOPY, NSC_BCOPY },
69 	{ "NSC_PAGEIO", NSC_PAGEIO, NSC_PAGEIO },
70 	{ "NSC_ABUF", NSC_ABUF, NSC_ABUF },
71 	{ "NSC_MIXED", NSC_MIXED, NSC_MIXED },
72 	{ "NSC_WRTHRU", NSC_WRTHRU, NSC_WRTHRU },
73 	{ "NSC_FORCED_WRTHRU", NSC_FORCED_WRTHRU, NSC_FORCED_WRTHRU },
74 	{ "NSC_NOCACHE", NSC_NOCACHE, NSC_NOCACHE },
75 	{ "NSC_QUEUE", NSC_QUEUE, NSC_QUEUE },
76 	{ "NSC_RDAHEAD", NSC_RDAHEAD, NSC_RDAHEAD },
77 	{ "NSC_NO_FORCED_WRTHRU", NSC_NO_FORCED_WRTHRU, NSC_NO_FORCED_WRTHRU },
78 	{ "NSC_METADATA", NSC_METADATA, NSC_METADATA },
79 	{ "NSC_SEQ_IO", NSC_SEQ_IO, NSC_SEQ_IO },
80 	{ NULL, 0, 0 }
81 };
82 
83 
84 static const mdb_bitmask_t nsc_fdflag_bits[] = {
85 	NSC_RW_BITS,
86 	{ NULL, 0, 0 }
87 };
88 
89 
90 static const mdb_bitmask_t nsc_fdmode_bits[] = {
91 	{ "NSC_MULTI", NSC_MULTI, NSC_MULTI },
92 	{ NULL, 0, 0 }
93 };
94 
95 
96 static const mdb_bitmask_t nsc_type_bits[] = {
97 	/* types */
98 	{ "NSC_NULL", NSC_NULL, NSC_NULL },
99 	{ "NSC_DEVICE", NSC_DEVICE, NSC_DEVICE },
100 	{ "NSC_FILE", NSC_FILE, NSC_FILE },
101 	{ "NSC_CACHE", NSC_CACHE, NSC_CACHE },
102 	{ "NSC_VCHR", NSC_VCHR, NSC_VCHR },
103 	{ "NSC_NCALL", NSC_NCALL, NSC_NCALL },
104 
105 	/* type flags */
106 	{ "NSC_ANON", NSC_ANON, NSC_ANON },
107 
108 	/* ids */
109 	{ "NSC_RAW_ID", NSC_RAW_ID, NSC_RAW_ID },
110 	{ "NSC_FILE_ID", NSC_FILE_ID, NSC_FILE_ID },
111 	{ "NSC_FREEZE_ID", NSC_FREEZE_ID, NSC_FREEZE_ID },
112 	{ "NSC_VCHR_ID", NSC_VCHR_ID, NSC_VCHR_ID },
113 	{ "NSC_NCALL_ID", NSC_NCALL_ID, NSC_NCALL_ID },
114 	{ "NSC_SDBC_ID", NSC_SDBC_ID, NSC_SDBC_ID },
115 	{ "NSC_RDCLR_ID", NSC_RDCLR_ID, NSC_RDCLR_ID },
116 	{ "NSC_RDCL_ID", NSC_RDCL_ID, NSC_RDCL_ID },
117 	{ "NSC_IIR_ID", NSC_IIR_ID, NSC_IIR_ID },
118 	{ "NSC_II_ID", NSC_II_ID, NSC_II_ID },
119 	{ "NSC_RDCHR_ID", NSC_RDCHR_ID, NSC_RDCHR_ID },
120 	{ "NSC_RDCH_ID", NSC_RDCH_ID, NSC_RDCH_ID },
121 	{ NULL, 0, 0 }
122 };
123 
124 
125 static const mdb_bitmask_t nsc_availpend_bits[] = {
126 	NSC_RW_BITS,
127 	{ "_NSC_OPEN", _NSC_OPEN, _NSC_OPEN },
128 	{ "_NSC_CLOSE", _NSC_CLOSE, _NSC_CLOSE },
129 	{ "_NSC_PINNED", _NSC_PINNED, _NSC_PINNED },
130 	{ "_NSC_ATTACH", _NSC_ATTACH, _NSC_ATTACH },
131 	{ "_NSC_DETACH", _NSC_DETACH, _NSC_DETACH },
132 	{ "_NSC_OWNER", _NSC_OWNER, _NSC_OWNER },
133 	{ NULL, 0, 0 }
134 };
135 
136 
137 static const mdb_bitmask_t nsc_ioflag_bits[] = {
138 	{ "NSC_REFCNT", NSC_REFCNT, NSC_REFCNT },
139 	{ "NSC_FILTER", NSC_FILTER, NSC_FILTER },
140 	{ NULL, 0, 0 }
141 };
142 
143 
144 static const mdb_bitmask_t nstset_flag_bits[] = {
145 	{ "NST_SF_KILL", NST_SF_KILL, NST_SF_KILL },
146 	{ NULL, 0, 0 }
147 };
148 
149 
150 static const mdb_bitmask_t nst_flag_bits[] = {
151 	{ "NST_TF_INUSE", NST_TF_INUSE, NST_TF_INUSE },
152 	{ "NST_TF_ACTIVE", NST_TF_ACTIVE, NST_TF_ACTIVE },
153 	{ "NST_TF_PENDING", NST_TF_PENDING, NST_TF_PENDING },
154 	{ "NST_TF_DESTROY", NST_TF_DESTROY, NST_TF_DESTROY },
155 	{ "NST_TF_KILL", NST_TF_KILL, NST_TF_KILL },
156 	{ NULL, 0, 0 }
157 };
158 
159 
160 /*
161  * Global data.
162  */
163 
164 static nsc_mem_t type_mem[20];
165 static int complex_walk;
166 static int complex_hdr;
167 
168 
169 /* ---------------------------------------------------------------------- */
170 
171 /*
172  * Walker for an nsc_io chain.
173  * A global walk is assumed to start at _nsc_io_top.
174  */
175 
176 static int
177 nsc_io_winit(mdb_walk_state_t *wsp)
178 {
179 	if (wsp->walk_addr == NULL &&
180 	    mdb_readvar(&wsp->walk_addr, "_nsc_io_top") == -1) {
181 		mdb_warn("unable to read '_nsc_io_top'");
182 		return (WALK_ERR);
183 	}
184 
185 	return (WALK_NEXT);
186 }
187 
188 
189 static int
190 nsc_io_wstep(mdb_walk_state_t *wsp)
191 {
192 	uintptr_t next;
193 	int status;
194 
195 	if (wsp->walk_addr == NULL)
196 		return (WALK_DONE);
197 
198 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
199 	    wsp->walk_cbdata);
200 
201 	next = wsp->walk_addr + OFFSETOF(nsc_io_t, next);
202 
203 	if (mdb_vread(&wsp->walk_addr, sizeof (uintptr_t), next) == -1) {
204 		mdb_warn("failed to read nsc_io_t.next at %p", next);
205 		return (WALK_DONE);
206 	}
207 
208 	return (status);
209 }
210 
211 
212 /* ---------------------------------------------------------------------- */
213 
214 /*
215  * Walker for an nsc_dev chain.
216  * A global walk is assumed to start at _nsc_dev_top.
217  */
218 
219 static int
220 nsc_dev_winit(mdb_walk_state_t *wsp)
221 {
222 	if (wsp->walk_addr == NULL &&
223 	    mdb_readvar(&wsp->walk_addr, "_nsc_dev_top") == -1) {
224 		mdb_warn("unable to read '_nsc_dev_top'");
225 		return (WALK_ERR);
226 	}
227 
228 	return (WALK_NEXT);
229 }
230 
231 
232 static int
233 nsc_dev_wstep(mdb_walk_state_t *wsp)
234 {
235 	uintptr_t next;
236 	int status;
237 
238 	if (wsp->walk_addr == NULL)
239 		return (WALK_DONE);
240 
241 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
242 	    wsp->walk_cbdata);
243 
244 	next = wsp->walk_addr + OFFSETOF(nsc_dev_t, nsc_next);
245 
246 	if (mdb_vread(&wsp->walk_addr, sizeof (uintptr_t), next) == -1) {
247 		mdb_warn("failed to read nsc_dev_t.nsc_next at %p", next);
248 		return (WALK_DONE);
249 	}
250 
251 	return (status);
252 }
253 
254 
255 /* ARGSUSED */
256 
257 static void
258 nsc_dev_wfini(mdb_walk_state_t *wsp)
259 {
260 	complex_walk = 0;
261 }
262 
263 
264 /* ---------------------------------------------------------------------- */
265 
266 /*
267  * Walker for a chain of nsc_devval_t structures.
268  * Global walks start from _nsc_devval_top;
269  */
270 
271 static int
272 nsc_devval_winit(mdb_walk_state_t *wsp)
273 {
274 	if (wsp->walk_addr == NULL &&
275 	    mdb_readvar(&wsp->walk_addr, "_nsc_devval_top") == -1) {
276 		mdb_warn("unable to read '_nsc_devval_top'");
277 		return (WALK_ERR);
278 	}
279 
280 	return (WALK_NEXT);
281 }
282 
283 
284 static int
285 nsc_devval_wstep(mdb_walk_state_t *wsp)
286 {
287 	uintptr_t devval = wsp->walk_addr;
288 	int status;
289 
290 	if (!devval)
291 		return (WALK_DONE);
292 
293 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
294 	    wsp->walk_cbdata);
295 
296 	/* move on to next devval */
297 
298 	if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr),
299 	    devval + OFFSETOF(nsc_devval_t, dv_next)) == -1) {
300 		mdb_warn("failed to read nsc_devval_t.dv_next");
301 		return (WALK_ERR);
302 	}
303 
304 	return (status);
305 }
306 
307 
308 /* ---------------------------------------------------------------------- */
309 
310 /*
311  * Walker for a chain of nsc_fd_t structures.
312  * No global walks.
313  */
314 
315 static int
316 nsc_fd_winit(mdb_walk_state_t *wsp)
317 {
318 	if (wsp->walk_addr == NULL) {
319 		mdb_warn("nsc_fd doesn't support global walks");
320 		return (WALK_ERR);
321 	}
322 
323 	return (WALK_NEXT);
324 }
325 
326 
327 static int
328 nsc_fd_wstep(mdb_walk_state_t *wsp)
329 {
330 	uintptr_t fd = wsp->walk_addr;
331 	int status;
332 
333 	if (!fd)
334 		return (WALK_DONE);
335 
336 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
337 	    wsp->walk_cbdata);
338 
339 	/* move on to next fd */
340 
341 	if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr),
342 	    fd + OFFSETOF(nsc_fd_t, sf_next)) == -1) {
343 		mdb_warn("failed to read nsc_fd_t.sf_next");
344 		return (WALK_ERR);
345 	}
346 
347 	return (status);
348 }
349 
350 
351 /* ---------------------------------------------------------------------- */
352 
353 /*
354  * Walker for a chain of nsc_iodev_t structures.
355  * No global walks.
356  */
357 
358 static int
359 nsc_iodev_winit(mdb_walk_state_t *wsp)
360 {
361 	if (wsp->walk_addr == NULL) {
362 		mdb_warn("nsc_iodev doesn't support global walks");
363 		return (WALK_ERR);
364 	}
365 
366 	return (WALK_NEXT);
367 }
368 
369 
370 static int
371 nsc_iodev_wstep(mdb_walk_state_t *wsp)
372 {
373 	uintptr_t iodev = wsp->walk_addr;
374 	int status;
375 
376 	if (!iodev)
377 		return (WALK_DONE);
378 
379 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
380 	    wsp->walk_cbdata);
381 
382 	if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr),
383 	    iodev + OFFSETOF(nsc_iodev_t, si_next)) == -1) {
384 		mdb_warn("failed to read nsc_iodev_t.si_next");
385 		return (WALK_ERR);
386 	}
387 
388 	return (status);
389 }
390 
391 
392 /* ---------------------------------------------------------------------- */
393 
394 /*
395  * Walker for a chain of nsc_service_t structures.
396  * Global walks start at _nsc_services.
397  */
398 
399 static int
400 nsc_service_winit(mdb_walk_state_t *wsp)
401 {
402 	if (wsp->walk_addr == NULL &&
403 	    mdb_readvar(&wsp->walk_addr, "_nsc_services") == -1) {
404 		mdb_warn("unable to read '_nsc_services'");
405 		return (WALK_ERR);
406 	}
407 
408 	return (WALK_NEXT);
409 }
410 
411 
412 static int
413 nsc_service_wstep(mdb_walk_state_t *wsp)
414 {
415 	uintptr_t service = wsp->walk_addr;
416 	int status;
417 
418 	if (!service)
419 		return (WALK_DONE);
420 
421 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
422 	    wsp->walk_cbdata);
423 
424 	/* move on to next service */
425 
426 	if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr),
427 	    service + OFFSETOF(nsc_service_t, s_next)) == -1) {
428 		mdb_warn("failed to read nsc_service_t.s_next");
429 		return (WALK_ERR);
430 	}
431 
432 	return (status);
433 }
434 
435 
436 /* ---------------------------------------------------------------------- */
437 
438 /*
439  * Walker for a chain of nsc_svc_t structures.
440  * No global walks.
441  */
442 
443 static int
444 nsc_svc_winit(mdb_walk_state_t *wsp)
445 {
446 	if (wsp->walk_addr == NULL) {
447 		mdb_warn("nsc_svc does not support global walks");
448 		return (WALK_ERR);
449 	}
450 
451 	return (WALK_NEXT);
452 }
453 
454 
455 static int
456 nsc_svc_wstep(mdb_walk_state_t *wsp)
457 {
458 	uintptr_t svc = wsp->walk_addr;
459 	int status;
460 
461 	if (!svc)
462 		return (WALK_DONE);
463 
464 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
465 	    wsp->walk_cbdata);
466 
467 	/* move on to next svc */
468 
469 	if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr),
470 	    svc + OFFSETOF(nsc_svc_t, svc_next)) == -1) {
471 		mdb_warn("failed to read nsc_svc_t.svc_next");
472 		return (WALK_ERR);
473 	}
474 
475 	return (status);
476 }
477 
478 
479 /* ---------------------------------------------------------------------- */
480 
481 /*
482  * Walker for a chain of nsc_val_t structures.
483  * No global walks.
484  */
485 
486 static int
487 nsc_val_winit(mdb_walk_state_t *wsp)
488 {
489 	if (wsp->walk_addr == NULL) {
490 		mdb_warn("nsc_val doesn't support global walks");
491 		return (WALK_ERR);
492 	}
493 
494 	return (WALK_NEXT);
495 }
496 
497 
498 static int
499 nsc_val_wstep(mdb_walk_state_t *wsp)
500 {
501 	uintptr_t val = wsp->walk_addr;
502 	int status;
503 
504 	if (!val)
505 		return (WALK_DONE);
506 
507 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
508 	    wsp->walk_cbdata);
509 
510 	/* move on to next val */
511 
512 	if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr),
513 	    val + OFFSETOF(nsc_val_t, sv_next)) == -1) {
514 		mdb_warn("failed to read nsc_val_t.sv_next");
515 		return (WALK_ERR);
516 	}
517 
518 	return (status);
519 }
520 
521 
522 /* ---------------------------------------------------------------------- */
523 
524 /*
525  * Walker for a chain of nstset_t structures.
526  * Global walks start at _nst_sets.
527  */
528 
529 static int
530 nstset_winit(mdb_walk_state_t *wsp)
531 {
532 	if (wsp->walk_addr == NULL &&
533 	    mdb_readvar(&wsp->walk_addr, "nst_sets") == -1) {
534 		mdb_warn("unable to read 'nst_sets'");
535 		return (WALK_ERR);
536 	}
537 
538 	return (WALK_NEXT);
539 }
540 
541 
542 static int
543 nstset_wstep(mdb_walk_state_t *wsp)
544 {
545 	uintptr_t set = wsp->walk_addr;
546 	int status;
547 
548 	if (!set)
549 		return (WALK_DONE);
550 
551 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
552 	    wsp->walk_cbdata);
553 
554 	/* move on to next set */
555 
556 	if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr),
557 	    set + OFFSETOF(nstset_t, set_next)) == -1) {
558 		mdb_warn("failed to read nstset_t.set_next");
559 		return (WALK_ERR);
560 	}
561 
562 	return (status);
563 }
564 
565 
566 /* ---------------------------------------------------------------------- */
567 
568 /*
569  * Walker for a chain of nsthread_t structures.
570  * No global walks.
571  */
572 
573 static int
574 nsthread_winit(mdb_walk_state_t *wsp)
575 {
576 	if (wsp->walk_addr == NULL) {
577 		mdb_warn("nsthread does not support global walks");
578 		return (WALK_ERR);
579 	}
580 
581 	return (WALK_NEXT);
582 }
583 
584 
585 static int
586 nsthread_wstep(mdb_walk_state_t *wsp)
587 {
588 	uintptr_t thread = wsp->walk_addr;
589 	int status;
590 
591 	if (!thread)
592 		return (WALK_DONE);
593 
594 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
595 	    wsp->walk_cbdata);
596 
597 	/* move on to next iodev */
598 
599 	if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr),
600 	    thread + OFFSETOF(nsthread_t, tp_chain)) == -1) {
601 		mdb_warn("failed to read nsthread_t.tp_chain");
602 		return (WALK_ERR);
603 	}
604 
605 	return (status);
606 }
607 
608 
609 /* ---------------------------------------------------------------------- */
610 
611 /*
612  * Walker for nsthread_t free/reuse chain.
613  * No global walks.
614  */
615 
616 static int
617 nst_free_winit(mdb_walk_state_t *wsp)
618 {
619 	if (wsp->walk_addr == NULL) {
620 		mdb_warn("nst_free does not support global walks");
621 		return (WALK_ERR);
622 	}
623 
624 	/* store starting address */
625 
626 	wsp->walk_data = (void *)wsp->walk_addr;
627 
628 	/* move on to next thread */
629 
630 	if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr),
631 	    wsp->walk_addr + OFFSETOF(nsthread_t, tp_link.q_forw)) == -1) {
632 		mdb_warn("failed to read nsthread_t.tp_link.q_forw");
633 		return (WALK_ERR);
634 	}
635 
636 	return (WALK_NEXT);
637 }
638 
639 
640 static int
641 nst_free_wstep(mdb_walk_state_t *wsp)
642 {
643 	uintptr_t thread = wsp->walk_addr;
644 	int status;
645 
646 	if (!thread)
647 		return (WALK_DONE);
648 
649 	if (thread == (uintptr_t)wsp->walk_data)
650 		return (WALK_DONE);
651 
652 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
653 	    wsp->walk_cbdata);
654 
655 	/* move on to next thread */
656 
657 	if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr),
658 	    thread + OFFSETOF(nsthread_t, tp_link.q_forw)) == -1) {
659 		mdb_warn("failed to read nsthread_t.tp_link.q_forw");
660 		return (WALK_ERR);
661 	}
662 
663 	return (status);
664 }
665 
666 
667 /* ---------------------------------------------------------------------- */
668 
669 /*
670  * Walker for a chain of nsc_mem_t structures.
671  * Global walks start at _nsc_mem_top.
672  */
673 
674 static int
675 nsc_mem_winit(mdb_walk_state_t *wsp)
676 {
677 	if (wsp->walk_addr == NULL &&
678 	    mdb_readvar(&wsp->walk_addr, "_nsc_mem_top") == -1) {
679 		mdb_warn("unable to read '_nsc_mem_top'");
680 		return (WALK_ERR);
681 	}
682 
683 	return (WALK_NEXT);
684 }
685 
686 
687 static int
688 nsc_mem_wstep(mdb_walk_state_t *wsp)
689 {
690 	uintptr_t mem = wsp->walk_addr;
691 	int status;
692 
693 	if (!mem)
694 		return (WALK_DONE);
695 
696 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
697 	    wsp->walk_cbdata);
698 
699 	/* move on to next mem */
700 
701 	if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr),
702 	    mem + OFFSETOF(nsc_mem_t, next)) == -1) {
703 		mdb_warn("failed to read nsc_mem_t.next");
704 		return (WALK_ERR);
705 	}
706 
707 	return (status);
708 }
709 
710 
711 /* ---------------------------------------------------------------------- */
712 
713 struct {
714 	char	*name;
715 	int	id;
716 } io_ids[] = {
717 	{ "NSC_RAW_ID", NSC_RAW_ID },
718 	{ "NSC_FILE_ID", NSC_FILE_ID },
719 	{ "NSC_FREEZE_ID", NSC_FREEZE_ID },
720 	{ "NSC_SDBC_ID", NSC_SDBC_ID },
721 	{ "NSC_RDCLR_ID", NSC_RDCLR_ID },
722 	{ "NSC_RDCL_ID", NSC_RDCL_ID },
723 	{ "NSC_IIR_ID", NSC_IIR_ID },
724 	{ "NSC_II_ID", NSC_II_ID },
725 	{ "NSC_RDCHR_ID", NSC_RDCHR_ID },
726 	{ "NSC_RDCH_ID", NSC_RDCH_ID },
727 	{ NULL, 0 }
728 };
729 
730 
731 static char *
732 nsc_io_id(const int id)
733 {
734 	int i;
735 
736 	for (i = 0; io_ids[i].name != NULL; i++) {
737 		if (io_ids[i].id == id) {
738 			return (io_ids[i].name);
739 		}
740 	}
741 
742 	return ("unknown");
743 }
744 
745 
746 /*
747  * Display a single nsc_io_t structure.
748  * If called with no address, performs a global walk of all nsc_ios.
749  */
750 static int
751 nsc_io(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
752 {
753 	char io_name[128];
754 	nsc_io_t *io;
755 	int v_opt;
756 
757 	v_opt = 0;
758 
759 	if (mdb_getopts(argc, argv,
760 	    'v', MDB_OPT_SETBITS, TRUE, &v_opt) != argc)
761 		return (DCMD_USAGE);
762 
763 	if (!(flags & DCMD_ADDRSPEC)) {
764 		if (mdb_walk_dcmd("nsctl`nsc_io",
765 		    "nsctl`nsc_io", argc, argv) == -1) {
766 			mdb_warn("failed to walk 'nsc_io'");
767 			return (DCMD_ERR);
768 		}
769 
770 		return (DCMD_OK);
771 	}
772 
773 	io = mdb_zalloc(sizeof (*io), UM_SLEEP | UM_GC);
774 	memset(io_name, 0, sizeof (io_name));
775 
776 	if (mdb_vread(io, sizeof (*io), addr) != sizeof (*io)) {
777 		mdb_warn("failed to read nsc_io at %p", addr);
778 		return (DCMD_ERR);
779 	}
780 
781 	if (io->name) {
782 		if (mdb_readstr(io_name, sizeof (io_name),
783 		    (uintptr_t)io->name) == -1) {
784 			mdb_warn("failed to read nsc_io_t.name");
785 			return (DCMD_ERR);
786 		}
787 	}
788 
789 	if (DCMD_HDRSPEC(flags)) {
790 		mdb_printf("%-?s  %8Tid       fl  ref abuf name\n", "io");
791 	}
792 
793 	mdb_printf("%0?p  %8T%08x %2x %4d %4d %s\n",
794 	    addr, io->id, io->flag, io->refcnt, io->abufcnt, io_name);
795 
796 	if (!v_opt)
797 		return (DCMD_OK);
798 
799 	mdb_inc_indent(4);
800 
801 	mdb_printf("id: %08x <%s>\n", io->id, nsc_io_id(io->id));
802 
803 	mdb_printf("provide: %08x <%b>\n", io->provide,
804 	    io->provide, nsc_type_bits);
805 
806 	mdb_printf("flag: %08x <%b>\n", io->flag, io->flag, nsc_ioflag_bits);
807 
808 	mdb_printf("pend: %d\n", io->pend);
809 
810 	mdb_dec_indent(4);
811 
812 	return (DCMD_OK);
813 }
814 
815 
816 /* ---------------------------------------------------------------------- */
817 
818 /*
819  * Display a single nsc_dev_t structure.
820  * If called with no address, performs a global walk of all nsc_devs.
821  */
822 static int
823 nsc_dev(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
824 {
825 	char path[NSC_MAXPATH+1];
826 	nsc_devval_t *dv;
827 	nsc_dev_t *dev;
828 	uintptr_t dev_pend;
829 	int a_opt, v_opt;
830 
831 	a_opt = v_opt = 0;
832 
833 	if (mdb_getopts(argc, argv,
834 	    'a', MDB_OPT_SETBITS, TRUE, &a_opt,
835 	    'v', MDB_OPT_SETBITS, TRUE, &v_opt) != argc)
836 		return (DCMD_USAGE);
837 
838 	if (!(flags & DCMD_ADDRSPEC)) {
839 		mdb_printf("Active device structures:\n");
840 
841 		if (mdb_walk_dcmd("nsctl`nsc_dev",
842 		    "nsctl`nsc_dev", argc, argv) == -1) {
843 			mdb_warn("failed to walk 'nsc_dev'");
844 			return (DCMD_ERR);
845 		}
846 
847 		if (a_opt) {
848 			if (mdb_readvar(&dev_pend, "_nsc_dev_pend") == -1) {
849 				mdb_warn("failed to read _nsc_dev_pend");
850 				return (DCMD_ERR);
851 			}
852 
853 			mdb_printf("\nPending device structures:");
854 
855 			if (dev_pend) {
856 				mdb_printf("\n");
857 
858 				if (mdb_pwalk_dcmd("nsctl`nsc_dev",
859 				    "nsctl`nsc_dev", argc, argv,
860 				    dev_pend) == -1) {
861 					mdb_warn("failed to walk "
862 					    "pending dev structs");
863 					return (DCMD_ERR);
864 				}
865 			} else {
866 				mdb_printf(" none\n");
867 			}
868 		}
869 
870 		return (DCMD_OK);
871 	}
872 
873 	memset(path, 0, sizeof (path));
874 	dev = mdb_zalloc(sizeof (*dev), UM_SLEEP | UM_GC);
875 
876 	if (mdb_vread(dev, sizeof (*dev), addr) != sizeof (*dev)) {
877 		mdb_warn("failed to read nsc_dev at %p", addr);
878 		return (DCMD_ERR);
879 	}
880 
881 	if (mdb_readstr(path, sizeof (path), (uintptr_t)dev->nsc_path) == -1) {
882 		mdb_warn("failed to read nsc_path at %p", dev->nsc_path);
883 		return (DCMD_ERR);
884 	}
885 
886 	if (DCMD_HDRSPEC(flags)) {
887 		mdb_printf("%-?s  %8Tref pend rpnd wait path\n", "dev");
888 	}
889 
890 	mdb_printf("%0?p  %8T%3d %4d %4d %4d %s\n",
891 	    addr, dev->nsc_refcnt, dev->nsc_pend, dev->nsc_rpend,
892 	    dev->nsc_wait, path);
893 
894 	if (!v_opt)
895 		return (DCMD_OK);
896 
897 	mdb_inc_indent(4);
898 
899 	mdb_printf("next: %0?p  %8Tclose: %0?p\n",
900 	    dev->nsc_next, dev->nsc_close);
901 
902 	mdb_printf("list: %0?p  %8Tlock: %0?p\n",
903 	    dev->nsc_list, addr + OFFSETOF(nsc_dev_t, nsc_lock));
904 
905 	mdb_printf("cv: %0?p  %8Tpath: %0?p  %8Tphash: %016llx\n",
906 	    addr + OFFSETOF(nsc_dev_t, nsc_cv),
907 	    dev->nsc_path, dev->nsc_phash);
908 
909 	mdb_printf("drop: %d  %8Treopen: %d\n",
910 	    dev->nsc_drop, dev->nsc_reopen);
911 
912 	if (dev->nsc_values) {
913 		dv = mdb_zalloc(sizeof (*dv), UM_SLEEP | UM_GC);
914 		if (mdb_vread(dv, sizeof (*dv), (uintptr_t)dev->nsc_values) !=
915 		    sizeof (*dv)) {
916 			mdb_warn("unable to read nsc_dev_t.nsc_values");
917 			mdb_dec_indent(4);
918 			return (DCMD_ERR);
919 		}
920 
921 		if (dv->dv_values) {
922 			mdb_printf("device/values: (nsc_devval: %0?p)\n",
923 			    dev->nsc_values);
924 
925 			mdb_inc_indent(4);
926 
927 			if (mdb_pwalk_dcmd("nsctl`nsc_val", "nsctl`nsc_val",
928 			    0, NULL, (uintptr_t)dv->dv_values) == -1) {
929 				mdb_dec_indent(8);
930 				return (DCMD_ERR);
931 			}
932 
933 			mdb_dec_indent(4);
934 		}
935 	}
936 
937 	mdb_dec_indent(4);
938 
939 	return (DCMD_OK);
940 }
941 
942 
943 /* ---------------------------------------------------------------------- */
944 
945 /*
946  * Display a single nsc_devval_t structure.
947  * If called with no address, performs a global walk of all nsc_devs.
948  */
949 static int
950 nsc_devval(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
951 {
952 	nsc_devval_t *dv;
953 	int a_opt;
954 
955 	a_opt = 0;
956 
957 	if (mdb_getopts(argc, argv,
958 	    'a', MDB_OPT_SETBITS, TRUE, &a_opt) != argc)
959 		return (DCMD_USAGE);
960 
961 	if (!(flags & DCMD_ADDRSPEC)) {
962 		if (mdb_walk_dcmd("nsctl`nsc_devval",
963 		    "nsctl`nsc_devval", argc, argv) == -1) {
964 			mdb_warn("failed to walk 'nsc_devval'");
965 			return (DCMD_ERR);
966 		}
967 
968 		return (DCMD_OK);
969 	}
970 
971 	dv = mdb_zalloc(sizeof (*dv), UM_SLEEP | UM_GC);
972 
973 	if (mdb_vread(dv, sizeof (*dv), addr) != sizeof (*dv)) {
974 		mdb_warn("failed to read nsc_devval at %p", addr);
975 		return (DCMD_ERR);
976 	}
977 
978 	if (!a_opt && !dv->dv_values) {
979 		return (DCMD_OK);
980 	}
981 
982 	if (DCMD_HDRSPEC(flags)) {
983 		mdb_printf("%-?s  %8T%?-s  %8Tpath\n", "devval", "phash");
984 	}
985 
986 	mdb_printf("%0?p  %8T%016llx  %8T%s\n", addr,
987 	    dv->dv_phash, dv->dv_path);
988 
989 	mdb_inc_indent(4);
990 
991 	if (dv->dv_values) {
992 		if (mdb_pwalk_dcmd("nsctl`nsc_val", "nsctl`nsc_val",
993 		    0, NULL, (uintptr_t)dv->dv_values) == -1) {
994 			return (DCMD_ERR);
995 		}
996 	} else {
997 		mdb_printf("No values\n");
998 	}
999 
1000 	mdb_dec_indent(4);
1001 
1002 	return (DCMD_OK);
1003 }
1004 
1005 
1006 /* ---------------------------------------------------------------------- */
1007 
1008 /*
1009  * Part 2 callback for the all devices and fds walk.  Called per iodev.
1010  */
1011 /* ARGSUSED */
1012 static int
1013 nsc_fd_iodev(uintptr_t addr, const void *data, void *cbdata)
1014 {
1015 	struct complex_args *fdall = cbdata;
1016 	struct nsc_fd_t *fd;
1017 
1018 	if (mdb_vread(&fd, sizeof (fd),
1019 	    addr + OFFSETOF(nsc_iodev_t, si_open)) == -1) {
1020 		mdb_warn("unable to read nsc_iodev_t.si_open");
1021 		return (WALK_ERR);
1022 	}
1023 
1024 	if (fd != NULL) {
1025 		if (mdb_pwalk_dcmd("nsctl`nsc_fd", "nsctl`nsc_fd",
1026 		    fdall->argc, fdall->argv, (uintptr_t)fd) == -1)
1027 			return (WALK_ERR);
1028 	}
1029 
1030 	return (WALK_NEXT);
1031 }
1032 
1033 
1034 /*
1035  * Part 1 callback for the all devices and fds walk.  Called per device.
1036  */
1037 /* ARGSUSED */
1038 static int
1039 nsc_fd_dev(uintptr_t addr, const void *data, void *cbdata)
1040 {
1041 	struct complex_args *fdall = cbdata;
1042 	nsc_iodev_t *iodev;
1043 	nsc_fd_t *fd;
1044 
1045 	if (mdb_vread(&iodev, sizeof (iodev),
1046 	    addr + OFFSETOF(nsc_dev_t, nsc_list)) == -1) {
1047 		mdb_warn("unable to read nsc_dev_t.nsc_list at %p", addr);
1048 		return (WALK_ERR);
1049 	}
1050 
1051 	/* walk iodev chains */
1052 
1053 	if (iodev != NULL) {
1054 		if (mdb_pwalk("nsctl`nsc_iodev",
1055 		    nsc_fd_iodev, fdall, (uintptr_t)iodev) == -1)
1056 			return (WALK_ERR);
1057 	}
1058 
1059 	/* walk nsc_close (closing fds) chains */
1060 
1061 	if (mdb_vread(&fd, sizeof (fd),
1062 	    addr + OFFSETOF(nsc_dev_t, nsc_close)) == -1) {
1063 		mdb_warn("unable to read nsc_dev_t.nsc_close at %p", addr);
1064 		return (WALK_ERR);
1065 	}
1066 
1067 	if (fd != NULL) {
1068 		if (mdb_pwalk_dcmd("nsctl`nsc_fd", "nsctl`nsc_fd",
1069 		    fdall->argc, fdall->argv, (uintptr_t)fd) == -1)
1070 			return (WALK_ERR);
1071 	}
1072 
1073 	return (WALK_NEXT);
1074 }
1075 
1076 
1077 /*
1078  * Walk all devices and fds in the system.
1079  */
1080 static int
1081 nsc_fd_all(int argc, const mdb_arg_t *argv)
1082 {
1083 	struct complex_args fdall;
1084 
1085 	fdall.argc = argc;
1086 	fdall.argv = (mdb_arg_t *)argv;
1087 
1088 	complex_walk = 1;
1089 	complex_hdr = 0;
1090 
1091 	if (mdb_walk("nsctl`nsc_dev", nsc_fd_dev, &fdall) == -1) {
1092 		return (DCMD_ERR);
1093 	}
1094 
1095 	return (DCMD_OK);
1096 }
1097 
1098 
1099 
1100 /*
1101  * Display an nsd_fd_t structure, or walk all devices and fds in the system.
1102  */
1103 static int
1104 nsc_fd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1105 {
1106 	char io_name[128], *io_namep;
1107 	char path[NSC_MAXPATH+1];
1108 	uintptr_t pathp;
1109 	nsc_fd_t *fd;
1110 	nsc_io_t *io;
1111 	int v_opt;
1112 	int hdr;
1113 
1114 	v_opt = 0;
1115 
1116 	if (mdb_getopts(argc, argv,
1117 	    'v', MDB_OPT_SETBITS, TRUE, &v_opt) != argc)
1118 		return (DCMD_USAGE);
1119 
1120 	if (!(flags & DCMD_ADDRSPEC)) {
1121 		return (nsc_fd_all(argc, argv));
1122 	}
1123 
1124 	memset(path, 0, sizeof (path));
1125 	fd = mdb_zalloc(sizeof (*fd), UM_SLEEP | UM_GC);
1126 	memset(io_name, 0, sizeof (io_name));
1127 
1128 	if (mdb_vread(fd, sizeof (*fd), addr) != sizeof (*fd)) {
1129 		mdb_warn("failed to read nsc_fd at %p", addr);
1130 		return (DCMD_ERR);
1131 	}
1132 
1133 	if (mdb_vread(&pathp, sizeof (pathp),
1134 	    (uintptr_t)fd->sf_dev + OFFSETOF(nsc_dev_t, nsc_path)) !=
1135 	    sizeof (pathp)) {
1136 		mdb_warn("failed to read nsc_dev.nsc_path");
1137 		return (DCMD_ERR);
1138 	}
1139 
1140 	if (mdb_readstr(path, sizeof (path), pathp) == -1) {
1141 		mdb_warn("failed to read nsc_path");
1142 		return (DCMD_ERR);
1143 	}
1144 
1145 	if (fd->sf_iodev) {
1146 		if (mdb_vread(&io, sizeof (io),
1147 		    (uintptr_t)fd->sf_iodev + OFFSETOF(nsc_iodev_t, si_io)) !=
1148 		    sizeof (io)) {
1149 			mdb_warn("failed to read nsc_iodev.si_io");
1150 			return (DCMD_ERR);
1151 		}
1152 
1153 		if (mdb_vread(&io_namep, sizeof (io_namep),
1154 		    (uintptr_t)io + OFFSETOF(nsc_io_t, name)) !=
1155 		    sizeof (io_namep)) {
1156 			mdb_warn("failed to read nsc_io_t.name");
1157 			return (DCMD_ERR);
1158 		}
1159 
1160 		if (mdb_readstr(io_name, sizeof (io_name),
1161 		    (uintptr_t)io_namep) == -1) {
1162 			mdb_warn("failed to read nsc_io_t.name string");
1163 			return (DCMD_ERR);
1164 		}
1165 	}
1166 
1167 	hdr = 0;
1168 	if (complex_walk) {
1169 		if (!complex_hdr) {
1170 			complex_hdr = 1;
1171 			hdr = 1;
1172 		}
1173 	} else if (DCMD_HDRSPEC(flags)) {
1174 		hdr = 1;
1175 	}
1176 
1177 	if (hdr) {
1178 		mdb_printf("%-?s  %8T%-?s  %8T%-8s  %-?s\n",
1179 		    "fd", "dev", "io", "cd");
1180 		mdb_printf("    %-?s  %8Trv pend av path\n", "arg");
1181 	}
1182 
1183 	mdb_printf("%0?p  %8T%0?p  %8T%-8s  %p\n",
1184 	    addr, fd->sf_dev, io_name, fd->sf_cd);
1185 	mdb_printf("    %0?p  %8T%2d %4x %2x %s\n",
1186 	    fd->sf_arg, fd->sf_reserve, fd->sf_pend,
1187 	    fd->sf_avail, path);
1188 
1189 	if (!v_opt)
1190 		return (DCMD_OK);
1191 
1192 	mdb_inc_indent(4);
1193 
1194 	mdb_printf("open type: %08x <%b>\n", fd->sf_type,
1195 	    fd->sf_type, nsc_type_bits);
1196 
1197 	mdb_printf("avail: %08x <%b>\n", fd->sf_avail,
1198 	    fd->sf_avail, nsc_availpend_bits);
1199 
1200 	mdb_printf("flag: %08x <%b>\n", fd->sf_flag,
1201 	    fd->sf_flag, nsc_fdflag_bits);
1202 
1203 	mdb_printf("rsrv mode: %08x <%b>\n", fd->sf_mode,
1204 	    fd->sf_mode, nsc_fdmode_bits);
1205 
1206 	mdb_printf("open lbolt: %?x  %8Treopen: %d\n", fd->sf_lbolt,
1207 	    fd->sf_reopen);
1208 
1209 	mdb_dec_indent(4);
1210 
1211 	return (DCMD_OK);
1212 }
1213 
1214 
1215 /* ---------------------------------------------------------------------- */
1216 
1217 /*
1218  * Callback for the all devices and iodevs walk.  Called per device.
1219  */
1220 /* ARGSUSED */
1221 static int
1222 nsc_iodev_dev(uintptr_t addr, const void *data, void *cbdata)
1223 {
1224 	struct complex_args *iodevall = cbdata;
1225 	uintptr_t iodev;
1226 
1227 	if (mdb_vread(&iodev, sizeof (iodev),
1228 	    addr + OFFSETOF(nsc_dev_t, nsc_list)) == -1) {
1229 		mdb_warn("unable to read nsc_dev_t.nsc_list at %p", addr);
1230 		return (WALK_ERR);
1231 	}
1232 
1233 	/* walk iodev chains */
1234 
1235 	if (iodev != NULL) {
1236 		if (mdb_pwalk_dcmd("nsctl`nsc_iodev", "nsctl`nsc_iodev",
1237 		    iodevall->argc, iodevall->argv, iodev) == -1)
1238 			return (WALK_ERR);
1239 	}
1240 
1241 	return (WALK_NEXT);
1242 }
1243 
1244 
1245 /*
1246  * Walk all devices and iodevs in the system.
1247  */
1248 static int
1249 nsc_iodev_all(int argc, const mdb_arg_t *argv)
1250 {
1251 	struct complex_args iodevall;
1252 
1253 	iodevall.argc = argc;
1254 	iodevall.argv = (mdb_arg_t *)argv;
1255 
1256 	complex_walk = 1;
1257 	complex_hdr = 0;
1258 
1259 	if (mdb_walk("nsctl`nsc_dev", nsc_iodev_dev, &iodevall) == -1) {
1260 		return (DCMD_ERR);
1261 	}
1262 
1263 	return (DCMD_OK);
1264 }
1265 
1266 
1267 /*
1268  * Display an nsc_iodev_t structure, or walk all devices and
1269  * iodevs in the system.
1270  */
1271 static int
1272 nsc_iodev(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1273 {
1274 	char io_name[128], *io_namep;
1275 	char path[NSC_MAXPATH+1];
1276 	nsc_iodev_t *iodev;
1277 	uintptr_t pathp;
1278 	int v_opt;
1279 	int hdr;
1280 
1281 	v_opt = 0;
1282 
1283 	if (mdb_getopts(argc, argv,
1284 	    'v', MDB_OPT_SETBITS, TRUE, &v_opt) != argc)
1285 		return (DCMD_USAGE);
1286 
1287 	if (!(flags & DCMD_ADDRSPEC)) {
1288 		return (nsc_iodev_all(argc, argv));
1289 	}
1290 
1291 	memset(path, 0, sizeof (path));
1292 	iodev = mdb_zalloc(sizeof (*iodev), UM_SLEEP | UM_GC);
1293 	memset(io_name, 0, sizeof (io_name));
1294 
1295 	if (mdb_vread(iodev, sizeof (*iodev), addr) != sizeof (*iodev)) {
1296 		mdb_warn("failed to read nsc_iodev at %p", addr);
1297 		return (DCMD_ERR);
1298 	}
1299 
1300 	if (mdb_vread(&pathp, sizeof (pathp),
1301 	    (uintptr_t)iodev->si_dev + OFFSETOF(nsc_dev_t, nsc_path)) !=
1302 	    sizeof (pathp)) {
1303 		mdb_warn("failed to read nsc_dev.nsc_path");
1304 		return (DCMD_ERR);
1305 	}
1306 
1307 	if (mdb_readstr(path, sizeof (path), pathp) == -1) {
1308 		mdb_warn("failed to read nsc_path");
1309 		return (DCMD_ERR);
1310 	}
1311 
1312 	if (mdb_vread(&io_namep, sizeof (io_namep),
1313 	    (uintptr_t)iodev->si_io + OFFSETOF(nsc_io_t, name)) !=
1314 	    sizeof (io_namep)) {
1315 		mdb_warn("failed to read nsc_io_t.name");
1316 		return (DCMD_ERR);
1317 	}
1318 
1319 	if (mdb_readstr(io_name, sizeof (io_name),
1320 	    (uintptr_t)io_namep) == -1) {
1321 		mdb_warn("failed to read nsc_io_t.name string");
1322 		return (DCMD_ERR);
1323 	}
1324 
1325 	hdr = 0;
1326 	if (complex_walk) {
1327 		if (!complex_hdr) {
1328 			complex_hdr = 1;
1329 			hdr = 1;
1330 		}
1331 	} else if (DCMD_HDRSPEC(flags)) {
1332 		hdr = 1;
1333 	}
1334 
1335 	if (hdr) {
1336 		mdb_printf("%-?s  %8T%-?s  ref %-8s path\n",
1337 		    "iodev", "dev", "io");
1338 	}
1339 
1340 	mdb_printf("%0?p  %8T%0?p  %3d %-8s %s\n",
1341 	    addr, iodev->si_dev, iodev->si_refcnt, io_name, path);
1342 
1343 	if (!v_opt)
1344 		return (DCMD_OK);
1345 
1346 	mdb_inc_indent(4);
1347 
1348 	mdb_printf("open fds: %?p  %8Tactive ios: %?p\n",
1349 	    iodev->si_open, iodev->si_active);
1350 
1351 	mdb_printf("busy: %d  %8Trsrv pend: %d\n",
1352 	    iodev->si_busy, iodev->si_rpend);
1353 
1354 	mdb_printf("pend: %08x <%b>\n", iodev->si_pend,
1355 	    iodev->si_pend, nsc_availpend_bits);
1356 
1357 	mdb_printf("avail: %08x <%b>\n", iodev->si_avail,
1358 	    iodev->si_avail, nsc_availpend_bits);
1359 
1360 	mdb_dec_indent(4);
1361 
1362 	return (DCMD_OK);
1363 }
1364 
1365 
1366 /* ---------------------------------------------------------------------- */
1367 
1368 /*
1369  * Display an nsc_service_t structure, or walk all services.
1370  */
1371 static int
1372 nsc_service(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1373 {
1374 	nsc_service_t *service;
1375 	char s_name[32];
1376 	int v_opt;
1377 
1378 	v_opt = 0;
1379 
1380 	if (mdb_getopts(argc, argv,
1381 	    'v', MDB_OPT_SETBITS, TRUE, &v_opt) != argc)
1382 		return (DCMD_USAGE);
1383 
1384 	if (!(flags & DCMD_ADDRSPEC)) {
1385 		if (mdb_walk_dcmd("nsctl`nsc_service",
1386 		    "nsctl`nsc_service", argc, argv) == -1) {
1387 			mdb_warn("failed to walk 'nsc_service'");
1388 			return (DCMD_ERR);
1389 		}
1390 
1391 		return (DCMD_OK);
1392 	}
1393 
1394 	service = mdb_zalloc(sizeof (*service), UM_SLEEP | UM_GC);
1395 
1396 	if (mdb_vread(service, sizeof (*service), addr) != sizeof (*service)) {
1397 		mdb_warn("failed to read nsc_service at %p", addr);
1398 		return (DCMD_ERR);
1399 	}
1400 
1401 	if (DCMD_HDRSPEC(flags)) {
1402 		mdb_printf("%-?s  %8Tname\n", "service");
1403 	}
1404 
1405 	memset(s_name, 0, sizeof (s_name));
1406 	if (service->s_name) {
1407 		if (mdb_readstr(s_name, sizeof (s_name),
1408 		    (uintptr_t)service->s_name) == -1) {
1409 			mdb_warn("failed to read nsc_io_t.name");
1410 			return (DCMD_ERR);
1411 		}
1412 	}
1413 
1414 	mdb_printf("%0?p  %8T%s\n", addr, s_name);
1415 
1416 	if (!v_opt)
1417 		return (DCMD_OK);
1418 
1419 	mdb_inc_indent(4);
1420 
1421 	mdb_printf("servers:\n");
1422 	if (service->s_servers == NULL) {
1423 		mdb_printf("<none>\n");
1424 	} else {
1425 		mdb_inc_indent(4);
1426 		if (mdb_pwalk_dcmd("nsctl`nsc_svc", "nsctl`nsc_svc",
1427 		    argc, argv, (uintptr_t)service->s_servers) == -1) {
1428 			mdb_dec_indent(8);
1429 			return (DCMD_ERR);
1430 		}
1431 		mdb_dec_indent(4);
1432 	}
1433 
1434 	mdb_printf("clients:\n");
1435 	if (service->s_clients == NULL) {
1436 		mdb_printf("<none>\n");
1437 	} else {
1438 		mdb_inc_indent(4);
1439 		if (mdb_pwalk_dcmd("nsctl`nsc_svc", "nsctl`nsc_svc",
1440 		    argc, argv, (uintptr_t)service->s_clients) == -1) {
1441 			mdb_dec_indent(8);
1442 			return (DCMD_ERR);
1443 		}
1444 		mdb_dec_indent(4);
1445 	}
1446 
1447 	mdb_dec_indent(4);
1448 
1449 	return (DCMD_OK);
1450 }
1451 
1452 
1453 /* ---------------------------------------------------------------------- */
1454 
1455 /*
1456  * Display an nsc_svc_t structure.
1457  */
1458 /*ARGSUSED*/
1459 static int
1460 nsc_svc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1461 {
1462 	nsc_svc_t *svc;
1463 
1464 	if (!(flags & DCMD_ADDRSPEC))
1465 		return (DCMD_USAGE);
1466 
1467 	svc = mdb_zalloc(sizeof (*svc), UM_SLEEP | UM_GC);
1468 
1469 	if (mdb_vread(svc, sizeof (*svc), addr) != sizeof (*svc)) {
1470 		mdb_warn("failed to read nsc_svc at %p", addr);
1471 		return (DCMD_ERR);
1472 	}
1473 
1474 	if (DCMD_HDRSPEC(flags)) {
1475 		mdb_printf("%-?s  %8T%-?s  %8Tfunc\n", "svc", "service");
1476 	}
1477 
1478 	mdb_printf("%0?p  %8T%0?p  %8T%a\n", addr, svc->svc_svc, svc->svc_fn);
1479 	return (DCMD_OK);
1480 }
1481 
1482 
1483 /* ---------------------------------------------------------------------- */
1484 
1485 /*
1486  * Display a single nsc_val_t structure.
1487  * If called with no address, performs a global walk of all nsc_devs.
1488  */
1489 /* ARGSUSED3 */
1490 static int
1491 nsc_val(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1492 {
1493 	nsc_val_t *vp;
1494 
1495 	if (argc != 0)
1496 		return (DCMD_USAGE);
1497 
1498 	if (!(flags & DCMD_ADDRSPEC)) {
1499 		mdb_warn("nsc_val requires an address");
1500 		return (DCMD_ERR);
1501 	}
1502 
1503 	vp = mdb_zalloc(sizeof (*vp), UM_SLEEP | UM_GC);
1504 
1505 	if (mdb_vread(vp, sizeof (*vp), addr) != sizeof (*vp)) {
1506 		mdb_warn("failed to read nsc_val at %p", addr);
1507 		return (DCMD_ERR);
1508 	}
1509 
1510 	if (DCMD_HDRSPEC(flags)) {
1511 		mdb_printf("%-?s  %8T%8-s  %8Tname\n", "val", "value");
1512 	}
1513 
1514 	mdb_printf("%0?p  %8T%08x  %8T%s\n", addr, vp->sv_value, vp->sv_name);
1515 
1516 	return (DCMD_OK);
1517 }
1518 
1519 
1520 /* ---------------------------------------------------------------------- */
1521 
1522 /*
1523  * Display an nstset_t structure, or walk all sets.
1524  */
1525 
1526 static int
1527 nstset(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1528 {
1529 	nstset_t *set;
1530 	int f_opt, r_opt, t_opt, v_opt;
1531 
1532 	f_opt = r_opt = t_opt = v_opt = 0;
1533 
1534 	if (mdb_getopts(argc, argv,
1535 	    'f', MDB_OPT_SETBITS, TRUE, &f_opt,		/* free list */
1536 	    'r', MDB_OPT_SETBITS, TRUE, &r_opt,		/* reuse list */
1537 	    't', MDB_OPT_SETBITS, TRUE, &t_opt,		/* all threads */
1538 	    'v', MDB_OPT_SETBITS, TRUE, &v_opt) != argc)
1539 		return (DCMD_USAGE);
1540 
1541 	/* displaying threads implies verbose */
1542 	if (f_opt || r_opt || t_opt)
1543 		v_opt = 1;
1544 
1545 	if (!(flags & DCMD_ADDRSPEC)) {
1546 		if (mdb_walk_dcmd("nsctl`nstset",
1547 		    "nsctl`nstset", argc, argv) == -1) {
1548 			mdb_warn("failed to walk 'nstset'");
1549 			return (DCMD_ERR);
1550 		}
1551 
1552 		return (DCMD_OK);
1553 	}
1554 
1555 	set = mdb_zalloc(sizeof (*set), UM_SLEEP | UM_GC);
1556 
1557 	if (mdb_vread(set, sizeof (*set), addr) != sizeof (*set)) {
1558 		mdb_warn("failed to read nstset at %p", addr);
1559 		return (DCMD_ERR);
1560 	}
1561 
1562 	if (DCMD_HDRSPEC(flags)) {
1563 		mdb_printf("%-?s  %8T  live   nthr flag name\n", "set");
1564 	}
1565 
1566 	mdb_printf("%0?p  %8T%6d %6d %4x %s\n", addr,
1567 	    set->set_nlive, set->set_nthread, set->set_flag, set->set_name);
1568 
1569 	if (!v_opt)
1570 		return (DCMD_OK);
1571 
1572 	mdb_inc_indent(4);
1573 
1574 	mdb_printf("chain: %0?p  %8Tpending: %4d  res_cnt: %4d\n",
1575 	    set->set_chain, set->set_pending, set->set_res_cnt);
1576 
1577 	if (set->set_reuse.q_forw == set->set_reuse.q_back &&
1578 	    (uintptr_t)set->set_reuse.q_forw ==
1579 	    (addr + OFFSETOF(nstset_t, set_reuse))) {
1580 		mdb_printf("reuse.forw: %-?s  %8Treuse.back: %s\n",
1581 		    "empty", "empty");
1582 	} else {
1583 		mdb_printf("reuse.forw: %0?p  %8Treuse.back: %0?p\n",
1584 		    set->set_reuse.q_forw, set->set_reuse.q_back);
1585 
1586 		/* display all threads in reuse list */
1587 		if (r_opt &&
1588 		    mdb_pwalk_dcmd("nsctl`nst_free", "nsctl`nsthread",
1589 		    0, (const mdb_arg_t *)NULL,
1590 		    (addr + OFFSETOF(nstset_t, set_reuse))) == -1) {
1591 			mdb_dec_indent(4);
1592 			return (DCMD_ERR);
1593 		}
1594 	}
1595 
1596 	if (set->set_free.q_forw == set->set_free.q_back &&
1597 	    (uintptr_t)set->set_free.q_forw ==
1598 	    (addr + OFFSETOF(nstset_t, set_free))) {
1599 		mdb_printf("free.forw:  %-?s  %8Tfree.back:  %s\n",
1600 		    "empty", "empty");
1601 	} else {
1602 		mdb_printf("free.forw:  %0?p  %8Tfree.back:  %0?p\n",
1603 		    set->set_free.q_forw, set->set_free.q_back);
1604 
1605 		/* display all threads in free list */
1606 		if (f_opt &&
1607 		    mdb_pwalk_dcmd("nsctl`nst_free", "nsctl`nsthread",
1608 		    0, (const mdb_arg_t *)NULL,
1609 		    (addr + OFFSETOF(nstset_t, set_free))) == -1) {
1610 			mdb_dec_indent(4);
1611 			return (DCMD_ERR);
1612 		}
1613 	}
1614 
1615 	mdb_printf("flag: %08x <%b>\n",
1616 	    set->set_flag, set->set_flag, nstset_flag_bits);
1617 
1618 	/* display all threads in set */
1619 	if (t_opt) {
1620 		mdb_printf("all threads in set:\n");
1621 		if (mdb_pwalk_dcmd("nsctl`nsthread", "nsctl`nsthread",
1622 		    0, (const mdb_arg_t *)NULL,
1623 		    (uintptr_t)set->set_chain) == -1) {
1624 			mdb_dec_indent(4);
1625 			return (DCMD_ERR);
1626 		}
1627 	}
1628 
1629 	mdb_dec_indent(4);
1630 
1631 	return (DCMD_OK);
1632 }
1633 
1634 
1635 /* ---------------------------------------------------------------------- */
1636 
1637 /*
1638  * Callback for the all nstsets and threads walk.  Called per set.
1639  */
1640 /* ARGSUSED */
1641 static int
1642 nst_thr_set(uintptr_t addr, const void *data, void *cbdata)
1643 {
1644 	struct complex_args *thrall = cbdata;
1645 	char set_name[48];
1646 	uintptr_t tp;
1647 
1648 	if (mdb_vread(&tp, sizeof (tp),
1649 	    addr + OFFSETOF(nstset_t, set_chain)) == -1) {
1650 		mdb_warn("unable to read nstset_t.set_chain at %p", addr);
1651 		return (WALK_ERR);
1652 	}
1653 
1654 	memset(set_name, 0, sizeof (set_name));
1655 
1656 	if (mdb_readstr(set_name, sizeof (set_name),
1657 	    addr + OFFSETOF(nstset_t, set_name)) == -1) {
1658 		mdb_warn("unable to read nstset_t.set_name at %p", addr);
1659 	}
1660 
1661 	mdb_printf("nstset: %0?p (%s)\n", addr, set_name);
1662 
1663 	/* walk thread chains */
1664 
1665 	if (tp != NULL) {
1666 		if (mdb_pwalk_dcmd("nsctl`nsthread", "nsctl`nsthread",
1667 		    thrall->argc, thrall->argv, tp) == -1)
1668 			return (WALK_ERR);
1669 	} else
1670 		mdb_printf("    no threads\n");
1671 
1672 	mdb_printf("\n");
1673 
1674 	return (WALK_NEXT);
1675 }
1676 
1677 
1678 /*
1679  * Walk all nstsets and threads in the system.
1680  */
1681 static int
1682 nst_thr_all(int argc, const mdb_arg_t *argv)
1683 {
1684 	struct complex_args thrall;
1685 
1686 	thrall.argc = argc;
1687 	thrall.argv = (mdb_arg_t *)argv;
1688 
1689 	if (mdb_walk("nsctl`nstset", nst_thr_set, &thrall) == -1)
1690 		return (DCMD_ERR);
1691 
1692 	return (DCMD_OK);
1693 }
1694 
1695 
1696 /*
1697  * Display an nsthread_t structure, or walk all threads.
1698  */
1699 
1700 static int
1701 nsthread(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1702 {
1703 	uintptr_t thrpend;
1704 	nsthread_t *tp;
1705 	int a_opt, v_opt;
1706 	int rc;
1707 
1708 	a_opt = v_opt = 0;
1709 
1710 	if (mdb_getopts(argc, argv,
1711 	    'a', MDB_OPT_SETBITS, TRUE, &a_opt,
1712 	    'v', MDB_OPT_SETBITS, TRUE, &v_opt) != argc)
1713 		return (DCMD_USAGE);
1714 
1715 	if (!(flags & DCMD_ADDRSPEC)) {
1716 		if ((rc = nst_thr_all(argc, argv)) != DCMD_OK)
1717 			return (rc);
1718 
1719 		if (a_opt) {
1720 			if (mdb_readvar(&thrpend, "nst_pending") == -1) {
1721 				mdb_warn("unable to read 'nst_pending'");
1722 				return (DCMD_ERR);
1723 			}
1724 
1725 			if (thrpend) {
1726 				mdb_printf("\nPending threads:\n");
1727 
1728 				if (mdb_pwalk_dcmd("nsctl`nsthread",
1729 				    "nsctl`nsthread", argc, argv,
1730 				    thrpend) == -1) {
1731 					mdb_warn("failed to walk 'nsthread'");
1732 					return (DCMD_ERR);
1733 				}
1734 			}
1735 		}
1736 
1737 		return (DCMD_OK);
1738 	}
1739 
1740 	tp = mdb_zalloc(sizeof (*tp), UM_SLEEP | UM_GC);
1741 
1742 	if (mdb_vread(tp, sizeof (*tp), addr) != sizeof (*tp)) {
1743 		mdb_warn("failed to read nsthread at %p", addr);
1744 		return (DCMD_ERR);
1745 	}
1746 
1747 	if (DCMD_HDRSPEC(flags)) {
1748 		mdb_printf("%-?s  %8Tflag %-?s  %8Tfunc\n", "thread", "arg");
1749 	}
1750 
1751 	mdb_printf("%0?p  %8T%4x %0?p  %8T%a\n",
1752 	    addr, tp->tp_flag, tp->tp_arg, tp->tp_func);
1753 
1754 	if (!v_opt)
1755 		return (DCMD_OK);
1756 
1757 	mdb_inc_indent(4);
1758 
1759 	mdb_printf("set: %0?p  %8Tchain: %0?p\n",
1760 	    tp->tp_set, tp->tp_chain);
1761 
1762 	mdb_printf("link.forw: %0?p  %8Tlink.back: %0?p\n",
1763 	    tp->tp_link.q_forw, tp->tp_link.q_back);
1764 
1765 	mdb_printf("flag: %08x <%b>\n",
1766 	    tp->tp_flag, tp->tp_flag, nst_flag_bits);
1767 
1768 	mdb_dec_indent(4);
1769 
1770 	return (DCMD_OK);
1771 }
1772 
1773 
1774 /* ---------------------------------------------------------------------- */
1775 
1776 static void
1777 nsc_rmap(char *name)
1778 {
1779 	nsc_rmmap_t slot;
1780 	uintptr_t addr;
1781 	int nslot;
1782 	char *cp;
1783 
1784 	if (mdb_readvar(&addr, name) == -1) {
1785 		mdb_warn("unable to read rmap '%s'", name);
1786 		return;
1787 	}
1788 
1789 	if (mdb_vread(&slot, sizeof (slot), addr) != sizeof (slot)) {
1790 		mdb_warn("unable to read rmap '%s' slot 0", name);
1791 		return;
1792 	}
1793 
1794 	mdb_printf("\nmap name		offset      size    nslot\n");
1795 	mdb_printf("%16s     %9d %9d    %5d\n",
1796 	    slot.name, slot.offset, slot.size, slot.inuse);
1797 
1798 	nslot = slot.inuse;
1799 	mdb_printf("\nslot name	       offset      size    inuse\n");
1800 
1801 	while (--nslot) {
1802 		addr += sizeof (slot);
1803 
1804 		if (mdb_vread(&slot, sizeof (slot), addr) != sizeof (slot)) {
1805 			mdb_warn("unable to read rmap '%s' slot @ %p",
1806 			    name, addr);
1807 			return;
1808 		}
1809 
1810 		if (!slot.inuse || !slot.size)
1811 			continue;
1812 
1813 		for (cp = slot.name; *cp; cp++)
1814 			if (*cp == ':')
1815 				*cp = ' ';
1816 
1817 		mdb_printf("%16s     %9d %9d %08x\n",
1818 		    slot.name, slot.offset, slot.size, slot.inuse);
1819 	}
1820 }
1821 
1822 
1823 static void
1824 nsc_rmhdr(void)
1825 {
1826 	nsc_rmhdr_t *rmhdr = mdb_zalloc(sizeof (*rmhdr), UM_SLEEP | UM_GC);
1827 	uintptr_t addr;
1828 
1829 	if (mdb_readvar(&addr, "_nsc_rmhdr_ptr") == -1) {
1830 		mdb_warn("unable to read _nsc_rmhdr_ptr");
1831 		return;
1832 	}
1833 
1834 	if (!addr) {
1835 		mdb_printf("\n\nGlobal header not initialised\n");
1836 		return;
1837 	}
1838 
1839 	if (mdb_vread(rmhdr, sizeof (*rmhdr), addr) != sizeof (*rmhdr)) {
1840 		mdb_warn("unable to read global header at %p", addr);
1841 		return;
1842 	}
1843 
1844 	mdb_printf("\n\nglobal header    (magic %08x, version %d, size %d)\n",
1845 	    rmhdr->magic, rmhdr->ver, rmhdr->size);
1846 
1847 	nsc_rmap("_nsc_global_map");
1848 }
1849 
1850 
1851 static nsc_mem_t *
1852 memptr(int type, int flag)
1853 {
1854 	int i;
1855 
1856 	type &= NSC_MEM_GLOBAL;
1857 
1858 	if (type)
1859 		flag = 0;
1860 
1861 	if (!type && !flag)
1862 		return (&type_mem[0]);
1863 
1864 	for (i = 1; i < (sizeof (type_mem) / sizeof (nsc_mem_t)); i++) {
1865 		if (!type_mem[i].flag && !type_mem[i].type) {
1866 			type_mem[i].flag = flag;
1867 			type_mem[i].type = type;
1868 			return (&type_mem[i]);
1869 		}
1870 
1871 		if (type_mem[i].flag == flag && type_mem[i].type == type)
1872 			return (&type_mem[i]);
1873 	}
1874 
1875 	return (&type_mem[i]);
1876 }
1877 
1878 
1879 #define	typename(t)	\
1880 		(((t) & NSC_MEM_GLOBAL) ? "gbl" : " - ")
1881 
1882 #define	memname(t)	\
1883 		(((t) & NSC_MEM_GLOBAL) ? "nsc_global" : "system kmem")
1884 
1885 static void
1886 nsc_mem_type(const int first, nsc_mem_t *mp)
1887 {
1888 	char *type, *name;
1889 
1890 	if (first) {
1891 		mdb_printf("\nregion	   typ  f      ");
1892 		mdb_printf("used       hwm    pgs  alloc  free\n");
1893 	}
1894 
1895 	type = typename(mp->type);
1896 	name = memname(mp->type);
1897 
1898 	mdb_printf("%16s %s %2x %9d %9d %6d  %5d %5d\n",
1899 	    name, type, mp->flag, mp->used, mp->hwm, mp->pagehwm,
1900 	    mp->nalloc, mp->nfree);
1901 }
1902 
1903 
1904 static int
1905 nsc_mem_all(int argc, const mdb_arg_t *argv, int v_opt)
1906 {
1907 	int first;
1908 	int i;
1909 
1910 	memset(type_mem, 0, sizeof (type_mem));
1911 
1912 	if (mdb_walk_dcmd("nsctl`nsc_mem",
1913 	    "nsctl`nsc_mem", argc, argv) == -1) {
1914 		mdb_warn("unable to walk 'nsc_mem'");
1915 		return (DCMD_ERR);
1916 	}
1917 
1918 	for (first = 1, i = 0;
1919 	    i < (sizeof (type_mem) / sizeof (nsc_mem_t)); first = 0, i++) {
1920 		if (type_mem[i].nalloc || type_mem[i].hwm) {
1921 			nsc_mem_type(first, &type_mem[i]);
1922 		}
1923 	}
1924 
1925 	if (v_opt)
1926 		nsc_rmhdr();
1927 
1928 	return (DCMD_OK);
1929 }
1930 
1931 
1932 static int
1933 nsc_mem(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1934 {
1935 	char name[16], *type, *cp;
1936 	nsc_mem_t mem, *mp;
1937 	int v_opt;
1938 
1939 	v_opt = 0;
1940 
1941 	if (mdb_getopts(argc, argv,
1942 	    'v', MDB_OPT_SETBITS, TRUE, &v_opt) != argc)
1943 		return (DCMD_USAGE);
1944 
1945 	if (!(flags & DCMD_ADDRSPEC)) {
1946 		return (nsc_mem_all(argc, argv, v_opt));
1947 	}
1948 
1949 	if (mdb_vread(&mem, sizeof (mem), addr) != sizeof (mem)) {
1950 		mdb_warn("failed to read nsc_mem_t at %p", addr);
1951 		return (DCMD_ERR);
1952 	}
1953 
1954 	if (mdb_readstr(name, sizeof (name), (uintptr_t)mem.name) == -1) {
1955 		mdb_warn("failed to read nsc_mem_t.name at %p", addr);
1956 		return (DCMD_ERR);
1957 	}
1958 
1959 	if (!mem.nalloc && !mem.hwm && !v_opt)
1960 		return (DCMD_OK);
1961 
1962 	if (DCMD_HDRSPEC(flags)) {
1963 		mdb_printf("name	     typ  f      ");
1964 		mdb_printf("used       hwm   pgs alloc  free     base\n");
1965 	}
1966 
1967 	type = typename(mem.type);
1968 	mp = memptr(mem.type, mem.flag);
1969 
1970 	for (cp = name; *cp; cp++)
1971 		if (*cp == ':')
1972 			*cp = ' ';
1973 
1974 	mdb_printf("%-16s %s %2x %9d %9d %5d %5d %5d %0?p\n",
1975 	    name, type, mem.flag, mem.used, mem.hwm, mem.pagehwm,
1976 	    mem.nalloc, mem.nfree, mem.base);
1977 
1978 	mp->used += mem.used;
1979 	mp->hwm += mem.hwm;
1980 	mp->pagehwm += mem.pagehwm;
1981 	mp->nalloc += mem.nalloc;
1982 	mp->nfree += mem.nfree;
1983 
1984 	return (DCMD_OK);
1985 }
1986 
1987 /*ARGSUSED*/
1988 static int
1989 nsc_vec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1990 {
1991 	nsc_vec_t *vec;
1992 
1993 	vec = mdb_zalloc(sizeof (*vec), UM_SLEEP | UM_GC);
1994 	if (mdb_vread(vec, sizeof (*vec), addr) != sizeof (*vec)) {
1995 		mdb_warn("failed to read nsc_vec at %p", addr);
1996 		return (DCMD_ERR);
1997 	}
1998 	mdb_printf("nsc_vec_t @ 0x%p = {\n", addr);
1999 	mdb_inc_indent(4);
2000 	mdb_printf("sv_addr: %p\n", vec->sv_addr);
2001 	mdb_printf("sv_vme:  %lu\n", vec->sv_vme);
2002 	mdb_printf("sv_len:  %d\n", vec->sv_len);
2003 	mdb_dec_indent(4);
2004 	mdb_printf("};\n");
2005 	if (vec->sv_addr)
2006 		return (DCMD_OK);
2007 	else
2008 		return (DCMD_ERR);
2009 }
2010 
2011 /* ---------------------------------------------------------------------- */
2012 /*
2013  * Display an nsc_buf_t structure.
2014  */
2015 
2016 #ifdef NSC_MULTI_TERABYTE
2017 #define	STRCONV	"ll"
2018 #else
2019 #define	STRCONV	""
2020 #endif
2021 
2022 /* ARGSUSED */
2023 static int
2024 nsc_buf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2025 {
2026 	nsc_buf_t *bh;
2027 	nsc_vec_t *v;
2028 
2029 	if (!(flags & DCMD_ADDRSPEC))
2030 		return (DCMD_USAGE);
2031 
2032 	bh = mdb_zalloc(sizeof (*bh), UM_SLEEP | UM_GC);
2033 
2034 	if (mdb_vread(bh, sizeof (*bh), addr) != sizeof (*bh)) {
2035 		mdb_warn("failed to read nsc_buf at %p", addr);
2036 		return (DCMD_ERR);
2037 	}
2038 
2039 	mdb_printf("nsc_buf_t @ 0x%p = {\n", addr);
2040 	mdb_inc_indent(4);
2041 	mdb_printf("sb_fd:    0x%p\n", bh->sb_fd);
2042 	mdb_printf("sb_pos:   0x%" STRCONV "x\n", bh->sb_pos);
2043 	mdb_printf("sb_len:   0x%" STRCONV "x\n", bh->sb_len);
2044 	mdb_printf("sb_flag:  0x%08x <%b>\n", bh->sb_flag,
2045 	    bh->sb_flag, nsc_bhflag_bits);
2046 	mdb_printf("sb_error: %d\n", bh->sb_error);
2047 #ifdef NSC_MULTI_TERABYTE
2048 	mdb_printf("sb_user:  0x%p\n", bh->sb_user);
2049 #else
2050 	mdb_printf("sb_user:  0x%x\n", bh->sb_user);
2051 #endif
2052 	mdb_printf("sb_vec:   0x%p\n", bh->sb_vec);
2053 	v = bh->sb_vec++;
2054 	while (nsc_vec((uintptr_t)v, flags, argc, argv) == DCMD_OK)
2055 		v++;
2056 
2057 	mdb_dec_indent(4);
2058 	mdb_printf("};\n");
2059 
2060 	return (DCMD_OK);
2061 }
2062 
2063 /* ---------------------------------------------------------------------- */
2064 
2065 /* ARGSUSED */
2066 static int
2067 nsc_dbuf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2068 {
2069 	nsc_dbuf_t *bh;
2070 
2071 	if (!(flags & DCMD_ADDRSPEC))
2072 		return (DCMD_USAGE);
2073 
2074 	bh = mdb_zalloc(sizeof (*bh), UM_SLEEP | UM_GC);
2075 
2076 	if (mdb_vread(bh, sizeof (*bh), addr) != sizeof (*bh)) {
2077 		mdb_warn("failed to read nsc_dbuf at %p", addr);
2078 		return (DCMD_ERR);
2079 	}
2080 
2081 	mdb_printf("nsc_dbuf_t @ 0x%p = {\n", addr);
2082 	mdb_inc_indent(4);
2083 	mdb_printf("db_disc:    0x%p\n", bh->db_disc);
2084 	mdb_printf("db_addr:    0x%p\n", bh->db_addr);
2085 	mdb_printf("db_next:    0x%p\n", bh->db_next);
2086 	mdb_printf("db_maxfbas: 0x%d\n", bh->db_maxfbas);
2087 
2088 
2089 	mdb_dec_indent(4);
2090 	mdb_printf("};\n");
2091 
2092 	return (DCMD_OK);
2093 }
2094 /* ---------------------------------------------------------------------- */
2095 
2096 /*
2097  * MDB module linkage information:
2098  */
2099 
2100 static const mdb_dcmd_t dcmds[] = {
2101 #if 0
2102 	{ "nsctl", NULL, "display nsctl module info", nsctl },
2103 #endif
2104 	{ "nsc_buf", ":", "list nsc_buf structure", nsc_buf },
2105 	{ "nsc_dbuf", ":", "list nsc_dbuf structure", nsc_dbuf },
2106 	{ "nsc_dev", "?[-av]", "list nsc_dev structure", nsc_dev },
2107 	{ "nsc_devval", "?[-a]", "list nsc_devval structure", nsc_devval },
2108 	{ "nsc_fd", "?[-v]", "list nsc_fd structure", nsc_fd },
2109 	{ "nsc_iodev", "?[-v]", "list nsc_iodev structure", nsc_iodev },
2110 	{ "nsc_io", "?[-v]", "list nsc_io structure", nsc_io },
2111 	{ "nsc_mem", "?[-v]", "list nsc_mem structure", nsc_mem },
2112 	{ "nsc_svc", ":", "list nsc_svc structure", nsc_svc },
2113 	{ "nsc_service", "?[-v]", "list nsc_service structure", nsc_service },
2114 	{ "nsc_val", ":", "list nsc_val structure", nsc_val },
2115 	{ "nstset", "?[-frtv]", "list nstset structure", nstset },
2116 	{ "nsthread", "?[-av]", "list nsthread structure", nsthread },
2117 	{ NULL }
2118 };
2119 
2120 
2121 static const mdb_walker_t walkers[] = {
2122 	{ "nsc_dev", "walk nsc_dev chain",
2123 	    nsc_dev_winit, nsc_dev_wstep, nsc_dev_wfini, NULL },
2124 	{ "nsc_devval", "walk nsc_devval chain",
2125 	    nsc_devval_winit, nsc_devval_wstep, NULL, NULL },
2126 	{ "nsc_fd", "walk nsc_fd chain",
2127 	    nsc_fd_winit, nsc_fd_wstep, NULL, NULL },
2128 	{ "nsc_io", "walk nsc_io chain",
2129 	    nsc_io_winit, nsc_io_wstep, NULL, NULL },
2130 	{ "nsc_iodev", "walk nsc_iodev chain",
2131 	    nsc_iodev_winit, nsc_iodev_wstep, NULL, NULL },
2132 	{ "nsc_mem", "walk nsc_mem chain",
2133 	    nsc_mem_winit, nsc_mem_wstep, NULL, NULL },
2134 	{ "nsc_service", "walk nsc_service chain",
2135 	    nsc_service_winit, nsc_service_wstep, NULL, NULL },
2136 	{ "nsc_svc", "walk nsc_svc chain",
2137 	    nsc_svc_winit, nsc_svc_wstep, NULL, NULL },
2138 	{ "nsc_val", "walk nsc_val chain",
2139 	    nsc_val_winit, nsc_val_wstep, NULL, NULL },
2140 	{ "nstset", "walk nstset chain",
2141 	    nstset_winit, nstset_wstep, NULL, NULL },
2142 	{ "nsthread", "walk nsthread chain",
2143 	    nsthread_winit, nsthread_wstep, NULL, NULL },
2144 	{ "nst_free", "walk nsthread free/reuse list",
2145 	    nst_free_winit, nst_free_wstep, NULL, NULL },
2146 	{ NULL }
2147 };
2148 
2149 
2150 static const mdb_modinfo_t modinfo = {
2151 	MDB_API_VERSION, dcmds, walkers
2152 };
2153 
2154 
2155 const mdb_modinfo_t *
2156 _mdb_init(void)
2157 {
2158 	return (&modinfo);
2159 }
2160