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 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #include <limits.h>
  27 #include <sys/mdb_modapi.h>
  28 #include <sys/sysinfo.h>
  29 #include <sys/sunmdi.h>
  30 #include <sys/scsi/scsi.h>
  31 
  32 #pragma pack(1)
  33 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
  34 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
  35 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
  36 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
  37 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
  38 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
  39 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h>
  40 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
  41 #pragma pack()
  42 
  43 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
  44 
  45 struct {
  46 
  47         int     value;
  48         char    *text;
  49 } devinfo_array[] = {
  50         { MPI2_SAS_DEVICE_INFO_SEP,             "SEP" },
  51         { MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE,    "ATAPI device" },
  52         { MPI2_SAS_DEVICE_INFO_LSI_DEVICE,      "LSI device" },
  53         { MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH,   "direct attach" },
  54         { MPI2_SAS_DEVICE_INFO_SSP_TARGET,      "SSP tgt" },
  55         { MPI2_SAS_DEVICE_INFO_STP_TARGET,      "STP tgt" },
  56         { MPI2_SAS_DEVICE_INFO_SMP_TARGET,      "SMP tgt" },
  57         { MPI2_SAS_DEVICE_INFO_SATA_DEVICE,     "SATA dev" },
  58         { MPI2_SAS_DEVICE_INFO_SSP_INITIATOR,   "SSP init" },
  59         { MPI2_SAS_DEVICE_INFO_STP_INITIATOR,   "STP init" },
  60         { MPI2_SAS_DEVICE_INFO_SMP_INITIATOR,   "SMP init" },
  61         { MPI2_SAS_DEVICE_INFO_SATA_HOST,       "SATA host" }
  62 };
  63 
  64 static int
  65 atoi(const char *p)
  66 {
  67         int n;
  68         int c = *p++;
  69 
  70         for (n = 0; c >= '0' && c <= '9'; c = *p++) {
  71                 n *= 10; /* two steps to avoid unnecessary overflow */
  72                 n += '0' - c; /* accum neg to avoid surprises at MAX */
  73         }
  74         return (-n);
  75 }
  76 
  77 int
  78 construct_path(uintptr_t addr, char *result)
  79 {
  80         struct  dev_info        d;
  81         char    devi_node[PATH_MAX];
  82         char    devi_addr[PATH_MAX];
  83 
  84         if (mdb_vread(&d, sizeof (d), addr) == -1) {
  85                 mdb_warn("couldn't read dev_info");
  86                 return (DCMD_ERR);
  87         }
  88 
  89         if (d.devi_parent) {
  90                 construct_path((uintptr_t)d.devi_parent, result);
  91                 mdb_readstr(devi_node, sizeof (devi_node),
  92                     (uintptr_t)d.devi_node_name);
  93                 mdb_readstr(devi_addr, sizeof (devi_addr),
  94                     (uintptr_t)d.devi_addr);
  95                 mdb_snprintf(result+strlen(result),
  96                     PATH_MAX-strlen(result),
  97                     "/%s%s%s", devi_node, (*devi_addr ? "@" : ""),
  98                     devi_addr);
  99         }
 100         return (DCMD_OK);
 101 }
 102 
 103 /* ARGSUSED */
 104 int
 105 mdi_info_cb(uintptr_t addr, const void *data, void *cbdata)
 106 {
 107         struct  mdi_pathinfo    pi;
 108         struct  mdi_client      c;
 109         char    dev_path[PATH_MAX];
 110         char    string[PATH_MAX];
 111         int     mdi_target = 0, mdi_lun = 0;
 112         int     target = *(int *)cbdata;
 113 
 114         if (mdb_vread(&pi, sizeof (pi), addr) == -1) {
 115                 mdb_warn("couldn't read mdi_pathinfo");
 116                 return (DCMD_ERR);
 117         }
 118         mdb_readstr(string, sizeof (string), (uintptr_t)pi.pi_addr);
 119         mdi_target = atoi(string);
 120         mdi_lun = atoi(strchr(string, ',')+1);
 121         if (target != mdi_target)
 122                 return (0);
 123 
 124         if (mdb_vread(&c, sizeof (c), (uintptr_t)pi.pi_client) == -1) {
 125                 mdb_warn("couldn't read mdi_client");
 126                 return (-1);
 127         }
 128 
 129         *dev_path = NULL;
 130         if (construct_path((uintptr_t)c.ct_dip, dev_path) != DCMD_OK)
 131                 strcpy(dev_path, "unknown");
 132 
 133         mdb_printf("LUN %d: %s\n", mdi_lun, dev_path);
 134         mdb_printf("       dip: %p %s path", c.ct_dip,
 135             (pi.pi_preferred ? "preferred" : ""));
 136         switch (pi.pi_state & MDI_PATHINFO_STATE_MASK) {
 137                 case MDI_PATHINFO_STATE_INIT:
 138                         mdb_printf(" initializing");
 139                         break;
 140                 case MDI_PATHINFO_STATE_ONLINE:
 141                         mdb_printf(" online");
 142                         break;
 143                 case MDI_PATHINFO_STATE_STANDBY:
 144                         mdb_printf(" standby");
 145                         break;
 146                 case MDI_PATHINFO_STATE_FAULT:
 147                         mdb_printf(" fault");
 148                         break;
 149                 case MDI_PATHINFO_STATE_OFFLINE:
 150                         mdb_printf(" offline");
 151                         break;
 152                 default:
 153                         mdb_printf(" invalid state");
 154                         break;
 155         }
 156         mdb_printf("\n");
 157         return (0);
 158 }
 159 
 160 void
 161 mdi_info(struct mptsas m, int target)
 162 {
 163         struct  dev_info        d;
 164         struct  mdi_phci        p;
 165 
 166         if (mdb_vread(&d, sizeof (d), (uintptr_t)m.m_dip) == -1) {
 167                 mdb_warn("couldn't read m_dip");
 168                 return;
 169         }
 170 
 171         if (MDI_PHCI(&d)) {
 172                 if (mdb_vread(&p, sizeof (p), (uintptr_t)d.devi_mdi_xhci)
 173                     == -1) {
 174                         mdb_warn("couldn't read m_dip.devi_mdi_xhci");
 175                         return;
 176                 }
 177                 if (p.ph_path_head)
 178                         mdb_pwalk("mdipi_phci_list", (mdb_walk_cb_t)mdi_info_cb,
 179                             &target, (uintptr_t)p.ph_path_head);
 180                 return;
 181         }
 182 }
 183 
 184 void
 185 print_cdb(mptsas_cmd_t *m)
 186 {
 187         struct  scsi_pkt        pkt;
 188         uchar_t cdb[512];       /* an arbitrarily large number */
 189         int     j;
 190 
 191         if (mdb_vread(&pkt, sizeof (pkt), (uintptr_t)m->cmd_pkt) == -1) {
 192                 mdb_warn("couldn't read cmd_pkt");
 193                 return;
 194         }
 195 
 196         /*
 197          * We use cmd_cdblen here because 5.10 doesn't
 198          * have the cdb length in the pkt
 199          */
 200         if (mdb_vread(&cdb, m->cmd_cdblen, (uintptr_t)pkt.pkt_cdbp) == -1) {
 201                 mdb_warn("couldn't read pkt_cdbp");
 202                 return;
 203         }
 204 
 205         mdb_printf("%3d,%-3d [ ",
 206             pkt.pkt_address.a_target, pkt.pkt_address.a_lun);
 207 
 208         for (j = 0; j < m->cmd_cdblen; j++)
 209                 mdb_printf("%02x ", cdb[j]);
 210 
 211         mdb_printf("]\n");
 212 }
 213 
 214 
 215 void
 216 display_ports(struct mptsas m)
 217 {
 218         int i;
 219         mdb_printf("\n");
 220         mdb_printf("phy number and port mapping table\n");
 221         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
 222                 if (m.m_phy_info[i].attached_devhdl) {
 223                         mdb_printf("phy %x --> port %x, phymask %x,"
 224                         "attached_devhdl %x\n", i, m.m_phy_info[i].port_num,
 225                             m.m_phy_info[i].phy_mask,
 226                             m.m_phy_info[i].attached_devhdl);
 227                 }
 228         }
 229         mdb_printf("\n");
 230 }
 231 static void *
 232 hash_traverse(mptsas_hash_table_t *hashtab, int pos, int alloc_size)
 233 {
 234         mptsas_hash_node_t *this = NULL;
 235         mptsas_hash_node_t h;
 236         void *ret = NULL;
 237 
 238         if (pos == MPTSAS_HASH_FIRST) {
 239                 hashtab->line = 0;
 240                 hashtab->cur = NULL;
 241                 this = hashtab->head[0];
 242         } else {
 243                 if (hashtab->cur == NULL) {
 244                         return (NULL);
 245                 } else {
 246                         mdb_vread(&h, sizeof (h), (uintptr_t)hashtab->cur);
 247                         this = h.next;
 248                 }
 249         }
 250 
 251         while (this == NULL) {
 252                 hashtab->line++;
 253                 if (hashtab->line >= MPTSAS_HASH_ARRAY_SIZE) {
 254                         /* the traverse reaches the end */
 255                         hashtab->cur = NULL;
 256                         return (NULL);
 257                 } else {
 258                         this = hashtab->head[hashtab->line];
 259                 }
 260         }
 261         hashtab->cur = this;
 262 
 263         if (mdb_vread(&h, sizeof (h), (uintptr_t)this) == -1) {
 264                 mdb_warn("couldn't read hashtab");
 265                 return (NULL);
 266         }
 267         ret = mdb_alloc(alloc_size, UM_SLEEP);
 268         if (mdb_vread(ret, alloc_size, (uintptr_t)h.data) == -1) {
 269                 mdb_warn("couldn't read hashdata");
 270                 return (NULL);
 271         }
 272         return (ret);
 273 }
 274 void
 275 display_targets(struct mptsas_slots *s)
 276 {
 277         mptsas_target_t *ptgt;
 278         mptsas_smp_t *psmp;
 279 
 280         mdb_printf("\n");
 281         mdb_printf("The SCSI target information\n");
 282         ptgt = (mptsas_target_t *)hash_traverse(&s->m_tgttbl,
 283             MPTSAS_HASH_FIRST, sizeof (mptsas_target_t));
 284         while (ptgt != NULL) {
 285                 mdb_printf("\n");
 286                 mdb_printf("devhdl %x, sasaddress %"PRIx64", phymask %x,"
 287                     "devinfo %x\n", ptgt->m_devhdl, ptgt->m_sas_wwn,
 288                     ptgt->m_phymask, ptgt->m_deviceinfo);
 289                 mdb_printf("throttle %x, dr_flag %x, m_t_ncmds %x, "
 290                     "enclosure %x, slot_num %x\n", ptgt->m_t_throttle,
 291                     ptgt->m_dr_flag, ptgt->m_t_ncmds, ptgt->m_enclosure,
 292                     ptgt->m_slot_num);
 293 
 294                 mdb_free(ptgt, sizeof (mptsas_target_t));
 295                 ptgt = (mptsas_target_t *)hash_traverse(
 296                     &s->m_tgttbl, MPTSAS_HASH_NEXT, sizeof (mptsas_target_t));
 297         }
 298         mdb_printf("\n");
 299         mdb_printf("The smp child information\n");
 300         psmp = (mptsas_smp_t *)hash_traverse(&s->m_smptbl,
 301             MPTSAS_HASH_FIRST, sizeof (mptsas_smp_t));
 302         while (psmp != NULL) {
 303                 mdb_printf("\n");
 304                 mdb_printf("devhdl %x, sasaddress %"PRIx64", phymask %x \n",
 305                     psmp->m_devhdl, psmp->m_sasaddr, psmp->m_phymask);
 306 
 307                 mdb_free(psmp, sizeof (mptsas_smp_t));
 308                 psmp = (mptsas_smp_t *)hash_traverse(
 309                     &s->m_smptbl, MPTSAS_HASH_NEXT, sizeof (mptsas_smp_t));
 310         }
 311         mdb_printf("\n");
 312 #if 0
 313         mdb_printf("targ         wwn      ncmds throttle "
 314             "dr_flag  timeout  dups\n");
 315         mdb_printf("-------------------------------"
 316             "--------------------------------\n");
 317         for (i = 0; i < MPTSAS_MAX_TARGETS; i++) {
 318                 if (s->m_target[i].m_sas_wwn || s->m_target[i].m_deviceinfo) {
 319                         mdb_printf("%4d ", i);
 320                         if (s->m_target[i].m_sas_wwn)
 321                                 mdb_printf("%"PRIx64" ",
 322                                     s->m_target[i].m_sas_wwn);
 323                         mdb_printf("%3d", s->m_target[i].m_t_ncmds);
 324                         switch (s->m_target[i].m_t_throttle) {
 325                                 case QFULL_THROTTLE:
 326                                         mdb_printf("   QFULL ");
 327                                         break;
 328                                 case DRAIN_THROTTLE:
 329                                         mdb_printf("   DRAIN ");
 330                                         break;
 331                                 case HOLD_THROTTLE:
 332                                         mdb_printf("    HOLD ");
 333                                         break;
 334                                 case MAX_THROTTLE:
 335                                         mdb_printf("     MAX ");
 336                                         break;
 337                                 case CHOKE_THROTTLE:
 338                                         mdb_printf("   CHOKE ");
 339                                         break;
 340                                 default:
 341                                         mdb_printf("%8d ",
 342                                             s->m_target[i].m_t_throttle);
 343                         }
 344                         switch (s->m_target[i].m_dr_flag) {
 345                                 case MPTSAS_DR_INACTIVE:
 346                                         mdb_printf("  INACTIVE ");
 347                                         break;
 348                                 case MPTSAS_DR_PRE_OFFLINE_TIMEOUT:
 349                                         mdb_printf("   TIMEOUT ");
 350                                         break;
 351                                 case MPTSAS_DR_PRE_OFFLINE_TIMEOUT_NO_CANCEL:
 352                                         mdb_printf("TIMEOUT_NC ");
 353                                         break;
 354                                 case MPTSAS_DR_OFFLINE_IN_PROGRESS:
 355                                         mdb_printf(" OFFLINING ");
 356                                         break;
 357                                 case MPTSAS_DR_ONLINE_IN_PROGRESS:
 358                                         mdb_printf("  ONLINING ");
 359                                         break;
 360                                 default:
 361                                         mdb_printf("   UNKNOWN ");
 362                                         break;
 363                                 }
 364                         mdb_printf("%3d/%-3d   %d/%d\n",
 365                             s->m_target[i].m_dr_timeout, m.m_offline_delay,
 366                             s->m_target[i].m_dr_online_dups,
 367                             s->m_target[i].m_dr_offline_dups);
 368 
 369                         if (verbose) {
 370                                 mdb_inc_indent(5);
 371                                 if ((s->m_target[i].m_deviceinfo &
 372                                     MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) ==
 373                                     MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
 374                                         mdb_printf("Fanout expander: ");
 375                                 if ((s->m_target[i].m_deviceinfo &
 376                                     MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) ==
 377                                     MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER)
 378                                         mdb_printf("Edge expander: ");
 379                                 if ((s->m_target[i].m_deviceinfo &
 380                                     MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) ==
 381                                     MPI2_SAS_DEVICE_INFO_END_DEVICE)
 382                                         mdb_printf("End device: ");
 383                                 if ((s->m_target[i].m_deviceinfo &
 384                                     MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) ==
 385                                     MPI2_SAS_DEVICE_INFO_NO_DEVICE)
 386                                         mdb_printf("No device ");
 387 
 388                                 for (loop = 0, comma = 0;
 389                                     loop < (sizeof (devinfo_array) /
 390                                     sizeof (devinfo_array[0])); loop++) {
 391                                         if (s->m_target[i].m_deviceinfo &
 392                                             devinfo_array[loop].value) {
 393                                                 mdb_printf("%s%s",
 394                                                     (comma ? ", " : ""),
 395                                                     devinfo_array[loop].text);
 396                                                 comma++;
 397                                         }
 398                                 }
 399                                 mdb_printf("\n");
 400 
 401                                 if (s->m_target[i].m_tgt_dip) {
 402                                         *target_path = 0;
 403                                         if (construct_path((uintptr_t)
 404                                             s->m_target[i].m_tgt_dip,
 405                                             target_path)
 406                                             == DCMD_OK)
 407                                                 mdb_printf("%s\n", target_path);
 408                                 }
 409                                 mdi_info(m, i);
 410                                 mdb_dec_indent(5);
 411                         }
 412                 }
 413         }
 414 #endif
 415 }
 416 
 417 int
 418 display_slotinfo()
 419 {
 420 #if 0
 421         int     i, nslots;
 422         struct  mptsas_cmd              c, *q, *slots;
 423         int     header_output = 0;
 424         int     rv = DCMD_OK;
 425         int     slots_in_use = 0;
 426         int     tcmds = 0;
 427         int     mismatch = 0;
 428         int     wq, dq;
 429         int     ncmds = 0;
 430         ulong_t saved_indent;
 431 
 432         nslots = s->m_n_slots;
 433 
 434         slots = mdb_alloc(sizeof (mptsas_cmd_t) * nslots, UM_SLEEP);
 435 
 436         for (i = 0; i < nslots; i++)
 437                 if (s->m_slot[i]) {
 438                         slots_in_use++;
 439                         if (mdb_vread(&slots[i], sizeof (mptsas_cmd_t),
 440                             (uintptr_t)s->m_slot[i]) == -1) {
 441                                 mdb_warn("couldn't read slot");
 442                                 s->m_slot[i] = NULL;
 443                         }
 444                         if ((slots[i].cmd_flags & CFLAG_CMDIOC) == 0)
 445                                 tcmds++;
 446                         if (i != slots[i].cmd_slot)
 447                                 mismatch++;
 448                 }
 449 
 450         for (q = m.m_waitq, wq = 0; q; q = c.cmd_linkp, wq++)
 451                 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q) == -1) {
 452                         mdb_warn("couldn't follow m_waitq");
 453                         rv = DCMD_ERR;
 454                         goto exit;
 455                 }
 456 
 457         for (q = m.m_doneq, dq = 0; q; q = c.cmd_linkp, dq++)
 458                 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q) == -1) {
 459                         mdb_warn("couldn't follow m_doneq");
 460                         rv = DCMD_ERR;
 461                         goto exit;
 462                 }
 463 
 464         for (i = 0; i < MPTSAS_MAX_TARGETS; i++)
 465                 ncmds += s->m_target[i].m_t_ncmds;
 466 
 467         mdb_printf("\n");
 468         mdb_printf("   mpt.  slot               mptsas_slots     slot");
 469         mdb_printf("\n");
 470         mdb_printf("m_ncmds total"
 471             " targ throttle m_t_ncmds targ_tot wq dq");
 472         mdb_printf("\n");
 473         mdb_printf("----------------------------------------------------");
 474         mdb_printf("\n");
 475 
 476         mdb_printf("%7d ", m.m_ncmds);
 477         mdb_printf("%s", (m.m_ncmds == slots_in_use ? "  " : "!="));
 478         mdb_printf("%3d               total %3d ", slots_in_use, ncmds);
 479         mdb_printf("%s", (tcmds == ncmds ? "     " : "   !="));
 480         mdb_printf("%3d %2d %2d\n", tcmds, wq, dq);
 481 
 482         saved_indent = mdb_dec_indent(0);
 483         mdb_dec_indent(saved_indent);
 484 
 485         for (i = 0; i < s->m_n_slots; i++)
 486                 if (s->m_slot[i]) {
 487                         if (!header_output) {
 488                                 mdb_printf("\n");
 489                                 mdb_printf("mptsas_cmd          slot cmd_slot "
 490                                     "cmd_flags cmd_pkt_flags scsi_pkt      "
 491                                     "  targ,lun [ pkt_cdbp ...\n");
 492                                 mdb_printf("-------------------------------"
 493                                     "--------------------------------------"
 494                                     "--------------------------------------"
 495                                     "------\n");
 496                                 header_output = 1;
 497                         }
 498                         mdb_printf("%16p %4d %s %4d  %8x      %8x %16p ",
 499                             s->m_slot[i], i,
 500                             (i == slots[i].cmd_slot?"   ":"BAD"),
 501                             slots[i].cmd_slot,
 502                             slots[i].cmd_flags,
 503                             slots[i].cmd_pkt_flags,
 504                             slots[i].cmd_pkt);
 505                         (void) print_cdb(&slots[i]);
 506                 }
 507 
 508         /* print the wait queue */
 509 
 510         for (q = m.m_waitq; q; q = c.cmd_linkp) {
 511                 if (q == m.m_waitq)
 512                         mdb_printf("\n");
 513                 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q)
 514                     == -1) {
 515                         mdb_warn("couldn't follow m_waitq");
 516                         rv = DCMD_ERR;
 517                         goto exit;
 518                 }
 519                 mdb_printf("%16p wait n/a %4d  %8x      %8x %16p ",
 520                     q, c.cmd_slot, c.cmd_flags, c.cmd_pkt_flags,
 521                     c.cmd_pkt);
 522                 print_cdb(&c);
 523         }
 524 
 525         /* print the done queue */
 526 
 527         for (q = m.m_doneq; q; q = c.cmd_linkp) {
 528                 if (q == m.m_doneq)
 529                         mdb_printf("\n");
 530                 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q)
 531                     == -1) {
 532                         mdb_warn("couldn't follow m_doneq");
 533                         rv = DCMD_ERR;
 534                         goto exit;
 535                 }
 536                 mdb_printf("%16p done  n/a %4d  %8x      %8x %16p ",
 537                     q, c.cmd_slot, c.cmd_flags, c.cmd_pkt_flags,
 538                     c.cmd_pkt);
 539                 print_cdb(&c);
 540         }
 541 
 542         mdb_inc_indent(saved_indent);
 543 
 544         if (m.m_ncmds != slots_in_use)
 545                 mdb_printf("WARNING: mpt.m_ncmds does not match the number of "
 546                     "slots in use\n");
 547 
 548         if (tcmds != ncmds)
 549                 mdb_printf("WARNING: the total of m_target[].m_t_ncmds does "
 550                     "not match the slots in use\n");
 551 
 552         if (mismatch)
 553                 mdb_printf("WARNING: corruption in slot table, "
 554                     "m_slot[].cmd_slot incorrect\n");
 555 
 556         /* now check for corruptions */
 557 
 558         for (q = m.m_waitq; q; q = c.cmd_linkp) {
 559                 for (i = 0; i < nslots; i++)
 560                         if (s->m_slot[i] == q)
 561                                 mdb_printf("WARNING: m_waitq entry"
 562                                     "(mptsas_cmd_t) %p is in m_slot[%i]\n",
 563                                     q, i);
 564 
 565                 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q) == -1) {
 566                         mdb_warn("couldn't follow m_waitq");
 567                         rv = DCMD_ERR;
 568                         goto exit;
 569                 }
 570         }
 571 
 572         for (q = m.m_doneq; q; q = c.cmd_linkp) {
 573                 for (i = 0; i < nslots; i++)
 574                         if (s->m_slot[i] == q)
 575                                 mdb_printf("WARNING: m_doneq entry "
 576                                 "(mptsas_cmd_t) %p is in m_slot[%i]\n", q, i);
 577 
 578                 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q) == -1) {
 579                         mdb_warn("couldn't follow m_doneq");
 580                         rv = DCMD_ERR;
 581                         goto exit;
 582                 }
 583                 if ((c.cmd_flags & CFLAG_FINISHED) == 0)
 584                         mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p "
 585                             "should have CFLAG_FINISHED set\n", q);
 586                 if (c.cmd_flags & CFLAG_IN_TRANSPORT)
 587                         mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p "
 588                             "should not have CFLAG_IN_TRANSPORT set\n", q);
 589                 if (c.cmd_flags & CFLAG_CMDARQ)
 590                         mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p "
 591                             "should not have CFLAG_CMDARQ set\n", q);
 592                 if (c.cmd_flags & CFLAG_COMPLETED)
 593                         mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p "
 594                             "should not have CFLAG_COMPLETED set\n", q);
 595         }
 596 
 597 exit:
 598         mdb_free(slots, sizeof (mptsas_cmd_t) * nslots);
 599         return (rv);
 600 #endif
 601         mdb_printf("\n");
 602         mdb_printf("The slot information is not implemented yet\n");
 603         return (0);
 604 }
 605 
 606 void
 607 display_deviceinfo(struct mptsas m)
 608 {
 609         char    device_path[PATH_MAX];
 610 
 611         *device_path = 0;
 612         if (construct_path((uintptr_t)m.m_dip, device_path) != DCMD_OK) {
 613                 strcpy(device_path, "couldn't determine device path");
 614         }
 615 
 616         mdb_printf("\n");
 617         mdb_printf("Path in device tree %s\n", device_path);
 618 #if 0
 619         mdb_printf("base_wwid          phys "
 620             "mptid prodid  devid        revid   ssid\n");
 621         mdb_printf("-----------------------------"
 622             "----------------------------------\n");
 623         mdb_printf("%"PRIx64"     %2d   %3d "
 624             "0x%04x 0x%04x ", m.un.m_base_wwid, m.m_num_phys, m.m_mptid,
 625             m.m_productid, m.m_devid);
 626         switch (m.m_devid) {
 627                 case MPTSAS_909:
 628                         mdb_printf("(909)   ");
 629                         break;
 630                 case MPTSAS_929:
 631                         mdb_printf("(929)   ");
 632                         break;
 633                 case MPTSAS_919:
 634                         mdb_printf("(919)   ");
 635                         break;
 636                 case MPTSAS_1030:
 637                         mdb_printf("(1030)  ");
 638                         break;
 639                 case MPTSAS_1064:
 640                         mdb_printf("(1064)  ");
 641                         break;
 642                 case MPTSAS_1068:
 643                         mdb_printf("(1068)  ");
 644                         break;
 645                 case MPTSAS_1064E:
 646                         mdb_printf("(1064E) ");
 647                         break;
 648                 case MPTSAS_1068E:
 649                         mdb_printf("(1068E) ");
 650                         break;
 651                 default:
 652                         mdb_printf("(?????) ");
 653                         break;
 654         }
 655         mdb_printf("0x%02x 0x%04x\n", m.m_revid, m.m_ssid);
 656         mdb_printf("%s\n", device_path);
 657 
 658         for (i = 0; i < MAX_MPI2_PORTS; i++) {
 659                 if (i%4 == 0)
 660                         mdb_printf("\n");
 661 
 662                 mdb_printf("%d:", i);
 663 
 664                 switch (m.m_port_type[i]) {
 665                         case MPI2_PORTFACTS_PORTTYPE_INACTIVE:
 666                                 mdb_printf("inactive     ",
 667                                     m.m_protocol_flags[i]);
 668                                 break;
 669                         case MPI2_PORTFACTS_PORTTYPE_SCSI:
 670                                 mdb_printf("SCSI (0x%1x)   ",
 671                                     m.m_protocol_flags[i]);
 672                                 break;
 673                         case MPI2_PORTFACTS_PORTTYPE_FC:
 674                                 mdb_printf("FC (0x%1x)     ",
 675                                     m.m_protocol_flags[i]);
 676                                 break;
 677                         case MPI2_PORTFACTS_PORTTYPE_ISCSI:
 678                                 mdb_printf("iSCSI (0x%1x)  ",
 679                                     m.m_protocol_flags[i]);
 680                                 break;
 681                         case MPI2_PORTFACTS_PORTTYPE_SAS:
 682                                 mdb_printf("SAS (0x%1x)    ",
 683                                     m.m_protocol_flags[i]);
 684                                 break;
 685                         default:
 686                                 mdb_printf("unknown      ");
 687                 }
 688         }
 689 #endif
 690         mdb_printf("\n");
 691 }
 692 
 693 static int
 694 mptsas_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 695 {
 696         struct mptsas           m;
 697         struct  mptsas_slots    *s;
 698 
 699         int                     nslots;
 700         int                     slot_size = 0;
 701         uint_t                  verbose = FALSE;
 702         uint_t                  target_info = FALSE;
 703         uint_t                  slot_info = FALSE;
 704         uint_t                  device_info = FALSE;
 705         uint_t                  port_info = FALSE;
 706         int                     rv = DCMD_OK;
 707         void                    *mptsas_state;
 708 
 709         if (!(flags & DCMD_ADDRSPEC)) {
 710                 mptsas_state = NULL;
 711                 if (mdb_readvar(&mptsas_state, "mptsas_state") == -1) {
 712                         mdb_warn("can't read mptsas_state");
 713                         return (DCMD_ERR);
 714                 }
 715                 if (mdb_pwalk_dcmd("genunix`softstate", "mpt_sas`mptsas", argc,
 716                     argv, (uintptr_t)mptsas_state) == -1) {
 717                         mdb_warn("mdb_pwalk_dcmd failed");
 718                         return (DCMD_ERR);
 719                 }
 720                 return (DCMD_OK);
 721         }
 722 
 723         if (mdb_getopts(argc, argv,
 724             's', MDB_OPT_SETBITS, TRUE, &slot_info,
 725             'd', MDB_OPT_SETBITS, TRUE, &device_info,
 726             't', MDB_OPT_SETBITS, TRUE, &target_info,
 727             'p', MDB_OPT_SETBITS, TRUE, &port_info,
 728             'v', MDB_OPT_SETBITS, TRUE, &verbose,
 729             NULL) != argc)
 730                 return (DCMD_USAGE);
 731 
 732 
 733         if (mdb_vread(&m, sizeof (m), addr) == -1) {
 734                 mdb_warn("couldn't read mpt struct at 0x%p", addr);
 735                 return (DCMD_ERR);
 736         }
 737 
 738         s = mdb_alloc(sizeof (mptsas_slots_t), UM_SLEEP);
 739 
 740         if (mdb_vread(s, sizeof (mptsas_slots_t),
 741             (uintptr_t)m.m_active) == -1) {
 742                 mdb_warn("couldn't read small mptsas_slots_t at 0x%p",
 743                     m.m_active);
 744                 mdb_free(s, sizeof (mptsas_slots_t));
 745                 return (DCMD_ERR);
 746         }
 747 
 748         nslots = s->m_n_slots;
 749 
 750         mdb_free(s, sizeof (mptsas_slots_t));
 751 
 752         slot_size = sizeof (mptsas_slots_t) +
 753             (sizeof (mptsas_cmd_t *) * (nslots-1));
 754 
 755         s = mdb_alloc(slot_size, UM_SLEEP);
 756 
 757         if (mdb_vread(s, slot_size, (uintptr_t)m.m_active) == -1) {
 758                 mdb_warn("couldn't read large mptsas_slots_t at 0x%p",
 759                     m.m_active);
 760                 mdb_free(s, slot_size);
 761                 return (DCMD_ERR);
 762         }
 763 
 764         /* processing completed */
 765 
 766         if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) ||
 767             (flags & DCMD_LOOPFIRST) || slot_info || device_info ||
 768             target_info) {
 769                 if ((flags & DCMD_LOOP) && !(flags & DCMD_LOOPFIRST))
 770                         mdb_printf("\n");
 771                 mdb_printf("        mptsas_t inst ncmds suspend  power");
 772                 mdb_printf("\n");
 773                 mdb_printf("========================================="
 774                     "=======================================");
 775                 mdb_printf("\n");
 776         }
 777 
 778         mdb_printf("%16p %4d %5d ", addr, m.m_instance, m.m_ncmds);
 779         mdb_printf("%7d", m.m_suspended);
 780         switch (m.m_power_level) {
 781                 case PM_LEVEL_D0:
 782                         mdb_printf(" ON=D0 ");
 783                         break;
 784                 case PM_LEVEL_D1:
 785                         mdb_printf("    D1 ");
 786                         break;
 787                 case PM_LEVEL_D2:
 788                         mdb_printf("    D2 ");
 789                         break;
 790                 case PM_LEVEL_D3:
 791                         mdb_printf("OFF=D3 ");
 792                         break;
 793                 default:
 794                         mdb_printf("INVALD ");
 795         }
 796         mdb_printf("\n");
 797 
 798         mdb_inc_indent(17);
 799 
 800         if (target_info)
 801                 display_targets(s);
 802 
 803         if (port_info)
 804                 display_ports(m);
 805 
 806         if (device_info)
 807                 display_deviceinfo(m);
 808 
 809         if (slot_info)
 810                 display_slotinfo();
 811 
 812         mdb_dec_indent(17);
 813 
 814         mdb_free(s, slot_size);
 815 
 816         return (rv);
 817 }
 818 /*
 819  * Only -t is implemented now, will add more later when the driver is stable
 820  */
 821 void
 822 mptsas_help()
 823 {
 824         mdb_printf("Prints summary information about each mpt_sas instance, "
 825             "including warning\nmessages when slot usage doesn't match "
 826             "summary information.\n"
 827             "Without the address of a \"struct mptsas\", prints every "
 828             "instance.\n\n"
 829             "Switches:\n"
 830             "  -t   includes information about targets\n"
 831             "  -p   includes information about port\n"
 832             "  -d   includes information about the hardware\n");
 833 }
 834 
 835 static const mdb_dcmd_t dcmds[] = {
 836         { "mptsas", "?[-tpd]", "print mpt_sas information", mptsas_dcmd,
 837             mptsas_help}, { NULL }
 838 };
 839 
 840 static const mdb_modinfo_t modinfo = {
 841         MDB_API_VERSION, dcmds, NULL
 842 };
 843 
 844 const mdb_modinfo_t *
 845 _mdb_init(void)
 846 {
 847         return (&modinfo);
 848 }