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 }