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),
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:
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\n",
290 ptgt->m_t_throttle, ptgt->m_dr_flag, ptgt->m_t_ncmds);
291
292 mdb_free(ptgt, sizeof (mptsas_target_t));
293 ptgt = (mptsas_target_t *)hash_traverse(
294 &s->m_tgttbl, MPTSAS_HASH_NEXT, sizeof (mptsas_target_t));
295 }
296 mdb_printf("\n");
297 mdb_printf("The smp child information\n");
298 psmp = (mptsas_smp_t *)hash_traverse(&s->m_smptbl,
299 MPTSAS_HASH_FIRST, sizeof (mptsas_smp_t));
300 while (psmp != NULL) {
301 mdb_printf("\n");
302 mdb_printf("devhdl %x, sasaddress %"PRIx64", phymask %x \n",
303 psmp->m_devhdl, psmp->m_sasaddr, psmp->m_phymask);
304
305 mdb_free(psmp, sizeof (mptsas_smp_t));
306 psmp = (mptsas_smp_t *)hash_traverse(
307 &s->m_smptbl, MPTSAS_HASH_NEXT, sizeof (mptsas_smp_t));
308 }
309 mdb_printf("\n");
310 #if 0
311 mdb_printf("targ wwn ncmds throttle "
312 "dr_flag timeout dups\n");
313 mdb_printf("-------------------------------"
314 "--------------------------------\n");
315 for (i = 0; i < MPTSAS_MAX_TARGETS; i++) {
316 if (s->m_target[i].m_sas_wwn || s->m_target[i].m_deviceinfo) {
317 mdb_printf("%4d ", i);
318 if (s->m_target[i].m_sas_wwn)
319 mdb_printf("%"PRIx64" ",
320 s->m_target[i].m_sas_wwn);
321 mdb_printf("%3d", s->m_target[i].m_t_ncmds);
322 switch (s->m_target[i].m_t_throttle) {
323 case QFULL_THROTTLE:
324 mdb_printf(" QFULL ");
325 break;
326 case DRAIN_THROTTLE:
327 mdb_printf(" DRAIN ");
328 break;
329 case HOLD_THROTTLE:
330 mdb_printf(" HOLD ");
331 break;
332 case MAX_THROTTLE:
333 mdb_printf(" MAX ");
334 break;
335 case CHOKE_THROTTLE:
336 mdb_printf(" CHOKE ");
337 break;
338 default:
339 mdb_printf("%8d ",
340 s->m_target[i].m_t_throttle);
410 }
411 }
412 #endif
413 }
414
415 int
416 display_slotinfo()
417 {
418 #if 0
419 int i, nslots;
420 struct mptsas_cmd c, *q, *slots;
421 int header_output = 0;
422 int rv = DCMD_OK;
423 int slots_in_use = 0;
424 int tcmds = 0;
425 int mismatch = 0;
426 int wq, dq;
427 int ncmds = 0;
428 ulong_t saved_indent;
429
430 nslots = s->m_n_slots;
431
432 slots = mdb_alloc(sizeof (mptsas_cmd_t) * nslots, UM_SLEEP);
433
434 for (i = 0; i < nslots; i++)
435 if (s->m_slot[i]) {
436 slots_in_use++;
437 if (mdb_vread(&slots[i], sizeof (mptsas_cmd_t),
438 (uintptr_t)s->m_slot[i]) == -1) {
439 mdb_warn("couldn't read slot");
440 s->m_slot[i] = NULL;
441 }
442 if ((slots[i].cmd_flags & CFLAG_CMDIOC) == 0)
443 tcmds++;
444 if (i != slots[i].cmd_slot)
445 mismatch++;
446 }
447
448 for (q = m.m_waitq, wq = 0; q; q = c.cmd_linkp, wq++)
449 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q) == -1) {
450 mdb_warn("couldn't follow m_waitq");
463 ncmds += s->m_target[i].m_t_ncmds;
464
465 mdb_printf("\n");
466 mdb_printf(" mpt. slot mptsas_slots slot");
467 mdb_printf("\n");
468 mdb_printf("m_ncmds total"
469 " targ throttle m_t_ncmds targ_tot wq dq");
470 mdb_printf("\n");
471 mdb_printf("----------------------------------------------------");
472 mdb_printf("\n");
473
474 mdb_printf("%7d ", m.m_ncmds);
475 mdb_printf("%s", (m.m_ncmds == slots_in_use ? " " : "!="));
476 mdb_printf("%3d total %3d ", slots_in_use, ncmds);
477 mdb_printf("%s", (tcmds == ncmds ? " " : " !="));
478 mdb_printf("%3d %2d %2d\n", tcmds, wq, dq);
479
480 saved_indent = mdb_dec_indent(0);
481 mdb_dec_indent(saved_indent);
482
483 for (i = 0; i < s->m_n_slots; i++)
484 if (s->m_slot[i]) {
485 if (!header_output) {
486 mdb_printf("\n");
487 mdb_printf("mptsas_cmd slot cmd_slot "
488 "cmd_flags cmd_pkt_flags scsi_pkt "
489 " targ,lun [ pkt_cdbp ...\n");
490 mdb_printf("-------------------------------"
491 "--------------------------------------"
492 "--------------------------------------"
493 "------\n");
494 header_output = 1;
495 }
496 mdb_printf("%16p %4d %s %4d %8x %8x %16p ",
497 s->m_slot[i], i,
498 (i == slots[i].cmd_slot?" ":"BAD"),
499 slots[i].cmd_slot,
500 slots[i].cmd_flags,
501 slots[i].cmd_pkt_flags,
502 slots[i].cmd_pkt);
503 (void) print_cdb(&slots[i]);
585 mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p "
586 "should not have CFLAG_IN_TRANSPORT set\n", q);
587 if (c.cmd_flags & CFLAG_CMDARQ)
588 mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p "
589 "should not have CFLAG_CMDARQ set\n", q);
590 if (c.cmd_flags & CFLAG_COMPLETED)
591 mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p "
592 "should not have CFLAG_COMPLETED set\n", q);
593 }
594
595 exit:
596 mdb_free(slots, sizeof (mptsas_cmd_t) * nslots);
597 return (rv);
598 #endif
599 mdb_printf("\n");
600 mdb_printf("The slot information is not implemented yet\n");
601 return (0);
602 }
603
604 void
605 display_deviceinfo(struct mptsas m)
606 {
607 char device_path[PATH_MAX];
608
609 *device_path = 0;
610 if (construct_path((uintptr_t)m.m_dip, device_path) != DCMD_OK) {
611 strcpy(device_path, "couldn't determine device path");
612 }
613
614 mdb_printf("\n");
615 mdb_printf("Path in device tree %s\n", device_path);
616 #if 0
617 mdb_printf("base_wwid phys "
618 "mptid prodid devid revid ssid\n");
619 mdb_printf("-----------------------------"
620 "----------------------------------\n");
621 mdb_printf("%"PRIx64" %2d %3d "
622 "0x%04x 0x%04x ", m.un.m_base_wwid, m.m_num_phys, m.m_mptid,
623 m.m_productid, m.m_devid);
624 switch (m.m_devid) {
625 case MPTSAS_909:
626 mdb_printf("(909) ");
627 break;
628 case MPTSAS_929:
629 mdb_printf("(929) ");
630 break;
726 'v', MDB_OPT_SETBITS, TRUE, &verbose,
727 NULL) != argc)
728 return (DCMD_USAGE);
729
730
731 if (mdb_vread(&m, sizeof (m), addr) == -1) {
732 mdb_warn("couldn't read mpt struct at 0x%p", addr);
733 return (DCMD_ERR);
734 }
735
736 s = mdb_alloc(sizeof (mptsas_slots_t), UM_SLEEP);
737
738 if (mdb_vread(s, sizeof (mptsas_slots_t),
739 (uintptr_t)m.m_active) == -1) {
740 mdb_warn("couldn't read small mptsas_slots_t at 0x%p",
741 m.m_active);
742 mdb_free(s, sizeof (mptsas_slots_t));
743 return (DCMD_ERR);
744 }
745
746 nslots = s->m_n_slots;
747
748 mdb_free(s, sizeof (mptsas_slots_t));
749
750 slot_size = sizeof (mptsas_slots_t) +
751 (sizeof (mptsas_cmd_t *) * (nslots-1));
752
753 s = mdb_alloc(slot_size, UM_SLEEP);
754
755 if (mdb_vread(s, slot_size, (uintptr_t)m.m_active) == -1) {
756 mdb_warn("couldn't read large mptsas_slots_t at 0x%p",
757 m.m_active);
758 mdb_free(s, slot_size);
759 return (DCMD_ERR);
760 }
761
762 /* processing completed */
763
764 if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) ||
765 (flags & DCMD_LOOPFIRST) || slot_info || device_info ||
766 target_info) {
779 case PM_LEVEL_D0:
780 mdb_printf(" ON=D0 ");
781 break;
782 case PM_LEVEL_D1:
783 mdb_printf(" D1 ");
784 break;
785 case PM_LEVEL_D2:
786 mdb_printf(" D2 ");
787 break;
788 case PM_LEVEL_D3:
789 mdb_printf("OFF=D3 ");
790 break;
791 default:
792 mdb_printf("INVALD ");
793 }
794 mdb_printf("\n");
795
796 mdb_inc_indent(17);
797
798 if (target_info)
799 display_targets(s);
800
801 if (port_info)
802 display_ports(m);
803
804 if (device_info)
805 display_deviceinfo(m);
806
807 if (slot_info)
808 display_slotinfo();
809
810 mdb_dec_indent(17);
811
812 mdb_free(s, slot_size);
813
814 return (rv);
815 }
816 /*
817 * Only -t is implemented now, will add more later when the driver is stable
818 */
819 void
820 mptsas_help()
821 {
822 mdb_printf("Prints summary information about each mpt_sas instance, "
823 "including warning\nmessages when slot usage doesn't match "
824 "summary information.\n"
825 "Without the address of a \"struct mptsas\", prints every "
826 "instance.\n\n"
827 "Switches:\n"
828 " -t includes information about targets\n"
829 " -p includes information about port\n"
830 " -d includes information about the hardware\n");
831 }
832
833 static const mdb_dcmd_t dcmds[] = {
834 { "mptsas", "?[-tpd]", "print mpt_sas information", mptsas_dcmd,
835 mptsas_help}, { NULL }
836 };
837
838 static const mdb_modinfo_t modinfo = {
|
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 /*
27 * Copyright 2014 Joyent, Inc. All rights reserved.
28 */
29
30 #include <limits.h>
31 #include <sys/mdb_modapi.h>
32 #include <sys/sysinfo.h>
33 #include <sys/sunmdi.h>
34 #include <sys/list.h>
35 #include <sys/scsi/scsi.h>
36
37 #pragma pack(1)
38 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
39 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
40 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
41 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
42 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
43 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
44 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h>
45 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
46 #pragma pack()
47
48 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
49 #include <sys/scsi/adapters/mpt_sas/mptsas_hash.h>
50
51 struct {
52 int value;
53 char *text;
54 } devinfo_array[] = {
55 { MPI2_SAS_DEVICE_INFO_SEP, "SEP" },
56 { MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE, "ATAPI device" },
57 { MPI2_SAS_DEVICE_INFO_LSI_DEVICE, "LSI device" },
58 { MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH, "direct attach" },
59 { MPI2_SAS_DEVICE_INFO_SSP_TARGET, "SSP tgt" },
60 { MPI2_SAS_DEVICE_INFO_STP_TARGET, "STP tgt" },
61 { MPI2_SAS_DEVICE_INFO_SMP_TARGET, "SMP tgt" },
62 { MPI2_SAS_DEVICE_INFO_SATA_DEVICE, "SATA dev" },
63 { MPI2_SAS_DEVICE_INFO_SSP_INITIATOR, "SSP init" },
64 { MPI2_SAS_DEVICE_INFO_STP_INITIATOR, "STP init" },
65 { MPI2_SAS_DEVICE_INFO_SMP_INITIATOR, "SMP init" },
66 { MPI2_SAS_DEVICE_INFO_SATA_HOST, "SATA host" }
67 };
68
69 int
70 construct_path(uintptr_t addr, char *result)
71 {
72 struct dev_info d;
73 char devi_node[PATH_MAX];
74 char devi_addr[PATH_MAX];
75
76 if (mdb_vread(&d, sizeof (d), addr) == -1) {
77 mdb_warn("couldn't read dev_info");
78 return (DCMD_ERR);
79 }
80
81 if (d.devi_parent) {
82 construct_path((uintptr_t)d.devi_parent, result);
83 mdb_readstr(devi_node, sizeof (devi_node),
84 (uintptr_t)d.devi_node_name);
85 mdb_readstr(devi_addr, sizeof (devi_addr),
86 (uintptr_t)d.devi_addr);
87 mdb_snprintf(result+strlen(result),
88 PATH_MAX-strlen(result),
91 }
92 return (DCMD_OK);
93 }
94
95 /* ARGSUSED */
96 int
97 mdi_info_cb(uintptr_t addr, const void *data, void *cbdata)
98 {
99 struct mdi_pathinfo pi;
100 struct mdi_client c;
101 char dev_path[PATH_MAX];
102 char string[PATH_MAX];
103 int mdi_target = 0, mdi_lun = 0;
104 int target = *(int *)cbdata;
105
106 if (mdb_vread(&pi, sizeof (pi), addr) == -1) {
107 mdb_warn("couldn't read mdi_pathinfo");
108 return (DCMD_ERR);
109 }
110 mdb_readstr(string, sizeof (string), (uintptr_t)pi.pi_addr);
111 mdi_target = (int)mdb_strtoull(string);
112 mdi_lun = (int)mdb_strtoull(strchr(string, ',') + 1);
113 if (target != mdi_target)
114 return (0);
115
116 if (mdb_vread(&c, sizeof (c), (uintptr_t)pi.pi_client) == -1) {
117 mdb_warn("couldn't read mdi_client");
118 return (-1);
119 }
120
121 *dev_path = NULL;
122 if (construct_path((uintptr_t)c.ct_dip, dev_path) != DCMD_OK)
123 strcpy(dev_path, "unknown");
124
125 mdb_printf("LUN %d: %s\n", mdi_lun, dev_path);
126 mdb_printf(" dip: %p %s path", c.ct_dip,
127 (pi.pi_preferred ? "preferred" : ""));
128 switch (pi.pi_state & MDI_PATHINFO_STATE_MASK) {
129 case MDI_PATHINFO_STATE_INIT:
130 mdb_printf(" initializing");
131 break;
132 case MDI_PATHINFO_STATE_ONLINE:
188 /*
189 * We use cmd_cdblen here because 5.10 doesn't
190 * have the cdb length in the pkt
191 */
192 if (mdb_vread(&cdb, m->cmd_cdblen, (uintptr_t)pkt.pkt_cdbp) == -1) {
193 mdb_warn("couldn't read pkt_cdbp");
194 return;
195 }
196
197 mdb_printf("%3d,%-3d [ ",
198 pkt.pkt_address.a_target, pkt.pkt_address.a_lun);
199
200 for (j = 0; j < m->cmd_cdblen; j++)
201 mdb_printf("%02x ", cdb[j]);
202
203 mdb_printf("]\n");
204 }
205
206
207 void
208 display_ports(struct mptsas *mp)
209 {
210 int i;
211 mdb_printf("\n");
212 mdb_printf("phy number and port mapping table\n");
213 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
214 if (mp->m_phy_info[i].attached_devhdl) {
215 mdb_printf("phy %x --> port %x, phymask %x,"
216 "attached_devhdl %x\n", i, mp->m_phy_info[i].port_num,
217 mp->m_phy_info[i].phy_mask,
218 mp->m_phy_info[i].attached_devhdl);
219 }
220 }
221 mdb_printf("\n");
222 }
223
224 static uintptr_t
225 klist_head(list_t *lp, uintptr_t klp)
226 {
227 if ((uintptr_t)lp->list_head.list_next ==
228 klp + offsetof(struct list, list_head))
229 return (NULL);
230
231 return ((uintptr_t)(((char *)lp->list_head.list_next) -
232 lp->list_offset));
233 }
234
235 static uintptr_t
236 klist_next(list_t *lp, uintptr_t klp, void *op)
237 {
238 /* LINTED E_BAD_PTR_CAST_ALIG */
239 struct list_node *np = (struct list_node *)(((char *)op) +
240 lp->list_offset);
241
242 if ((uintptr_t)np->list_next == klp + offsetof(struct list, list_head))
243 return (NULL);
244
245 return (((uintptr_t)(np->list_next)) - lp->list_offset);
246 }
247
248 static void *
249 krefhash_first(uintptr_t khp)
250 {
251 refhash_t mh;
252 uintptr_t klp;
253 uintptr_t kop;
254 void *rp;
255
256 mdb_vread(&mh, sizeof (mh), khp);
257 klp = klist_head(&mh.rh_objs, khp + offsetof(refhash_t, rh_objs));
258 if (klp == 0)
259 return (NULL);
260
261 kop = klp - mh.rh_link_off;
262 rp = mdb_alloc(mh.rh_obj_size, UM_SLEEP);
263 mdb_vread(rp, mh.rh_obj_size, kop);
264
265 return (rp);
266 }
267
268 static void *
269 krefhash_next(uintptr_t khp, void *op)
270 {
271 refhash_t mh;
272 void *prev = op;
273 refhash_link_t *lp;
274 uintptr_t klp;
275 uintptr_t kop;
276 refhash_link_t ml;
277 void *rp;
278
279 mdb_vread(&mh, sizeof (mh), khp);
280 /* LINTED E_BAD_PTR_CAST_ALIG */
281 lp = (refhash_link_t *)(((char *)(op)) + mh.rh_link_off);
282 ml = *lp;
283 while ((klp = klist_next(&mh.rh_objs,
284 khp + offsetof(refhash_t, rh_objs), &ml)) != NULL) {
285 mdb_vread(&ml, sizeof (ml), klp);
286 if (!(ml.rhl_flags & RHL_F_DEAD))
287 break;
288 }
289
290 if (klp == 0) {
291 mdb_free(prev, mh.rh_obj_size);
292 return (NULL);
293 }
294
295 kop = klp - mh.rh_link_off;
296 rp = mdb_alloc(mh.rh_obj_size, UM_SLEEP);
297 mdb_vread(rp, mh.rh_obj_size, kop);
298
299 mdb_free(prev, mh.rh_obj_size);
300 return (rp);
301 }
302
303 void
304 display_targets(struct mptsas *mp)
305 {
306 mptsas_target_t *ptgt;
307 mptsas_smp_t *psmp;
308
309 mdb_printf("\n");
310 mdb_printf("The SCSI target information\n");
311 for (ptgt = (mptsas_target_t *)krefhash_first((uintptr_t)mp->m_targets);
312 ptgt != NULL;
313 ptgt = krefhash_next((uintptr_t)mp->m_targets, ptgt)) {
314 mdb_printf("\n");
315 mdb_printf("devhdl %x, sasaddress %"PRIx64", phymask %x,"
316 "devinfo %x\n", ptgt->m_devhdl, ptgt->m_addr.mta_wwn,
317 ptgt->m_addr.mta_phymask, ptgt->m_deviceinfo);
318 mdb_printf("throttle %x, dr_flag %x, m_t_ncmds %x, "
319 "enclosure %x, slot_num %x\n", ptgt->m_t_throttle,
320 ptgt->m_dr_flag, ptgt->m_t_ncmds, ptgt->m_enclosure,
321 ptgt->m_slot_num);
322 }
323
324 mdb_printf("\n");
325 mdb_printf("The smp child information\n");
326 for (psmp = (mptsas_smp_t *)krefhash_first(
327 (uintptr_t)mp->m_smp_targets);
328 psmp != NULL;
329 psmp = krefhash_next((uintptr_t)mp->m_smp_targets, psmp)) {
330 mdb_printf("\n");
331 mdb_printf("devhdl %x, sasaddress %"PRIx64", phymask %x \n",
332 psmp->m_devhdl, psmp->m_addr.mta_wwn,
333 psmp->m_addr.mta_phymask);
334 }
335 mdb_printf("\n");
336 #if 0
337 mdb_printf("targ wwn ncmds throttle "
338 "dr_flag timeout dups\n");
339 mdb_printf("-------------------------------"
340 "--------------------------------\n");
341 for (i = 0; i < MPTSAS_MAX_TARGETS; i++) {
342 if (s->m_target[i].m_addr.mta_wwn ||
343 s->m_target[i].m_deviceinfo) {
344 mdb_printf("%4d ", i);
345 if (s->m_target[i].m_addr.mta_wwn)
346 mdb_printf("%"PRIx64" ",
347 s->m_target[i].m_addr.mta_wwn);
348 mdb_printf("%3d", s->m_target[i].m_t_ncmds);
349 switch (s->m_target[i].m_t_throttle) {
350 case QFULL_THROTTLE:
351 mdb_printf(" QFULL ");
352 break;
353 case DRAIN_THROTTLE:
354 mdb_printf(" DRAIN ");
355 break;
356 case HOLD_THROTTLE:
357 mdb_printf(" HOLD ");
358 break;
359 case MAX_THROTTLE:
360 mdb_printf(" MAX ");
361 break;
362 case CHOKE_THROTTLE:
363 mdb_printf(" CHOKE ");
364 break;
365 default:
366 mdb_printf("%8d ",
367 s->m_target[i].m_t_throttle);
437 }
438 }
439 #endif
440 }
441
442 int
443 display_slotinfo()
444 {
445 #if 0
446 int i, nslots;
447 struct mptsas_cmd c, *q, *slots;
448 int header_output = 0;
449 int rv = DCMD_OK;
450 int slots_in_use = 0;
451 int tcmds = 0;
452 int mismatch = 0;
453 int wq, dq;
454 int ncmds = 0;
455 ulong_t saved_indent;
456
457 nslots = s->m_n_normal;
458
459 slots = mdb_alloc(sizeof (mptsas_cmd_t) * nslots, UM_SLEEP);
460
461 for (i = 0; i < nslots; i++)
462 if (s->m_slot[i]) {
463 slots_in_use++;
464 if (mdb_vread(&slots[i], sizeof (mptsas_cmd_t),
465 (uintptr_t)s->m_slot[i]) == -1) {
466 mdb_warn("couldn't read slot");
467 s->m_slot[i] = NULL;
468 }
469 if ((slots[i].cmd_flags & CFLAG_CMDIOC) == 0)
470 tcmds++;
471 if (i != slots[i].cmd_slot)
472 mismatch++;
473 }
474
475 for (q = m.m_waitq, wq = 0; q; q = c.cmd_linkp, wq++)
476 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q) == -1) {
477 mdb_warn("couldn't follow m_waitq");
490 ncmds += s->m_target[i].m_t_ncmds;
491
492 mdb_printf("\n");
493 mdb_printf(" mpt. slot mptsas_slots slot");
494 mdb_printf("\n");
495 mdb_printf("m_ncmds total"
496 " targ throttle m_t_ncmds targ_tot wq dq");
497 mdb_printf("\n");
498 mdb_printf("----------------------------------------------------");
499 mdb_printf("\n");
500
501 mdb_printf("%7d ", m.m_ncmds);
502 mdb_printf("%s", (m.m_ncmds == slots_in_use ? " " : "!="));
503 mdb_printf("%3d total %3d ", slots_in_use, ncmds);
504 mdb_printf("%s", (tcmds == ncmds ? " " : " !="));
505 mdb_printf("%3d %2d %2d\n", tcmds, wq, dq);
506
507 saved_indent = mdb_dec_indent(0);
508 mdb_dec_indent(saved_indent);
509
510 for (i = 0; i < s->m_n_normal; i++)
511 if (s->m_slot[i]) {
512 if (!header_output) {
513 mdb_printf("\n");
514 mdb_printf("mptsas_cmd slot cmd_slot "
515 "cmd_flags cmd_pkt_flags scsi_pkt "
516 " targ,lun [ pkt_cdbp ...\n");
517 mdb_printf("-------------------------------"
518 "--------------------------------------"
519 "--------------------------------------"
520 "------\n");
521 header_output = 1;
522 }
523 mdb_printf("%16p %4d %s %4d %8x %8x %16p ",
524 s->m_slot[i], i,
525 (i == slots[i].cmd_slot?" ":"BAD"),
526 slots[i].cmd_slot,
527 slots[i].cmd_flags,
528 slots[i].cmd_pkt_flags,
529 slots[i].cmd_pkt);
530 (void) print_cdb(&slots[i]);
612 mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p "
613 "should not have CFLAG_IN_TRANSPORT set\n", q);
614 if (c.cmd_flags & CFLAG_CMDARQ)
615 mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p "
616 "should not have CFLAG_CMDARQ set\n", q);
617 if (c.cmd_flags & CFLAG_COMPLETED)
618 mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p "
619 "should not have CFLAG_COMPLETED set\n", q);
620 }
621
622 exit:
623 mdb_free(slots, sizeof (mptsas_cmd_t) * nslots);
624 return (rv);
625 #endif
626 mdb_printf("\n");
627 mdb_printf("The slot information is not implemented yet\n");
628 return (0);
629 }
630
631 void
632 display_deviceinfo(struct mptsas *mp)
633 {
634 char device_path[PATH_MAX];
635
636 *device_path = 0;
637 if (construct_path((uintptr_t)mp->m_dip, device_path) != DCMD_OK) {
638 strcpy(device_path, "couldn't determine device path");
639 }
640
641 mdb_printf("\n");
642 mdb_printf("Path in device tree %s\n", device_path);
643 #if 0
644 mdb_printf("base_wwid phys "
645 "mptid prodid devid revid ssid\n");
646 mdb_printf("-----------------------------"
647 "----------------------------------\n");
648 mdb_printf("%"PRIx64" %2d %3d "
649 "0x%04x 0x%04x ", m.un.m_base_wwid, m.m_num_phys, m.m_mptid,
650 m.m_productid, m.m_devid);
651 switch (m.m_devid) {
652 case MPTSAS_909:
653 mdb_printf("(909) ");
654 break;
655 case MPTSAS_929:
656 mdb_printf("(929) ");
657 break;
753 'v', MDB_OPT_SETBITS, TRUE, &verbose,
754 NULL) != argc)
755 return (DCMD_USAGE);
756
757
758 if (mdb_vread(&m, sizeof (m), addr) == -1) {
759 mdb_warn("couldn't read mpt struct at 0x%p", addr);
760 return (DCMD_ERR);
761 }
762
763 s = mdb_alloc(sizeof (mptsas_slots_t), UM_SLEEP);
764
765 if (mdb_vread(s, sizeof (mptsas_slots_t),
766 (uintptr_t)m.m_active) == -1) {
767 mdb_warn("couldn't read small mptsas_slots_t at 0x%p",
768 m.m_active);
769 mdb_free(s, sizeof (mptsas_slots_t));
770 return (DCMD_ERR);
771 }
772
773 nslots = s->m_n_normal;
774
775 mdb_free(s, sizeof (mptsas_slots_t));
776
777 slot_size = sizeof (mptsas_slots_t) +
778 (sizeof (mptsas_cmd_t *) * (nslots-1));
779
780 s = mdb_alloc(slot_size, UM_SLEEP);
781
782 if (mdb_vread(s, slot_size, (uintptr_t)m.m_active) == -1) {
783 mdb_warn("couldn't read large mptsas_slots_t at 0x%p",
784 m.m_active);
785 mdb_free(s, slot_size);
786 return (DCMD_ERR);
787 }
788
789 /* processing completed */
790
791 if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) ||
792 (flags & DCMD_LOOPFIRST) || slot_info || device_info ||
793 target_info) {
806 case PM_LEVEL_D0:
807 mdb_printf(" ON=D0 ");
808 break;
809 case PM_LEVEL_D1:
810 mdb_printf(" D1 ");
811 break;
812 case PM_LEVEL_D2:
813 mdb_printf(" D2 ");
814 break;
815 case PM_LEVEL_D3:
816 mdb_printf("OFF=D3 ");
817 break;
818 default:
819 mdb_printf("INVALD ");
820 }
821 mdb_printf("\n");
822
823 mdb_inc_indent(17);
824
825 if (target_info)
826 display_targets(&m);
827
828 if (port_info)
829 display_ports(&m);
830
831 if (device_info)
832 display_deviceinfo(&m);
833
834 if (slot_info)
835 display_slotinfo();
836
837 mdb_dec_indent(17);
838
839 mdb_free(s, slot_size);
840
841 return (rv);
842 }
843
844 void
845 mptsas_help()
846 {
847 mdb_printf("Prints summary information about each mpt_sas instance, "
848 "including warning\nmessages when slot usage doesn't match "
849 "summary information.\n"
850 "Without the address of a \"struct mptsas\", prints every "
851 "instance.\n\n"
852 "Switches:\n"
853 " -t includes information about targets\n"
854 " -p includes information about port\n"
855 " -d includes information about the hardware\n");
856 }
857
858 static const mdb_dcmd_t dcmds[] = {
859 { "mptsas", "?[-tpd]", "print mpt_sas information", mptsas_dcmd,
860 mptsas_help}, { NULL }
861 };
862
863 static const mdb_modinfo_t modinfo = {
|