xref: /onnv-gate/usr/src/cmd/mdb/common/modules/pmcs/pmcs.c (revision 10743:9bd3b79547a5)
110696SDavid.Hollister@Sun.COM /*
210696SDavid.Hollister@Sun.COM  * CDDL HEADER START
310696SDavid.Hollister@Sun.COM  *
410696SDavid.Hollister@Sun.COM  * The contents of this file are subject to the terms of the
510696SDavid.Hollister@Sun.COM  * Common Development and Distribution License (the "License").
610696SDavid.Hollister@Sun.COM  * You may not use this file except in compliance with the License.
710696SDavid.Hollister@Sun.COM  *
810696SDavid.Hollister@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910696SDavid.Hollister@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1010696SDavid.Hollister@Sun.COM  * See the License for the specific language governing permissions
1110696SDavid.Hollister@Sun.COM  * and limitations under the License.
1210696SDavid.Hollister@Sun.COM  *
1310696SDavid.Hollister@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1410696SDavid.Hollister@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510696SDavid.Hollister@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1610696SDavid.Hollister@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1710696SDavid.Hollister@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1810696SDavid.Hollister@Sun.COM  *
1910696SDavid.Hollister@Sun.COM  * CDDL HEADER END
2010696SDavid.Hollister@Sun.COM  */
2110696SDavid.Hollister@Sun.COM /*
2210696SDavid.Hollister@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2310696SDavid.Hollister@Sun.COM  * Use is subject to license terms.
2410696SDavid.Hollister@Sun.COM  */
2510696SDavid.Hollister@Sun.COM 
2610696SDavid.Hollister@Sun.COM #include <limits.h>
2710696SDavid.Hollister@Sun.COM #include <sys/mdb_modapi.h>
2810696SDavid.Hollister@Sun.COM #include <sys/sysinfo.h>
2910696SDavid.Hollister@Sun.COM #include <sys/scsi/scsi.h>
3010696SDavid.Hollister@Sun.COM #include <sys/scsi/adapters/pmcs/pmcs.h>
3110696SDavid.Hollister@Sun.COM 
3210696SDavid.Hollister@Sun.COM #define	MDB_RD(a, b, c)	mdb_vread(a, b, (uintptr_t)c)
3310696SDavid.Hollister@Sun.COM #define	NOREAD(a, b)	mdb_warn("could not read " #a " at 0x%p", b)
3410696SDavid.Hollister@Sun.COM 
3510696SDavid.Hollister@Sun.COM static pmcs_hw_t ss;
3610696SDavid.Hollister@Sun.COM static pmcs_xscsi_t **targets = NULL;
3710696SDavid.Hollister@Sun.COM static int target_idx;
3810696SDavid.Hollister@Sun.COM 
3910696SDavid.Hollister@Sun.COM static uint32_t	sas_phys, sata_phys, exp_phys, num_expanders, empty_phys;
4010696SDavid.Hollister@Sun.COM 
4110696SDavid.Hollister@Sun.COM static pmcs_phy_t *pmcs_next_sibling(pmcs_phy_t *phyp);
42*10743SDavid.Hollister@Sun.COM static void display_one_work(pmcwork_t *wp, int verbose, int idx);
4310696SDavid.Hollister@Sun.COM 
4410696SDavid.Hollister@Sun.COM static void
4510696SDavid.Hollister@Sun.COM print_sas_address(pmcs_phy_t *phy)
4610696SDavid.Hollister@Sun.COM {
4710696SDavid.Hollister@Sun.COM 	int idx;
4810696SDavid.Hollister@Sun.COM 
4910696SDavid.Hollister@Sun.COM 	for (idx = 0; idx < 8; idx++) {
5010696SDavid.Hollister@Sun.COM 		mdb_printf("%02x", phy->sas_address[idx]);
5110696SDavid.Hollister@Sun.COM 	}
5210696SDavid.Hollister@Sun.COM }
5310696SDavid.Hollister@Sun.COM 
5410696SDavid.Hollister@Sun.COM /*ARGSUSED*/
5510696SDavid.Hollister@Sun.COM static void
5610696SDavid.Hollister@Sun.COM display_ic(struct pmcs_hw m, int verbose)
5710696SDavid.Hollister@Sun.COM {
5810696SDavid.Hollister@Sun.COM 	int msec_per_tick;
5910696SDavid.Hollister@Sun.COM 
6010696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&msec_per_tick, "msec_per_tick") == -1) {
6110696SDavid.Hollister@Sun.COM 		mdb_warn("can't read msec_per_tick");
6210696SDavid.Hollister@Sun.COM 		msec_per_tick = 0;
6310696SDavid.Hollister@Sun.COM 	}
6410696SDavid.Hollister@Sun.COM 
6510696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
6610696SDavid.Hollister@Sun.COM 	mdb_printf("Interrupt coalescing timer info\n");
6710696SDavid.Hollister@Sun.COM 	mdb_printf("-------------------------------\n");
6810696SDavid.Hollister@Sun.COM 	if (msec_per_tick == 0) {
6910696SDavid.Hollister@Sun.COM 		mdb_printf("Quantum                       : ?? ms\n");
7010696SDavid.Hollister@Sun.COM 	} else {
7110696SDavid.Hollister@Sun.COM 		mdb_printf("Quantum                       : %d ms\n",
7210696SDavid.Hollister@Sun.COM 		    m.io_intr_coal.quantum * msec_per_tick);
7310696SDavid.Hollister@Sun.COM 	}
7410696SDavid.Hollister@Sun.COM 	mdb_printf("Timer enabled                 : ");
7510696SDavid.Hollister@Sun.COM 	if (m.io_intr_coal.timer_on) {
7610696SDavid.Hollister@Sun.COM 		mdb_printf("Yes\n");
7710696SDavid.Hollister@Sun.COM 		mdb_printf("Coalescing timer value        : %d us\n",
7810696SDavid.Hollister@Sun.COM 		    m.io_intr_coal.intr_coal_timer);
7910696SDavid.Hollister@Sun.COM 	} else {
8010696SDavid.Hollister@Sun.COM 		mdb_printf("No\n");
8110696SDavid.Hollister@Sun.COM 	}
8210696SDavid.Hollister@Sun.COM 	mdb_printf("Total nsecs between interrupts: %ld\n",
8310696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.nsecs_between_intrs);
8410696SDavid.Hollister@Sun.COM 	mdb_printf("Time of last I/O interrupt    : %ld\n",
8510696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.last_io_comp);
8610696SDavid.Hollister@Sun.COM 	mdb_printf("Number of I/O interrupts      : %d\n",
8710696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.num_intrs);
8810696SDavid.Hollister@Sun.COM 	mdb_printf("Number of I/O completions     : %d\n",
8910696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.num_io_completions);
9010696SDavid.Hollister@Sun.COM 	mdb_printf("Max I/O completion interrupts : %d\n",
9110696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.max_io_completions);
9210696SDavid.Hollister@Sun.COM 	mdb_printf("Measured ECHO int latency     : %d ns\n",
9310696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.intr_latency);
9410696SDavid.Hollister@Sun.COM 	mdb_printf("Interrupt threshold           : %d\n",
9510696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.intr_threshold);
9610696SDavid.Hollister@Sun.COM }
9710696SDavid.Hollister@Sun.COM 
9810696SDavid.Hollister@Sun.COM /*ARGSUSED*/
9910696SDavid.Hollister@Sun.COM static int
10010696SDavid.Hollister@Sun.COM pmcs_iport_phy_walk_cb(uintptr_t addr, const void *wdata, void *priv)
10110696SDavid.Hollister@Sun.COM {
10210696SDavid.Hollister@Sun.COM 	struct pmcs_phy		phy;
10310696SDavid.Hollister@Sun.COM 
10410696SDavid.Hollister@Sun.COM 	if (mdb_vread(&phy, sizeof (struct pmcs_phy), addr) !=
10510696SDavid.Hollister@Sun.COM 	    sizeof (struct pmcs_phy)) {
10610696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
10710696SDavid.Hollister@Sun.COM 	}
10810696SDavid.Hollister@Sun.COM 
10910696SDavid.Hollister@Sun.COM 	mdb_printf("%16p %2d\n", addr, phy.phynum);
11010696SDavid.Hollister@Sun.COM 
11110696SDavid.Hollister@Sun.COM 	return (0);
11210696SDavid.Hollister@Sun.COM }
11310696SDavid.Hollister@Sun.COM 
11410696SDavid.Hollister@Sun.COM /*ARGSUSED*/
11510696SDavid.Hollister@Sun.COM static int
11610696SDavid.Hollister@Sun.COM pmcs_iport_walk_cb(uintptr_t addr, const void *wdata, void *priv)
11710696SDavid.Hollister@Sun.COM {
11810696SDavid.Hollister@Sun.COM 	struct pmcs_iport	iport;
11910696SDavid.Hollister@Sun.COM 	uintptr_t		list_addr;
12010696SDavid.Hollister@Sun.COM 	char			*ua_state;
12110696SDavid.Hollister@Sun.COM 	char			portid[4];
12210696SDavid.Hollister@Sun.COM 	char			unit_address[34];
12310696SDavid.Hollister@Sun.COM 
12410696SDavid.Hollister@Sun.COM 	if (mdb_vread(&iport, sizeof (struct pmcs_iport), addr) !=
12510696SDavid.Hollister@Sun.COM 	    sizeof (struct pmcs_iport)) {
12610696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
12710696SDavid.Hollister@Sun.COM 	}
12810696SDavid.Hollister@Sun.COM 
12910696SDavid.Hollister@Sun.COM 	if (mdb_readstr(unit_address, sizeof (unit_address),
13010696SDavid.Hollister@Sun.COM 	    (uintptr_t)(iport.ua)) == -1) {
13110696SDavid.Hollister@Sun.COM 		strncpy(unit_address, "Unset", sizeof (unit_address));
13210696SDavid.Hollister@Sun.COM 	}
13310696SDavid.Hollister@Sun.COM 
13410696SDavid.Hollister@Sun.COM 	if (iport.portid == 0xffff) {
13510696SDavid.Hollister@Sun.COM 		mdb_snprintf(portid, sizeof (portid), "%s", "-");
13610696SDavid.Hollister@Sun.COM 	} else {
13710696SDavid.Hollister@Sun.COM 		mdb_snprintf(portid, sizeof (portid), "%d", iport.portid);
13810696SDavid.Hollister@Sun.COM 	}
13910696SDavid.Hollister@Sun.COM 
14010696SDavid.Hollister@Sun.COM 	switch (iport.ua_state) {
14110696SDavid.Hollister@Sun.COM 	case UA_INACTIVE:
14210696SDavid.Hollister@Sun.COM 		ua_state = "Inactive";
14310696SDavid.Hollister@Sun.COM 		break;
14410696SDavid.Hollister@Sun.COM 	case UA_PEND_ACTIVATE:
14510696SDavid.Hollister@Sun.COM 		ua_state = "PendActivate";
14610696SDavid.Hollister@Sun.COM 		break;
14710696SDavid.Hollister@Sun.COM 	case UA_ACTIVE:
14810696SDavid.Hollister@Sun.COM 		ua_state = "Active";
14910696SDavid.Hollister@Sun.COM 		break;
15010696SDavid.Hollister@Sun.COM 	case UA_PEND_DEACTIVATE:
15110696SDavid.Hollister@Sun.COM 		ua_state = "PendDeactivate";
15210696SDavid.Hollister@Sun.COM 		break;
15310696SDavid.Hollister@Sun.COM 	default:
15410696SDavid.Hollister@Sun.COM 		ua_state = "Unknown";
15510696SDavid.Hollister@Sun.COM 	}
15610696SDavid.Hollister@Sun.COM 
15710696SDavid.Hollister@Sun.COM 	if (strlen(unit_address) < 3) {
15810696SDavid.Hollister@Sun.COM 		/* Standard iport unit address */
15910696SDavid.Hollister@Sun.COM 		mdb_printf("UA %-16s %16s %8s %8s %16s", "Iport", "UA State",
16010696SDavid.Hollister@Sun.COM 		    "PortID", "NumPhys", "DIP\n");
16110696SDavid.Hollister@Sun.COM 		mdb_printf("%2s %16p %16s %8s %8d %16p\n", unit_address, addr,
16210696SDavid.Hollister@Sun.COM 		    ua_state, portid, iport.nphy, iport.dip);
16310696SDavid.Hollister@Sun.COM 	} else {
16410696SDavid.Hollister@Sun.COM 		/* Temporary iport unit address */
16510696SDavid.Hollister@Sun.COM 		mdb_printf("%-32s %16s %20s %8s %8s %16s", "UA", "Iport",
16610696SDavid.Hollister@Sun.COM 		    "UA State", "PortID", "NumPhys", "DIP\n");
16710696SDavid.Hollister@Sun.COM 		mdb_printf("%32s %16p %20s %8s %8d %16p\n", unit_address, addr,
16810696SDavid.Hollister@Sun.COM 		    ua_state, portid, iport.nphy, iport.dip);
16910696SDavid.Hollister@Sun.COM 	}
17010696SDavid.Hollister@Sun.COM 
17110696SDavid.Hollister@Sun.COM 	if (iport.nphy > 0) {
17210696SDavid.Hollister@Sun.COM 		mdb_inc_indent(4);
17310696SDavid.Hollister@Sun.COM 		mdb_printf("%-18s %8s", "Phy", "PhyNum\n");
17410696SDavid.Hollister@Sun.COM 		mdb_inc_indent(2);
17510696SDavid.Hollister@Sun.COM 		list_addr =
17610696SDavid.Hollister@Sun.COM 		    (uintptr_t)(addr + offsetof(struct pmcs_iport, phys));
17710696SDavid.Hollister@Sun.COM 		if (mdb_pwalk("list", pmcs_iport_phy_walk_cb, NULL,
17810696SDavid.Hollister@Sun.COM 		    list_addr) == -1) {
17910696SDavid.Hollister@Sun.COM 			mdb_warn("pmcs iport walk failed");
18010696SDavid.Hollister@Sun.COM 		}
18110696SDavid.Hollister@Sun.COM 		mdb_dec_indent(6);
18210696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
18310696SDavid.Hollister@Sun.COM 	}
18410696SDavid.Hollister@Sun.COM 
18510696SDavid.Hollister@Sun.COM 	return (0);
18610696SDavid.Hollister@Sun.COM }
18710696SDavid.Hollister@Sun.COM 
18810696SDavid.Hollister@Sun.COM /*ARGSUSED*/
18910696SDavid.Hollister@Sun.COM static void
19010696SDavid.Hollister@Sun.COM display_iport(struct pmcs_hw m, uintptr_t addr, int verbose)
19110696SDavid.Hollister@Sun.COM {
19210696SDavid.Hollister@Sun.COM 	uintptr_t	list_addr;
19310696SDavid.Hollister@Sun.COM 
19410696SDavid.Hollister@Sun.COM 	if (m.iports_attached) {
19510696SDavid.Hollister@Sun.COM 		mdb_printf("Iport information:\n");
19610696SDavid.Hollister@Sun.COM 		mdb_printf("-----------------\n");
19710696SDavid.Hollister@Sun.COM 	} else {
19810696SDavid.Hollister@Sun.COM 		mdb_printf("No Iports found.\n\n");
19910696SDavid.Hollister@Sun.COM 		return;
20010696SDavid.Hollister@Sun.COM 	}
20110696SDavid.Hollister@Sun.COM 
20210696SDavid.Hollister@Sun.COM 	list_addr = (uintptr_t)(addr + offsetof(struct pmcs_hw, iports));
20310696SDavid.Hollister@Sun.COM 
20410696SDavid.Hollister@Sun.COM 	if (mdb_pwalk("list", pmcs_iport_walk_cb, NULL, list_addr) == -1) {
20510696SDavid.Hollister@Sun.COM 		mdb_warn("pmcs iport walk failed");
20610696SDavid.Hollister@Sun.COM 	}
20710696SDavid.Hollister@Sun.COM 
20810696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
20910696SDavid.Hollister@Sun.COM }
21010696SDavid.Hollister@Sun.COM 
211*10743SDavid.Hollister@Sun.COM static void
212*10743SDavid.Hollister@Sun.COM display_completion_queue(struct pmcs_hw ss)
213*10743SDavid.Hollister@Sun.COM {
214*10743SDavid.Hollister@Sun.COM 	pmcs_iocomp_cb_t ccb, *ccbp;
215*10743SDavid.Hollister@Sun.COM 	pmcwork_t work;
216*10743SDavid.Hollister@Sun.COM 
217*10743SDavid.Hollister@Sun.COM 	if (ss.iocomp_cb_head == NULL) {
218*10743SDavid.Hollister@Sun.COM 		mdb_printf("Completion queue is empty.\n");
219*10743SDavid.Hollister@Sun.COM 		return;
220*10743SDavid.Hollister@Sun.COM 	}
221*10743SDavid.Hollister@Sun.COM 
222*10743SDavid.Hollister@Sun.COM 	ccbp = ss.iocomp_cb_head;
223*10743SDavid.Hollister@Sun.COM 	mdb_printf("%8s %10s %20s %8s %8s O D\n",
224*10743SDavid.Hollister@Sun.COM 	    "HTag", "State", "Phy Path", "Target", "Timer");
225*10743SDavid.Hollister@Sun.COM 
226*10743SDavid.Hollister@Sun.COM 	while (ccbp) {
227*10743SDavid.Hollister@Sun.COM 		if (mdb_vread(&ccb, sizeof (pmcs_iocomp_cb_t),
228*10743SDavid.Hollister@Sun.COM 		    (uintptr_t)ccbp) != sizeof (pmcs_iocomp_cb_t)) {
229*10743SDavid.Hollister@Sun.COM 			mdb_warn("Unable to read completion queue entry\n");
230*10743SDavid.Hollister@Sun.COM 			return;
231*10743SDavid.Hollister@Sun.COM 		}
232*10743SDavid.Hollister@Sun.COM 
233*10743SDavid.Hollister@Sun.COM 		if (mdb_vread(&work, sizeof (pmcwork_t), (uintptr_t)ccb.pwrk)
234*10743SDavid.Hollister@Sun.COM 		    != sizeof (pmcwork_t)) {
235*10743SDavid.Hollister@Sun.COM 			mdb_warn("Unable to read work structure\n");
236*10743SDavid.Hollister@Sun.COM 			return;
237*10743SDavid.Hollister@Sun.COM 		}
238*10743SDavid.Hollister@Sun.COM 
239*10743SDavid.Hollister@Sun.COM 		/*
240*10743SDavid.Hollister@Sun.COM 		 * Only print the work structure if it's still active.  If
241*10743SDavid.Hollister@Sun.COM 		 * it's not, it's been completed since we started looking at
242*10743SDavid.Hollister@Sun.COM 		 * it.
243*10743SDavid.Hollister@Sun.COM 		 */
244*10743SDavid.Hollister@Sun.COM 		if (work.state != PMCS_WORK_STATE_NIL) {
245*10743SDavid.Hollister@Sun.COM 			display_one_work(&work, 0, 0);
246*10743SDavid.Hollister@Sun.COM 		}
247*10743SDavid.Hollister@Sun.COM 		ccbp = ccb.next;
248*10743SDavid.Hollister@Sun.COM 	}
249*10743SDavid.Hollister@Sun.COM }
250*10743SDavid.Hollister@Sun.COM 
25110696SDavid.Hollister@Sun.COM /*ARGSUSED*/
25210696SDavid.Hollister@Sun.COM static void
25310696SDavid.Hollister@Sun.COM display_hwinfo(struct pmcs_hw m, int verbose)
25410696SDavid.Hollister@Sun.COM {
25510696SDavid.Hollister@Sun.COM 	struct pmcs_hw	*mp = &m;
25610696SDavid.Hollister@Sun.COM 	char		*fwsupport;
25710696SDavid.Hollister@Sun.COM 
25810696SDavid.Hollister@Sun.COM 	switch (PMCS_FW_TYPE(mp)) {
25910696SDavid.Hollister@Sun.COM 	case PMCS_FW_TYPE_RELEASED:
26010696SDavid.Hollister@Sun.COM 		fwsupport = "Released";
26110696SDavid.Hollister@Sun.COM 		break;
26210696SDavid.Hollister@Sun.COM 	case PMCS_FW_TYPE_DEVELOPMENT:
26310696SDavid.Hollister@Sun.COM 		fwsupport = "Development";
26410696SDavid.Hollister@Sun.COM 		break;
26510696SDavid.Hollister@Sun.COM 	case PMCS_FW_TYPE_ALPHA:
26610696SDavid.Hollister@Sun.COM 		fwsupport = "Alpha";
26710696SDavid.Hollister@Sun.COM 		break;
26810696SDavid.Hollister@Sun.COM 	case PMCS_FW_TYPE_BETA:
26910696SDavid.Hollister@Sun.COM 		fwsupport = "Beta";
27010696SDavid.Hollister@Sun.COM 		break;
27110696SDavid.Hollister@Sun.COM 	default:
27210696SDavid.Hollister@Sun.COM 		fwsupport = "Special";
27310696SDavid.Hollister@Sun.COM 		break;
27410696SDavid.Hollister@Sun.COM 	}
27510696SDavid.Hollister@Sun.COM 
27610696SDavid.Hollister@Sun.COM 	mdb_printf("\nHardware information:\n");
27710696SDavid.Hollister@Sun.COM 	mdb_printf("---------------------\n");
27810696SDavid.Hollister@Sun.COM 
27910696SDavid.Hollister@Sun.COM 	mdb_printf("Chip revision:    %c\n", 'A' + m.chiprev);
28010696SDavid.Hollister@Sun.COM 	mdb_printf("SAS WWID:         %"PRIx64"\n", m.sas_wwns[0]);
28110696SDavid.Hollister@Sun.COM 	mdb_printf("Firmware version: %x.%x.%x (%s)\n",
28210696SDavid.Hollister@Sun.COM 	    PMCS_FW_MAJOR(mp), PMCS_FW_MINOR(mp), PMCS_FW_MICRO(mp),
28310696SDavid.Hollister@Sun.COM 	    fwsupport);
28410696SDavid.Hollister@Sun.COM 
28510696SDavid.Hollister@Sun.COM 	mdb_printf("Number of PHYs:   %d\n", m.nphy);
28610696SDavid.Hollister@Sun.COM 	mdb_printf("Maximum commands: %d\n", m.max_cmd);
28710696SDavid.Hollister@Sun.COM 	mdb_printf("Maximum devices:  %d\n", m.max_dev);
28810696SDavid.Hollister@Sun.COM 	mdb_printf("I/O queue depth:  %d\n", m.ioq_depth);
28910696SDavid.Hollister@Sun.COM 	if (m.fwlog == 0) {
29010696SDavid.Hollister@Sun.COM 		mdb_printf("Firmware logging: Disabled\n");
29110696SDavid.Hollister@Sun.COM 	} else {
29210696SDavid.Hollister@Sun.COM 		mdb_printf("Firmware logging: Enabled (%d)\n", m.fwlog);
29310696SDavid.Hollister@Sun.COM 	}
29410696SDavid.Hollister@Sun.COM }
29510696SDavid.Hollister@Sun.COM 
29610696SDavid.Hollister@Sun.COM static void
29710696SDavid.Hollister@Sun.COM display_targets(struct pmcs_hw m, int verbose, int totals_only)
29810696SDavid.Hollister@Sun.COM {
29910696SDavid.Hollister@Sun.COM 	char		*dtype;
30010696SDavid.Hollister@Sun.COM 	pmcs_xscsi_t	xs;
30110696SDavid.Hollister@Sun.COM 	pmcs_phy_t	phy;
30210696SDavid.Hollister@Sun.COM 	uint16_t	max_dev, idx;
30310696SDavid.Hollister@Sun.COM 	uint32_t	sas_targets = 0, smp_targets = 0, sata_targets = 0;
30410696SDavid.Hollister@Sun.COM 
30510696SDavid.Hollister@Sun.COM 	max_dev = m.max_dev;
30610696SDavid.Hollister@Sun.COM 
30710696SDavid.Hollister@Sun.COM 	if (targets == NULL) {
30810696SDavid.Hollister@Sun.COM 		targets = mdb_alloc(sizeof (targets) * max_dev, UM_SLEEP);
30910696SDavid.Hollister@Sun.COM 	}
31010696SDavid.Hollister@Sun.COM 
31110696SDavid.Hollister@Sun.COM 	if (MDB_RD(targets, sizeof (targets) * max_dev, m.targets) == -1) {
31210696SDavid.Hollister@Sun.COM 		NOREAD(targets, m.targets);
31310696SDavid.Hollister@Sun.COM 		return;
31410696SDavid.Hollister@Sun.COM 	}
31510696SDavid.Hollister@Sun.COM 
31610696SDavid.Hollister@Sun.COM 	if (!totals_only) {
31710696SDavid.Hollister@Sun.COM 		mdb_printf("\nTarget information:\n");
31810696SDavid.Hollister@Sun.COM 		mdb_printf("---------------------------------------\n");
31910696SDavid.Hollister@Sun.COM 		mdb_printf("VTGT %-16s %-16s %-5s %8s %s", "SAS Address",
32010696SDavid.Hollister@Sun.COM 		    "PHY Address", "DType", "Active", "DS");
32110696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
32210696SDavid.Hollister@Sun.COM 	}
32310696SDavid.Hollister@Sun.COM 
32410696SDavid.Hollister@Sun.COM 	for (idx = 0; idx < max_dev; idx++) {
32510696SDavid.Hollister@Sun.COM 		if (targets[idx] == NULL) {
32610696SDavid.Hollister@Sun.COM 			continue;
32710696SDavid.Hollister@Sun.COM 		}
32810696SDavid.Hollister@Sun.COM 
32910696SDavid.Hollister@Sun.COM 		if (MDB_RD(&xs, sizeof (xs), targets[idx]) == -1) {
33010696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_xscsi_t, targets[idx]);
33110696SDavid.Hollister@Sun.COM 			continue;
33210696SDavid.Hollister@Sun.COM 		}
33310696SDavid.Hollister@Sun.COM 
33410696SDavid.Hollister@Sun.COM 		/*
33510696SDavid.Hollister@Sun.COM 		 * It has to be one of new, assigned or dying to be of interest.
33610696SDavid.Hollister@Sun.COM 		 */
33710696SDavid.Hollister@Sun.COM 		if (xs.new == 0 && xs.assigned == 0 && xs.dying == 0) {
33810696SDavid.Hollister@Sun.COM 			continue;
33910696SDavid.Hollister@Sun.COM 		}
34010696SDavid.Hollister@Sun.COM 
34110696SDavid.Hollister@Sun.COM 		switch (xs.dtype) {
34210696SDavid.Hollister@Sun.COM 		case NOTHING:
34310696SDavid.Hollister@Sun.COM 			dtype = "None";
34410696SDavid.Hollister@Sun.COM 			break;
34510696SDavid.Hollister@Sun.COM 		case SATA:
34610696SDavid.Hollister@Sun.COM 			dtype = "SATA";
34710696SDavid.Hollister@Sun.COM 			sata_targets++;
34810696SDavid.Hollister@Sun.COM 			break;
34910696SDavid.Hollister@Sun.COM 		case SAS:
35010696SDavid.Hollister@Sun.COM 			dtype = "SAS";
35110696SDavid.Hollister@Sun.COM 			sas_targets++;
35210696SDavid.Hollister@Sun.COM 			break;
35310696SDavid.Hollister@Sun.COM 		case EXPANDER:
35410696SDavid.Hollister@Sun.COM 			dtype = "SMP";
35510696SDavid.Hollister@Sun.COM 			smp_targets++;
35610696SDavid.Hollister@Sun.COM 			break;
35710696SDavid.Hollister@Sun.COM 		}
35810696SDavid.Hollister@Sun.COM 
35910696SDavid.Hollister@Sun.COM 		if (totals_only) {
36010696SDavid.Hollister@Sun.COM 			continue;
36110696SDavid.Hollister@Sun.COM 		}
36210696SDavid.Hollister@Sun.COM 
36310696SDavid.Hollister@Sun.COM 		if (xs.phy) {
36410696SDavid.Hollister@Sun.COM 			if (MDB_RD(&phy, sizeof (phy), xs.phy) == -1) {
36510696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_phy_t, xs.phy);
36610696SDavid.Hollister@Sun.COM 				continue;
36710696SDavid.Hollister@Sun.COM 			}
36810696SDavid.Hollister@Sun.COM 			mdb_printf("%4d ", idx);
36910696SDavid.Hollister@Sun.COM 			print_sas_address(&phy);
37010696SDavid.Hollister@Sun.COM 			mdb_printf(" %16p", xs.phy);
37110696SDavid.Hollister@Sun.COM 		} else {
37210696SDavid.Hollister@Sun.COM 			mdb_printf("%4d %16s", idx, "<no phy avail>");
37310696SDavid.Hollister@Sun.COM 		}
37410696SDavid.Hollister@Sun.COM 		mdb_printf(" %5s", dtype);
37510696SDavid.Hollister@Sun.COM 		mdb_printf(" %8d", xs.actv_cnt);
37610696SDavid.Hollister@Sun.COM 		mdb_printf(" %2d", xs.dev_state);
37710696SDavid.Hollister@Sun.COM 
37810696SDavid.Hollister@Sun.COM 		if (verbose) {
37910696SDavid.Hollister@Sun.COM 			if (xs.new) {
38010696SDavid.Hollister@Sun.COM 				mdb_printf(" new");
38110696SDavid.Hollister@Sun.COM 			} else if (xs.dying) {
38210696SDavid.Hollister@Sun.COM 				mdb_printf(" dying");
38310696SDavid.Hollister@Sun.COM 			} else if (xs.assigned) {
38410696SDavid.Hollister@Sun.COM 				mdb_printf(" assigned");
38510696SDavid.Hollister@Sun.COM 			}
38610696SDavid.Hollister@Sun.COM 			if (xs.draining) {
38710696SDavid.Hollister@Sun.COM 				mdb_printf(" draining");
38810696SDavid.Hollister@Sun.COM 			}
38910696SDavid.Hollister@Sun.COM 			if (xs.reset_wait) {
39010696SDavid.Hollister@Sun.COM 				mdb_printf(" reset_wait");
39110696SDavid.Hollister@Sun.COM 			}
39210696SDavid.Hollister@Sun.COM 			if (xs.resetting) {
39310696SDavid.Hollister@Sun.COM 				mdb_printf(" resetting");
39410696SDavid.Hollister@Sun.COM 			}
39510696SDavid.Hollister@Sun.COM 			if (xs.recover_wait) {
39610696SDavid.Hollister@Sun.COM 				mdb_printf(" recover_wait");
39710696SDavid.Hollister@Sun.COM 			}
39810696SDavid.Hollister@Sun.COM 			if (xs.recovering) {
39910696SDavid.Hollister@Sun.COM 				mdb_printf(" recovering");
40010696SDavid.Hollister@Sun.COM 			}
40110696SDavid.Hollister@Sun.COM 			if (xs.event_recovery) {
40210696SDavid.Hollister@Sun.COM 				mdb_printf(" event recovery");
40310696SDavid.Hollister@Sun.COM 			}
40410696SDavid.Hollister@Sun.COM 			if (xs.special_running) {
40510696SDavid.Hollister@Sun.COM 				mdb_printf(" special_active");
40610696SDavid.Hollister@Sun.COM 			}
40710696SDavid.Hollister@Sun.COM 			if (xs.ncq) {
40810696SDavid.Hollister@Sun.COM 				mdb_printf(" ncq_tagmap=0x%x qdepth=%d",
40910696SDavid.Hollister@Sun.COM 				    xs.tagmap, xs.qdepth);
41010696SDavid.Hollister@Sun.COM 			} else if (xs.pio) {
41110696SDavid.Hollister@Sun.COM 				mdb_printf(" pio");
41210696SDavid.Hollister@Sun.COM 			}
41310696SDavid.Hollister@Sun.COM 		}
41410696SDavid.Hollister@Sun.COM 
41510696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
41610696SDavid.Hollister@Sun.COM 	}
41710696SDavid.Hollister@Sun.COM 
41810696SDavid.Hollister@Sun.COM 	if (!totals_only) {
41910696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
42010696SDavid.Hollister@Sun.COM 	}
42110696SDavid.Hollister@Sun.COM 
42210696SDavid.Hollister@Sun.COM 	mdb_printf("%19s %d (%d SAS + %d SATA + %d SMP)\n",
42310696SDavid.Hollister@Sun.COM 	    "Configured targets:", (sas_targets + sata_targets + smp_targets),
42410696SDavid.Hollister@Sun.COM 	    sas_targets, sata_targets, smp_targets);
42510696SDavid.Hollister@Sun.COM }
42610696SDavid.Hollister@Sun.COM 
427*10743SDavid.Hollister@Sun.COM static char *
428*10743SDavid.Hollister@Sun.COM work_state_to_string(uint32_t state)
429*10743SDavid.Hollister@Sun.COM {
430*10743SDavid.Hollister@Sun.COM 	char *state_string;
431*10743SDavid.Hollister@Sun.COM 
432*10743SDavid.Hollister@Sun.COM 	switch (state) {
433*10743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_NIL:
434*10743SDavid.Hollister@Sun.COM 		state_string = "Free";
435*10743SDavid.Hollister@Sun.COM 		break;
436*10743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_READY:
437*10743SDavid.Hollister@Sun.COM 		state_string = "Ready";
438*10743SDavid.Hollister@Sun.COM 		break;
439*10743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_ONCHIP:
440*10743SDavid.Hollister@Sun.COM 		state_string = "On Chip";
441*10743SDavid.Hollister@Sun.COM 		break;
442*10743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_INTR:
443*10743SDavid.Hollister@Sun.COM 		state_string = "In Intr";
444*10743SDavid.Hollister@Sun.COM 		break;
445*10743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_IOCOMPQ:
446*10743SDavid.Hollister@Sun.COM 		state_string = "I/O Comp";
447*10743SDavid.Hollister@Sun.COM 		break;
448*10743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_ABORTED:
449*10743SDavid.Hollister@Sun.COM 		state_string = "I/O Aborted";
450*10743SDavid.Hollister@Sun.COM 		break;
451*10743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_TIMED_OUT:
452*10743SDavid.Hollister@Sun.COM 		state_string = "I/O Timed Out";
453*10743SDavid.Hollister@Sun.COM 		break;
454*10743SDavid.Hollister@Sun.COM 	default:
455*10743SDavid.Hollister@Sun.COM 		state_string = "INVALID";
456*10743SDavid.Hollister@Sun.COM 		break;
457*10743SDavid.Hollister@Sun.COM 	}
458*10743SDavid.Hollister@Sun.COM 
459*10743SDavid.Hollister@Sun.COM 	return (state_string);
460*10743SDavid.Hollister@Sun.COM }
461*10743SDavid.Hollister@Sun.COM 
462*10743SDavid.Hollister@Sun.COM static void
463*10743SDavid.Hollister@Sun.COM display_one_work(pmcwork_t *wp, int verbose, int idx)
464*10743SDavid.Hollister@Sun.COM {
465*10743SDavid.Hollister@Sun.COM 	char		*state, *last_state;
466*10743SDavid.Hollister@Sun.COM 	char		*path;
467*10743SDavid.Hollister@Sun.COM 	pmcs_xscsi_t	xs;
468*10743SDavid.Hollister@Sun.COM 	pmcs_phy_t	phy;
469*10743SDavid.Hollister@Sun.COM 	int		tgt;
470*10743SDavid.Hollister@Sun.COM 
471*10743SDavid.Hollister@Sun.COM 	state = work_state_to_string(wp->state);
472*10743SDavid.Hollister@Sun.COM 	last_state = work_state_to_string(wp->last_state);
473*10743SDavid.Hollister@Sun.COM 
474*10743SDavid.Hollister@Sun.COM 	if (wp->ssp_event && wp->ssp_event != 0xffffffff) {
475*10743SDavid.Hollister@Sun.COM 		mdb_printf("SSP event 0x%x", wp->ssp_event);
476*10743SDavid.Hollister@Sun.COM 	}
477*10743SDavid.Hollister@Sun.COM 
478*10743SDavid.Hollister@Sun.COM 	tgt = -1;
479*10743SDavid.Hollister@Sun.COM 	if (wp->xp) {
480*10743SDavid.Hollister@Sun.COM 		if (MDB_RD(&xs, sizeof (xs), wp->xp) == -1) {
481*10743SDavid.Hollister@Sun.COM 			NOREAD(pmcs_xscsi_t, wp->xp);
482*10743SDavid.Hollister@Sun.COM 		} else {
483*10743SDavid.Hollister@Sun.COM 			tgt = xs.target_num;
484*10743SDavid.Hollister@Sun.COM 		}
485*10743SDavid.Hollister@Sun.COM 	}
486*10743SDavid.Hollister@Sun.COM 	if (wp->phy) {
487*10743SDavid.Hollister@Sun.COM 		if (MDB_RD(&phy, sizeof (phy), wp->phy) == -1) {
488*10743SDavid.Hollister@Sun.COM 			NOREAD(pmcs_phy_t, wp->phy);
489*10743SDavid.Hollister@Sun.COM 		}
490*10743SDavid.Hollister@Sun.COM 		path = phy.path;
491*10743SDavid.Hollister@Sun.COM 	} else {
492*10743SDavid.Hollister@Sun.COM 		path = "N/A";
493*10743SDavid.Hollister@Sun.COM 	}
494*10743SDavid.Hollister@Sun.COM 
495*10743SDavid.Hollister@Sun.COM 	if (verbose) {
496*10743SDavid.Hollister@Sun.COM 		mdb_printf("%4d ", idx);
497*10743SDavid.Hollister@Sun.COM 	}
498*10743SDavid.Hollister@Sun.COM 	if (tgt == -1) {
499*10743SDavid.Hollister@Sun.COM 		mdb_printf("%08x %10s %20s      N/A %8u %1d %1d ",
500*10743SDavid.Hollister@Sun.COM 		    wp->htag, state, path, wp->timer,
501*10743SDavid.Hollister@Sun.COM 		    wp->onwire, wp->dead);
502*10743SDavid.Hollister@Sun.COM 	} else {
503*10743SDavid.Hollister@Sun.COM 		mdb_printf("%08x %10s %20s %8d %8u %1d %1d ",
504*10743SDavid.Hollister@Sun.COM 		    wp->htag, state, path, tgt, wp->timer,
505*10743SDavid.Hollister@Sun.COM 		    wp->onwire, wp->dead);
506*10743SDavid.Hollister@Sun.COM 	}
507*10743SDavid.Hollister@Sun.COM 	if (verbose) {
508*10743SDavid.Hollister@Sun.COM 		mdb_printf("%08x %10s 0x%016p 0x%016p\n",
509*10743SDavid.Hollister@Sun.COM 		    wp->last_htag, last_state, wp->last_phy, wp->last_xp);
510*10743SDavid.Hollister@Sun.COM 	} else {
511*10743SDavid.Hollister@Sun.COM 		mdb_printf("\n");
512*10743SDavid.Hollister@Sun.COM 	}
513*10743SDavid.Hollister@Sun.COM }
514*10743SDavid.Hollister@Sun.COM 
51510696SDavid.Hollister@Sun.COM static void
51610696SDavid.Hollister@Sun.COM display_work(struct pmcs_hw m, int verbose)
51710696SDavid.Hollister@Sun.COM {
51810696SDavid.Hollister@Sun.COM 	int		idx;
519*10743SDavid.Hollister@Sun.COM 	boolean_t	header_printed = B_FALSE;
52010696SDavid.Hollister@Sun.COM 	pmcwork_t	work, *wp = &work;
52110696SDavid.Hollister@Sun.COM 	uintptr_t	_wp;
52210696SDavid.Hollister@Sun.COM 
52310696SDavid.Hollister@Sun.COM 	mdb_printf("\nActive Work structure information:\n");
52410696SDavid.Hollister@Sun.COM 	mdb_printf("----------------------------------\n");
52510696SDavid.Hollister@Sun.COM 
52610696SDavid.Hollister@Sun.COM 	_wp = (uintptr_t)m.work;
52710696SDavid.Hollister@Sun.COM 
52810696SDavid.Hollister@Sun.COM 	for (idx = 0; idx < m.max_cmd; idx++, _wp += sizeof (pmcwork_t)) {
52910696SDavid.Hollister@Sun.COM 		if (MDB_RD(&work, sizeof (pmcwork_t), _wp) == -1) {
53010696SDavid.Hollister@Sun.COM 			NOREAD(pmcwork_t, _wp);
53110696SDavid.Hollister@Sun.COM 			continue;
53210696SDavid.Hollister@Sun.COM 		}
533*10743SDavid.Hollister@Sun.COM 
534*10743SDavid.Hollister@Sun.COM 		if (!verbose && (wp->htag == PMCS_TAG_TYPE_FREE)) {
53510696SDavid.Hollister@Sun.COM 			continue;
53610696SDavid.Hollister@Sun.COM 		}
537*10743SDavid.Hollister@Sun.COM 
538*10743SDavid.Hollister@Sun.COM 		if (header_printed == B_FALSE) {
539*10743SDavid.Hollister@Sun.COM 			if (verbose) {
540*10743SDavid.Hollister@Sun.COM 				mdb_printf("%4s ", "Idx");
541*10743SDavid.Hollister@Sun.COM 			}
542*10743SDavid.Hollister@Sun.COM 			mdb_printf("%8s %10s %20s %8s %8s O D ",
54310696SDavid.Hollister@Sun.COM 			    "HTag", "State", "Phy Path", "Target", "Timer");
544*10743SDavid.Hollister@Sun.COM 			if (verbose) {
545*10743SDavid.Hollister@Sun.COM 				mdb_printf("%8s %10s %18s %18s\n", "LastHTAG",
546*10743SDavid.Hollister@Sun.COM 				    "LastState", "LastPHY", "LastTgt");
547*10743SDavid.Hollister@Sun.COM 			} else {
548*10743SDavid.Hollister@Sun.COM 				mdb_printf("\n");
549*10743SDavid.Hollister@Sun.COM 			}
550*10743SDavid.Hollister@Sun.COM 			header_printed = B_TRUE;
55110696SDavid.Hollister@Sun.COM 		}
552*10743SDavid.Hollister@Sun.COM 
553*10743SDavid.Hollister@Sun.COM 		display_one_work(wp, verbose, idx);
55410696SDavid.Hollister@Sun.COM 	}
55510696SDavid.Hollister@Sun.COM }
55610696SDavid.Hollister@Sun.COM 
55710696SDavid.Hollister@Sun.COM static void
558*10743SDavid.Hollister@Sun.COM print_spcmd(pmcs_cmd_t *sp, void *kaddr, int printhdr, int verbose)
55910696SDavid.Hollister@Sun.COM {
560*10743SDavid.Hollister@Sun.COM 	int cdb_size, idx;
561*10743SDavid.Hollister@Sun.COM 	struct scsi_pkt pkt;
562*10743SDavid.Hollister@Sun.COM 	uchar_t cdb[256];
563*10743SDavid.Hollister@Sun.COM 
56410696SDavid.Hollister@Sun.COM 	if (printhdr) {
565*10743SDavid.Hollister@Sun.COM 		if (verbose) {
566*10743SDavid.Hollister@Sun.COM 			mdb_printf("%16s %16s %16s %8s %s CDB\n", "Command",
567*10743SDavid.Hollister@Sun.COM 			    "SCSA pkt", "DMA Chunks", "HTAG", "SATL Tag");
568*10743SDavid.Hollister@Sun.COM 		} else {
569*10743SDavid.Hollister@Sun.COM 			mdb_printf("%16s %16s %16s %8s %s\n", "Command",
570*10743SDavid.Hollister@Sun.COM 			    "SCSA pkt", "DMA Chunks", "HTAG", "SATL Tag");
571*10743SDavid.Hollister@Sun.COM 		}
57210696SDavid.Hollister@Sun.COM 	}
573*10743SDavid.Hollister@Sun.COM 
574*10743SDavid.Hollister@Sun.COM 	mdb_printf("%16p %16p %16p %08x %08x ",
57510696SDavid.Hollister@Sun.COM 	    kaddr, sp->cmd_pkt, sp->cmd_clist, sp->cmd_tag, sp->cmd_satltag);
576*10743SDavid.Hollister@Sun.COM 
577*10743SDavid.Hollister@Sun.COM 	/*
578*10743SDavid.Hollister@Sun.COM 	 * If we're printing verbose, dump the CDB as well.
579*10743SDavid.Hollister@Sun.COM 	 */
580*10743SDavid.Hollister@Sun.COM 	if (verbose) {
581*10743SDavid.Hollister@Sun.COM 		if (sp->cmd_pkt) {
582*10743SDavid.Hollister@Sun.COM 			if (mdb_vread(&pkt, sizeof (struct scsi_pkt),
583*10743SDavid.Hollister@Sun.COM 			    (uintptr_t)sp->cmd_pkt) !=
584*10743SDavid.Hollister@Sun.COM 			    sizeof (struct scsi_pkt)) {
585*10743SDavid.Hollister@Sun.COM 				mdb_warn("Unable to read SCSI pkt\n");
586*10743SDavid.Hollister@Sun.COM 				return;
587*10743SDavid.Hollister@Sun.COM 			}
588*10743SDavid.Hollister@Sun.COM 			cdb_size = pkt.pkt_cdblen;
589*10743SDavid.Hollister@Sun.COM 			if (mdb_vread(&cdb[0], cdb_size,
590*10743SDavid.Hollister@Sun.COM 			    (uintptr_t)pkt.pkt_cdbp) != cdb_size) {
591*10743SDavid.Hollister@Sun.COM 				mdb_warn("Unable to read CDB\n");
592*10743SDavid.Hollister@Sun.COM 				return;
593*10743SDavid.Hollister@Sun.COM 			}
594*10743SDavid.Hollister@Sun.COM 
595*10743SDavid.Hollister@Sun.COM 			for (idx = 0; idx < cdb_size; idx++) {
596*10743SDavid.Hollister@Sun.COM 				mdb_printf("%02x ", cdb[idx]);
597*10743SDavid.Hollister@Sun.COM 			}
598*10743SDavid.Hollister@Sun.COM 		} else {
599*10743SDavid.Hollister@Sun.COM 			mdb_printf("N/A");
600*10743SDavid.Hollister@Sun.COM 		}
601*10743SDavid.Hollister@Sun.COM 
602*10743SDavid.Hollister@Sun.COM 		mdb_printf("\n");
603*10743SDavid.Hollister@Sun.COM 	} else {
604*10743SDavid.Hollister@Sun.COM 		mdb_printf("\n");
605*10743SDavid.Hollister@Sun.COM 	}
60610696SDavid.Hollister@Sun.COM }
60710696SDavid.Hollister@Sun.COM 
60810696SDavid.Hollister@Sun.COM /*ARGSUSED1*/
60910696SDavid.Hollister@Sun.COM static void
61010696SDavid.Hollister@Sun.COM display_waitqs(struct pmcs_hw m, int verbose)
61110696SDavid.Hollister@Sun.COM {
61210696SDavid.Hollister@Sun.COM 	pmcs_cmd_t	*sp, s;
61310696SDavid.Hollister@Sun.COM 	pmcs_xscsi_t	xs;
61410696SDavid.Hollister@Sun.COM 	int		first, i;
61510696SDavid.Hollister@Sun.COM 	int		max_dev = m.max_dev;
61610696SDavid.Hollister@Sun.COM 
61710696SDavid.Hollister@Sun.COM 	sp = m.dq.stqh_first;
61810696SDavid.Hollister@Sun.COM 	first = 1;
61910696SDavid.Hollister@Sun.COM 	while (sp) {
62010696SDavid.Hollister@Sun.COM 		if (first) {
62110696SDavid.Hollister@Sun.COM 			mdb_printf("\nDead Command Queue:\n");
62210696SDavid.Hollister@Sun.COM 			mdb_printf("---------------------------\n");
62310696SDavid.Hollister@Sun.COM 		}
62410696SDavid.Hollister@Sun.COM 		if (MDB_RD(&s, sizeof (s), sp) == -1) {
62510696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_cmd_t, sp);
62610696SDavid.Hollister@Sun.COM 			break;
62710696SDavid.Hollister@Sun.COM 		}
628*10743SDavid.Hollister@Sun.COM 		print_spcmd(&s, sp, first, verbose);
62910696SDavid.Hollister@Sun.COM 		sp = s.cmd_next.stqe_next;
63010696SDavid.Hollister@Sun.COM 		first = 0;
63110696SDavid.Hollister@Sun.COM 	}
63210696SDavid.Hollister@Sun.COM 
63310696SDavid.Hollister@Sun.COM 	sp = m.cq.stqh_first;
63410696SDavid.Hollister@Sun.COM 	first = 1;
63510696SDavid.Hollister@Sun.COM 	while (sp) {
63610696SDavid.Hollister@Sun.COM 		if (first) {
63710696SDavid.Hollister@Sun.COM 			mdb_printf("\nCompletion Command Queue:\n");
63810696SDavid.Hollister@Sun.COM 			mdb_printf("---------------------------\n");
63910696SDavid.Hollister@Sun.COM 		}
64010696SDavid.Hollister@Sun.COM 		if (MDB_RD(&s, sizeof (s), sp) == -1) {
64110696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_cmd_t, sp);
64210696SDavid.Hollister@Sun.COM 			break;
64310696SDavid.Hollister@Sun.COM 		}
644*10743SDavid.Hollister@Sun.COM 		print_spcmd(&s, sp, first, verbose);
64510696SDavid.Hollister@Sun.COM 		sp = s.cmd_next.stqe_next;
64610696SDavid.Hollister@Sun.COM 		first = 0;
64710696SDavid.Hollister@Sun.COM 	}
64810696SDavid.Hollister@Sun.COM 
64910696SDavid.Hollister@Sun.COM 
65010696SDavid.Hollister@Sun.COM 	if (targets == NULL) {
65110696SDavid.Hollister@Sun.COM 		targets = mdb_alloc(sizeof (targets) * max_dev, UM_SLEEP);
65210696SDavid.Hollister@Sun.COM 	}
65310696SDavid.Hollister@Sun.COM 
65410696SDavid.Hollister@Sun.COM 	if (MDB_RD(targets, sizeof (targets) * max_dev, m.targets) == -1) {
65510696SDavid.Hollister@Sun.COM 		NOREAD(targets, m.targets);
65610696SDavid.Hollister@Sun.COM 		return;
65710696SDavid.Hollister@Sun.COM 	}
65810696SDavid.Hollister@Sun.COM 
65910696SDavid.Hollister@Sun.COM 	for (i = 0; i < max_dev; i++) {
66010696SDavid.Hollister@Sun.COM 		if (targets[i] == NULL) {
66110696SDavid.Hollister@Sun.COM 			continue;
66210696SDavid.Hollister@Sun.COM 		}
66310696SDavid.Hollister@Sun.COM 		if (MDB_RD(&xs, sizeof (xs), targets[i]) == -1) {
66410696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_xscsi_t, targets[i]);
66510696SDavid.Hollister@Sun.COM 			continue;
66610696SDavid.Hollister@Sun.COM 		}
66710696SDavid.Hollister@Sun.COM 		sp = xs.wq.stqh_first;
66810696SDavid.Hollister@Sun.COM 		first = 1;
66910696SDavid.Hollister@Sun.COM 		while (sp) {
67010696SDavid.Hollister@Sun.COM 			if (first) {
67110696SDavid.Hollister@Sun.COM 				mdb_printf("\nTarget %u Wait Queue:\n",
67210696SDavid.Hollister@Sun.COM 				    xs.target_num);
67310696SDavid.Hollister@Sun.COM 				mdb_printf("---------------------------\n");
67410696SDavid.Hollister@Sun.COM 			}
67510696SDavid.Hollister@Sun.COM 			if (MDB_RD(&s, sizeof (s), sp) == -1) {
67610696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_cmd_t, sp);
67710696SDavid.Hollister@Sun.COM 				break;
67810696SDavid.Hollister@Sun.COM 			}
679*10743SDavid.Hollister@Sun.COM 			print_spcmd(&s, sp, first, verbose);
68010696SDavid.Hollister@Sun.COM 			sp = s.cmd_next.stqe_next;
68110696SDavid.Hollister@Sun.COM 			first = 0;
68210696SDavid.Hollister@Sun.COM 		}
68310696SDavid.Hollister@Sun.COM 		sp = xs.aq.stqh_first;
68410696SDavid.Hollister@Sun.COM 		first = 1;
68510696SDavid.Hollister@Sun.COM 		while (sp) {
68610696SDavid.Hollister@Sun.COM 			if (first) {
68710696SDavid.Hollister@Sun.COM 				mdb_printf("\nTarget %u Active Queue:\n",
68810696SDavid.Hollister@Sun.COM 				    xs.target_num);
68910696SDavid.Hollister@Sun.COM 				mdb_printf("---------------------------\n");
69010696SDavid.Hollister@Sun.COM 			}
69110696SDavid.Hollister@Sun.COM 			if (MDB_RD(&s, sizeof (s), sp) == -1) {
69210696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_cmd_t, sp);
69310696SDavid.Hollister@Sun.COM 				break;
69410696SDavid.Hollister@Sun.COM 			}
695*10743SDavid.Hollister@Sun.COM 			print_spcmd(&s, sp, first, verbose);
69610696SDavid.Hollister@Sun.COM 			sp = s.cmd_next.stqe_next;
69710696SDavid.Hollister@Sun.COM 			first = 0;
69810696SDavid.Hollister@Sun.COM 		}
69910696SDavid.Hollister@Sun.COM 		sp = xs.sq.stqh_first;
70010696SDavid.Hollister@Sun.COM 		first = 1;
70110696SDavid.Hollister@Sun.COM 		while (sp) {
70210696SDavid.Hollister@Sun.COM 			if (first) {
70310696SDavid.Hollister@Sun.COM 				mdb_printf("\nTarget %u Special Queue:\n",
70410696SDavid.Hollister@Sun.COM 				    xs.target_num);
70510696SDavid.Hollister@Sun.COM 				mdb_printf("---------------------------\n");
70610696SDavid.Hollister@Sun.COM 			}
70710696SDavid.Hollister@Sun.COM 			if (MDB_RD(&s, sizeof (s), sp) == -1) {
70810696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_cmd_t, sp);
70910696SDavid.Hollister@Sun.COM 				break;
71010696SDavid.Hollister@Sun.COM 			}
711*10743SDavid.Hollister@Sun.COM 			print_spcmd(&s, sp, first, verbose);
71210696SDavid.Hollister@Sun.COM 			sp = s.cmd_next.stqe_next;
71310696SDavid.Hollister@Sun.COM 			first = 0;
71410696SDavid.Hollister@Sun.COM 		}
71510696SDavid.Hollister@Sun.COM 	}
71610696SDavid.Hollister@Sun.COM }
71710696SDavid.Hollister@Sun.COM 
71810696SDavid.Hollister@Sun.COM static char *
71910696SDavid.Hollister@Sun.COM ibq_type(int qnum)
72010696SDavid.Hollister@Sun.COM {
72110696SDavid.Hollister@Sun.COM 	if (qnum < 0 || qnum >= PMCS_NIQ) {
72210696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
72310696SDavid.Hollister@Sun.COM 	}
72410696SDavid.Hollister@Sun.COM 
72510696SDavid.Hollister@Sun.COM 	if (qnum < PMCS_IQ_OTHER) {
72610696SDavid.Hollister@Sun.COM 		return ("I/O");
72710696SDavid.Hollister@Sun.COM 	}
72810696SDavid.Hollister@Sun.COM 
72910696SDavid.Hollister@Sun.COM 	return ("Other");
73010696SDavid.Hollister@Sun.COM }
73110696SDavid.Hollister@Sun.COM 
73210696SDavid.Hollister@Sun.COM static char *
73310696SDavid.Hollister@Sun.COM obq_type(int qnum)
73410696SDavid.Hollister@Sun.COM {
73510696SDavid.Hollister@Sun.COM 	switch (qnum) {
73610696SDavid.Hollister@Sun.COM 	case PMCS_OQ_IODONE:
73710696SDavid.Hollister@Sun.COM 		return ("I/O");
73810696SDavid.Hollister@Sun.COM 		break;
73910696SDavid.Hollister@Sun.COM 	case PMCS_OQ_GENERAL:
74010696SDavid.Hollister@Sun.COM 		return ("General");
74110696SDavid.Hollister@Sun.COM 		break;
74210696SDavid.Hollister@Sun.COM 	case PMCS_OQ_EVENTS:
74310696SDavid.Hollister@Sun.COM 		return ("Events");
74410696SDavid.Hollister@Sun.COM 		break;
74510696SDavid.Hollister@Sun.COM 	default:
74610696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
74710696SDavid.Hollister@Sun.COM 	}
74810696SDavid.Hollister@Sun.COM }
74910696SDavid.Hollister@Sun.COM 
75010696SDavid.Hollister@Sun.COM static char *
75110696SDavid.Hollister@Sun.COM iomb_cat(uint32_t cat)
75210696SDavid.Hollister@Sun.COM {
75310696SDavid.Hollister@Sun.COM 	switch (cat) {
75410696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_NET:
75510696SDavid.Hollister@Sun.COM 		return ("NET");
75610696SDavid.Hollister@Sun.COM 		break;
75710696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_FC:
75810696SDavid.Hollister@Sun.COM 		return ("FC");
75910696SDavid.Hollister@Sun.COM 		break;
76010696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_SAS:
76110696SDavid.Hollister@Sun.COM 		return ("SAS");
76210696SDavid.Hollister@Sun.COM 		break;
76310696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_SCSI:
76410696SDavid.Hollister@Sun.COM 		return ("SCSI");
76510696SDavid.Hollister@Sun.COM 		break;
76610696SDavid.Hollister@Sun.COM 	default:
76710696SDavid.Hollister@Sun.COM 		return ("???");
76810696SDavid.Hollister@Sun.COM 	}
76910696SDavid.Hollister@Sun.COM }
77010696SDavid.Hollister@Sun.COM 
77110696SDavid.Hollister@Sun.COM static char *
77210696SDavid.Hollister@Sun.COM inbound_iomb_opcode(uint32_t opcode)
77310696SDavid.Hollister@Sun.COM {
77410696SDavid.Hollister@Sun.COM 	switch (opcode) {
77510696SDavid.Hollister@Sun.COM 	case PMCIN_ECHO:
77610696SDavid.Hollister@Sun.COM 		return ("ECHO");
77710696SDavid.Hollister@Sun.COM 		break;
77810696SDavid.Hollister@Sun.COM 	case PMCIN_GET_INFO:
77910696SDavid.Hollister@Sun.COM 		return ("GET_INFO");
78010696SDavid.Hollister@Sun.COM 		break;
78110696SDavid.Hollister@Sun.COM 	case PMCIN_GET_VPD:
78210696SDavid.Hollister@Sun.COM 		return ("GET_VPD");
78310696SDavid.Hollister@Sun.COM 		break;
78410696SDavid.Hollister@Sun.COM 	case PMCIN_PHY_START:
78510696SDavid.Hollister@Sun.COM 		return ("PHY_START");
78610696SDavid.Hollister@Sun.COM 		break;
78710696SDavid.Hollister@Sun.COM 	case PMCIN_PHY_STOP:
78810696SDavid.Hollister@Sun.COM 		return ("PHY_STOP");
78910696SDavid.Hollister@Sun.COM 		break;
79010696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_IO_START:
79110696SDavid.Hollister@Sun.COM 		return ("INI_IO_START");
79210696SDavid.Hollister@Sun.COM 		break;
79310696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_TM_START:
79410696SDavid.Hollister@Sun.COM 		return ("INI_TM_START");
79510696SDavid.Hollister@Sun.COM 		break;
79610696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_EXT_IO_START:
79710696SDavid.Hollister@Sun.COM 		return ("INI_EXT_IO_START");
79810696SDavid.Hollister@Sun.COM 		break;
79910696SDavid.Hollister@Sun.COM 	case PMCIN_DEVICE_HANDLE_ACCEPT:
80010696SDavid.Hollister@Sun.COM 		return ("DEVICE_HANDLE_ACCEPT");
80110696SDavid.Hollister@Sun.COM 		break;
80210696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_TGT_IO_START:
80310696SDavid.Hollister@Sun.COM 		return ("TGT_IO_START");
80410696SDavid.Hollister@Sun.COM 		break;
80510696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_TGT_RESPONSE_START:
80610696SDavid.Hollister@Sun.COM 		return ("TGT_RESPONSE_START");
80710696SDavid.Hollister@Sun.COM 		break;
80810696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_EDC_EXT_IO_START:
80910696SDavid.Hollister@Sun.COM 		return ("INI_EDC_EXT_IO_START");
81010696SDavid.Hollister@Sun.COM 		break;
81110696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_EDC_EXT_IO_START1:
81210696SDavid.Hollister@Sun.COM 		return ("INI_EDC_EXT_IO_START1");
81310696SDavid.Hollister@Sun.COM 		break;
81410696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_TGT_EDC_IO_START:
81510696SDavid.Hollister@Sun.COM 		return ("TGT_EDC_IO_START");
81610696SDavid.Hollister@Sun.COM 		break;
81710696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_ABORT:
81810696SDavid.Hollister@Sun.COM 		return ("SSP_ABORT");
81910696SDavid.Hollister@Sun.COM 		break;
82010696SDavid.Hollister@Sun.COM 	case PMCIN_DEREGISTER_DEVICE_HANDLE:
82110696SDavid.Hollister@Sun.COM 		return ("DEREGISTER_DEVICE_HANDLE");
82210696SDavid.Hollister@Sun.COM 		break;
82310696SDavid.Hollister@Sun.COM 	case PMCIN_GET_DEVICE_HANDLE:
82410696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_HANDLE");
82510696SDavid.Hollister@Sun.COM 		break;
82610696SDavid.Hollister@Sun.COM 	case PMCIN_SMP_REQUEST:
82710696SDavid.Hollister@Sun.COM 		return ("SMP_REQUEST");
82810696SDavid.Hollister@Sun.COM 		break;
82910696SDavid.Hollister@Sun.COM 	case PMCIN_SMP_RESPONSE:
83010696SDavid.Hollister@Sun.COM 		return ("SMP_RESPONSE");
83110696SDavid.Hollister@Sun.COM 		break;
83210696SDavid.Hollister@Sun.COM 	case PMCIN_SMP_ABORT:
83310696SDavid.Hollister@Sun.COM 		return ("SMP_ABORT");
83410696SDavid.Hollister@Sun.COM 		break;
83510696SDavid.Hollister@Sun.COM 	case PMCIN_ASSISTED_DISCOVERY:
83610696SDavid.Hollister@Sun.COM 		return ("ASSISTED_DISCOVERY");
83710696SDavid.Hollister@Sun.COM 		break;
83810696SDavid.Hollister@Sun.COM 	case PMCIN_REGISTER_DEVICE:
83910696SDavid.Hollister@Sun.COM 		return ("REGISTER_DEVICE");
84010696SDavid.Hollister@Sun.COM 		break;
84110696SDavid.Hollister@Sun.COM 	case PMCIN_SATA_HOST_IO_START:
84210696SDavid.Hollister@Sun.COM 		return ("SATA_HOST_IO_START");
84310696SDavid.Hollister@Sun.COM 		break;
84410696SDavid.Hollister@Sun.COM 	case PMCIN_SATA_ABORT:
84510696SDavid.Hollister@Sun.COM 		return ("SATA_ABORT");
84610696SDavid.Hollister@Sun.COM 		break;
84710696SDavid.Hollister@Sun.COM 	case PMCIN_LOCAL_PHY_CONTROL:
84810696SDavid.Hollister@Sun.COM 		return ("LOCAL_PHY_CONTROL");
84910696SDavid.Hollister@Sun.COM 		break;
85010696SDavid.Hollister@Sun.COM 	case PMCIN_GET_DEVICE_INFO:
85110696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_INFO");
85210696SDavid.Hollister@Sun.COM 		break;
85310696SDavid.Hollister@Sun.COM 	case PMCIN_TWI:
85410696SDavid.Hollister@Sun.COM 		return ("TWI");
85510696SDavid.Hollister@Sun.COM 		break;
85610696SDavid.Hollister@Sun.COM 	case PMCIN_FW_FLASH_UPDATE:
85710696SDavid.Hollister@Sun.COM 		return ("FW_FLASH_UPDATE");
85810696SDavid.Hollister@Sun.COM 		break;
85910696SDavid.Hollister@Sun.COM 	case PMCIN_SET_VPD:
86010696SDavid.Hollister@Sun.COM 		return ("SET_VPD");
86110696SDavid.Hollister@Sun.COM 		break;
86210696SDavid.Hollister@Sun.COM 	case PMCIN_GPIO:
86310696SDavid.Hollister@Sun.COM 		return ("GPIO");
86410696SDavid.Hollister@Sun.COM 		break;
86510696SDavid.Hollister@Sun.COM 	case PMCIN_SAS_DIAG_MODE_START_END:
86610696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_MODE_START_END");
86710696SDavid.Hollister@Sun.COM 		break;
86810696SDavid.Hollister@Sun.COM 	case PMCIN_SAS_DIAG_EXECUTE:
86910696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_EXECUTE");
87010696SDavid.Hollister@Sun.COM 		break;
87110696SDavid.Hollister@Sun.COM 	case PMCIN_SAW_HW_EVENT_ACK:
87210696SDavid.Hollister@Sun.COM 		return ("SAS_HW_EVENT_ACK");
87310696SDavid.Hollister@Sun.COM 		break;
87410696SDavid.Hollister@Sun.COM 	case PMCIN_GET_TIME_STAMP:
87510696SDavid.Hollister@Sun.COM 		return ("GET_TIME_STAMP");
87610696SDavid.Hollister@Sun.COM 		break;
87710696SDavid.Hollister@Sun.COM 	case PMCIN_PORT_CONTROL:
87810696SDavid.Hollister@Sun.COM 		return ("PORT_CONTROL");
87910696SDavid.Hollister@Sun.COM 		break;
88010696SDavid.Hollister@Sun.COM 	case PMCIN_GET_NVMD_DATA:
88110696SDavid.Hollister@Sun.COM 		return ("GET_NVMD_DATA");
88210696SDavid.Hollister@Sun.COM 		break;
88310696SDavid.Hollister@Sun.COM 	case PMCIN_SET_NVMD_DATA:
88410696SDavid.Hollister@Sun.COM 		return ("SET_NVMD_DATA");
88510696SDavid.Hollister@Sun.COM 		break;
88610696SDavid.Hollister@Sun.COM 	case PMCIN_SET_DEVICE_STATE:
88710696SDavid.Hollister@Sun.COM 		return ("SET_DEVICE_STATE");
88810696SDavid.Hollister@Sun.COM 		break;
88910696SDavid.Hollister@Sun.COM 	case PMCIN_GET_DEVICE_STATE:
89010696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_STATE");
89110696SDavid.Hollister@Sun.COM 		break;
89210696SDavid.Hollister@Sun.COM 	default:
89310696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
89410696SDavid.Hollister@Sun.COM 		break;
89510696SDavid.Hollister@Sun.COM 	}
89610696SDavid.Hollister@Sun.COM }
89710696SDavid.Hollister@Sun.COM 
89810696SDavid.Hollister@Sun.COM static char *
89910696SDavid.Hollister@Sun.COM outbound_iomb_opcode(uint32_t opcode)
90010696SDavid.Hollister@Sun.COM {
90110696SDavid.Hollister@Sun.COM 	switch (opcode) {
90210696SDavid.Hollister@Sun.COM 	case PMCOUT_ECHO:
90310696SDavid.Hollister@Sun.COM 		return ("ECHO");
90410696SDavid.Hollister@Sun.COM 		break;
90510696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_INFO:
90610696SDavid.Hollister@Sun.COM 		return ("GET_INFO");
90710696SDavid.Hollister@Sun.COM 		break;
90810696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_VPD:
90910696SDavid.Hollister@Sun.COM 		return ("GET_VPD");
91010696SDavid.Hollister@Sun.COM 		break;
91110696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_HW_EVENT:
91210696SDavid.Hollister@Sun.COM 		return ("SAS_HW_EVENT");
91310696SDavid.Hollister@Sun.COM 		break;
91410696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_COMPLETION:
91510696SDavid.Hollister@Sun.COM 		return ("SSP_COMPLETION");
91610696SDavid.Hollister@Sun.COM 		break;
91710696SDavid.Hollister@Sun.COM 	case PMCOUT_SMP_COMPLETION:
91810696SDavid.Hollister@Sun.COM 		return ("SMP_COMPLETION");
91910696SDavid.Hollister@Sun.COM 		break;
92010696SDavid.Hollister@Sun.COM 	case PMCOUT_LOCAL_PHY_CONTROL:
92110696SDavid.Hollister@Sun.COM 		return ("LOCAL_PHY_CONTROL");
92210696SDavid.Hollister@Sun.COM 		break;
92310696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_ASSISTED_DISCOVERY_EVENT:
92410696SDavid.Hollister@Sun.COM 		return ("SAS_ASSISTED_DISCOVERY_SENT");
92510696SDavid.Hollister@Sun.COM 		break;
92610696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_ASSISTED_DISCOVERY_EVENT:
92710696SDavid.Hollister@Sun.COM 		return ("SATA_ASSISTED_DISCOVERY_SENT");
92810696SDavid.Hollister@Sun.COM 		break;
92910696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_REGISTRATION:
93010696SDavid.Hollister@Sun.COM 		return ("DEVICE_REGISTRATION");
93110696SDavid.Hollister@Sun.COM 		break;
93210696SDavid.Hollister@Sun.COM 	case PMCOUT_DEREGISTER_DEVICE_HANDLE:
93310696SDavid.Hollister@Sun.COM 		return ("DEREGISTER_DEVICE_HANDLE");
93410696SDavid.Hollister@Sun.COM 		break;
93510696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_DEVICE_HANDLE:
93610696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_HANDLE");
93710696SDavid.Hollister@Sun.COM 		break;
93810696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_COMPLETION:
93910696SDavid.Hollister@Sun.COM 		return ("SATA_COMPLETION");
94010696SDavid.Hollister@Sun.COM 		break;
94110696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_EVENT:
94210696SDavid.Hollister@Sun.COM 		return ("SATA_EVENT");
94310696SDavid.Hollister@Sun.COM 		break;
94410696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_EVENT:
94510696SDavid.Hollister@Sun.COM 		return ("SSP_EVENT");
94610696SDavid.Hollister@Sun.COM 		break;
94710696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_HANDLE_ARRIVED:
94810696SDavid.Hollister@Sun.COM 		return ("DEVICE_HANDLE_ARRIVED");
94910696SDavid.Hollister@Sun.COM 		break;
95010696SDavid.Hollister@Sun.COM 	case PMCOUT_SMP_REQUEST_RECEIVED:
95110696SDavid.Hollister@Sun.COM 		return ("SMP_REQUEST_RECEIVED");
95210696SDavid.Hollister@Sun.COM 		break;
95310696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_REQUEST_RECEIVED:
95410696SDavid.Hollister@Sun.COM 		return ("SSP_REQUEST_RECEIVED");
95510696SDavid.Hollister@Sun.COM 		break;
95610696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_INFO:
95710696SDavid.Hollister@Sun.COM 		return ("DEVICE_INFO");
95810696SDavid.Hollister@Sun.COM 		break;
95910696SDavid.Hollister@Sun.COM 	case PMCOUT_FW_FLASH_UPDATE:
96010696SDavid.Hollister@Sun.COM 		return ("FW_FLASH_UPDATE");
96110696SDavid.Hollister@Sun.COM 		break;
96210696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_VPD:
96310696SDavid.Hollister@Sun.COM 		return ("SET_VPD");
96410696SDavid.Hollister@Sun.COM 		break;
96510696SDavid.Hollister@Sun.COM 	case PMCOUT_GPIO:
96610696SDavid.Hollister@Sun.COM 		return ("GPIO");
96710696SDavid.Hollister@Sun.COM 		break;
96810696SDavid.Hollister@Sun.COM 	case PMCOUT_GPIO_EVENT:
96910696SDavid.Hollister@Sun.COM 		return ("GPIO_EVENT");
97010696SDavid.Hollister@Sun.COM 		break;
97110696SDavid.Hollister@Sun.COM 	case PMCOUT_GENERAL_EVENT:
97210696SDavid.Hollister@Sun.COM 		return ("GENERAL_EVENT");
97310696SDavid.Hollister@Sun.COM 		break;
97410696SDavid.Hollister@Sun.COM 	case PMCOUT_TWI:
97510696SDavid.Hollister@Sun.COM 		return ("TWI");
97610696SDavid.Hollister@Sun.COM 		break;
97710696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_ABORT:
97810696SDavid.Hollister@Sun.COM 		return ("SSP_ABORT");
97910696SDavid.Hollister@Sun.COM 		break;
98010696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_ABORT:
98110696SDavid.Hollister@Sun.COM 		return ("SATA_ABORT");
98210696SDavid.Hollister@Sun.COM 		break;
98310696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_DIAG_MODE_START_END:
98410696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_MODE_START_END");
98510696SDavid.Hollister@Sun.COM 		break;
98610696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_DIAG_EXECUTE:
98710696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_EXECUTE");
98810696SDavid.Hollister@Sun.COM 		break;
98910696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_TIME_STAMP:
99010696SDavid.Hollister@Sun.COM 		return ("GET_TIME_STAMP");
99110696SDavid.Hollister@Sun.COM 		break;
99210696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_HW_EVENT_ACK_ACK:
99310696SDavid.Hollister@Sun.COM 		return ("SAS_HW_EVENT_ACK_ACK");
99410696SDavid.Hollister@Sun.COM 		break;
99510696SDavid.Hollister@Sun.COM 	case PMCOUT_PORT_CONTROL:
99610696SDavid.Hollister@Sun.COM 		return ("PORT_CONTROL");
99710696SDavid.Hollister@Sun.COM 		break;
99810696SDavid.Hollister@Sun.COM 	case PMCOUT_SKIP_ENTRIES:
99910696SDavid.Hollister@Sun.COM 		return ("SKIP_ENTRIES");
100010696SDavid.Hollister@Sun.COM 		break;
100110696SDavid.Hollister@Sun.COM 	case PMCOUT_SMP_ABORT:
100210696SDavid.Hollister@Sun.COM 		return ("SMP_ABORT");
100310696SDavid.Hollister@Sun.COM 		break;
100410696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_NVMD_DATA:
100510696SDavid.Hollister@Sun.COM 		return ("GET_NVMD_DATA");
100610696SDavid.Hollister@Sun.COM 		break;
100710696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_NVMD_DATA:
100810696SDavid.Hollister@Sun.COM 		return ("SET_NVMD_DATA");
100910696SDavid.Hollister@Sun.COM 		break;
101010696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_HANDLE_REMOVED:
101110696SDavid.Hollister@Sun.COM 		return ("DEVICE_HANDLE_REMOVED");
101210696SDavid.Hollister@Sun.COM 		break;
101310696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_DEVICE_STATE:
101410696SDavid.Hollister@Sun.COM 		return ("SET_DEVICE_STATE");
101510696SDavid.Hollister@Sun.COM 		break;
101610696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_DEVICE_STATE:
101710696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_STATE");
101810696SDavid.Hollister@Sun.COM 		break;
101910696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_DEVICE_INFO:
102010696SDavid.Hollister@Sun.COM 		return ("SET_DEVICE_INFO");
102110696SDavid.Hollister@Sun.COM 		break;
102210696SDavid.Hollister@Sun.COM 	default:
102310696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
102410696SDavid.Hollister@Sun.COM 		break;
102510696SDavid.Hollister@Sun.COM 	}
102610696SDavid.Hollister@Sun.COM }
102710696SDavid.Hollister@Sun.COM 
102810696SDavid.Hollister@Sun.COM static void
102910696SDavid.Hollister@Sun.COM dump_one_qentry_outbound(uint32_t *qentryp, int idx)
103010696SDavid.Hollister@Sun.COM {
103110696SDavid.Hollister@Sun.COM 	int qeidx;
103210696SDavid.Hollister@Sun.COM 	uint32_t word0 = LE_32(*qentryp);
103310696SDavid.Hollister@Sun.COM 
103410696SDavid.Hollister@Sun.COM 	mdb_printf("Entry #%02d\n", idx);
103510696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
103610696SDavid.Hollister@Sun.COM 
103710696SDavid.Hollister@Sun.COM 	mdb_printf("Header: 0x%08x (", word0);
103810696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_VALID) {
103910696SDavid.Hollister@Sun.COM 		mdb_printf("VALID, ");
104010696SDavid.Hollister@Sun.COM 	}
104110696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_HIPRI) {
104210696SDavid.Hollister@Sun.COM 		mdb_printf("HIPRI, ");
104310696SDavid.Hollister@Sun.COM 	}
104410696SDavid.Hollister@Sun.COM 	mdb_printf("OBID=%d, ",
104510696SDavid.Hollister@Sun.COM 	    (word0 & PMCS_IOMB_OBID_MASK) >> PMCS_IOMB_OBID_SHIFT);
104610696SDavid.Hollister@Sun.COM 	mdb_printf("CAT=%s, ",
104710696SDavid.Hollister@Sun.COM 	    iomb_cat((word0 & PMCS_IOMB_CAT_MASK) >> PMCS_IOMB_CAT_SHIFT));
104810696SDavid.Hollister@Sun.COM 	mdb_printf("OPCODE=%s",
104910696SDavid.Hollister@Sun.COM 	    outbound_iomb_opcode(word0 & PMCS_IOMB_OPCODE_MASK));
105010696SDavid.Hollister@Sun.COM 	mdb_printf(")\n");
105110696SDavid.Hollister@Sun.COM 
105210696SDavid.Hollister@Sun.COM 	mdb_printf("Remaining Payload:\n");
105310696SDavid.Hollister@Sun.COM 
105410696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
105510696SDavid.Hollister@Sun.COM 	for (qeidx = 1; qeidx < (PMCS_QENTRY_SIZE / 4); qeidx++) {
105610696SDavid.Hollister@Sun.COM 		mdb_printf("%08x ", LE_32(*(qentryp + qeidx)));
105710696SDavid.Hollister@Sun.COM 	}
105810696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
105910696SDavid.Hollister@Sun.COM 	mdb_dec_indent(4);
106010696SDavid.Hollister@Sun.COM }
106110696SDavid.Hollister@Sun.COM 
106210696SDavid.Hollister@Sun.COM static void
106310696SDavid.Hollister@Sun.COM display_outbound_queues(struct pmcs_hw ss, uint_t verbose)
106410696SDavid.Hollister@Sun.COM {
106510696SDavid.Hollister@Sun.COM 	int		idx, qidx;
106610696SDavid.Hollister@Sun.COM 	uintptr_t	obqp;
106710696SDavid.Hollister@Sun.COM 	uint32_t	*cip;
106810696SDavid.Hollister@Sun.COM 	uint32_t	*qentryp = mdb_alloc(PMCS_QENTRY_SIZE, UM_SLEEP);
106910696SDavid.Hollister@Sun.COM 	uint32_t	last_consumed, oqpi;
107010696SDavid.Hollister@Sun.COM 
107110696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
107210696SDavid.Hollister@Sun.COM 	mdb_printf("Outbound Queues\n");
107310696SDavid.Hollister@Sun.COM 	mdb_printf("---------------\n");
107410696SDavid.Hollister@Sun.COM 
107510696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
107610696SDavid.Hollister@Sun.COM 
107710696SDavid.Hollister@Sun.COM 	for (qidx = 0; qidx < PMCS_NOQ; qidx++) {
107810696SDavid.Hollister@Sun.COM 		obqp = (uintptr_t)ss.oqp[qidx];
107910696SDavid.Hollister@Sun.COM 
108010696SDavid.Hollister@Sun.COM 		if (obqp == NULL) {
108110696SDavid.Hollister@Sun.COM 			mdb_printf("No outbound queue ptr for queue #%d\n",
108210696SDavid.Hollister@Sun.COM 			    qidx);
108310696SDavid.Hollister@Sun.COM 			continue;
108410696SDavid.Hollister@Sun.COM 		}
108510696SDavid.Hollister@Sun.COM 
108610696SDavid.Hollister@Sun.COM 		mdb_printf("Outbound Queue #%d (Queue Type = %s)\n", qidx,
108710696SDavid.Hollister@Sun.COM 		    obq_type(qidx));
108810696SDavid.Hollister@Sun.COM 		/*
108910696SDavid.Hollister@Sun.COM 		 * Chip is the producer, so read the actual producer index
109010696SDavid.Hollister@Sun.COM 		 * and not the driver's version
109110696SDavid.Hollister@Sun.COM 		 */
109210696SDavid.Hollister@Sun.COM 		cip = (uint32_t *)((void *)ss.cip);
109310696SDavid.Hollister@Sun.COM 		if (MDB_RD(&oqpi, 4, cip + OQPI_BASE_OFFSET +
109410696SDavid.Hollister@Sun.COM 		    (qidx * 4)) == -1) {
109510696SDavid.Hollister@Sun.COM 			mdb_warn("Couldn't read oqpi\n");
109610696SDavid.Hollister@Sun.COM 			break;
109710696SDavid.Hollister@Sun.COM 		}
109810696SDavid.Hollister@Sun.COM 
109910696SDavid.Hollister@Sun.COM 		mdb_printf("Producer index: %d  Consumer index: %d\n\n",
110010696SDavid.Hollister@Sun.COM 		    LE_32(oqpi), ss.oqci[qidx]);
110110696SDavid.Hollister@Sun.COM 		mdb_inc_indent(2);
110210696SDavid.Hollister@Sun.COM 
110310696SDavid.Hollister@Sun.COM 		if (ss.oqci[qidx] == 0) {
110410696SDavid.Hollister@Sun.COM 			last_consumed = ss.ioq_depth - 1;
110510696SDavid.Hollister@Sun.COM 		} else {
110610696SDavid.Hollister@Sun.COM 			last_consumed = ss.oqci[qidx] - 1;
110710696SDavid.Hollister@Sun.COM 		}
110810696SDavid.Hollister@Sun.COM 
110910696SDavid.Hollister@Sun.COM 
111010696SDavid.Hollister@Sun.COM 		if (!verbose) {
111110696SDavid.Hollister@Sun.COM 			mdb_printf("Last processed entry:\n");
111210696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
111310696SDavid.Hollister@Sun.COM 			    (obqp + (PMCS_QENTRY_SIZE * last_consumed)))
111410696SDavid.Hollister@Sun.COM 			    == -1) {
111510696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
111610696SDavid.Hollister@Sun.COM 				    (obqp + (PMCS_QENTRY_SIZE *
111710696SDavid.Hollister@Sun.COM 				    last_consumed)));
111810696SDavid.Hollister@Sun.COM 				break;
111910696SDavid.Hollister@Sun.COM 			}
112010696SDavid.Hollister@Sun.COM 			dump_one_qentry_outbound(qentryp, last_consumed);
112110696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
112210696SDavid.Hollister@Sun.COM 			mdb_dec_indent(2);
112310696SDavid.Hollister@Sun.COM 			continue;
112410696SDavid.Hollister@Sun.COM 		}
112510696SDavid.Hollister@Sun.COM 
112610696SDavid.Hollister@Sun.COM 		for (idx = 0; idx < ss.ioq_depth; idx++) {
112710696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
112810696SDavid.Hollister@Sun.COM 			    (obqp + (PMCS_QENTRY_SIZE * idx))) == -1) {
112910696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
113010696SDavid.Hollister@Sun.COM 				    (obqp + (PMCS_QENTRY_SIZE * idx)));
113110696SDavid.Hollister@Sun.COM 				break;
113210696SDavid.Hollister@Sun.COM 			}
113310696SDavid.Hollister@Sun.COM 			dump_one_qentry_outbound(qentryp, idx);
113410696SDavid.Hollister@Sun.COM 		}
113510696SDavid.Hollister@Sun.COM 
113610696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
113710696SDavid.Hollister@Sun.COM 		mdb_dec_indent(2);
113810696SDavid.Hollister@Sun.COM 	}
113910696SDavid.Hollister@Sun.COM 
114010696SDavid.Hollister@Sun.COM 	mdb_dec_indent(2);
114110696SDavid.Hollister@Sun.COM 	mdb_free(qentryp, PMCS_QENTRY_SIZE);
114210696SDavid.Hollister@Sun.COM }
114310696SDavid.Hollister@Sun.COM 
114410696SDavid.Hollister@Sun.COM static void
114510696SDavid.Hollister@Sun.COM dump_one_qentry_inbound(uint32_t *qentryp, int idx)
114610696SDavid.Hollister@Sun.COM {
114710696SDavid.Hollister@Sun.COM 	int qeidx;
114810696SDavid.Hollister@Sun.COM 	uint32_t word0 = LE_32(*qentryp);
114910696SDavid.Hollister@Sun.COM 
115010696SDavid.Hollister@Sun.COM 	mdb_printf("Entry #%02d\n", idx);
115110696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
115210696SDavid.Hollister@Sun.COM 
115310696SDavid.Hollister@Sun.COM 	mdb_printf("Header: 0x%08x (", word0);
115410696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_VALID) {
115510696SDavid.Hollister@Sun.COM 		mdb_printf("VALID, ");
115610696SDavid.Hollister@Sun.COM 	}
115710696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_HIPRI) {
115810696SDavid.Hollister@Sun.COM 		mdb_printf("HIPRI, ");
115910696SDavid.Hollister@Sun.COM 	}
116010696SDavid.Hollister@Sun.COM 	mdb_printf("OBID=%d, ",
116110696SDavid.Hollister@Sun.COM 	    (word0 & PMCS_IOMB_OBID_MASK) >> PMCS_IOMB_OBID_SHIFT);
116210696SDavid.Hollister@Sun.COM 	mdb_printf("CAT=%s, ",
116310696SDavid.Hollister@Sun.COM 	    iomb_cat((word0 & PMCS_IOMB_CAT_MASK) >> PMCS_IOMB_CAT_SHIFT));
116410696SDavid.Hollister@Sun.COM 	mdb_printf("OPCODE=%s",
116510696SDavid.Hollister@Sun.COM 	    inbound_iomb_opcode(word0 & PMCS_IOMB_OPCODE_MASK));
116610696SDavid.Hollister@Sun.COM 	mdb_printf(")\n");
116710696SDavid.Hollister@Sun.COM 
116810696SDavid.Hollister@Sun.COM 	mdb_printf("HTAG: 0x%08x\n", LE_32(*(qentryp + 1)));
116910696SDavid.Hollister@Sun.COM 	mdb_printf("Remaining Payload:\n");
117010696SDavid.Hollister@Sun.COM 
117110696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
117210696SDavid.Hollister@Sun.COM 	for (qeidx = 2; qeidx < (PMCS_QENTRY_SIZE / 4); qeidx++) {
117310696SDavid.Hollister@Sun.COM 		mdb_printf("%08x ", LE_32(*(qentryp + qeidx)));
117410696SDavid.Hollister@Sun.COM 	}
117510696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
117610696SDavid.Hollister@Sun.COM 	mdb_dec_indent(4);
117710696SDavid.Hollister@Sun.COM }
117810696SDavid.Hollister@Sun.COM 
117910696SDavid.Hollister@Sun.COM static void
118010696SDavid.Hollister@Sun.COM display_inbound_queues(struct pmcs_hw ss, uint_t verbose)
118110696SDavid.Hollister@Sun.COM {
118210696SDavid.Hollister@Sun.COM 	int		idx, qidx, iqci, last_consumed;
118310696SDavid.Hollister@Sun.COM 	uintptr_t	ibqp;
118410696SDavid.Hollister@Sun.COM 	uint32_t	*qentryp = mdb_alloc(PMCS_QENTRY_SIZE, UM_SLEEP);
118510696SDavid.Hollister@Sun.COM 	uint32_t	*cip;
118610696SDavid.Hollister@Sun.COM 
118710696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
118810696SDavid.Hollister@Sun.COM 	mdb_printf("Inbound Queues\n");
118910696SDavid.Hollister@Sun.COM 	mdb_printf("--------------\n");
119010696SDavid.Hollister@Sun.COM 
119110696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
119210696SDavid.Hollister@Sun.COM 
119310696SDavid.Hollister@Sun.COM 	for (qidx = 0; qidx < PMCS_NIQ; qidx++) {
119410696SDavid.Hollister@Sun.COM 		ibqp = (uintptr_t)ss.iqp[qidx];
119510696SDavid.Hollister@Sun.COM 
119610696SDavid.Hollister@Sun.COM 		if (ibqp == NULL) {
119710696SDavid.Hollister@Sun.COM 			mdb_printf("No inbound queue ptr for queue #%d\n",
119810696SDavid.Hollister@Sun.COM 			    qidx);
119910696SDavid.Hollister@Sun.COM 			continue;
120010696SDavid.Hollister@Sun.COM 		}
120110696SDavid.Hollister@Sun.COM 
120210696SDavid.Hollister@Sun.COM 		mdb_printf("Inbound Queue #%d (Queue Type = %s)\n", qidx,
120310696SDavid.Hollister@Sun.COM 		    ibq_type(qidx));
120410696SDavid.Hollister@Sun.COM 
120510696SDavid.Hollister@Sun.COM 		cip = (uint32_t *)((void *)ss.cip);
120610696SDavid.Hollister@Sun.COM 		if (MDB_RD(&iqci, 4, cip + (qidx * 4)) == -1) {
120710696SDavid.Hollister@Sun.COM 			mdb_warn("Couldn't read iqci\n");
120810696SDavid.Hollister@Sun.COM 			break;
120910696SDavid.Hollister@Sun.COM 		}
121010696SDavid.Hollister@Sun.COM 		iqci = LE_32(iqci);
121110696SDavid.Hollister@Sun.COM 
121210696SDavid.Hollister@Sun.COM 		mdb_printf("Producer index: %d  Consumer index: %d\n\n",
121310696SDavid.Hollister@Sun.COM 		    ss.shadow_iqpi[qidx], iqci);
121410696SDavid.Hollister@Sun.COM 		mdb_inc_indent(2);
121510696SDavid.Hollister@Sun.COM 
121610696SDavid.Hollister@Sun.COM 		if (iqci == 0) {
121710696SDavid.Hollister@Sun.COM 			last_consumed = ss.ioq_depth - 1;
121810696SDavid.Hollister@Sun.COM 		} else {
121910696SDavid.Hollister@Sun.COM 			last_consumed = iqci - 1;
122010696SDavid.Hollister@Sun.COM 		}
122110696SDavid.Hollister@Sun.COM 
122210696SDavid.Hollister@Sun.COM 		if (!verbose) {
122310696SDavid.Hollister@Sun.COM 			mdb_printf("Last processed entry:\n");
122410696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
122510696SDavid.Hollister@Sun.COM 			    (ibqp + (PMCS_QENTRY_SIZE * last_consumed)))
122610696SDavid.Hollister@Sun.COM 			    == -1) {
122710696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
122810696SDavid.Hollister@Sun.COM 				    (ibqp + (PMCS_QENTRY_SIZE *
122910696SDavid.Hollister@Sun.COM 				    last_consumed)));
123010696SDavid.Hollister@Sun.COM 				break;
123110696SDavid.Hollister@Sun.COM 			}
123210696SDavid.Hollister@Sun.COM 			dump_one_qentry_inbound(qentryp, last_consumed);
123310696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
123410696SDavid.Hollister@Sun.COM 			mdb_dec_indent(2);
123510696SDavid.Hollister@Sun.COM 			continue;
123610696SDavid.Hollister@Sun.COM 		}
123710696SDavid.Hollister@Sun.COM 
123810696SDavid.Hollister@Sun.COM 		for (idx = 0; idx < ss.ioq_depth; idx++) {
123910696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
124010696SDavid.Hollister@Sun.COM 			    (ibqp + (PMCS_QENTRY_SIZE * idx))) == -1) {
124110696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
124210696SDavid.Hollister@Sun.COM 				    (ibqp + (PMCS_QENTRY_SIZE * idx)));
124310696SDavid.Hollister@Sun.COM 				break;
124410696SDavid.Hollister@Sun.COM 			}
124510696SDavid.Hollister@Sun.COM 			dump_one_qentry_inbound(qentryp, idx);
124610696SDavid.Hollister@Sun.COM 		}
124710696SDavid.Hollister@Sun.COM 
124810696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
124910696SDavid.Hollister@Sun.COM 		mdb_dec_indent(2);
125010696SDavid.Hollister@Sun.COM 	}
125110696SDavid.Hollister@Sun.COM 
125210696SDavid.Hollister@Sun.COM 	mdb_dec_indent(2);
125310696SDavid.Hollister@Sun.COM 	mdb_free(qentryp, PMCS_QENTRY_SIZE);
125410696SDavid.Hollister@Sun.COM }
125510696SDavid.Hollister@Sun.COM 
125610696SDavid.Hollister@Sun.COM static void
125710696SDavid.Hollister@Sun.COM display_phy(struct pmcs_phy phy, int verbose, int totals_only)
125810696SDavid.Hollister@Sun.COM {
125910696SDavid.Hollister@Sun.COM 	char		*dtype, *speed;
126010696SDavid.Hollister@Sun.COM 	char		*yes = "Yes";
126110696SDavid.Hollister@Sun.COM 	char		*no = "No";
126210696SDavid.Hollister@Sun.COM 	char		*cfgd = no;
126310696SDavid.Hollister@Sun.COM 	char		*apend = no;
126410696SDavid.Hollister@Sun.COM 	char		*asent = no;
126510696SDavid.Hollister@Sun.COM 	char		*dead = no;
126610696SDavid.Hollister@Sun.COM 	char		*changed = no;
126710696SDavid.Hollister@Sun.COM 
126810696SDavid.Hollister@Sun.COM 	switch (phy.dtype) {
126910696SDavid.Hollister@Sun.COM 	case NOTHING:
127010696SDavid.Hollister@Sun.COM 		dtype = "None";
127110696SDavid.Hollister@Sun.COM 		break;
127210696SDavid.Hollister@Sun.COM 	case SATA:
127310696SDavid.Hollister@Sun.COM 		dtype = "SATA";
127410696SDavid.Hollister@Sun.COM 		if (phy.configured) {
127510696SDavid.Hollister@Sun.COM 			++sata_phys;
127610696SDavid.Hollister@Sun.COM 		}
127710696SDavid.Hollister@Sun.COM 		break;
127810696SDavid.Hollister@Sun.COM 	case SAS:
127910696SDavid.Hollister@Sun.COM 		dtype = "SAS";
128010696SDavid.Hollister@Sun.COM 		if (phy.configured) {
128110696SDavid.Hollister@Sun.COM 			++sas_phys;
128210696SDavid.Hollister@Sun.COM 		}
128310696SDavid.Hollister@Sun.COM 		break;
128410696SDavid.Hollister@Sun.COM 	case EXPANDER:
128510696SDavid.Hollister@Sun.COM 		dtype = "EXP";
128610696SDavid.Hollister@Sun.COM 		if (phy.configured) {
128710696SDavid.Hollister@Sun.COM 			++exp_phys;
128810696SDavid.Hollister@Sun.COM 		}
128910696SDavid.Hollister@Sun.COM 		break;
129010696SDavid.Hollister@Sun.COM 	}
129110696SDavid.Hollister@Sun.COM 
129210696SDavid.Hollister@Sun.COM 	if (phy.dtype == NOTHING) {
129310696SDavid.Hollister@Sun.COM 		empty_phys++;
129410696SDavid.Hollister@Sun.COM 	} else if ((phy.dtype == EXPANDER) && phy.configured) {
129510696SDavid.Hollister@Sun.COM 		num_expanders++;
129610696SDavid.Hollister@Sun.COM 	}
129710696SDavid.Hollister@Sun.COM 
129810696SDavid.Hollister@Sun.COM 	if (totals_only) {
129910696SDavid.Hollister@Sun.COM 		return;
130010696SDavid.Hollister@Sun.COM 	}
130110696SDavid.Hollister@Sun.COM 
130210696SDavid.Hollister@Sun.COM 	switch (phy.link_rate) {
130310696SDavid.Hollister@Sun.COM 	case SAS_LINK_RATE_1_5GBIT:
130410696SDavid.Hollister@Sun.COM 		speed = "1.5Gb/s";
130510696SDavid.Hollister@Sun.COM 		break;
130610696SDavid.Hollister@Sun.COM 	case SAS_LINK_RATE_3GBIT:
130710696SDavid.Hollister@Sun.COM 		speed = "3 Gb/s";
130810696SDavid.Hollister@Sun.COM 		break;
130910696SDavid.Hollister@Sun.COM 	case SAS_LINK_RATE_6GBIT:
131010696SDavid.Hollister@Sun.COM 		speed = "6 Gb/s";
131110696SDavid.Hollister@Sun.COM 		break;
131210696SDavid.Hollister@Sun.COM 	default:
131310696SDavid.Hollister@Sun.COM 		speed = "N/A";
131410696SDavid.Hollister@Sun.COM 		break;
131510696SDavid.Hollister@Sun.COM 	}
131610696SDavid.Hollister@Sun.COM 
131710696SDavid.Hollister@Sun.COM 	if ((phy.dtype != NOTHING) || verbose) {
131810696SDavid.Hollister@Sun.COM 		print_sas_address(&phy);
131910696SDavid.Hollister@Sun.COM 
132010696SDavid.Hollister@Sun.COM 		if (phy.device_id != PMCS_INVALID_DEVICE_ID) {
132110696SDavid.Hollister@Sun.COM 			mdb_printf(" %3d %4d %6s %4s ",
132210696SDavid.Hollister@Sun.COM 			    phy.device_id, phy.phynum, speed, dtype);
132310696SDavid.Hollister@Sun.COM 		} else {
132410696SDavid.Hollister@Sun.COM 			mdb_printf(" N/A %4d %6s %4s ",
132510696SDavid.Hollister@Sun.COM 			    phy.phynum, speed, dtype);
132610696SDavid.Hollister@Sun.COM 		}
132710696SDavid.Hollister@Sun.COM 
132810696SDavid.Hollister@Sun.COM 		if (verbose) {
132910696SDavid.Hollister@Sun.COM 			if (phy.abort_sent) {
133010696SDavid.Hollister@Sun.COM 				asent = yes;
133110696SDavid.Hollister@Sun.COM 			}
133210696SDavid.Hollister@Sun.COM 			if (phy.abort_pending) {
133310696SDavid.Hollister@Sun.COM 				apend = yes;
133410696SDavid.Hollister@Sun.COM 			}
133510696SDavid.Hollister@Sun.COM 			if (phy.configured) {
133610696SDavid.Hollister@Sun.COM 				cfgd = yes;
133710696SDavid.Hollister@Sun.COM 			}
133810696SDavid.Hollister@Sun.COM 			if (phy.dead) {
133910696SDavid.Hollister@Sun.COM 				dead = yes;
134010696SDavid.Hollister@Sun.COM 			}
134110696SDavid.Hollister@Sun.COM 			if (phy.changed) {
134210696SDavid.Hollister@Sun.COM 				changed = yes;
134310696SDavid.Hollister@Sun.COM 			}
134410696SDavid.Hollister@Sun.COM 
134510696SDavid.Hollister@Sun.COM 			mdb_printf("%-4s %-4s %-4s %-4s %-4s %3d "
134610696SDavid.Hollister@Sun.COM 			    "0x%p ", cfgd, apend, asent,
134710696SDavid.Hollister@Sun.COM 			    changed, dead, phy.ref_count, phy.phy_lock);
134810696SDavid.Hollister@Sun.COM 		}
134910696SDavid.Hollister@Sun.COM 
135010696SDavid.Hollister@Sun.COM 		mdb_printf("Path: %s\n", phy.path);
135110696SDavid.Hollister@Sun.COM 	}
135210696SDavid.Hollister@Sun.COM }
135310696SDavid.Hollister@Sun.COM 
135410696SDavid.Hollister@Sun.COM static void
135510696SDavid.Hollister@Sun.COM display_phys(struct pmcs_hw ss, int verbose, struct pmcs_phy *parent, int level,
135610696SDavid.Hollister@Sun.COM     int totals_only)
135710696SDavid.Hollister@Sun.COM {
135810696SDavid.Hollister@Sun.COM 	pmcs_phy_t	phy;
135910696SDavid.Hollister@Sun.COM 	pmcs_phy_t	*pphy = parent;
136010696SDavid.Hollister@Sun.COM 
136110696SDavid.Hollister@Sun.COM 	mdb_inc_indent(3);
136210696SDavid.Hollister@Sun.COM 
136310696SDavid.Hollister@Sun.COM 	if (parent == NULL) {
136410696SDavid.Hollister@Sun.COM 		pphy = (pmcs_phy_t *)ss.root_phys;
136510696SDavid.Hollister@Sun.COM 	} else {
136610696SDavid.Hollister@Sun.COM 		pphy = (pmcs_phy_t *)parent;
136710696SDavid.Hollister@Sun.COM 	}
136810696SDavid.Hollister@Sun.COM 
136910696SDavid.Hollister@Sun.COM 	if (level == 0) {
137010696SDavid.Hollister@Sun.COM 		sas_phys = 0;
137110696SDavid.Hollister@Sun.COM 		sata_phys = 0;
137210696SDavid.Hollister@Sun.COM 		exp_phys = 0;
137310696SDavid.Hollister@Sun.COM 		num_expanders = 0;
137410696SDavid.Hollister@Sun.COM 		empty_phys = 0;
137510696SDavid.Hollister@Sun.COM 	}
137610696SDavid.Hollister@Sun.COM 
137710696SDavid.Hollister@Sun.COM 	if (!totals_only) {
137810696SDavid.Hollister@Sun.COM 		if (level == 0) {
137910696SDavid.Hollister@Sun.COM 			mdb_printf("PHY information\n");
138010696SDavid.Hollister@Sun.COM 		}
138110696SDavid.Hollister@Sun.COM 		mdb_printf("--------\n");
138210696SDavid.Hollister@Sun.COM 		mdb_printf("Level %2d\n", level);
138310696SDavid.Hollister@Sun.COM 		mdb_printf("--------\n");
138410696SDavid.Hollister@Sun.COM 		mdb_printf("SAS Address      Hdl Phy#  Speed Type ");
138510696SDavid.Hollister@Sun.COM 
138610696SDavid.Hollister@Sun.COM 		if (verbose) {
138710696SDavid.Hollister@Sun.COM 			mdb_printf("Cfgd AbtP AbtS Chgd Dead Ref Lock\n");
138810696SDavid.Hollister@Sun.COM 		} else {
138910696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
139010696SDavid.Hollister@Sun.COM 		}
139110696SDavid.Hollister@Sun.COM 	}
139210696SDavid.Hollister@Sun.COM 
139310696SDavid.Hollister@Sun.COM 	while (pphy) {
139410696SDavid.Hollister@Sun.COM 		if (MDB_RD(&phy, sizeof (phy), (uintptr_t)pphy) == -1) {
139510696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_phy_t, phy);
139610696SDavid.Hollister@Sun.COM 			break;
139710696SDavid.Hollister@Sun.COM 		}
139810696SDavid.Hollister@Sun.COM 
139910696SDavid.Hollister@Sun.COM 		display_phy(phy, verbose, totals_only);
140010696SDavid.Hollister@Sun.COM 
140110696SDavid.Hollister@Sun.COM 		if (phy.children) {
140210696SDavid.Hollister@Sun.COM 			display_phys(ss, verbose, phy.children, level + 1,
140310696SDavid.Hollister@Sun.COM 			    totals_only);
140410696SDavid.Hollister@Sun.COM 			if (!totals_only) {
140510696SDavid.Hollister@Sun.COM 				mdb_printf("\n");
140610696SDavid.Hollister@Sun.COM 			}
140710696SDavid.Hollister@Sun.COM 		}
140810696SDavid.Hollister@Sun.COM 
140910696SDavid.Hollister@Sun.COM 		pphy = phy.sibling;
141010696SDavid.Hollister@Sun.COM 	}
141110696SDavid.Hollister@Sun.COM 
141210696SDavid.Hollister@Sun.COM 	mdb_dec_indent(3);
141310696SDavid.Hollister@Sun.COM 
141410696SDavid.Hollister@Sun.COM 	if (level == 0) {
141510696SDavid.Hollister@Sun.COM 		if (verbose) {
141610696SDavid.Hollister@Sun.COM 			mdb_printf("%19s %d (%d SAS + %d SATA + %d SMP) "
141710696SDavid.Hollister@Sun.COM 			    "(+%d subsidiary + %d empty)\n", "Occupied PHYs:",
141810696SDavid.Hollister@Sun.COM 			    (sas_phys + sata_phys + num_expanders),
141910696SDavid.Hollister@Sun.COM 			    sas_phys, sata_phys, num_expanders,
142010696SDavid.Hollister@Sun.COM 			    (exp_phys - num_expanders), empty_phys);
142110696SDavid.Hollister@Sun.COM 		} else {
142210696SDavid.Hollister@Sun.COM 			mdb_printf("%19s %d (%d SAS + %d SATA + %d SMP)\n",
142310696SDavid.Hollister@Sun.COM 			    "Occupied PHYs:",
142410696SDavid.Hollister@Sun.COM 			    (sas_phys + sata_phys + num_expanders),
142510696SDavid.Hollister@Sun.COM 			    sas_phys, sata_phys, num_expanders);
142610696SDavid.Hollister@Sun.COM 		}
142710696SDavid.Hollister@Sun.COM 	}
142810696SDavid.Hollister@Sun.COM }
142910696SDavid.Hollister@Sun.COM 
143010696SDavid.Hollister@Sun.COM /*
143110696SDavid.Hollister@Sun.COM  * MAX_INST_STRLEN is the largest string size from which we will attempt
143210696SDavid.Hollister@Sun.COM  * to convert to an instance number.  The string will be formed up as
143310696SDavid.Hollister@Sun.COM  * "0t<inst>\0" so that mdb_strtoull can parse it properly.
143410696SDavid.Hollister@Sun.COM  */
143510696SDavid.Hollister@Sun.COM #define	MAX_INST_STRLEN	8
143610696SDavid.Hollister@Sun.COM 
143710696SDavid.Hollister@Sun.COM static int
143810696SDavid.Hollister@Sun.COM pmcs_dump_tracelog(boolean_t filter, int instance)
143910696SDavid.Hollister@Sun.COM {
144010696SDavid.Hollister@Sun.COM 	pmcs_tbuf_t *tbuf_addr;
144110696SDavid.Hollister@Sun.COM 	uint_t tbuf_idx;
144210696SDavid.Hollister@Sun.COM 	pmcs_tbuf_t tbuf;
144310696SDavid.Hollister@Sun.COM 	boolean_t wrap, elem_filtered;
144410696SDavid.Hollister@Sun.COM 	uint_t start_idx, elems_to_print, idx, tbuf_num_elems;
144510696SDavid.Hollister@Sun.COM 	char *bufp;
144610696SDavid.Hollister@Sun.COM 	char elem_inst[MAX_INST_STRLEN], ei_idx;
144710696SDavid.Hollister@Sun.COM 
144810696SDavid.Hollister@Sun.COM 	/* Get the address of the first element */
144910696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&tbuf_addr, "pmcs_tbuf") == -1) {
145010696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf");
145110696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
145210696SDavid.Hollister@Sun.COM 	}
145310696SDavid.Hollister@Sun.COM 
145410696SDavid.Hollister@Sun.COM 	/* Get the total number */
145510696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&tbuf_num_elems, "pmcs_tbuf_num_elems") == -1) {
145610696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf_num_elems");
145710696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
145810696SDavid.Hollister@Sun.COM 	}
145910696SDavid.Hollister@Sun.COM 
146010696SDavid.Hollister@Sun.COM 	/* Get the current index */
146110696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&tbuf_idx, "pmcs_tbuf_idx") == -1) {
146210696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf_idx");
146310696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
146410696SDavid.Hollister@Sun.COM 	}
146510696SDavid.Hollister@Sun.COM 
146610696SDavid.Hollister@Sun.COM 	/* Indicator as to whether the buffer has wrapped */
146710696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&wrap, "pmcs_tbuf_wrap") == -1) {
146810696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf_wrap");
146910696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
147010696SDavid.Hollister@Sun.COM 	}
147110696SDavid.Hollister@Sun.COM 
147210696SDavid.Hollister@Sun.COM 	/* Figure out where we start and stop */
147310696SDavid.Hollister@Sun.COM 	if (wrap) {
147410696SDavid.Hollister@Sun.COM 		start_idx = tbuf_idx;
147510696SDavid.Hollister@Sun.COM 		elems_to_print = tbuf_num_elems;
147610696SDavid.Hollister@Sun.COM 	} else {
147710696SDavid.Hollister@Sun.COM 		start_idx = 0;
147810696SDavid.Hollister@Sun.COM 		elems_to_print = tbuf_idx;
147910696SDavid.Hollister@Sun.COM 	}
148010696SDavid.Hollister@Sun.COM 
148110696SDavid.Hollister@Sun.COM 	idx = start_idx;
148210696SDavid.Hollister@Sun.COM 
148310696SDavid.Hollister@Sun.COM 	/* Dump the buffer contents */
148410696SDavid.Hollister@Sun.COM 	while (elems_to_print != 0) {
148510696SDavid.Hollister@Sun.COM 		if (MDB_RD(&tbuf, sizeof (pmcs_tbuf_t), (tbuf_addr + idx))
148610696SDavid.Hollister@Sun.COM 		    == -1) {
148710696SDavid.Hollister@Sun.COM 			NOREAD(tbuf, (tbuf_addr + idx));
148810696SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
148910696SDavid.Hollister@Sun.COM 		}
149010696SDavid.Hollister@Sun.COM 
149110696SDavid.Hollister@Sun.COM 		elem_filtered = B_FALSE;
149210696SDavid.Hollister@Sun.COM 
149310696SDavid.Hollister@Sun.COM 		if (filter) {
149410696SDavid.Hollister@Sun.COM 			bufp = tbuf.buf;
149510696SDavid.Hollister@Sun.COM 			/* Skip the driver name */
149610696SDavid.Hollister@Sun.COM 			while (*bufp < '0' || *bufp > '9') {
149710696SDavid.Hollister@Sun.COM 				bufp++;
149810696SDavid.Hollister@Sun.COM 			}
149910696SDavid.Hollister@Sun.COM 
150010696SDavid.Hollister@Sun.COM 			ei_idx = 0;
150110696SDavid.Hollister@Sun.COM 			elem_inst[ei_idx++] = '0';
150210696SDavid.Hollister@Sun.COM 			elem_inst[ei_idx++] = 't';
150310696SDavid.Hollister@Sun.COM 			while (*bufp != ':' && ei_idx < (MAX_INST_STRLEN - 1)) {
150410696SDavid.Hollister@Sun.COM 				elem_inst[ei_idx++] = *bufp;
150510696SDavid.Hollister@Sun.COM 				bufp++;
150610696SDavid.Hollister@Sun.COM 			}
150710696SDavid.Hollister@Sun.COM 			elem_inst[ei_idx] = 0;
150810696SDavid.Hollister@Sun.COM 
150910696SDavid.Hollister@Sun.COM 			/* Get the instance */
151010696SDavid.Hollister@Sun.COM 			if ((int)mdb_strtoull(elem_inst) != instance) {
151110696SDavid.Hollister@Sun.COM 				elem_filtered = B_TRUE;
151210696SDavid.Hollister@Sun.COM 			}
151310696SDavid.Hollister@Sun.COM 		}
151410696SDavid.Hollister@Sun.COM 
151510696SDavid.Hollister@Sun.COM 		if (!elem_filtered) {
151610696SDavid.Hollister@Sun.COM 			mdb_printf("%Y.%09ld %s\n", tbuf.timestamp, tbuf.buf);
151710696SDavid.Hollister@Sun.COM 		}
151810696SDavid.Hollister@Sun.COM 
151910696SDavid.Hollister@Sun.COM 		--elems_to_print;
152010696SDavid.Hollister@Sun.COM 		if (++idx == tbuf_num_elems) {
152110696SDavid.Hollister@Sun.COM 			idx = 0;
152210696SDavid.Hollister@Sun.COM 		}
152310696SDavid.Hollister@Sun.COM 	}
152410696SDavid.Hollister@Sun.COM 
152510696SDavid.Hollister@Sun.COM 	return (DCMD_OK);
152610696SDavid.Hollister@Sun.COM }
152710696SDavid.Hollister@Sun.COM 
152810696SDavid.Hollister@Sun.COM /*
152910696SDavid.Hollister@Sun.COM  * Walkers
153010696SDavid.Hollister@Sun.COM  */
153110696SDavid.Hollister@Sun.COM static int
153210696SDavid.Hollister@Sun.COM targets_walk_i(mdb_walk_state_t *wsp)
153310696SDavid.Hollister@Sun.COM {
153410696SDavid.Hollister@Sun.COM 	if (wsp->walk_addr == NULL) {
153510696SDavid.Hollister@Sun.COM 		mdb_warn("Can not perform global walk\n");
153610696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
153710696SDavid.Hollister@Sun.COM 	}
153810696SDavid.Hollister@Sun.COM 
153910696SDavid.Hollister@Sun.COM 	/*
154010696SDavid.Hollister@Sun.COM 	 * Address provided belongs to HBA softstate.  Get the targets pointer
154110696SDavid.Hollister@Sun.COM 	 * to begin the walk.
154210696SDavid.Hollister@Sun.COM 	 */
154310696SDavid.Hollister@Sun.COM 	if (mdb_vread(&ss, sizeof (pmcs_hw_t), wsp->walk_addr) !=
154410696SDavid.Hollister@Sun.COM 	    sizeof (pmcs_hw_t)) {
154510696SDavid.Hollister@Sun.COM 		mdb_warn("Unable to read HBA softstate\n");
154610696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
154710696SDavid.Hollister@Sun.COM 	}
154810696SDavid.Hollister@Sun.COM 
154910696SDavid.Hollister@Sun.COM 	if (targets == NULL) {
155010696SDavid.Hollister@Sun.COM 		targets = mdb_alloc(sizeof (targets) * ss.max_dev, UM_SLEEP);
155110696SDavid.Hollister@Sun.COM 	}
155210696SDavid.Hollister@Sun.COM 
155310696SDavid.Hollister@Sun.COM 	if (MDB_RD(targets, sizeof (targets) * ss.max_dev, ss.targets) == -1) {
155410696SDavid.Hollister@Sun.COM 		NOREAD(targets, ss.targets);
155510696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
155610696SDavid.Hollister@Sun.COM 	}
155710696SDavid.Hollister@Sun.COM 
155810696SDavid.Hollister@Sun.COM 	target_idx = 0;
155910696SDavid.Hollister@Sun.COM 	wsp->walk_addr = (uintptr_t)(targets[0]);
156010696SDavid.Hollister@Sun.COM 	wsp->walk_data = mdb_alloc(sizeof (pmcs_xscsi_t), UM_SLEEP);
156110696SDavid.Hollister@Sun.COM 
156210696SDavid.Hollister@Sun.COM 	return (WALK_NEXT);
156310696SDavid.Hollister@Sun.COM }
156410696SDavid.Hollister@Sun.COM 
156510696SDavid.Hollister@Sun.COM static int
156610696SDavid.Hollister@Sun.COM targets_walk_s(mdb_walk_state_t *wsp)
156710696SDavid.Hollister@Sun.COM {
156810696SDavid.Hollister@Sun.COM 	int status;
156910696SDavid.Hollister@Sun.COM 
157010696SDavid.Hollister@Sun.COM 	if (target_idx == ss.max_dev) {
157110696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
157210696SDavid.Hollister@Sun.COM 	}
157310696SDavid.Hollister@Sun.COM 
157410696SDavid.Hollister@Sun.COM 	if (mdb_vread(wsp->walk_data, sizeof (pmcs_xscsi_t),
157510696SDavid.Hollister@Sun.COM 	    wsp->walk_addr) == -1) {
157610696SDavid.Hollister@Sun.COM 		mdb_warn("Failed to read target at %p", (void *)wsp->walk_addr);
157710696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
157810696SDavid.Hollister@Sun.COM 	}
157910696SDavid.Hollister@Sun.COM 
158010696SDavid.Hollister@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
158110696SDavid.Hollister@Sun.COM 	    wsp->walk_cbdata);
158210696SDavid.Hollister@Sun.COM 
158310696SDavid.Hollister@Sun.COM 	do {
158410696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)(targets[++target_idx]);
158510696SDavid.Hollister@Sun.COM 	} while ((wsp->walk_addr == NULL) && (target_idx < ss.max_dev));
158610696SDavid.Hollister@Sun.COM 
158710696SDavid.Hollister@Sun.COM 	if (target_idx == ss.max_dev) {
158810696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
158910696SDavid.Hollister@Sun.COM 	}
159010696SDavid.Hollister@Sun.COM 
159110696SDavid.Hollister@Sun.COM 	return (status);
159210696SDavid.Hollister@Sun.COM }
159310696SDavid.Hollister@Sun.COM 
159410696SDavid.Hollister@Sun.COM static void
159510696SDavid.Hollister@Sun.COM targets_walk_f(mdb_walk_state_t *wsp)
159610696SDavid.Hollister@Sun.COM {
159710696SDavid.Hollister@Sun.COM 	mdb_free(wsp->walk_data, sizeof (pmcs_xscsi_t));
159810696SDavid.Hollister@Sun.COM }
159910696SDavid.Hollister@Sun.COM 
160010696SDavid.Hollister@Sun.COM 
160110696SDavid.Hollister@Sun.COM static pmcs_phy_t *
160210696SDavid.Hollister@Sun.COM pmcs_next_sibling(pmcs_phy_t *phyp)
160310696SDavid.Hollister@Sun.COM {
160410696SDavid.Hollister@Sun.COM 	pmcs_phy_t parent;
160510696SDavid.Hollister@Sun.COM 
160610696SDavid.Hollister@Sun.COM 	/*
160710696SDavid.Hollister@Sun.COM 	 * First, if this is a root PHY, there are no more siblings
160810696SDavid.Hollister@Sun.COM 	 */
160910696SDavid.Hollister@Sun.COM 	if (phyp->level == 0) {
161010696SDavid.Hollister@Sun.COM 		return (NULL);
161110696SDavid.Hollister@Sun.COM 	}
161210696SDavid.Hollister@Sun.COM 
161310696SDavid.Hollister@Sun.COM 	/*
161410696SDavid.Hollister@Sun.COM 	 * Otherwise, next sibling is the parent's sibling
161510696SDavid.Hollister@Sun.COM 	 */
161610696SDavid.Hollister@Sun.COM 	while (phyp->level > 0) {
161710696SDavid.Hollister@Sun.COM 		if (mdb_vread(&parent, sizeof (pmcs_phy_t),
161810696SDavid.Hollister@Sun.COM 		    (uintptr_t)phyp->parent) == -1) {
161910696SDavid.Hollister@Sun.COM 			mdb_warn("pmcs_next_sibling: Failed to read PHY at %p",
162010696SDavid.Hollister@Sun.COM 			    (void *)phyp->parent);
162110696SDavid.Hollister@Sun.COM 			return (NULL);
162210696SDavid.Hollister@Sun.COM 		}
162310696SDavid.Hollister@Sun.COM 
162410696SDavid.Hollister@Sun.COM 		if (parent.sibling != NULL) {
162510696SDavid.Hollister@Sun.COM 			break;
162610696SDavid.Hollister@Sun.COM 		}
162710696SDavid.Hollister@Sun.COM 
162810696SDavid.Hollister@Sun.COM 		phyp = phyp->parent;
162910696SDavid.Hollister@Sun.COM 	}
163010696SDavid.Hollister@Sun.COM 
163110696SDavid.Hollister@Sun.COM 	return (parent.sibling);
163210696SDavid.Hollister@Sun.COM }
163310696SDavid.Hollister@Sun.COM 
163410696SDavid.Hollister@Sun.COM static int
163510696SDavid.Hollister@Sun.COM phy_walk_i(mdb_walk_state_t *wsp)
163610696SDavid.Hollister@Sun.COM {
163710696SDavid.Hollister@Sun.COM 	if (wsp->walk_addr == NULL) {
163810696SDavid.Hollister@Sun.COM 		mdb_warn("Can not perform global walk\n");
163910696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
164010696SDavid.Hollister@Sun.COM 	}
164110696SDavid.Hollister@Sun.COM 
164210696SDavid.Hollister@Sun.COM 	/*
164310696SDavid.Hollister@Sun.COM 	 * Address provided belongs to HBA softstate.  Get the targets pointer
164410696SDavid.Hollister@Sun.COM 	 * to begin the walk.
164510696SDavid.Hollister@Sun.COM 	 */
164610696SDavid.Hollister@Sun.COM 	if (mdb_vread(&ss, sizeof (pmcs_hw_t), wsp->walk_addr) !=
164710696SDavid.Hollister@Sun.COM 	    sizeof (pmcs_hw_t)) {
164810696SDavid.Hollister@Sun.COM 		mdb_warn("Unable to read HBA softstate\n");
164910696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
165010696SDavid.Hollister@Sun.COM 	}
165110696SDavid.Hollister@Sun.COM 
165210696SDavid.Hollister@Sun.COM 	wsp->walk_addr = (uintptr_t)(ss.root_phys);
165310696SDavid.Hollister@Sun.COM 	wsp->walk_data = mdb_alloc(sizeof (pmcs_phy_t), UM_SLEEP);
165410696SDavid.Hollister@Sun.COM 
165510696SDavid.Hollister@Sun.COM 	return (WALK_NEXT);
165610696SDavid.Hollister@Sun.COM }
165710696SDavid.Hollister@Sun.COM 
165810696SDavid.Hollister@Sun.COM static int
165910696SDavid.Hollister@Sun.COM phy_walk_s(mdb_walk_state_t *wsp)
166010696SDavid.Hollister@Sun.COM {
166110696SDavid.Hollister@Sun.COM 	pmcs_phy_t *phyp, *nphyp;
166210696SDavid.Hollister@Sun.COM 	int status;
166310696SDavid.Hollister@Sun.COM 
166410696SDavid.Hollister@Sun.COM 	if (mdb_vread(wsp->walk_data, sizeof (pmcs_phy_t),
166510696SDavid.Hollister@Sun.COM 	    wsp->walk_addr) == -1) {
166610696SDavid.Hollister@Sun.COM 		mdb_warn("phy_walk_s: Failed to read PHY at %p",
166710696SDavid.Hollister@Sun.COM 		    (void *)wsp->walk_addr);
166810696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
166910696SDavid.Hollister@Sun.COM 	}
167010696SDavid.Hollister@Sun.COM 
167110696SDavid.Hollister@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
167210696SDavid.Hollister@Sun.COM 	    wsp->walk_cbdata);
167310696SDavid.Hollister@Sun.COM 
167410696SDavid.Hollister@Sun.COM 	phyp = (pmcs_phy_t *)wsp->walk_data;
167510696SDavid.Hollister@Sun.COM 	if (phyp->children) {
167610696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)(phyp->children);
167710696SDavid.Hollister@Sun.COM 	} else {
167810696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)(phyp->sibling);
167910696SDavid.Hollister@Sun.COM 	}
168010696SDavid.Hollister@Sun.COM 
168110696SDavid.Hollister@Sun.COM 	if (wsp->walk_addr == NULL) {
168210696SDavid.Hollister@Sun.COM 		/*
168310696SDavid.Hollister@Sun.COM 		 * We reached the end of this sibling list.  Trudge back up
168410696SDavid.Hollister@Sun.COM 		 * to the parent and find the next sibling after the expander
168510696SDavid.Hollister@Sun.COM 		 * we just finished traversing, if there is one.
168610696SDavid.Hollister@Sun.COM 		 */
168710696SDavid.Hollister@Sun.COM 		nphyp = pmcs_next_sibling(phyp);
168810696SDavid.Hollister@Sun.COM 
168910696SDavid.Hollister@Sun.COM 		if (nphyp == NULL) {
169010696SDavid.Hollister@Sun.COM 			return (WALK_DONE);
169110696SDavid.Hollister@Sun.COM 		}
169210696SDavid.Hollister@Sun.COM 
169310696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)nphyp;
169410696SDavid.Hollister@Sun.COM 	}
169510696SDavid.Hollister@Sun.COM 
169610696SDavid.Hollister@Sun.COM 	return (status);
169710696SDavid.Hollister@Sun.COM }
169810696SDavid.Hollister@Sun.COM 
169910696SDavid.Hollister@Sun.COM static void
170010696SDavid.Hollister@Sun.COM phy_walk_f(mdb_walk_state_t *wsp)
170110696SDavid.Hollister@Sun.COM {
170210696SDavid.Hollister@Sun.COM 	mdb_free(wsp->walk_data, sizeof (pmcs_phy_t));
170310696SDavid.Hollister@Sun.COM }
170410696SDavid.Hollister@Sun.COM 
1705*10743SDavid.Hollister@Sun.COM static void
1706*10743SDavid.Hollister@Sun.COM display_matching_work(struct pmcs_hw ss, uintmax_t index, uintmax_t snum,
1707*10743SDavid.Hollister@Sun.COM     uintmax_t tag_type)
1708*10743SDavid.Hollister@Sun.COM {
1709*10743SDavid.Hollister@Sun.COM 	int		idx;
1710*10743SDavid.Hollister@Sun.COM 	pmcwork_t	work, *wp = &work;
1711*10743SDavid.Hollister@Sun.COM 	uintptr_t	_wp;
1712*10743SDavid.Hollister@Sun.COM 	boolean_t	printed_header = B_FALSE;
1713*10743SDavid.Hollister@Sun.COM 	uint32_t	mask, mask_val, match_val;
1714*10743SDavid.Hollister@Sun.COM 	char		*match_type;
1715*10743SDavid.Hollister@Sun.COM 
1716*10743SDavid.Hollister@Sun.COM 	if (index != UINT_MAX) {
1717*10743SDavid.Hollister@Sun.COM 		match_type = "index";
1718*10743SDavid.Hollister@Sun.COM 		mask = PMCS_TAG_INDEX_MASK;
1719*10743SDavid.Hollister@Sun.COM 		mask_val = index << PMCS_TAG_INDEX_SHIFT;
1720*10743SDavid.Hollister@Sun.COM 		match_val = index;
1721*10743SDavid.Hollister@Sun.COM 	} else if (snum != UINT_MAX) {
1722*10743SDavid.Hollister@Sun.COM 		match_type = "serial number";
1723*10743SDavid.Hollister@Sun.COM 		mask = PMCS_TAG_SERNO_MASK;
1724*10743SDavid.Hollister@Sun.COM 		mask_val = snum << PMCS_TAG_SERNO_SHIFT;
1725*10743SDavid.Hollister@Sun.COM 		match_val = snum;
1726*10743SDavid.Hollister@Sun.COM 	} else {
1727*10743SDavid.Hollister@Sun.COM 		switch (tag_type) {
1728*10743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_NONE:
1729*10743SDavid.Hollister@Sun.COM 			match_type = "tag type NONE";
1730*10743SDavid.Hollister@Sun.COM 			break;
1731*10743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_CBACK:
1732*10743SDavid.Hollister@Sun.COM 			match_type = "tag type CBACK";
1733*10743SDavid.Hollister@Sun.COM 			break;
1734*10743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_WAIT:
1735*10743SDavid.Hollister@Sun.COM 			match_type = "tag type WAIT";
1736*10743SDavid.Hollister@Sun.COM 			break;
1737*10743SDavid.Hollister@Sun.COM 		}
1738*10743SDavid.Hollister@Sun.COM 		mask = PMCS_TAG_TYPE_MASK;
1739*10743SDavid.Hollister@Sun.COM 		mask_val = tag_type << PMCS_TAG_TYPE_SHIFT;
1740*10743SDavid.Hollister@Sun.COM 		match_val = tag_type;
1741*10743SDavid.Hollister@Sun.COM 	}
1742*10743SDavid.Hollister@Sun.COM 
1743*10743SDavid.Hollister@Sun.COM 	_wp = (uintptr_t)ss.work;
1744*10743SDavid.Hollister@Sun.COM 
1745*10743SDavid.Hollister@Sun.COM 	for (idx = 0; idx < ss.max_cmd; idx++, _wp += sizeof (pmcwork_t)) {
1746*10743SDavid.Hollister@Sun.COM 		if (MDB_RD(&work, sizeof (pmcwork_t), _wp) == -1) {
1747*10743SDavid.Hollister@Sun.COM 			NOREAD(pmcwork_t, _wp);
1748*10743SDavid.Hollister@Sun.COM 			continue;
1749*10743SDavid.Hollister@Sun.COM 		}
1750*10743SDavid.Hollister@Sun.COM 
1751*10743SDavid.Hollister@Sun.COM 		if ((work.htag & mask) != mask_val) {
1752*10743SDavid.Hollister@Sun.COM 			continue;
1753*10743SDavid.Hollister@Sun.COM 		}
1754*10743SDavid.Hollister@Sun.COM 
1755*10743SDavid.Hollister@Sun.COM 		if (printed_header == B_FALSE) {
1756*10743SDavid.Hollister@Sun.COM 			if (tag_type) {
1757*10743SDavid.Hollister@Sun.COM 				mdb_printf("\nWork structures matching %s\n\n",
1758*10743SDavid.Hollister@Sun.COM 				    match_type, match_val);
1759*10743SDavid.Hollister@Sun.COM 			} else {
1760*10743SDavid.Hollister@Sun.COM 				mdb_printf("\nWork structures matching %s of "
1761*10743SDavid.Hollister@Sun.COM 				    "0x%x\n\n", match_type, match_val);
1762*10743SDavid.Hollister@Sun.COM 			}
1763*10743SDavid.Hollister@Sun.COM 			mdb_printf("%8s %10s %20s %8s %8s O D\n",
1764*10743SDavid.Hollister@Sun.COM 			    "HTag", "State", "Phy Path", "Target", "Timer");
1765*10743SDavid.Hollister@Sun.COM 			printed_header = B_TRUE;
1766*10743SDavid.Hollister@Sun.COM 		}
1767*10743SDavid.Hollister@Sun.COM 
1768*10743SDavid.Hollister@Sun.COM 		display_one_work(wp, 0, 0);
1769*10743SDavid.Hollister@Sun.COM 	}
1770*10743SDavid.Hollister@Sun.COM 
1771*10743SDavid.Hollister@Sun.COM 	if (!printed_header) {
1772*10743SDavid.Hollister@Sun.COM 		mdb_printf("No work structure matches found\n");
1773*10743SDavid.Hollister@Sun.COM 	}
1774*10743SDavid.Hollister@Sun.COM }
1775*10743SDavid.Hollister@Sun.COM 
1776*10743SDavid.Hollister@Sun.COM static int
1777*10743SDavid.Hollister@Sun.COM pmcs_tag(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1778*10743SDavid.Hollister@Sun.COM {
1779*10743SDavid.Hollister@Sun.COM 	struct	pmcs_hw		ss;
1780*10743SDavid.Hollister@Sun.COM 	uintmax_t		tag_type = UINT_MAX;
1781*10743SDavid.Hollister@Sun.COM 	uintmax_t		snum = UINT_MAX;
1782*10743SDavid.Hollister@Sun.COM 	uintmax_t		index = UINT_MAX;
1783*10743SDavid.Hollister@Sun.COM 	int			args = 0;
1784*10743SDavid.Hollister@Sun.COM 	void			*pmcs_state;
1785*10743SDavid.Hollister@Sun.COM 	char			*state_str;
1786*10743SDavid.Hollister@Sun.COM 	struct dev_info		dip;
1787*10743SDavid.Hollister@Sun.COM 
1788*10743SDavid.Hollister@Sun.COM 	if (!(flags & DCMD_ADDRSPEC)) {
1789*10743SDavid.Hollister@Sun.COM 		pmcs_state = NULL;
1790*10743SDavid.Hollister@Sun.COM 		if (mdb_readvar(&pmcs_state, "pmcs_softc_state") == -1) {
1791*10743SDavid.Hollister@Sun.COM 			mdb_warn("can't read pmcs_softc_state");
1792*10743SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
1793*10743SDavid.Hollister@Sun.COM 		}
1794*10743SDavid.Hollister@Sun.COM 		if (mdb_pwalk_dcmd("genunix`softstate", "pmcs`pmcs_tag", argc,
1795*10743SDavid.Hollister@Sun.COM 		    argv, (uintptr_t)pmcs_state) == -1) {
1796*10743SDavid.Hollister@Sun.COM 			mdb_warn("mdb_pwalk_dcmd failed");
1797*10743SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
1798*10743SDavid.Hollister@Sun.COM 		}
1799*10743SDavid.Hollister@Sun.COM 		return (DCMD_OK);
1800*10743SDavid.Hollister@Sun.COM 	}
1801*10743SDavid.Hollister@Sun.COM 
1802*10743SDavid.Hollister@Sun.COM 	if (mdb_getopts(argc, argv,
1803*10743SDavid.Hollister@Sun.COM 	    'i', MDB_OPT_UINT64, &index,
1804*10743SDavid.Hollister@Sun.COM 	    's', MDB_OPT_UINT64, &snum,
1805*10743SDavid.Hollister@Sun.COM 	    't', MDB_OPT_UINT64, &tag_type) != argc)
1806*10743SDavid.Hollister@Sun.COM 		return (DCMD_USAGE);
1807*10743SDavid.Hollister@Sun.COM 
1808*10743SDavid.Hollister@Sun.COM 	/*
1809*10743SDavid.Hollister@Sun.COM 	 * Count the number of supplied options and make sure they are
1810*10743SDavid.Hollister@Sun.COM 	 * within appropriate ranges.  If they're set to UINT_MAX, that means
1811*10743SDavid.Hollister@Sun.COM 	 * they were not supplied, in which case reset them to 0.
1812*10743SDavid.Hollister@Sun.COM 	 */
1813*10743SDavid.Hollister@Sun.COM 	if (index != UINT_MAX) {
1814*10743SDavid.Hollister@Sun.COM 		args++;
1815*10743SDavid.Hollister@Sun.COM 		if (index > PMCS_TAG_INDEX_MASK) {
1816*10743SDavid.Hollister@Sun.COM 			mdb_warn("Index is out of range\n");
1817*10743SDavid.Hollister@Sun.COM 			return (DCMD_USAGE);
1818*10743SDavid.Hollister@Sun.COM 		}
1819*10743SDavid.Hollister@Sun.COM 	}
1820*10743SDavid.Hollister@Sun.COM 
1821*10743SDavid.Hollister@Sun.COM 	if (tag_type != UINT_MAX) {
1822*10743SDavid.Hollister@Sun.COM 		args++;
1823*10743SDavid.Hollister@Sun.COM 		switch (tag_type) {
1824*10743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_NONE:
1825*10743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_CBACK:
1826*10743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_WAIT:
1827*10743SDavid.Hollister@Sun.COM 			break;
1828*10743SDavid.Hollister@Sun.COM 		default:
1829*10743SDavid.Hollister@Sun.COM 			mdb_warn("Invalid tag type\n");
1830*10743SDavid.Hollister@Sun.COM 			return (DCMD_USAGE);
1831*10743SDavid.Hollister@Sun.COM 		}
1832*10743SDavid.Hollister@Sun.COM 	}
1833*10743SDavid.Hollister@Sun.COM 
1834*10743SDavid.Hollister@Sun.COM 	if (snum != UINT_MAX) {
1835*10743SDavid.Hollister@Sun.COM 		args++;
1836*10743SDavid.Hollister@Sun.COM 		if (snum > (PMCS_TAG_SERNO_MASK >> PMCS_TAG_SERNO_SHIFT)) {
1837*10743SDavid.Hollister@Sun.COM 			mdb_warn("Serial number is out of range\n");
1838*10743SDavid.Hollister@Sun.COM 			return (DCMD_USAGE);
1839*10743SDavid.Hollister@Sun.COM 		}
1840*10743SDavid.Hollister@Sun.COM 	}
1841*10743SDavid.Hollister@Sun.COM 
1842*10743SDavid.Hollister@Sun.COM 	/*
1843*10743SDavid.Hollister@Sun.COM 	 * Make sure 1 and only 1 option is specified
1844*10743SDavid.Hollister@Sun.COM 	 */
1845*10743SDavid.Hollister@Sun.COM 	if ((args == 0) || (args > 1)) {
1846*10743SDavid.Hollister@Sun.COM 		mdb_warn("Exactly one of -i, -s and -t must be specified\n");
1847*10743SDavid.Hollister@Sun.COM 		return (DCMD_USAGE);
1848*10743SDavid.Hollister@Sun.COM 	}
1849*10743SDavid.Hollister@Sun.COM 
1850*10743SDavid.Hollister@Sun.COM 	if (MDB_RD(&ss, sizeof (ss), addr) == -1) {
1851*10743SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
1852*10743SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
1853*10743SDavid.Hollister@Sun.COM 	}
1854*10743SDavid.Hollister@Sun.COM 
1855*10743SDavid.Hollister@Sun.COM 	if (MDB_RD(&dip, sizeof (struct dev_info), ss.dip) == -1) {
1856*10743SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
1857*10743SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
1858*10743SDavid.Hollister@Sun.COM 	}
1859*10743SDavid.Hollister@Sun.COM 
1860*10743SDavid.Hollister@Sun.COM 	/* processing completed */
1861*10743SDavid.Hollister@Sun.COM 
1862*10743SDavid.Hollister@Sun.COM 	if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) ||
1863*10743SDavid.Hollister@Sun.COM 	    (flags & DCMD_LOOPFIRST)) {
1864*10743SDavid.Hollister@Sun.COM 		if ((flags & DCMD_LOOP) && !(flags & DCMD_LOOPFIRST))
1865*10743SDavid.Hollister@Sun.COM 			mdb_printf("\n");
1866*10743SDavid.Hollister@Sun.COM 		mdb_printf("%16s %9s %4s B C  WorkFlags wserno DbgMsk %16s\n",
1867*10743SDavid.Hollister@Sun.COM 		    "Address", "State", "Inst", "DIP");
1868*10743SDavid.Hollister@Sun.COM 		mdb_printf("================================="
1869*10743SDavid.Hollister@Sun.COM 		    "============================================\n");
1870*10743SDavid.Hollister@Sun.COM 	}
1871*10743SDavid.Hollister@Sun.COM 
1872*10743SDavid.Hollister@Sun.COM 	switch (ss.state) {
1873*10743SDavid.Hollister@Sun.COM 	case STATE_NIL:
1874*10743SDavid.Hollister@Sun.COM 		state_str = "Invalid";
1875*10743SDavid.Hollister@Sun.COM 		break;
1876*10743SDavid.Hollister@Sun.COM 	case STATE_PROBING:
1877*10743SDavid.Hollister@Sun.COM 		state_str = "Probing";
1878*10743SDavid.Hollister@Sun.COM 		break;
1879*10743SDavid.Hollister@Sun.COM 	case STATE_RUNNING:
1880*10743SDavid.Hollister@Sun.COM 		state_str = "Running";
1881*10743SDavid.Hollister@Sun.COM 		break;
1882*10743SDavid.Hollister@Sun.COM 	case STATE_UNPROBING:
1883*10743SDavid.Hollister@Sun.COM 		state_str = "Unprobing";
1884*10743SDavid.Hollister@Sun.COM 		break;
1885*10743SDavid.Hollister@Sun.COM 	case STATE_DEAD:
1886*10743SDavid.Hollister@Sun.COM 		state_str = "Dead";
1887*10743SDavid.Hollister@Sun.COM 		break;
1888*10743SDavid.Hollister@Sun.COM 	}
1889*10743SDavid.Hollister@Sun.COM 
1890*10743SDavid.Hollister@Sun.COM 	mdb_printf("%16p %9s %4d %1d %1d 0x%08x 0x%04x 0x%04x %16p\n", addr,
1891*10743SDavid.Hollister@Sun.COM 	    state_str, dip.devi_instance, ss.blocked, ss.configuring,
1892*10743SDavid.Hollister@Sun.COM 	    ss.work_flags, ss.wserno, ss.debug_mask, ss.dip);
1893*10743SDavid.Hollister@Sun.COM 	mdb_printf("\n");
1894*10743SDavid.Hollister@Sun.COM 
1895*10743SDavid.Hollister@Sun.COM 	mdb_inc_indent(4);
1896*10743SDavid.Hollister@Sun.COM 	display_matching_work(ss, index, snum, tag_type);
1897*10743SDavid.Hollister@Sun.COM 	mdb_dec_indent(4);
1898*10743SDavid.Hollister@Sun.COM 	mdb_printf("\n");
1899*10743SDavid.Hollister@Sun.COM 
1900*10743SDavid.Hollister@Sun.COM 	return (DCMD_OK);
1901*10743SDavid.Hollister@Sun.COM }
1902*10743SDavid.Hollister@Sun.COM 
190310696SDavid.Hollister@Sun.COM static int
190410696SDavid.Hollister@Sun.COM pmcs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
190510696SDavid.Hollister@Sun.COM {
190610696SDavid.Hollister@Sun.COM 	struct	pmcs_hw		ss;
190710696SDavid.Hollister@Sun.COM 	uint_t			verbose = FALSE;
190810696SDavid.Hollister@Sun.COM 	uint_t			phy_info = FALSE;
190910696SDavid.Hollister@Sun.COM 	uint_t			hw_info = FALSE;
191010696SDavid.Hollister@Sun.COM 	uint_t			target_info = FALSE;
191110696SDavid.Hollister@Sun.COM 	uint_t			work_info = FALSE;
191210696SDavid.Hollister@Sun.COM 	uint_t			ic_info = FALSE;
191310696SDavid.Hollister@Sun.COM 	uint_t			iport_info = FALSE;
191410696SDavid.Hollister@Sun.COM 	uint_t			waitqs_info = FALSE;
191510696SDavid.Hollister@Sun.COM 	uint_t			tracelog = FALSE;
191610696SDavid.Hollister@Sun.COM 	uint_t			ibq = FALSE;
191710696SDavid.Hollister@Sun.COM 	uint_t			obq = FALSE;
191810696SDavid.Hollister@Sun.COM 	uint_t			tgt_phy_count = FALSE;
1919*10743SDavid.Hollister@Sun.COM 	uint_t			compq = FALSE;
192010696SDavid.Hollister@Sun.COM 	int			rv = DCMD_OK;
192110696SDavid.Hollister@Sun.COM 	void			*pmcs_state;
192210696SDavid.Hollister@Sun.COM 	char			*state_str;
192310696SDavid.Hollister@Sun.COM 	struct dev_info		dip;
192410696SDavid.Hollister@Sun.COM 
192510696SDavid.Hollister@Sun.COM 	if (!(flags & DCMD_ADDRSPEC)) {
192610696SDavid.Hollister@Sun.COM 		pmcs_state = NULL;
192710696SDavid.Hollister@Sun.COM 		if (mdb_readvar(&pmcs_state, "pmcs_softc_state") == -1) {
192810696SDavid.Hollister@Sun.COM 			mdb_warn("can't read pmcs_softc_state");
192910696SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
193010696SDavid.Hollister@Sun.COM 		}
193110696SDavid.Hollister@Sun.COM 		if (mdb_pwalk_dcmd("genunix`softstate", "pmcs`pmcs", argc, argv,
193210696SDavid.Hollister@Sun.COM 		    (uintptr_t)pmcs_state) == -1) {
193310696SDavid.Hollister@Sun.COM 			mdb_warn("mdb_pwalk_dcmd failed");
193410696SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
193510696SDavid.Hollister@Sun.COM 		}
193610696SDavid.Hollister@Sun.COM 		return (DCMD_OK);
193710696SDavid.Hollister@Sun.COM 	}
193810696SDavid.Hollister@Sun.COM 
193910696SDavid.Hollister@Sun.COM 	if (mdb_getopts(argc, argv,
1940*10743SDavid.Hollister@Sun.COM 	    'c', MDB_OPT_SETBITS, TRUE, &compq,
194110696SDavid.Hollister@Sun.COM 	    'h', MDB_OPT_SETBITS, TRUE, &hw_info,
194210696SDavid.Hollister@Sun.COM 	    'i', MDB_OPT_SETBITS, TRUE, &ic_info,
194310696SDavid.Hollister@Sun.COM 	    'I', MDB_OPT_SETBITS, TRUE, &iport_info,
194410696SDavid.Hollister@Sun.COM 	    'l', MDB_OPT_SETBITS, TRUE, &tracelog,
194510696SDavid.Hollister@Sun.COM 	    'p', MDB_OPT_SETBITS, TRUE, &phy_info,
194610696SDavid.Hollister@Sun.COM 	    'q', MDB_OPT_SETBITS, TRUE, &ibq,
194710696SDavid.Hollister@Sun.COM 	    'Q', MDB_OPT_SETBITS, TRUE, &obq,
194810696SDavid.Hollister@Sun.COM 	    't', MDB_OPT_SETBITS, TRUE, &target_info,
194910696SDavid.Hollister@Sun.COM 	    'T', MDB_OPT_SETBITS, TRUE, &tgt_phy_count,
195010696SDavid.Hollister@Sun.COM 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
195110696SDavid.Hollister@Sun.COM 	    'w', MDB_OPT_SETBITS, TRUE, &work_info,
195210696SDavid.Hollister@Sun.COM 	    'W', MDB_OPT_SETBITS, TRUE, &waitqs_info,
195310696SDavid.Hollister@Sun.COM 	    NULL) != argc)
195410696SDavid.Hollister@Sun.COM 		return (DCMD_USAGE);
195510696SDavid.Hollister@Sun.COM 
195610696SDavid.Hollister@Sun.COM 	if (MDB_RD(&ss, sizeof (ss), addr) == -1) {
195710696SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
195810696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
195910696SDavid.Hollister@Sun.COM 	}
196010696SDavid.Hollister@Sun.COM 
196110696SDavid.Hollister@Sun.COM 	if (MDB_RD(&dip, sizeof (struct dev_info), ss.dip) == -1) {
196210696SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
196310696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
196410696SDavid.Hollister@Sun.COM 	}
196510696SDavid.Hollister@Sun.COM 
196610696SDavid.Hollister@Sun.COM 	/*
196710696SDavid.Hollister@Sun.COM 	 * Dumping the trace log is special.  It's global, not per-HBA.
196810696SDavid.Hollister@Sun.COM 	 * Thus, a provided address is ignored.  In addition, other options
196910696SDavid.Hollister@Sun.COM 	 * cannot be specified at the same time.
197010696SDavid.Hollister@Sun.COM 	 */
197110696SDavid.Hollister@Sun.COM 	if (tracelog) {
197210696SDavid.Hollister@Sun.COM 		if (hw_info || ic_info || iport_info || phy_info || work_info ||
1973*10743SDavid.Hollister@Sun.COM 		    target_info || waitqs_info || ibq || obq || tgt_phy_count ||
1974*10743SDavid.Hollister@Sun.COM 		    compq) {
197510696SDavid.Hollister@Sun.COM 			return (DCMD_USAGE);
197610696SDavid.Hollister@Sun.COM 		}
197710696SDavid.Hollister@Sun.COM 
197810696SDavid.Hollister@Sun.COM 		if ((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) {
197910696SDavid.Hollister@Sun.COM 			return (pmcs_dump_tracelog(B_TRUE, dip.devi_instance));
198010696SDavid.Hollister@Sun.COM 		} else if (flags & DCMD_LOOPFIRST) {
198110696SDavid.Hollister@Sun.COM 			return (pmcs_dump_tracelog(B_FALSE, 0));
198210696SDavid.Hollister@Sun.COM 		} else {
198310696SDavid.Hollister@Sun.COM 			return (DCMD_OK);
198410696SDavid.Hollister@Sun.COM 		}
198510696SDavid.Hollister@Sun.COM 	}
198610696SDavid.Hollister@Sun.COM 
198710696SDavid.Hollister@Sun.COM 	/* processing completed */
198810696SDavid.Hollister@Sun.COM 
198910696SDavid.Hollister@Sun.COM 	if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) ||
199010696SDavid.Hollister@Sun.COM 	    (flags & DCMD_LOOPFIRST) || phy_info || target_info || hw_info ||
1991*10743SDavid.Hollister@Sun.COM 	    work_info || waitqs_info || ibq || obq || tgt_phy_count || compq) {
199210696SDavid.Hollister@Sun.COM 		if ((flags & DCMD_LOOP) && !(flags & DCMD_LOOPFIRST))
199310696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
199410696SDavid.Hollister@Sun.COM 		mdb_printf("%16s %9s %4s B C  WorkFlags wserno DbgMsk %16s\n",
199510696SDavid.Hollister@Sun.COM 		    "Address", "State", "Inst", "DIP");
199610696SDavid.Hollister@Sun.COM 		mdb_printf("================================="
199710696SDavid.Hollister@Sun.COM 		    "============================================\n");
199810696SDavid.Hollister@Sun.COM 	}
199910696SDavid.Hollister@Sun.COM 
200010696SDavid.Hollister@Sun.COM 	switch (ss.state) {
200110696SDavid.Hollister@Sun.COM 	case STATE_NIL:
200210696SDavid.Hollister@Sun.COM 		state_str = "Invalid";
200310696SDavid.Hollister@Sun.COM 		break;
200410696SDavid.Hollister@Sun.COM 	case STATE_PROBING:
200510696SDavid.Hollister@Sun.COM 		state_str = "Probing";
200610696SDavid.Hollister@Sun.COM 		break;
200710696SDavid.Hollister@Sun.COM 	case STATE_RUNNING:
200810696SDavid.Hollister@Sun.COM 		state_str = "Running";
200910696SDavid.Hollister@Sun.COM 		break;
201010696SDavid.Hollister@Sun.COM 	case STATE_UNPROBING:
201110696SDavid.Hollister@Sun.COM 		state_str = "Unprobing";
201210696SDavid.Hollister@Sun.COM 		break;
201310696SDavid.Hollister@Sun.COM 	case STATE_DEAD:
201410696SDavid.Hollister@Sun.COM 		state_str = "Dead";
201510696SDavid.Hollister@Sun.COM 		break;
201610696SDavid.Hollister@Sun.COM 	}
201710696SDavid.Hollister@Sun.COM 
201810696SDavid.Hollister@Sun.COM 	mdb_printf("%16p %9s %4d %1d %1d 0x%08x 0x%04x 0x%04x %16p\n", addr,
201910696SDavid.Hollister@Sun.COM 	    state_str, dip.devi_instance, ss.blocked, ss.configuring,
202010696SDavid.Hollister@Sun.COM 	    ss.work_flags, ss.wserno, ss.debug_mask, ss.dip);
202110696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
202210696SDavid.Hollister@Sun.COM 
202310696SDavid.Hollister@Sun.COM 	mdb_inc_indent(4);
202410696SDavid.Hollister@Sun.COM 
202510696SDavid.Hollister@Sun.COM 	if (waitqs_info)
202610696SDavid.Hollister@Sun.COM 		display_waitqs(ss, verbose);
202710696SDavid.Hollister@Sun.COM 
202810696SDavid.Hollister@Sun.COM 	if (hw_info)
202910696SDavid.Hollister@Sun.COM 		display_hwinfo(ss, verbose);
203010696SDavid.Hollister@Sun.COM 
203110696SDavid.Hollister@Sun.COM 	if (phy_info || tgt_phy_count)
203210696SDavid.Hollister@Sun.COM 		display_phys(ss, verbose, NULL, 0, tgt_phy_count);
203310696SDavid.Hollister@Sun.COM 
203410696SDavid.Hollister@Sun.COM 	if (target_info || tgt_phy_count)
203510696SDavid.Hollister@Sun.COM 		display_targets(ss, verbose, tgt_phy_count);
203610696SDavid.Hollister@Sun.COM 
203710696SDavid.Hollister@Sun.COM 	if (work_info)
203810696SDavid.Hollister@Sun.COM 		display_work(ss, verbose);
203910696SDavid.Hollister@Sun.COM 
204010696SDavid.Hollister@Sun.COM 	if (ic_info)
204110696SDavid.Hollister@Sun.COM 		display_ic(ss, verbose);
204210696SDavid.Hollister@Sun.COM 
204310696SDavid.Hollister@Sun.COM 	if (ibq)
204410696SDavid.Hollister@Sun.COM 		display_inbound_queues(ss, verbose);
204510696SDavid.Hollister@Sun.COM 
204610696SDavid.Hollister@Sun.COM 	if (obq)
204710696SDavid.Hollister@Sun.COM 		display_outbound_queues(ss, verbose);
204810696SDavid.Hollister@Sun.COM 
204910696SDavid.Hollister@Sun.COM 	if (iport_info)
205010696SDavid.Hollister@Sun.COM 		display_iport(ss, addr, verbose);
205110696SDavid.Hollister@Sun.COM 
2052*10743SDavid.Hollister@Sun.COM 	if (compq)
2053*10743SDavid.Hollister@Sun.COM 		display_completion_queue(ss);
2054*10743SDavid.Hollister@Sun.COM 
205510696SDavid.Hollister@Sun.COM 	mdb_dec_indent(4);
205610696SDavid.Hollister@Sun.COM 
205710696SDavid.Hollister@Sun.COM 	return (rv);
205810696SDavid.Hollister@Sun.COM }
205910696SDavid.Hollister@Sun.COM 
206010696SDavid.Hollister@Sun.COM void
206110696SDavid.Hollister@Sun.COM pmcs_help()
206210696SDavid.Hollister@Sun.COM {
206310696SDavid.Hollister@Sun.COM 	mdb_printf("Prints summary information about each pmcs instance.\n"
2064*10743SDavid.Hollister@Sun.COM 	    "    -c: Dump the completion queue\n"
206510696SDavid.Hollister@Sun.COM 	    "    -h: Print more detailed hardware information\n"
206610696SDavid.Hollister@Sun.COM 	    "    -i: Print interrupt coalescing information\n"
206710696SDavid.Hollister@Sun.COM 	    "    -I: Print information about each iport\n"
206810696SDavid.Hollister@Sun.COM 	    "    -l: Dump the trace log (cannot be used with other options)\n"
206910696SDavid.Hollister@Sun.COM 	    "    -p: Print information about each attached PHY\n"
207010696SDavid.Hollister@Sun.COM 	    "    -q: Dump inbound queues\n"
207110696SDavid.Hollister@Sun.COM 	    "    -Q: Dump outbound queues\n"
207210696SDavid.Hollister@Sun.COM 	    "    -t: Print information about each known target\n"
207310696SDavid.Hollister@Sun.COM 	    "    -T: Print target and PHY count summary\n"
207410696SDavid.Hollister@Sun.COM 	    "    -w: Dump work structures\n"
207510696SDavid.Hollister@Sun.COM 	    "    -W: List pmcs cmds waiting on various queues\n"
207610696SDavid.Hollister@Sun.COM 	    "    -v: Add verbosity to the above options\n");
207710696SDavid.Hollister@Sun.COM }
207810696SDavid.Hollister@Sun.COM 
2079*10743SDavid.Hollister@Sun.COM void
2080*10743SDavid.Hollister@Sun.COM pmcs_tag_help()
2081*10743SDavid.Hollister@Sun.COM {
2082*10743SDavid.Hollister@Sun.COM 	mdb_printf("Print all work structures by matching the tag.\n"
2083*10743SDavid.Hollister@Sun.COM 	    "    -i index:        Match tag index (0x000 - 0xfff)\n"
2084*10743SDavid.Hollister@Sun.COM 	    "    -s serialnumber: Match serial number (0x0000 - 0xffff)\n"
2085*10743SDavid.Hollister@Sun.COM 	    "    -t tagtype:      Match tag type [NONE(1), CBACK(2), "
2086*10743SDavid.Hollister@Sun.COM 	    "WAIT(3)]\n");
2087*10743SDavid.Hollister@Sun.COM }
2088*10743SDavid.Hollister@Sun.COM 
208910696SDavid.Hollister@Sun.COM static const mdb_dcmd_t dcmds[] = {
2090*10743SDavid.Hollister@Sun.COM 	{ "pmcs", "?[-chiIpQqtTwWv] | -l", "print pmcs information",
209110696SDavid.Hollister@Sun.COM 	    pmcs_dcmd, pmcs_help
209210696SDavid.Hollister@Sun.COM 	},
2093*10743SDavid.Hollister@Sun.COM 	{ "pmcs_tag", "?[-t tagtype|-s serialnum|-i index]",
2094*10743SDavid.Hollister@Sun.COM 	    "Find work structures by tag type, serial number or index",
2095*10743SDavid.Hollister@Sun.COM 	    pmcs_tag, pmcs_tag_help
2096*10743SDavid.Hollister@Sun.COM 	},
209710696SDavid.Hollister@Sun.COM 	{ NULL }
209810696SDavid.Hollister@Sun.COM };
209910696SDavid.Hollister@Sun.COM 
210010696SDavid.Hollister@Sun.COM static const mdb_walker_t walkers[] = {
210110696SDavid.Hollister@Sun.COM 	{ "pmcs_targets", "walk target structures",
210210696SDavid.Hollister@Sun.COM 		targets_walk_i, targets_walk_s, targets_walk_f },
210310696SDavid.Hollister@Sun.COM 	{ "pmcs_phys", "walk PHY structures",
210410696SDavid.Hollister@Sun.COM 		phy_walk_i, phy_walk_s, phy_walk_f },
210510696SDavid.Hollister@Sun.COM 	{ NULL }
210610696SDavid.Hollister@Sun.COM };
210710696SDavid.Hollister@Sun.COM 
210810696SDavid.Hollister@Sun.COM static const mdb_modinfo_t modinfo = {
210910696SDavid.Hollister@Sun.COM 	MDB_API_VERSION, dcmds, walkers
211010696SDavid.Hollister@Sun.COM };
211110696SDavid.Hollister@Sun.COM 
211210696SDavid.Hollister@Sun.COM const mdb_modinfo_t *
211310696SDavid.Hollister@Sun.COM _mdb_init(void)
211410696SDavid.Hollister@Sun.COM {
211510696SDavid.Hollister@Sun.COM 	return (&modinfo);
211610696SDavid.Hollister@Sun.COM }
2117