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 }