xref: /onnv-gate/usr/src/cmd/mdb/common/modules/pmcs/pmcs.c (revision 10755:4e696bc2e825)
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);
4210743SDavid.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 
21110743SDavid.Hollister@Sun.COM static void
21210743SDavid.Hollister@Sun.COM display_completion_queue(struct pmcs_hw ss)
21310743SDavid.Hollister@Sun.COM {
21410743SDavid.Hollister@Sun.COM 	pmcs_iocomp_cb_t ccb, *ccbp;
21510743SDavid.Hollister@Sun.COM 	pmcwork_t work;
21610743SDavid.Hollister@Sun.COM 
21710743SDavid.Hollister@Sun.COM 	if (ss.iocomp_cb_head == NULL) {
21810743SDavid.Hollister@Sun.COM 		mdb_printf("Completion queue is empty.\n");
21910743SDavid.Hollister@Sun.COM 		return;
22010743SDavid.Hollister@Sun.COM 	}
22110743SDavid.Hollister@Sun.COM 
22210743SDavid.Hollister@Sun.COM 	ccbp = ss.iocomp_cb_head;
22310743SDavid.Hollister@Sun.COM 	mdb_printf("%8s %10s %20s %8s %8s O D\n",
22410743SDavid.Hollister@Sun.COM 	    "HTag", "State", "Phy Path", "Target", "Timer");
22510743SDavid.Hollister@Sun.COM 
22610743SDavid.Hollister@Sun.COM 	while (ccbp) {
22710743SDavid.Hollister@Sun.COM 		if (mdb_vread(&ccb, sizeof (pmcs_iocomp_cb_t),
22810743SDavid.Hollister@Sun.COM 		    (uintptr_t)ccbp) != sizeof (pmcs_iocomp_cb_t)) {
22910743SDavid.Hollister@Sun.COM 			mdb_warn("Unable to read completion queue entry\n");
23010743SDavid.Hollister@Sun.COM 			return;
23110743SDavid.Hollister@Sun.COM 		}
23210743SDavid.Hollister@Sun.COM 
23310743SDavid.Hollister@Sun.COM 		if (mdb_vread(&work, sizeof (pmcwork_t), (uintptr_t)ccb.pwrk)
23410743SDavid.Hollister@Sun.COM 		    != sizeof (pmcwork_t)) {
23510743SDavid.Hollister@Sun.COM 			mdb_warn("Unable to read work structure\n");
23610743SDavid.Hollister@Sun.COM 			return;
23710743SDavid.Hollister@Sun.COM 		}
23810743SDavid.Hollister@Sun.COM 
23910743SDavid.Hollister@Sun.COM 		/*
24010743SDavid.Hollister@Sun.COM 		 * Only print the work structure if it's still active.  If
24110743SDavid.Hollister@Sun.COM 		 * it's not, it's been completed since we started looking at
24210743SDavid.Hollister@Sun.COM 		 * it.
24310743SDavid.Hollister@Sun.COM 		 */
24410743SDavid.Hollister@Sun.COM 		if (work.state != PMCS_WORK_STATE_NIL) {
24510743SDavid.Hollister@Sun.COM 			display_one_work(&work, 0, 0);
24610743SDavid.Hollister@Sun.COM 		}
24710743SDavid.Hollister@Sun.COM 		ccbp = ccb.next;
24810743SDavid.Hollister@Sun.COM 	}
24910743SDavid.Hollister@Sun.COM }
25010743SDavid.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 		/*
335*10755SJesse.Butler@Sun.COM 		 * It has to be new or assigned to be of interest.
33610696SDavid.Hollister@Sun.COM 		 */
337*10755SJesse.Butler@Sun.COM 		if (xs.new == 0 && xs.assigned == 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");
381*10755SJesse.Butler@Sun.COM 			}
382*10755SJesse.Butler@Sun.COM 			if (xs.assigned) {
38310696SDavid.Hollister@Sun.COM 				mdb_printf(" assigned");
38410696SDavid.Hollister@Sun.COM 			}
38510696SDavid.Hollister@Sun.COM 			if (xs.draining) {
38610696SDavid.Hollister@Sun.COM 				mdb_printf(" draining");
38710696SDavid.Hollister@Sun.COM 			}
38810696SDavid.Hollister@Sun.COM 			if (xs.reset_wait) {
38910696SDavid.Hollister@Sun.COM 				mdb_printf(" reset_wait");
39010696SDavid.Hollister@Sun.COM 			}
39110696SDavid.Hollister@Sun.COM 			if (xs.resetting) {
39210696SDavid.Hollister@Sun.COM 				mdb_printf(" resetting");
39310696SDavid.Hollister@Sun.COM 			}
39410696SDavid.Hollister@Sun.COM 			if (xs.recover_wait) {
39510696SDavid.Hollister@Sun.COM 				mdb_printf(" recover_wait");
39610696SDavid.Hollister@Sun.COM 			}
39710696SDavid.Hollister@Sun.COM 			if (xs.recovering) {
39810696SDavid.Hollister@Sun.COM 				mdb_printf(" recovering");
39910696SDavid.Hollister@Sun.COM 			}
40010696SDavid.Hollister@Sun.COM 			if (xs.event_recovery) {
40110696SDavid.Hollister@Sun.COM 				mdb_printf(" event recovery");
40210696SDavid.Hollister@Sun.COM 			}
40310696SDavid.Hollister@Sun.COM 			if (xs.special_running) {
40410696SDavid.Hollister@Sun.COM 				mdb_printf(" special_active");
40510696SDavid.Hollister@Sun.COM 			}
40610696SDavid.Hollister@Sun.COM 			if (xs.ncq) {
40710696SDavid.Hollister@Sun.COM 				mdb_printf(" ncq_tagmap=0x%x qdepth=%d",
40810696SDavid.Hollister@Sun.COM 				    xs.tagmap, xs.qdepth);
40910696SDavid.Hollister@Sun.COM 			} else if (xs.pio) {
41010696SDavid.Hollister@Sun.COM 				mdb_printf(" pio");
41110696SDavid.Hollister@Sun.COM 			}
41210696SDavid.Hollister@Sun.COM 		}
41310696SDavid.Hollister@Sun.COM 
41410696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
41510696SDavid.Hollister@Sun.COM 	}
41610696SDavid.Hollister@Sun.COM 
41710696SDavid.Hollister@Sun.COM 	if (!totals_only) {
41810696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
41910696SDavid.Hollister@Sun.COM 	}
42010696SDavid.Hollister@Sun.COM 
42110696SDavid.Hollister@Sun.COM 	mdb_printf("%19s %d (%d SAS + %d SATA + %d SMP)\n",
42210696SDavid.Hollister@Sun.COM 	    "Configured targets:", (sas_targets + sata_targets + smp_targets),
42310696SDavid.Hollister@Sun.COM 	    sas_targets, sata_targets, smp_targets);
42410696SDavid.Hollister@Sun.COM }
42510696SDavid.Hollister@Sun.COM 
42610743SDavid.Hollister@Sun.COM static char *
42710743SDavid.Hollister@Sun.COM work_state_to_string(uint32_t state)
42810743SDavid.Hollister@Sun.COM {
42910743SDavid.Hollister@Sun.COM 	char *state_string;
43010743SDavid.Hollister@Sun.COM 
43110743SDavid.Hollister@Sun.COM 	switch (state) {
43210743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_NIL:
43310743SDavid.Hollister@Sun.COM 		state_string = "Free";
43410743SDavid.Hollister@Sun.COM 		break;
43510743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_READY:
43610743SDavid.Hollister@Sun.COM 		state_string = "Ready";
43710743SDavid.Hollister@Sun.COM 		break;
43810743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_ONCHIP:
43910743SDavid.Hollister@Sun.COM 		state_string = "On Chip";
44010743SDavid.Hollister@Sun.COM 		break;
44110743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_INTR:
44210743SDavid.Hollister@Sun.COM 		state_string = "In Intr";
44310743SDavid.Hollister@Sun.COM 		break;
44410743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_IOCOMPQ:
44510743SDavid.Hollister@Sun.COM 		state_string = "I/O Comp";
44610743SDavid.Hollister@Sun.COM 		break;
44710743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_ABORTED:
44810743SDavid.Hollister@Sun.COM 		state_string = "I/O Aborted";
44910743SDavid.Hollister@Sun.COM 		break;
45010743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_TIMED_OUT:
45110743SDavid.Hollister@Sun.COM 		state_string = "I/O Timed Out";
45210743SDavid.Hollister@Sun.COM 		break;
45310743SDavid.Hollister@Sun.COM 	default:
45410743SDavid.Hollister@Sun.COM 		state_string = "INVALID";
45510743SDavid.Hollister@Sun.COM 		break;
45610743SDavid.Hollister@Sun.COM 	}
45710743SDavid.Hollister@Sun.COM 
45810743SDavid.Hollister@Sun.COM 	return (state_string);
45910743SDavid.Hollister@Sun.COM }
46010743SDavid.Hollister@Sun.COM 
46110743SDavid.Hollister@Sun.COM static void
46210743SDavid.Hollister@Sun.COM display_one_work(pmcwork_t *wp, int verbose, int idx)
46310743SDavid.Hollister@Sun.COM {
46410743SDavid.Hollister@Sun.COM 	char		*state, *last_state;
46510743SDavid.Hollister@Sun.COM 	char		*path;
46610743SDavid.Hollister@Sun.COM 	pmcs_xscsi_t	xs;
46710743SDavid.Hollister@Sun.COM 	pmcs_phy_t	phy;
46810743SDavid.Hollister@Sun.COM 	int		tgt;
46910743SDavid.Hollister@Sun.COM 
47010743SDavid.Hollister@Sun.COM 	state = work_state_to_string(wp->state);
47110743SDavid.Hollister@Sun.COM 	last_state = work_state_to_string(wp->last_state);
47210743SDavid.Hollister@Sun.COM 
47310743SDavid.Hollister@Sun.COM 	if (wp->ssp_event && wp->ssp_event != 0xffffffff) {
47410743SDavid.Hollister@Sun.COM 		mdb_printf("SSP event 0x%x", wp->ssp_event);
47510743SDavid.Hollister@Sun.COM 	}
47610743SDavid.Hollister@Sun.COM 
47710743SDavid.Hollister@Sun.COM 	tgt = -1;
47810743SDavid.Hollister@Sun.COM 	if (wp->xp) {
47910743SDavid.Hollister@Sun.COM 		if (MDB_RD(&xs, sizeof (xs), wp->xp) == -1) {
48010743SDavid.Hollister@Sun.COM 			NOREAD(pmcs_xscsi_t, wp->xp);
48110743SDavid.Hollister@Sun.COM 		} else {
48210743SDavid.Hollister@Sun.COM 			tgt = xs.target_num;
48310743SDavid.Hollister@Sun.COM 		}
48410743SDavid.Hollister@Sun.COM 	}
48510743SDavid.Hollister@Sun.COM 	if (wp->phy) {
48610743SDavid.Hollister@Sun.COM 		if (MDB_RD(&phy, sizeof (phy), wp->phy) == -1) {
48710743SDavid.Hollister@Sun.COM 			NOREAD(pmcs_phy_t, wp->phy);
48810743SDavid.Hollister@Sun.COM 		}
48910743SDavid.Hollister@Sun.COM 		path = phy.path;
49010743SDavid.Hollister@Sun.COM 	} else {
49110743SDavid.Hollister@Sun.COM 		path = "N/A";
49210743SDavid.Hollister@Sun.COM 	}
49310743SDavid.Hollister@Sun.COM 
49410743SDavid.Hollister@Sun.COM 	if (verbose) {
49510743SDavid.Hollister@Sun.COM 		mdb_printf("%4d ", idx);
49610743SDavid.Hollister@Sun.COM 	}
49710743SDavid.Hollister@Sun.COM 	if (tgt == -1) {
49810743SDavid.Hollister@Sun.COM 		mdb_printf("%08x %10s %20s      N/A %8u %1d %1d ",
49910743SDavid.Hollister@Sun.COM 		    wp->htag, state, path, wp->timer,
50010743SDavid.Hollister@Sun.COM 		    wp->onwire, wp->dead);
50110743SDavid.Hollister@Sun.COM 	} else {
50210743SDavid.Hollister@Sun.COM 		mdb_printf("%08x %10s %20s %8d %8u %1d %1d ",
50310743SDavid.Hollister@Sun.COM 		    wp->htag, state, path, tgt, wp->timer,
50410743SDavid.Hollister@Sun.COM 		    wp->onwire, wp->dead);
50510743SDavid.Hollister@Sun.COM 	}
50610743SDavid.Hollister@Sun.COM 	if (verbose) {
50710743SDavid.Hollister@Sun.COM 		mdb_printf("%08x %10s 0x%016p 0x%016p\n",
50810743SDavid.Hollister@Sun.COM 		    wp->last_htag, last_state, wp->last_phy, wp->last_xp);
50910743SDavid.Hollister@Sun.COM 	} else {
51010743SDavid.Hollister@Sun.COM 		mdb_printf("\n");
51110743SDavid.Hollister@Sun.COM 	}
51210743SDavid.Hollister@Sun.COM }
51310743SDavid.Hollister@Sun.COM 
51410696SDavid.Hollister@Sun.COM static void
51510696SDavid.Hollister@Sun.COM display_work(struct pmcs_hw m, int verbose)
51610696SDavid.Hollister@Sun.COM {
51710696SDavid.Hollister@Sun.COM 	int		idx;
51810743SDavid.Hollister@Sun.COM 	boolean_t	header_printed = B_FALSE;
51910696SDavid.Hollister@Sun.COM 	pmcwork_t	work, *wp = &work;
52010696SDavid.Hollister@Sun.COM 	uintptr_t	_wp;
52110696SDavid.Hollister@Sun.COM 
52210696SDavid.Hollister@Sun.COM 	mdb_printf("\nActive Work structure information:\n");
52310696SDavid.Hollister@Sun.COM 	mdb_printf("----------------------------------\n");
52410696SDavid.Hollister@Sun.COM 
52510696SDavid.Hollister@Sun.COM 	_wp = (uintptr_t)m.work;
52610696SDavid.Hollister@Sun.COM 
52710696SDavid.Hollister@Sun.COM 	for (idx = 0; idx < m.max_cmd; idx++, _wp += sizeof (pmcwork_t)) {
52810696SDavid.Hollister@Sun.COM 		if (MDB_RD(&work, sizeof (pmcwork_t), _wp) == -1) {
52910696SDavid.Hollister@Sun.COM 			NOREAD(pmcwork_t, _wp);
53010696SDavid.Hollister@Sun.COM 			continue;
53110696SDavid.Hollister@Sun.COM 		}
53210743SDavid.Hollister@Sun.COM 
53310743SDavid.Hollister@Sun.COM 		if (!verbose && (wp->htag == PMCS_TAG_TYPE_FREE)) {
53410696SDavid.Hollister@Sun.COM 			continue;
53510696SDavid.Hollister@Sun.COM 		}
53610743SDavid.Hollister@Sun.COM 
53710743SDavid.Hollister@Sun.COM 		if (header_printed == B_FALSE) {
53810743SDavid.Hollister@Sun.COM 			if (verbose) {
53910743SDavid.Hollister@Sun.COM 				mdb_printf("%4s ", "Idx");
54010743SDavid.Hollister@Sun.COM 			}
54110743SDavid.Hollister@Sun.COM 			mdb_printf("%8s %10s %20s %8s %8s O D ",
54210696SDavid.Hollister@Sun.COM 			    "HTag", "State", "Phy Path", "Target", "Timer");
54310743SDavid.Hollister@Sun.COM 			if (verbose) {
54410743SDavid.Hollister@Sun.COM 				mdb_printf("%8s %10s %18s %18s\n", "LastHTAG",
54510743SDavid.Hollister@Sun.COM 				    "LastState", "LastPHY", "LastTgt");
54610743SDavid.Hollister@Sun.COM 			} else {
54710743SDavid.Hollister@Sun.COM 				mdb_printf("\n");
54810743SDavid.Hollister@Sun.COM 			}
54910743SDavid.Hollister@Sun.COM 			header_printed = B_TRUE;
55010696SDavid.Hollister@Sun.COM 		}
55110743SDavid.Hollister@Sun.COM 
55210743SDavid.Hollister@Sun.COM 		display_one_work(wp, verbose, idx);
55310696SDavid.Hollister@Sun.COM 	}
55410696SDavid.Hollister@Sun.COM }
55510696SDavid.Hollister@Sun.COM 
55610696SDavid.Hollister@Sun.COM static void
55710743SDavid.Hollister@Sun.COM print_spcmd(pmcs_cmd_t *sp, void *kaddr, int printhdr, int verbose)
55810696SDavid.Hollister@Sun.COM {
55910743SDavid.Hollister@Sun.COM 	int cdb_size, idx;
56010743SDavid.Hollister@Sun.COM 	struct scsi_pkt pkt;
56110743SDavid.Hollister@Sun.COM 	uchar_t cdb[256];
56210743SDavid.Hollister@Sun.COM 
56310696SDavid.Hollister@Sun.COM 	if (printhdr) {
56410743SDavid.Hollister@Sun.COM 		if (verbose) {
56510743SDavid.Hollister@Sun.COM 			mdb_printf("%16s %16s %16s %8s %s CDB\n", "Command",
56610743SDavid.Hollister@Sun.COM 			    "SCSA pkt", "DMA Chunks", "HTAG", "SATL Tag");
56710743SDavid.Hollister@Sun.COM 		} else {
56810743SDavid.Hollister@Sun.COM 			mdb_printf("%16s %16s %16s %8s %s\n", "Command",
56910743SDavid.Hollister@Sun.COM 			    "SCSA pkt", "DMA Chunks", "HTAG", "SATL Tag");
57010743SDavid.Hollister@Sun.COM 		}
57110696SDavid.Hollister@Sun.COM 	}
57210743SDavid.Hollister@Sun.COM 
57310743SDavid.Hollister@Sun.COM 	mdb_printf("%16p %16p %16p %08x %08x ",
57410696SDavid.Hollister@Sun.COM 	    kaddr, sp->cmd_pkt, sp->cmd_clist, sp->cmd_tag, sp->cmd_satltag);
57510743SDavid.Hollister@Sun.COM 
57610743SDavid.Hollister@Sun.COM 	/*
57710743SDavid.Hollister@Sun.COM 	 * If we're printing verbose, dump the CDB as well.
57810743SDavid.Hollister@Sun.COM 	 */
57910743SDavid.Hollister@Sun.COM 	if (verbose) {
58010743SDavid.Hollister@Sun.COM 		if (sp->cmd_pkt) {
58110743SDavid.Hollister@Sun.COM 			if (mdb_vread(&pkt, sizeof (struct scsi_pkt),
58210743SDavid.Hollister@Sun.COM 			    (uintptr_t)sp->cmd_pkt) !=
58310743SDavid.Hollister@Sun.COM 			    sizeof (struct scsi_pkt)) {
58410743SDavid.Hollister@Sun.COM 				mdb_warn("Unable to read SCSI pkt\n");
58510743SDavid.Hollister@Sun.COM 				return;
58610743SDavid.Hollister@Sun.COM 			}
58710743SDavid.Hollister@Sun.COM 			cdb_size = pkt.pkt_cdblen;
58810743SDavid.Hollister@Sun.COM 			if (mdb_vread(&cdb[0], cdb_size,
58910743SDavid.Hollister@Sun.COM 			    (uintptr_t)pkt.pkt_cdbp) != cdb_size) {
59010743SDavid.Hollister@Sun.COM 				mdb_warn("Unable to read CDB\n");
59110743SDavid.Hollister@Sun.COM 				return;
59210743SDavid.Hollister@Sun.COM 			}
59310743SDavid.Hollister@Sun.COM 
59410743SDavid.Hollister@Sun.COM 			for (idx = 0; idx < cdb_size; idx++) {
59510743SDavid.Hollister@Sun.COM 				mdb_printf("%02x ", cdb[idx]);
59610743SDavid.Hollister@Sun.COM 			}
59710743SDavid.Hollister@Sun.COM 		} else {
59810743SDavid.Hollister@Sun.COM 			mdb_printf("N/A");
59910743SDavid.Hollister@Sun.COM 		}
60010743SDavid.Hollister@Sun.COM 
60110743SDavid.Hollister@Sun.COM 		mdb_printf("\n");
60210743SDavid.Hollister@Sun.COM 	} else {
60310743SDavid.Hollister@Sun.COM 		mdb_printf("\n");
60410743SDavid.Hollister@Sun.COM 	}
60510696SDavid.Hollister@Sun.COM }
60610696SDavid.Hollister@Sun.COM 
60710696SDavid.Hollister@Sun.COM /*ARGSUSED1*/
60810696SDavid.Hollister@Sun.COM static void
60910696SDavid.Hollister@Sun.COM display_waitqs(struct pmcs_hw m, int verbose)
61010696SDavid.Hollister@Sun.COM {
61110696SDavid.Hollister@Sun.COM 	pmcs_cmd_t	*sp, s;
61210696SDavid.Hollister@Sun.COM 	pmcs_xscsi_t	xs;
61310696SDavid.Hollister@Sun.COM 	int		first, i;
61410696SDavid.Hollister@Sun.COM 	int		max_dev = m.max_dev;
61510696SDavid.Hollister@Sun.COM 
61610696SDavid.Hollister@Sun.COM 	sp = m.dq.stqh_first;
61710696SDavid.Hollister@Sun.COM 	first = 1;
61810696SDavid.Hollister@Sun.COM 	while (sp) {
61910696SDavid.Hollister@Sun.COM 		if (first) {
62010696SDavid.Hollister@Sun.COM 			mdb_printf("\nDead Command Queue:\n");
62110696SDavid.Hollister@Sun.COM 			mdb_printf("---------------------------\n");
62210696SDavid.Hollister@Sun.COM 		}
62310696SDavid.Hollister@Sun.COM 		if (MDB_RD(&s, sizeof (s), sp) == -1) {
62410696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_cmd_t, sp);
62510696SDavid.Hollister@Sun.COM 			break;
62610696SDavid.Hollister@Sun.COM 		}
62710743SDavid.Hollister@Sun.COM 		print_spcmd(&s, sp, first, verbose);
62810696SDavid.Hollister@Sun.COM 		sp = s.cmd_next.stqe_next;
62910696SDavid.Hollister@Sun.COM 		first = 0;
63010696SDavid.Hollister@Sun.COM 	}
63110696SDavid.Hollister@Sun.COM 
63210696SDavid.Hollister@Sun.COM 	sp = m.cq.stqh_first;
63310696SDavid.Hollister@Sun.COM 	first = 1;
63410696SDavid.Hollister@Sun.COM 	while (sp) {
63510696SDavid.Hollister@Sun.COM 		if (first) {
63610696SDavid.Hollister@Sun.COM 			mdb_printf("\nCompletion Command Queue:\n");
63710696SDavid.Hollister@Sun.COM 			mdb_printf("---------------------------\n");
63810696SDavid.Hollister@Sun.COM 		}
63910696SDavid.Hollister@Sun.COM 		if (MDB_RD(&s, sizeof (s), sp) == -1) {
64010696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_cmd_t, sp);
64110696SDavid.Hollister@Sun.COM 			break;
64210696SDavid.Hollister@Sun.COM 		}
64310743SDavid.Hollister@Sun.COM 		print_spcmd(&s, sp, first, verbose);
64410696SDavid.Hollister@Sun.COM 		sp = s.cmd_next.stqe_next;
64510696SDavid.Hollister@Sun.COM 		first = 0;
64610696SDavid.Hollister@Sun.COM 	}
64710696SDavid.Hollister@Sun.COM 
64810696SDavid.Hollister@Sun.COM 
64910696SDavid.Hollister@Sun.COM 	if (targets == NULL) {
65010696SDavid.Hollister@Sun.COM 		targets = mdb_alloc(sizeof (targets) * max_dev, UM_SLEEP);
65110696SDavid.Hollister@Sun.COM 	}
65210696SDavid.Hollister@Sun.COM 
65310696SDavid.Hollister@Sun.COM 	if (MDB_RD(targets, sizeof (targets) * max_dev, m.targets) == -1) {
65410696SDavid.Hollister@Sun.COM 		NOREAD(targets, m.targets);
65510696SDavid.Hollister@Sun.COM 		return;
65610696SDavid.Hollister@Sun.COM 	}
65710696SDavid.Hollister@Sun.COM 
65810696SDavid.Hollister@Sun.COM 	for (i = 0; i < max_dev; i++) {
65910696SDavid.Hollister@Sun.COM 		if (targets[i] == NULL) {
66010696SDavid.Hollister@Sun.COM 			continue;
66110696SDavid.Hollister@Sun.COM 		}
66210696SDavid.Hollister@Sun.COM 		if (MDB_RD(&xs, sizeof (xs), targets[i]) == -1) {
66310696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_xscsi_t, targets[i]);
66410696SDavid.Hollister@Sun.COM 			continue;
66510696SDavid.Hollister@Sun.COM 		}
66610696SDavid.Hollister@Sun.COM 		sp = xs.wq.stqh_first;
66710696SDavid.Hollister@Sun.COM 		first = 1;
66810696SDavid.Hollister@Sun.COM 		while (sp) {
66910696SDavid.Hollister@Sun.COM 			if (first) {
67010696SDavid.Hollister@Sun.COM 				mdb_printf("\nTarget %u Wait Queue:\n",
67110696SDavid.Hollister@Sun.COM 				    xs.target_num);
67210696SDavid.Hollister@Sun.COM 				mdb_printf("---------------------------\n");
67310696SDavid.Hollister@Sun.COM 			}
67410696SDavid.Hollister@Sun.COM 			if (MDB_RD(&s, sizeof (s), sp) == -1) {
67510696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_cmd_t, sp);
67610696SDavid.Hollister@Sun.COM 				break;
67710696SDavid.Hollister@Sun.COM 			}
67810743SDavid.Hollister@Sun.COM 			print_spcmd(&s, sp, first, verbose);
67910696SDavid.Hollister@Sun.COM 			sp = s.cmd_next.stqe_next;
68010696SDavid.Hollister@Sun.COM 			first = 0;
68110696SDavid.Hollister@Sun.COM 		}
68210696SDavid.Hollister@Sun.COM 		sp = xs.aq.stqh_first;
68310696SDavid.Hollister@Sun.COM 		first = 1;
68410696SDavid.Hollister@Sun.COM 		while (sp) {
68510696SDavid.Hollister@Sun.COM 			if (first) {
68610696SDavid.Hollister@Sun.COM 				mdb_printf("\nTarget %u Active Queue:\n",
68710696SDavid.Hollister@Sun.COM 				    xs.target_num);
68810696SDavid.Hollister@Sun.COM 				mdb_printf("---------------------------\n");
68910696SDavid.Hollister@Sun.COM 			}
69010696SDavid.Hollister@Sun.COM 			if (MDB_RD(&s, sizeof (s), sp) == -1) {
69110696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_cmd_t, sp);
69210696SDavid.Hollister@Sun.COM 				break;
69310696SDavid.Hollister@Sun.COM 			}
69410743SDavid.Hollister@Sun.COM 			print_spcmd(&s, sp, first, verbose);
69510696SDavid.Hollister@Sun.COM 			sp = s.cmd_next.stqe_next;
69610696SDavid.Hollister@Sun.COM 			first = 0;
69710696SDavid.Hollister@Sun.COM 		}
69810696SDavid.Hollister@Sun.COM 		sp = xs.sq.stqh_first;
69910696SDavid.Hollister@Sun.COM 		first = 1;
70010696SDavid.Hollister@Sun.COM 		while (sp) {
70110696SDavid.Hollister@Sun.COM 			if (first) {
70210696SDavid.Hollister@Sun.COM 				mdb_printf("\nTarget %u Special Queue:\n",
70310696SDavid.Hollister@Sun.COM 				    xs.target_num);
70410696SDavid.Hollister@Sun.COM 				mdb_printf("---------------------------\n");
70510696SDavid.Hollister@Sun.COM 			}
70610696SDavid.Hollister@Sun.COM 			if (MDB_RD(&s, sizeof (s), sp) == -1) {
70710696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_cmd_t, sp);
70810696SDavid.Hollister@Sun.COM 				break;
70910696SDavid.Hollister@Sun.COM 			}
71010743SDavid.Hollister@Sun.COM 			print_spcmd(&s, sp, first, verbose);
71110696SDavid.Hollister@Sun.COM 			sp = s.cmd_next.stqe_next;
71210696SDavid.Hollister@Sun.COM 			first = 0;
71310696SDavid.Hollister@Sun.COM 		}
71410696SDavid.Hollister@Sun.COM 	}
71510696SDavid.Hollister@Sun.COM }
71610696SDavid.Hollister@Sun.COM 
71710696SDavid.Hollister@Sun.COM static char *
71810696SDavid.Hollister@Sun.COM ibq_type(int qnum)
71910696SDavid.Hollister@Sun.COM {
72010696SDavid.Hollister@Sun.COM 	if (qnum < 0 || qnum >= PMCS_NIQ) {
72110696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
72210696SDavid.Hollister@Sun.COM 	}
72310696SDavid.Hollister@Sun.COM 
72410696SDavid.Hollister@Sun.COM 	if (qnum < PMCS_IQ_OTHER) {
72510696SDavid.Hollister@Sun.COM 		return ("I/O");
72610696SDavid.Hollister@Sun.COM 	}
72710696SDavid.Hollister@Sun.COM 
72810696SDavid.Hollister@Sun.COM 	return ("Other");
72910696SDavid.Hollister@Sun.COM }
73010696SDavid.Hollister@Sun.COM 
73110696SDavid.Hollister@Sun.COM static char *
73210696SDavid.Hollister@Sun.COM obq_type(int qnum)
73310696SDavid.Hollister@Sun.COM {
73410696SDavid.Hollister@Sun.COM 	switch (qnum) {
73510696SDavid.Hollister@Sun.COM 	case PMCS_OQ_IODONE:
73610696SDavid.Hollister@Sun.COM 		return ("I/O");
73710696SDavid.Hollister@Sun.COM 		break;
73810696SDavid.Hollister@Sun.COM 	case PMCS_OQ_GENERAL:
73910696SDavid.Hollister@Sun.COM 		return ("General");
74010696SDavid.Hollister@Sun.COM 		break;
74110696SDavid.Hollister@Sun.COM 	case PMCS_OQ_EVENTS:
74210696SDavid.Hollister@Sun.COM 		return ("Events");
74310696SDavid.Hollister@Sun.COM 		break;
74410696SDavid.Hollister@Sun.COM 	default:
74510696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
74610696SDavid.Hollister@Sun.COM 	}
74710696SDavid.Hollister@Sun.COM }
74810696SDavid.Hollister@Sun.COM 
74910696SDavid.Hollister@Sun.COM static char *
75010696SDavid.Hollister@Sun.COM iomb_cat(uint32_t cat)
75110696SDavid.Hollister@Sun.COM {
75210696SDavid.Hollister@Sun.COM 	switch (cat) {
75310696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_NET:
75410696SDavid.Hollister@Sun.COM 		return ("NET");
75510696SDavid.Hollister@Sun.COM 		break;
75610696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_FC:
75710696SDavid.Hollister@Sun.COM 		return ("FC");
75810696SDavid.Hollister@Sun.COM 		break;
75910696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_SAS:
76010696SDavid.Hollister@Sun.COM 		return ("SAS");
76110696SDavid.Hollister@Sun.COM 		break;
76210696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_SCSI:
76310696SDavid.Hollister@Sun.COM 		return ("SCSI");
76410696SDavid.Hollister@Sun.COM 		break;
76510696SDavid.Hollister@Sun.COM 	default:
76610696SDavid.Hollister@Sun.COM 		return ("???");
76710696SDavid.Hollister@Sun.COM 	}
76810696SDavid.Hollister@Sun.COM }
76910696SDavid.Hollister@Sun.COM 
77010696SDavid.Hollister@Sun.COM static char *
77110696SDavid.Hollister@Sun.COM inbound_iomb_opcode(uint32_t opcode)
77210696SDavid.Hollister@Sun.COM {
77310696SDavid.Hollister@Sun.COM 	switch (opcode) {
77410696SDavid.Hollister@Sun.COM 	case PMCIN_ECHO:
77510696SDavid.Hollister@Sun.COM 		return ("ECHO");
77610696SDavid.Hollister@Sun.COM 		break;
77710696SDavid.Hollister@Sun.COM 	case PMCIN_GET_INFO:
77810696SDavid.Hollister@Sun.COM 		return ("GET_INFO");
77910696SDavid.Hollister@Sun.COM 		break;
78010696SDavid.Hollister@Sun.COM 	case PMCIN_GET_VPD:
78110696SDavid.Hollister@Sun.COM 		return ("GET_VPD");
78210696SDavid.Hollister@Sun.COM 		break;
78310696SDavid.Hollister@Sun.COM 	case PMCIN_PHY_START:
78410696SDavid.Hollister@Sun.COM 		return ("PHY_START");
78510696SDavid.Hollister@Sun.COM 		break;
78610696SDavid.Hollister@Sun.COM 	case PMCIN_PHY_STOP:
78710696SDavid.Hollister@Sun.COM 		return ("PHY_STOP");
78810696SDavid.Hollister@Sun.COM 		break;
78910696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_IO_START:
79010696SDavid.Hollister@Sun.COM 		return ("INI_IO_START");
79110696SDavid.Hollister@Sun.COM 		break;
79210696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_TM_START:
79310696SDavid.Hollister@Sun.COM 		return ("INI_TM_START");
79410696SDavid.Hollister@Sun.COM 		break;
79510696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_EXT_IO_START:
79610696SDavid.Hollister@Sun.COM 		return ("INI_EXT_IO_START");
79710696SDavid.Hollister@Sun.COM 		break;
79810696SDavid.Hollister@Sun.COM 	case PMCIN_DEVICE_HANDLE_ACCEPT:
79910696SDavid.Hollister@Sun.COM 		return ("DEVICE_HANDLE_ACCEPT");
80010696SDavid.Hollister@Sun.COM 		break;
80110696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_TGT_IO_START:
80210696SDavid.Hollister@Sun.COM 		return ("TGT_IO_START");
80310696SDavid.Hollister@Sun.COM 		break;
80410696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_TGT_RESPONSE_START:
80510696SDavid.Hollister@Sun.COM 		return ("TGT_RESPONSE_START");
80610696SDavid.Hollister@Sun.COM 		break;
80710696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_EDC_EXT_IO_START:
80810696SDavid.Hollister@Sun.COM 		return ("INI_EDC_EXT_IO_START");
80910696SDavid.Hollister@Sun.COM 		break;
81010696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_EDC_EXT_IO_START1:
81110696SDavid.Hollister@Sun.COM 		return ("INI_EDC_EXT_IO_START1");
81210696SDavid.Hollister@Sun.COM 		break;
81310696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_TGT_EDC_IO_START:
81410696SDavid.Hollister@Sun.COM 		return ("TGT_EDC_IO_START");
81510696SDavid.Hollister@Sun.COM 		break;
81610696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_ABORT:
81710696SDavid.Hollister@Sun.COM 		return ("SSP_ABORT");
81810696SDavid.Hollister@Sun.COM 		break;
81910696SDavid.Hollister@Sun.COM 	case PMCIN_DEREGISTER_DEVICE_HANDLE:
82010696SDavid.Hollister@Sun.COM 		return ("DEREGISTER_DEVICE_HANDLE");
82110696SDavid.Hollister@Sun.COM 		break;
82210696SDavid.Hollister@Sun.COM 	case PMCIN_GET_DEVICE_HANDLE:
82310696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_HANDLE");
82410696SDavid.Hollister@Sun.COM 		break;
82510696SDavid.Hollister@Sun.COM 	case PMCIN_SMP_REQUEST:
82610696SDavid.Hollister@Sun.COM 		return ("SMP_REQUEST");
82710696SDavid.Hollister@Sun.COM 		break;
82810696SDavid.Hollister@Sun.COM 	case PMCIN_SMP_RESPONSE:
82910696SDavid.Hollister@Sun.COM 		return ("SMP_RESPONSE");
83010696SDavid.Hollister@Sun.COM 		break;
83110696SDavid.Hollister@Sun.COM 	case PMCIN_SMP_ABORT:
83210696SDavid.Hollister@Sun.COM 		return ("SMP_ABORT");
83310696SDavid.Hollister@Sun.COM 		break;
83410696SDavid.Hollister@Sun.COM 	case PMCIN_ASSISTED_DISCOVERY:
83510696SDavid.Hollister@Sun.COM 		return ("ASSISTED_DISCOVERY");
83610696SDavid.Hollister@Sun.COM 		break;
83710696SDavid.Hollister@Sun.COM 	case PMCIN_REGISTER_DEVICE:
83810696SDavid.Hollister@Sun.COM 		return ("REGISTER_DEVICE");
83910696SDavid.Hollister@Sun.COM 		break;
84010696SDavid.Hollister@Sun.COM 	case PMCIN_SATA_HOST_IO_START:
84110696SDavid.Hollister@Sun.COM 		return ("SATA_HOST_IO_START");
84210696SDavid.Hollister@Sun.COM 		break;
84310696SDavid.Hollister@Sun.COM 	case PMCIN_SATA_ABORT:
84410696SDavid.Hollister@Sun.COM 		return ("SATA_ABORT");
84510696SDavid.Hollister@Sun.COM 		break;
84610696SDavid.Hollister@Sun.COM 	case PMCIN_LOCAL_PHY_CONTROL:
84710696SDavid.Hollister@Sun.COM 		return ("LOCAL_PHY_CONTROL");
84810696SDavid.Hollister@Sun.COM 		break;
84910696SDavid.Hollister@Sun.COM 	case PMCIN_GET_DEVICE_INFO:
85010696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_INFO");
85110696SDavid.Hollister@Sun.COM 		break;
85210696SDavid.Hollister@Sun.COM 	case PMCIN_TWI:
85310696SDavid.Hollister@Sun.COM 		return ("TWI");
85410696SDavid.Hollister@Sun.COM 		break;
85510696SDavid.Hollister@Sun.COM 	case PMCIN_FW_FLASH_UPDATE:
85610696SDavid.Hollister@Sun.COM 		return ("FW_FLASH_UPDATE");
85710696SDavid.Hollister@Sun.COM 		break;
85810696SDavid.Hollister@Sun.COM 	case PMCIN_SET_VPD:
85910696SDavid.Hollister@Sun.COM 		return ("SET_VPD");
86010696SDavid.Hollister@Sun.COM 		break;
86110696SDavid.Hollister@Sun.COM 	case PMCIN_GPIO:
86210696SDavid.Hollister@Sun.COM 		return ("GPIO");
86310696SDavid.Hollister@Sun.COM 		break;
86410696SDavid.Hollister@Sun.COM 	case PMCIN_SAS_DIAG_MODE_START_END:
86510696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_MODE_START_END");
86610696SDavid.Hollister@Sun.COM 		break;
86710696SDavid.Hollister@Sun.COM 	case PMCIN_SAS_DIAG_EXECUTE:
86810696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_EXECUTE");
86910696SDavid.Hollister@Sun.COM 		break;
87010696SDavid.Hollister@Sun.COM 	case PMCIN_SAW_HW_EVENT_ACK:
87110696SDavid.Hollister@Sun.COM 		return ("SAS_HW_EVENT_ACK");
87210696SDavid.Hollister@Sun.COM 		break;
87310696SDavid.Hollister@Sun.COM 	case PMCIN_GET_TIME_STAMP:
87410696SDavid.Hollister@Sun.COM 		return ("GET_TIME_STAMP");
87510696SDavid.Hollister@Sun.COM 		break;
87610696SDavid.Hollister@Sun.COM 	case PMCIN_PORT_CONTROL:
87710696SDavid.Hollister@Sun.COM 		return ("PORT_CONTROL");
87810696SDavid.Hollister@Sun.COM 		break;
87910696SDavid.Hollister@Sun.COM 	case PMCIN_GET_NVMD_DATA:
88010696SDavid.Hollister@Sun.COM 		return ("GET_NVMD_DATA");
88110696SDavid.Hollister@Sun.COM 		break;
88210696SDavid.Hollister@Sun.COM 	case PMCIN_SET_NVMD_DATA:
88310696SDavid.Hollister@Sun.COM 		return ("SET_NVMD_DATA");
88410696SDavid.Hollister@Sun.COM 		break;
88510696SDavid.Hollister@Sun.COM 	case PMCIN_SET_DEVICE_STATE:
88610696SDavid.Hollister@Sun.COM 		return ("SET_DEVICE_STATE");
88710696SDavid.Hollister@Sun.COM 		break;
88810696SDavid.Hollister@Sun.COM 	case PMCIN_GET_DEVICE_STATE:
88910696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_STATE");
89010696SDavid.Hollister@Sun.COM 		break;
89110696SDavid.Hollister@Sun.COM 	default:
89210696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
89310696SDavid.Hollister@Sun.COM 		break;
89410696SDavid.Hollister@Sun.COM 	}
89510696SDavid.Hollister@Sun.COM }
89610696SDavid.Hollister@Sun.COM 
89710696SDavid.Hollister@Sun.COM static char *
89810696SDavid.Hollister@Sun.COM outbound_iomb_opcode(uint32_t opcode)
89910696SDavid.Hollister@Sun.COM {
90010696SDavid.Hollister@Sun.COM 	switch (opcode) {
90110696SDavid.Hollister@Sun.COM 	case PMCOUT_ECHO:
90210696SDavid.Hollister@Sun.COM 		return ("ECHO");
90310696SDavid.Hollister@Sun.COM 		break;
90410696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_INFO:
90510696SDavid.Hollister@Sun.COM 		return ("GET_INFO");
90610696SDavid.Hollister@Sun.COM 		break;
90710696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_VPD:
90810696SDavid.Hollister@Sun.COM 		return ("GET_VPD");
90910696SDavid.Hollister@Sun.COM 		break;
91010696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_HW_EVENT:
91110696SDavid.Hollister@Sun.COM 		return ("SAS_HW_EVENT");
91210696SDavid.Hollister@Sun.COM 		break;
91310696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_COMPLETION:
91410696SDavid.Hollister@Sun.COM 		return ("SSP_COMPLETION");
91510696SDavid.Hollister@Sun.COM 		break;
91610696SDavid.Hollister@Sun.COM 	case PMCOUT_SMP_COMPLETION:
91710696SDavid.Hollister@Sun.COM 		return ("SMP_COMPLETION");
91810696SDavid.Hollister@Sun.COM 		break;
91910696SDavid.Hollister@Sun.COM 	case PMCOUT_LOCAL_PHY_CONTROL:
92010696SDavid.Hollister@Sun.COM 		return ("LOCAL_PHY_CONTROL");
92110696SDavid.Hollister@Sun.COM 		break;
92210696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_ASSISTED_DISCOVERY_EVENT:
92310696SDavid.Hollister@Sun.COM 		return ("SAS_ASSISTED_DISCOVERY_SENT");
92410696SDavid.Hollister@Sun.COM 		break;
92510696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_ASSISTED_DISCOVERY_EVENT:
92610696SDavid.Hollister@Sun.COM 		return ("SATA_ASSISTED_DISCOVERY_SENT");
92710696SDavid.Hollister@Sun.COM 		break;
92810696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_REGISTRATION:
92910696SDavid.Hollister@Sun.COM 		return ("DEVICE_REGISTRATION");
93010696SDavid.Hollister@Sun.COM 		break;
93110696SDavid.Hollister@Sun.COM 	case PMCOUT_DEREGISTER_DEVICE_HANDLE:
93210696SDavid.Hollister@Sun.COM 		return ("DEREGISTER_DEVICE_HANDLE");
93310696SDavid.Hollister@Sun.COM 		break;
93410696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_DEVICE_HANDLE:
93510696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_HANDLE");
93610696SDavid.Hollister@Sun.COM 		break;
93710696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_COMPLETION:
93810696SDavid.Hollister@Sun.COM 		return ("SATA_COMPLETION");
93910696SDavid.Hollister@Sun.COM 		break;
94010696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_EVENT:
94110696SDavid.Hollister@Sun.COM 		return ("SATA_EVENT");
94210696SDavid.Hollister@Sun.COM 		break;
94310696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_EVENT:
94410696SDavid.Hollister@Sun.COM 		return ("SSP_EVENT");
94510696SDavid.Hollister@Sun.COM 		break;
94610696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_HANDLE_ARRIVED:
94710696SDavid.Hollister@Sun.COM 		return ("DEVICE_HANDLE_ARRIVED");
94810696SDavid.Hollister@Sun.COM 		break;
94910696SDavid.Hollister@Sun.COM 	case PMCOUT_SMP_REQUEST_RECEIVED:
95010696SDavid.Hollister@Sun.COM 		return ("SMP_REQUEST_RECEIVED");
95110696SDavid.Hollister@Sun.COM 		break;
95210696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_REQUEST_RECEIVED:
95310696SDavid.Hollister@Sun.COM 		return ("SSP_REQUEST_RECEIVED");
95410696SDavid.Hollister@Sun.COM 		break;
95510696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_INFO:
95610696SDavid.Hollister@Sun.COM 		return ("DEVICE_INFO");
95710696SDavid.Hollister@Sun.COM 		break;
95810696SDavid.Hollister@Sun.COM 	case PMCOUT_FW_FLASH_UPDATE:
95910696SDavid.Hollister@Sun.COM 		return ("FW_FLASH_UPDATE");
96010696SDavid.Hollister@Sun.COM 		break;
96110696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_VPD:
96210696SDavid.Hollister@Sun.COM 		return ("SET_VPD");
96310696SDavid.Hollister@Sun.COM 		break;
96410696SDavid.Hollister@Sun.COM 	case PMCOUT_GPIO:
96510696SDavid.Hollister@Sun.COM 		return ("GPIO");
96610696SDavid.Hollister@Sun.COM 		break;
96710696SDavid.Hollister@Sun.COM 	case PMCOUT_GPIO_EVENT:
96810696SDavid.Hollister@Sun.COM 		return ("GPIO_EVENT");
96910696SDavid.Hollister@Sun.COM 		break;
97010696SDavid.Hollister@Sun.COM 	case PMCOUT_GENERAL_EVENT:
97110696SDavid.Hollister@Sun.COM 		return ("GENERAL_EVENT");
97210696SDavid.Hollister@Sun.COM 		break;
97310696SDavid.Hollister@Sun.COM 	case PMCOUT_TWI:
97410696SDavid.Hollister@Sun.COM 		return ("TWI");
97510696SDavid.Hollister@Sun.COM 		break;
97610696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_ABORT:
97710696SDavid.Hollister@Sun.COM 		return ("SSP_ABORT");
97810696SDavid.Hollister@Sun.COM 		break;
97910696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_ABORT:
98010696SDavid.Hollister@Sun.COM 		return ("SATA_ABORT");
98110696SDavid.Hollister@Sun.COM 		break;
98210696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_DIAG_MODE_START_END:
98310696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_MODE_START_END");
98410696SDavid.Hollister@Sun.COM 		break;
98510696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_DIAG_EXECUTE:
98610696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_EXECUTE");
98710696SDavid.Hollister@Sun.COM 		break;
98810696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_TIME_STAMP:
98910696SDavid.Hollister@Sun.COM 		return ("GET_TIME_STAMP");
99010696SDavid.Hollister@Sun.COM 		break;
99110696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_HW_EVENT_ACK_ACK:
99210696SDavid.Hollister@Sun.COM 		return ("SAS_HW_EVENT_ACK_ACK");
99310696SDavid.Hollister@Sun.COM 		break;
99410696SDavid.Hollister@Sun.COM 	case PMCOUT_PORT_CONTROL:
99510696SDavid.Hollister@Sun.COM 		return ("PORT_CONTROL");
99610696SDavid.Hollister@Sun.COM 		break;
99710696SDavid.Hollister@Sun.COM 	case PMCOUT_SKIP_ENTRIES:
99810696SDavid.Hollister@Sun.COM 		return ("SKIP_ENTRIES");
99910696SDavid.Hollister@Sun.COM 		break;
100010696SDavid.Hollister@Sun.COM 	case PMCOUT_SMP_ABORT:
100110696SDavid.Hollister@Sun.COM 		return ("SMP_ABORT");
100210696SDavid.Hollister@Sun.COM 		break;
100310696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_NVMD_DATA:
100410696SDavid.Hollister@Sun.COM 		return ("GET_NVMD_DATA");
100510696SDavid.Hollister@Sun.COM 		break;
100610696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_NVMD_DATA:
100710696SDavid.Hollister@Sun.COM 		return ("SET_NVMD_DATA");
100810696SDavid.Hollister@Sun.COM 		break;
100910696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_HANDLE_REMOVED:
101010696SDavid.Hollister@Sun.COM 		return ("DEVICE_HANDLE_REMOVED");
101110696SDavid.Hollister@Sun.COM 		break;
101210696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_DEVICE_STATE:
101310696SDavid.Hollister@Sun.COM 		return ("SET_DEVICE_STATE");
101410696SDavid.Hollister@Sun.COM 		break;
101510696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_DEVICE_STATE:
101610696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_STATE");
101710696SDavid.Hollister@Sun.COM 		break;
101810696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_DEVICE_INFO:
101910696SDavid.Hollister@Sun.COM 		return ("SET_DEVICE_INFO");
102010696SDavid.Hollister@Sun.COM 		break;
102110696SDavid.Hollister@Sun.COM 	default:
102210696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
102310696SDavid.Hollister@Sun.COM 		break;
102410696SDavid.Hollister@Sun.COM 	}
102510696SDavid.Hollister@Sun.COM }
102610696SDavid.Hollister@Sun.COM 
102710696SDavid.Hollister@Sun.COM static void
102810696SDavid.Hollister@Sun.COM dump_one_qentry_outbound(uint32_t *qentryp, int idx)
102910696SDavid.Hollister@Sun.COM {
103010696SDavid.Hollister@Sun.COM 	int qeidx;
103110696SDavid.Hollister@Sun.COM 	uint32_t word0 = LE_32(*qentryp);
103210696SDavid.Hollister@Sun.COM 
103310696SDavid.Hollister@Sun.COM 	mdb_printf("Entry #%02d\n", idx);
103410696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
103510696SDavid.Hollister@Sun.COM 
103610696SDavid.Hollister@Sun.COM 	mdb_printf("Header: 0x%08x (", word0);
103710696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_VALID) {
103810696SDavid.Hollister@Sun.COM 		mdb_printf("VALID, ");
103910696SDavid.Hollister@Sun.COM 	}
104010696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_HIPRI) {
104110696SDavid.Hollister@Sun.COM 		mdb_printf("HIPRI, ");
104210696SDavid.Hollister@Sun.COM 	}
104310696SDavid.Hollister@Sun.COM 	mdb_printf("OBID=%d, ",
104410696SDavid.Hollister@Sun.COM 	    (word0 & PMCS_IOMB_OBID_MASK) >> PMCS_IOMB_OBID_SHIFT);
104510696SDavid.Hollister@Sun.COM 	mdb_printf("CAT=%s, ",
104610696SDavid.Hollister@Sun.COM 	    iomb_cat((word0 & PMCS_IOMB_CAT_MASK) >> PMCS_IOMB_CAT_SHIFT));
104710696SDavid.Hollister@Sun.COM 	mdb_printf("OPCODE=%s",
104810696SDavid.Hollister@Sun.COM 	    outbound_iomb_opcode(word0 & PMCS_IOMB_OPCODE_MASK));
104910696SDavid.Hollister@Sun.COM 	mdb_printf(")\n");
105010696SDavid.Hollister@Sun.COM 
105110696SDavid.Hollister@Sun.COM 	mdb_printf("Remaining Payload:\n");
105210696SDavid.Hollister@Sun.COM 
105310696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
105410696SDavid.Hollister@Sun.COM 	for (qeidx = 1; qeidx < (PMCS_QENTRY_SIZE / 4); qeidx++) {
105510696SDavid.Hollister@Sun.COM 		mdb_printf("%08x ", LE_32(*(qentryp + qeidx)));
105610696SDavid.Hollister@Sun.COM 	}
105710696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
105810696SDavid.Hollister@Sun.COM 	mdb_dec_indent(4);
105910696SDavid.Hollister@Sun.COM }
106010696SDavid.Hollister@Sun.COM 
106110696SDavid.Hollister@Sun.COM static void
106210696SDavid.Hollister@Sun.COM display_outbound_queues(struct pmcs_hw ss, uint_t verbose)
106310696SDavid.Hollister@Sun.COM {
106410696SDavid.Hollister@Sun.COM 	int		idx, qidx;
106510696SDavid.Hollister@Sun.COM 	uintptr_t	obqp;
106610696SDavid.Hollister@Sun.COM 	uint32_t	*cip;
106710696SDavid.Hollister@Sun.COM 	uint32_t	*qentryp = mdb_alloc(PMCS_QENTRY_SIZE, UM_SLEEP);
106810696SDavid.Hollister@Sun.COM 	uint32_t	last_consumed, oqpi;
106910696SDavid.Hollister@Sun.COM 
107010696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
107110696SDavid.Hollister@Sun.COM 	mdb_printf("Outbound Queues\n");
107210696SDavid.Hollister@Sun.COM 	mdb_printf("---------------\n");
107310696SDavid.Hollister@Sun.COM 
107410696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
107510696SDavid.Hollister@Sun.COM 
107610696SDavid.Hollister@Sun.COM 	for (qidx = 0; qidx < PMCS_NOQ; qidx++) {
107710696SDavid.Hollister@Sun.COM 		obqp = (uintptr_t)ss.oqp[qidx];
107810696SDavid.Hollister@Sun.COM 
107910696SDavid.Hollister@Sun.COM 		if (obqp == NULL) {
108010696SDavid.Hollister@Sun.COM 			mdb_printf("No outbound queue ptr for queue #%d\n",
108110696SDavid.Hollister@Sun.COM 			    qidx);
108210696SDavid.Hollister@Sun.COM 			continue;
108310696SDavid.Hollister@Sun.COM 		}
108410696SDavid.Hollister@Sun.COM 
108510696SDavid.Hollister@Sun.COM 		mdb_printf("Outbound Queue #%d (Queue Type = %s)\n", qidx,
108610696SDavid.Hollister@Sun.COM 		    obq_type(qidx));
108710696SDavid.Hollister@Sun.COM 		/*
108810696SDavid.Hollister@Sun.COM 		 * Chip is the producer, so read the actual producer index
108910696SDavid.Hollister@Sun.COM 		 * and not the driver's version
109010696SDavid.Hollister@Sun.COM 		 */
109110696SDavid.Hollister@Sun.COM 		cip = (uint32_t *)((void *)ss.cip);
109210696SDavid.Hollister@Sun.COM 		if (MDB_RD(&oqpi, 4, cip + OQPI_BASE_OFFSET +
109310696SDavid.Hollister@Sun.COM 		    (qidx * 4)) == -1) {
109410696SDavid.Hollister@Sun.COM 			mdb_warn("Couldn't read oqpi\n");
109510696SDavid.Hollister@Sun.COM 			break;
109610696SDavid.Hollister@Sun.COM 		}
109710696SDavid.Hollister@Sun.COM 
109810696SDavid.Hollister@Sun.COM 		mdb_printf("Producer index: %d  Consumer index: %d\n\n",
109910696SDavid.Hollister@Sun.COM 		    LE_32(oqpi), ss.oqci[qidx]);
110010696SDavid.Hollister@Sun.COM 		mdb_inc_indent(2);
110110696SDavid.Hollister@Sun.COM 
110210696SDavid.Hollister@Sun.COM 		if (ss.oqci[qidx] == 0) {
110310696SDavid.Hollister@Sun.COM 			last_consumed = ss.ioq_depth - 1;
110410696SDavid.Hollister@Sun.COM 		} else {
110510696SDavid.Hollister@Sun.COM 			last_consumed = ss.oqci[qidx] - 1;
110610696SDavid.Hollister@Sun.COM 		}
110710696SDavid.Hollister@Sun.COM 
110810696SDavid.Hollister@Sun.COM 
110910696SDavid.Hollister@Sun.COM 		if (!verbose) {
111010696SDavid.Hollister@Sun.COM 			mdb_printf("Last processed entry:\n");
111110696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
111210696SDavid.Hollister@Sun.COM 			    (obqp + (PMCS_QENTRY_SIZE * last_consumed)))
111310696SDavid.Hollister@Sun.COM 			    == -1) {
111410696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
111510696SDavid.Hollister@Sun.COM 				    (obqp + (PMCS_QENTRY_SIZE *
111610696SDavid.Hollister@Sun.COM 				    last_consumed)));
111710696SDavid.Hollister@Sun.COM 				break;
111810696SDavid.Hollister@Sun.COM 			}
111910696SDavid.Hollister@Sun.COM 			dump_one_qentry_outbound(qentryp, last_consumed);
112010696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
112110696SDavid.Hollister@Sun.COM 			mdb_dec_indent(2);
112210696SDavid.Hollister@Sun.COM 			continue;
112310696SDavid.Hollister@Sun.COM 		}
112410696SDavid.Hollister@Sun.COM 
112510696SDavid.Hollister@Sun.COM 		for (idx = 0; idx < ss.ioq_depth; idx++) {
112610696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
112710696SDavid.Hollister@Sun.COM 			    (obqp + (PMCS_QENTRY_SIZE * idx))) == -1) {
112810696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
112910696SDavid.Hollister@Sun.COM 				    (obqp + (PMCS_QENTRY_SIZE * idx)));
113010696SDavid.Hollister@Sun.COM 				break;
113110696SDavid.Hollister@Sun.COM 			}
113210696SDavid.Hollister@Sun.COM 			dump_one_qentry_outbound(qentryp, idx);
113310696SDavid.Hollister@Sun.COM 		}
113410696SDavid.Hollister@Sun.COM 
113510696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
113610696SDavid.Hollister@Sun.COM 		mdb_dec_indent(2);
113710696SDavid.Hollister@Sun.COM 	}
113810696SDavid.Hollister@Sun.COM 
113910696SDavid.Hollister@Sun.COM 	mdb_dec_indent(2);
114010696SDavid.Hollister@Sun.COM 	mdb_free(qentryp, PMCS_QENTRY_SIZE);
114110696SDavid.Hollister@Sun.COM }
114210696SDavid.Hollister@Sun.COM 
114310696SDavid.Hollister@Sun.COM static void
114410696SDavid.Hollister@Sun.COM dump_one_qentry_inbound(uint32_t *qentryp, int idx)
114510696SDavid.Hollister@Sun.COM {
114610696SDavid.Hollister@Sun.COM 	int qeidx;
114710696SDavid.Hollister@Sun.COM 	uint32_t word0 = LE_32(*qentryp);
114810696SDavid.Hollister@Sun.COM 
114910696SDavid.Hollister@Sun.COM 	mdb_printf("Entry #%02d\n", idx);
115010696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
115110696SDavid.Hollister@Sun.COM 
115210696SDavid.Hollister@Sun.COM 	mdb_printf("Header: 0x%08x (", word0);
115310696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_VALID) {
115410696SDavid.Hollister@Sun.COM 		mdb_printf("VALID, ");
115510696SDavid.Hollister@Sun.COM 	}
115610696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_HIPRI) {
115710696SDavid.Hollister@Sun.COM 		mdb_printf("HIPRI, ");
115810696SDavid.Hollister@Sun.COM 	}
115910696SDavid.Hollister@Sun.COM 	mdb_printf("OBID=%d, ",
116010696SDavid.Hollister@Sun.COM 	    (word0 & PMCS_IOMB_OBID_MASK) >> PMCS_IOMB_OBID_SHIFT);
116110696SDavid.Hollister@Sun.COM 	mdb_printf("CAT=%s, ",
116210696SDavid.Hollister@Sun.COM 	    iomb_cat((word0 & PMCS_IOMB_CAT_MASK) >> PMCS_IOMB_CAT_SHIFT));
116310696SDavid.Hollister@Sun.COM 	mdb_printf("OPCODE=%s",
116410696SDavid.Hollister@Sun.COM 	    inbound_iomb_opcode(word0 & PMCS_IOMB_OPCODE_MASK));
116510696SDavid.Hollister@Sun.COM 	mdb_printf(")\n");
116610696SDavid.Hollister@Sun.COM 
116710696SDavid.Hollister@Sun.COM 	mdb_printf("HTAG: 0x%08x\n", LE_32(*(qentryp + 1)));
116810696SDavid.Hollister@Sun.COM 	mdb_printf("Remaining Payload:\n");
116910696SDavid.Hollister@Sun.COM 
117010696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
117110696SDavid.Hollister@Sun.COM 	for (qeidx = 2; qeidx < (PMCS_QENTRY_SIZE / 4); qeidx++) {
117210696SDavid.Hollister@Sun.COM 		mdb_printf("%08x ", LE_32(*(qentryp + qeidx)));
117310696SDavid.Hollister@Sun.COM 	}
117410696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
117510696SDavid.Hollister@Sun.COM 	mdb_dec_indent(4);
117610696SDavid.Hollister@Sun.COM }
117710696SDavid.Hollister@Sun.COM 
117810696SDavid.Hollister@Sun.COM static void
117910696SDavid.Hollister@Sun.COM display_inbound_queues(struct pmcs_hw ss, uint_t verbose)
118010696SDavid.Hollister@Sun.COM {
118110696SDavid.Hollister@Sun.COM 	int		idx, qidx, iqci, last_consumed;
118210696SDavid.Hollister@Sun.COM 	uintptr_t	ibqp;
118310696SDavid.Hollister@Sun.COM 	uint32_t	*qentryp = mdb_alloc(PMCS_QENTRY_SIZE, UM_SLEEP);
118410696SDavid.Hollister@Sun.COM 	uint32_t	*cip;
118510696SDavid.Hollister@Sun.COM 
118610696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
118710696SDavid.Hollister@Sun.COM 	mdb_printf("Inbound Queues\n");
118810696SDavid.Hollister@Sun.COM 	mdb_printf("--------------\n");
118910696SDavid.Hollister@Sun.COM 
119010696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
119110696SDavid.Hollister@Sun.COM 
119210696SDavid.Hollister@Sun.COM 	for (qidx = 0; qidx < PMCS_NIQ; qidx++) {
119310696SDavid.Hollister@Sun.COM 		ibqp = (uintptr_t)ss.iqp[qidx];
119410696SDavid.Hollister@Sun.COM 
119510696SDavid.Hollister@Sun.COM 		if (ibqp == NULL) {
119610696SDavid.Hollister@Sun.COM 			mdb_printf("No inbound queue ptr for queue #%d\n",
119710696SDavid.Hollister@Sun.COM 			    qidx);
119810696SDavid.Hollister@Sun.COM 			continue;
119910696SDavid.Hollister@Sun.COM 		}
120010696SDavid.Hollister@Sun.COM 
120110696SDavid.Hollister@Sun.COM 		mdb_printf("Inbound Queue #%d (Queue Type = %s)\n", qidx,
120210696SDavid.Hollister@Sun.COM 		    ibq_type(qidx));
120310696SDavid.Hollister@Sun.COM 
120410696SDavid.Hollister@Sun.COM 		cip = (uint32_t *)((void *)ss.cip);
120510696SDavid.Hollister@Sun.COM 		if (MDB_RD(&iqci, 4, cip + (qidx * 4)) == -1) {
120610696SDavid.Hollister@Sun.COM 			mdb_warn("Couldn't read iqci\n");
120710696SDavid.Hollister@Sun.COM 			break;
120810696SDavid.Hollister@Sun.COM 		}
120910696SDavid.Hollister@Sun.COM 		iqci = LE_32(iqci);
121010696SDavid.Hollister@Sun.COM 
121110696SDavid.Hollister@Sun.COM 		mdb_printf("Producer index: %d  Consumer index: %d\n\n",
121210696SDavid.Hollister@Sun.COM 		    ss.shadow_iqpi[qidx], iqci);
121310696SDavid.Hollister@Sun.COM 		mdb_inc_indent(2);
121410696SDavid.Hollister@Sun.COM 
121510696SDavid.Hollister@Sun.COM 		if (iqci == 0) {
121610696SDavid.Hollister@Sun.COM 			last_consumed = ss.ioq_depth - 1;
121710696SDavid.Hollister@Sun.COM 		} else {
121810696SDavid.Hollister@Sun.COM 			last_consumed = iqci - 1;
121910696SDavid.Hollister@Sun.COM 		}
122010696SDavid.Hollister@Sun.COM 
122110696SDavid.Hollister@Sun.COM 		if (!verbose) {
122210696SDavid.Hollister@Sun.COM 			mdb_printf("Last processed entry:\n");
122310696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
122410696SDavid.Hollister@Sun.COM 			    (ibqp + (PMCS_QENTRY_SIZE * last_consumed)))
122510696SDavid.Hollister@Sun.COM 			    == -1) {
122610696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
122710696SDavid.Hollister@Sun.COM 				    (ibqp + (PMCS_QENTRY_SIZE *
122810696SDavid.Hollister@Sun.COM 				    last_consumed)));
122910696SDavid.Hollister@Sun.COM 				break;
123010696SDavid.Hollister@Sun.COM 			}
123110696SDavid.Hollister@Sun.COM 			dump_one_qentry_inbound(qentryp, last_consumed);
123210696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
123310696SDavid.Hollister@Sun.COM 			mdb_dec_indent(2);
123410696SDavid.Hollister@Sun.COM 			continue;
123510696SDavid.Hollister@Sun.COM 		}
123610696SDavid.Hollister@Sun.COM 
123710696SDavid.Hollister@Sun.COM 		for (idx = 0; idx < ss.ioq_depth; idx++) {
123810696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
123910696SDavid.Hollister@Sun.COM 			    (ibqp + (PMCS_QENTRY_SIZE * idx))) == -1) {
124010696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
124110696SDavid.Hollister@Sun.COM 				    (ibqp + (PMCS_QENTRY_SIZE * idx)));
124210696SDavid.Hollister@Sun.COM 				break;
124310696SDavid.Hollister@Sun.COM 			}
124410696SDavid.Hollister@Sun.COM 			dump_one_qentry_inbound(qentryp, idx);
124510696SDavid.Hollister@Sun.COM 		}
124610696SDavid.Hollister@Sun.COM 
124710696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
124810696SDavid.Hollister@Sun.COM 		mdb_dec_indent(2);
124910696SDavid.Hollister@Sun.COM 	}
125010696SDavid.Hollister@Sun.COM 
125110696SDavid.Hollister@Sun.COM 	mdb_dec_indent(2);
125210696SDavid.Hollister@Sun.COM 	mdb_free(qentryp, PMCS_QENTRY_SIZE);
125310696SDavid.Hollister@Sun.COM }
125410696SDavid.Hollister@Sun.COM 
125510696SDavid.Hollister@Sun.COM static void
125610696SDavid.Hollister@Sun.COM display_phy(struct pmcs_phy phy, int verbose, int totals_only)
125710696SDavid.Hollister@Sun.COM {
125810696SDavid.Hollister@Sun.COM 	char		*dtype, *speed;
125910696SDavid.Hollister@Sun.COM 	char		*yes = "Yes";
126010696SDavid.Hollister@Sun.COM 	char		*no = "No";
126110696SDavid.Hollister@Sun.COM 	char		*cfgd = no;
126210696SDavid.Hollister@Sun.COM 	char		*apend = no;
126310696SDavid.Hollister@Sun.COM 	char		*asent = no;
126410696SDavid.Hollister@Sun.COM 	char		*dead = no;
126510696SDavid.Hollister@Sun.COM 	char		*changed = no;
126610696SDavid.Hollister@Sun.COM 
126710696SDavid.Hollister@Sun.COM 	switch (phy.dtype) {
126810696SDavid.Hollister@Sun.COM 	case NOTHING:
126910696SDavid.Hollister@Sun.COM 		dtype = "None";
127010696SDavid.Hollister@Sun.COM 		break;
127110696SDavid.Hollister@Sun.COM 	case SATA:
127210696SDavid.Hollister@Sun.COM 		dtype = "SATA";
127310696SDavid.Hollister@Sun.COM 		if (phy.configured) {
127410696SDavid.Hollister@Sun.COM 			++sata_phys;
127510696SDavid.Hollister@Sun.COM 		}
127610696SDavid.Hollister@Sun.COM 		break;
127710696SDavid.Hollister@Sun.COM 	case SAS:
127810696SDavid.Hollister@Sun.COM 		dtype = "SAS";
127910696SDavid.Hollister@Sun.COM 		if (phy.configured) {
128010696SDavid.Hollister@Sun.COM 			++sas_phys;
128110696SDavid.Hollister@Sun.COM 		}
128210696SDavid.Hollister@Sun.COM 		break;
128310696SDavid.Hollister@Sun.COM 	case EXPANDER:
128410696SDavid.Hollister@Sun.COM 		dtype = "EXP";
128510696SDavid.Hollister@Sun.COM 		if (phy.configured) {
128610696SDavid.Hollister@Sun.COM 			++exp_phys;
128710696SDavid.Hollister@Sun.COM 		}
128810696SDavid.Hollister@Sun.COM 		break;
128910696SDavid.Hollister@Sun.COM 	}
129010696SDavid.Hollister@Sun.COM 
129110696SDavid.Hollister@Sun.COM 	if (phy.dtype == NOTHING) {
129210696SDavid.Hollister@Sun.COM 		empty_phys++;
129310696SDavid.Hollister@Sun.COM 	} else if ((phy.dtype == EXPANDER) && phy.configured) {
129410696SDavid.Hollister@Sun.COM 		num_expanders++;
129510696SDavid.Hollister@Sun.COM 	}
129610696SDavid.Hollister@Sun.COM 
129710696SDavid.Hollister@Sun.COM 	if (totals_only) {
129810696SDavid.Hollister@Sun.COM 		return;
129910696SDavid.Hollister@Sun.COM 	}
130010696SDavid.Hollister@Sun.COM 
130110696SDavid.Hollister@Sun.COM 	switch (phy.link_rate) {
130210696SDavid.Hollister@Sun.COM 	case SAS_LINK_RATE_1_5GBIT:
130310696SDavid.Hollister@Sun.COM 		speed = "1.5Gb/s";
130410696SDavid.Hollister@Sun.COM 		break;
130510696SDavid.Hollister@Sun.COM 	case SAS_LINK_RATE_3GBIT:
130610696SDavid.Hollister@Sun.COM 		speed = "3 Gb/s";
130710696SDavid.Hollister@Sun.COM 		break;
130810696SDavid.Hollister@Sun.COM 	case SAS_LINK_RATE_6GBIT:
130910696SDavid.Hollister@Sun.COM 		speed = "6 Gb/s";
131010696SDavid.Hollister@Sun.COM 		break;
131110696SDavid.Hollister@Sun.COM 	default:
131210696SDavid.Hollister@Sun.COM 		speed = "N/A";
131310696SDavid.Hollister@Sun.COM 		break;
131410696SDavid.Hollister@Sun.COM 	}
131510696SDavid.Hollister@Sun.COM 
131610696SDavid.Hollister@Sun.COM 	if ((phy.dtype != NOTHING) || verbose) {
131710696SDavid.Hollister@Sun.COM 		print_sas_address(&phy);
131810696SDavid.Hollister@Sun.COM 
131910696SDavid.Hollister@Sun.COM 		if (phy.device_id != PMCS_INVALID_DEVICE_ID) {
132010696SDavid.Hollister@Sun.COM 			mdb_printf(" %3d %4d %6s %4s ",
132110696SDavid.Hollister@Sun.COM 			    phy.device_id, phy.phynum, speed, dtype);
132210696SDavid.Hollister@Sun.COM 		} else {
132310696SDavid.Hollister@Sun.COM 			mdb_printf(" N/A %4d %6s %4s ",
132410696SDavid.Hollister@Sun.COM 			    phy.phynum, speed, dtype);
132510696SDavid.Hollister@Sun.COM 		}
132610696SDavid.Hollister@Sun.COM 
132710696SDavid.Hollister@Sun.COM 		if (verbose) {
132810696SDavid.Hollister@Sun.COM 			if (phy.abort_sent) {
132910696SDavid.Hollister@Sun.COM 				asent = yes;
133010696SDavid.Hollister@Sun.COM 			}
133110696SDavid.Hollister@Sun.COM 			if (phy.abort_pending) {
133210696SDavid.Hollister@Sun.COM 				apend = yes;
133310696SDavid.Hollister@Sun.COM 			}
133410696SDavid.Hollister@Sun.COM 			if (phy.configured) {
133510696SDavid.Hollister@Sun.COM 				cfgd = yes;
133610696SDavid.Hollister@Sun.COM 			}
133710696SDavid.Hollister@Sun.COM 			if (phy.dead) {
133810696SDavid.Hollister@Sun.COM 				dead = yes;
133910696SDavid.Hollister@Sun.COM 			}
134010696SDavid.Hollister@Sun.COM 			if (phy.changed) {
134110696SDavid.Hollister@Sun.COM 				changed = yes;
134210696SDavid.Hollister@Sun.COM 			}
134310696SDavid.Hollister@Sun.COM 
134410696SDavid.Hollister@Sun.COM 			mdb_printf("%-4s %-4s %-4s %-4s %-4s %3d "
134510696SDavid.Hollister@Sun.COM 			    "0x%p ", cfgd, apend, asent,
134610696SDavid.Hollister@Sun.COM 			    changed, dead, phy.ref_count, phy.phy_lock);
134710696SDavid.Hollister@Sun.COM 		}
134810696SDavid.Hollister@Sun.COM 
134910696SDavid.Hollister@Sun.COM 		mdb_printf("Path: %s\n", phy.path);
135010696SDavid.Hollister@Sun.COM 	}
135110696SDavid.Hollister@Sun.COM }
135210696SDavid.Hollister@Sun.COM 
135310696SDavid.Hollister@Sun.COM static void
135410696SDavid.Hollister@Sun.COM display_phys(struct pmcs_hw ss, int verbose, struct pmcs_phy *parent, int level,
135510696SDavid.Hollister@Sun.COM     int totals_only)
135610696SDavid.Hollister@Sun.COM {
135710696SDavid.Hollister@Sun.COM 	pmcs_phy_t	phy;
135810696SDavid.Hollister@Sun.COM 	pmcs_phy_t	*pphy = parent;
135910696SDavid.Hollister@Sun.COM 
136010696SDavid.Hollister@Sun.COM 	mdb_inc_indent(3);
136110696SDavid.Hollister@Sun.COM 
136210696SDavid.Hollister@Sun.COM 	if (parent == NULL) {
136310696SDavid.Hollister@Sun.COM 		pphy = (pmcs_phy_t *)ss.root_phys;
136410696SDavid.Hollister@Sun.COM 	} else {
136510696SDavid.Hollister@Sun.COM 		pphy = (pmcs_phy_t *)parent;
136610696SDavid.Hollister@Sun.COM 	}
136710696SDavid.Hollister@Sun.COM 
136810696SDavid.Hollister@Sun.COM 	if (level == 0) {
136910696SDavid.Hollister@Sun.COM 		sas_phys = 0;
137010696SDavid.Hollister@Sun.COM 		sata_phys = 0;
137110696SDavid.Hollister@Sun.COM 		exp_phys = 0;
137210696SDavid.Hollister@Sun.COM 		num_expanders = 0;
137310696SDavid.Hollister@Sun.COM 		empty_phys = 0;
137410696SDavid.Hollister@Sun.COM 	}
137510696SDavid.Hollister@Sun.COM 
137610696SDavid.Hollister@Sun.COM 	if (!totals_only) {
137710696SDavid.Hollister@Sun.COM 		if (level == 0) {
137810696SDavid.Hollister@Sun.COM 			mdb_printf("PHY information\n");
137910696SDavid.Hollister@Sun.COM 		}
138010696SDavid.Hollister@Sun.COM 		mdb_printf("--------\n");
138110696SDavid.Hollister@Sun.COM 		mdb_printf("Level %2d\n", level);
138210696SDavid.Hollister@Sun.COM 		mdb_printf("--------\n");
138310696SDavid.Hollister@Sun.COM 		mdb_printf("SAS Address      Hdl Phy#  Speed Type ");
138410696SDavid.Hollister@Sun.COM 
138510696SDavid.Hollister@Sun.COM 		if (verbose) {
138610696SDavid.Hollister@Sun.COM 			mdb_printf("Cfgd AbtP AbtS Chgd Dead Ref Lock\n");
138710696SDavid.Hollister@Sun.COM 		} else {
138810696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
138910696SDavid.Hollister@Sun.COM 		}
139010696SDavid.Hollister@Sun.COM 	}
139110696SDavid.Hollister@Sun.COM 
139210696SDavid.Hollister@Sun.COM 	while (pphy) {
139310696SDavid.Hollister@Sun.COM 		if (MDB_RD(&phy, sizeof (phy), (uintptr_t)pphy) == -1) {
139410696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_phy_t, phy);
139510696SDavid.Hollister@Sun.COM 			break;
139610696SDavid.Hollister@Sun.COM 		}
139710696SDavid.Hollister@Sun.COM 
139810696SDavid.Hollister@Sun.COM 		display_phy(phy, verbose, totals_only);
139910696SDavid.Hollister@Sun.COM 
140010696SDavid.Hollister@Sun.COM 		if (phy.children) {
140110696SDavid.Hollister@Sun.COM 			display_phys(ss, verbose, phy.children, level + 1,
140210696SDavid.Hollister@Sun.COM 			    totals_only);
140310696SDavid.Hollister@Sun.COM 			if (!totals_only) {
140410696SDavid.Hollister@Sun.COM 				mdb_printf("\n");
140510696SDavid.Hollister@Sun.COM 			}
140610696SDavid.Hollister@Sun.COM 		}
140710696SDavid.Hollister@Sun.COM 
140810696SDavid.Hollister@Sun.COM 		pphy = phy.sibling;
140910696SDavid.Hollister@Sun.COM 	}
141010696SDavid.Hollister@Sun.COM 
141110696SDavid.Hollister@Sun.COM 	mdb_dec_indent(3);
141210696SDavid.Hollister@Sun.COM 
141310696SDavid.Hollister@Sun.COM 	if (level == 0) {
141410696SDavid.Hollister@Sun.COM 		if (verbose) {
141510696SDavid.Hollister@Sun.COM 			mdb_printf("%19s %d (%d SAS + %d SATA + %d SMP) "
141610696SDavid.Hollister@Sun.COM 			    "(+%d subsidiary + %d empty)\n", "Occupied PHYs:",
141710696SDavid.Hollister@Sun.COM 			    (sas_phys + sata_phys + num_expanders),
141810696SDavid.Hollister@Sun.COM 			    sas_phys, sata_phys, num_expanders,
141910696SDavid.Hollister@Sun.COM 			    (exp_phys - num_expanders), empty_phys);
142010696SDavid.Hollister@Sun.COM 		} else {
142110696SDavid.Hollister@Sun.COM 			mdb_printf("%19s %d (%d SAS + %d SATA + %d SMP)\n",
142210696SDavid.Hollister@Sun.COM 			    "Occupied PHYs:",
142310696SDavid.Hollister@Sun.COM 			    (sas_phys + sata_phys + num_expanders),
142410696SDavid.Hollister@Sun.COM 			    sas_phys, sata_phys, num_expanders);
142510696SDavid.Hollister@Sun.COM 		}
142610696SDavid.Hollister@Sun.COM 	}
142710696SDavid.Hollister@Sun.COM }
142810696SDavid.Hollister@Sun.COM 
142910696SDavid.Hollister@Sun.COM /*
143010696SDavid.Hollister@Sun.COM  * MAX_INST_STRLEN is the largest string size from which we will attempt
143110696SDavid.Hollister@Sun.COM  * to convert to an instance number.  The string will be formed up as
143210696SDavid.Hollister@Sun.COM  * "0t<inst>\0" so that mdb_strtoull can parse it properly.
143310696SDavid.Hollister@Sun.COM  */
143410696SDavid.Hollister@Sun.COM #define	MAX_INST_STRLEN	8
143510696SDavid.Hollister@Sun.COM 
143610696SDavid.Hollister@Sun.COM static int
143710696SDavid.Hollister@Sun.COM pmcs_dump_tracelog(boolean_t filter, int instance)
143810696SDavid.Hollister@Sun.COM {
143910696SDavid.Hollister@Sun.COM 	pmcs_tbuf_t *tbuf_addr;
144010696SDavid.Hollister@Sun.COM 	uint_t tbuf_idx;
144110696SDavid.Hollister@Sun.COM 	pmcs_tbuf_t tbuf;
144210696SDavid.Hollister@Sun.COM 	boolean_t wrap, elem_filtered;
144310696SDavid.Hollister@Sun.COM 	uint_t start_idx, elems_to_print, idx, tbuf_num_elems;
144410696SDavid.Hollister@Sun.COM 	char *bufp;
144510696SDavid.Hollister@Sun.COM 	char elem_inst[MAX_INST_STRLEN], ei_idx;
144610696SDavid.Hollister@Sun.COM 
144710696SDavid.Hollister@Sun.COM 	/* Get the address of the first element */
144810696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&tbuf_addr, "pmcs_tbuf") == -1) {
144910696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf");
145010696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
145110696SDavid.Hollister@Sun.COM 	}
145210696SDavid.Hollister@Sun.COM 
145310696SDavid.Hollister@Sun.COM 	/* Get the total number */
145410696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&tbuf_num_elems, "pmcs_tbuf_num_elems") == -1) {
145510696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf_num_elems");
145610696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
145710696SDavid.Hollister@Sun.COM 	}
145810696SDavid.Hollister@Sun.COM 
145910696SDavid.Hollister@Sun.COM 	/* Get the current index */
146010696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&tbuf_idx, "pmcs_tbuf_idx") == -1) {
146110696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf_idx");
146210696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
146310696SDavid.Hollister@Sun.COM 	}
146410696SDavid.Hollister@Sun.COM 
146510696SDavid.Hollister@Sun.COM 	/* Indicator as to whether the buffer has wrapped */
146610696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&wrap, "pmcs_tbuf_wrap") == -1) {
146710696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf_wrap");
146810696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
146910696SDavid.Hollister@Sun.COM 	}
147010696SDavid.Hollister@Sun.COM 
147110696SDavid.Hollister@Sun.COM 	/* Figure out where we start and stop */
147210696SDavid.Hollister@Sun.COM 	if (wrap) {
147310696SDavid.Hollister@Sun.COM 		start_idx = tbuf_idx;
147410696SDavid.Hollister@Sun.COM 		elems_to_print = tbuf_num_elems;
147510696SDavid.Hollister@Sun.COM 	} else {
147610696SDavid.Hollister@Sun.COM 		start_idx = 0;
147710696SDavid.Hollister@Sun.COM 		elems_to_print = tbuf_idx;
147810696SDavid.Hollister@Sun.COM 	}
147910696SDavid.Hollister@Sun.COM 
148010696SDavid.Hollister@Sun.COM 	idx = start_idx;
148110696SDavid.Hollister@Sun.COM 
148210696SDavid.Hollister@Sun.COM 	/* Dump the buffer contents */
148310696SDavid.Hollister@Sun.COM 	while (elems_to_print != 0) {
148410696SDavid.Hollister@Sun.COM 		if (MDB_RD(&tbuf, sizeof (pmcs_tbuf_t), (tbuf_addr + idx))
148510696SDavid.Hollister@Sun.COM 		    == -1) {
148610696SDavid.Hollister@Sun.COM 			NOREAD(tbuf, (tbuf_addr + idx));
148710696SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
148810696SDavid.Hollister@Sun.COM 		}
148910696SDavid.Hollister@Sun.COM 
149010696SDavid.Hollister@Sun.COM 		elem_filtered = B_FALSE;
149110696SDavid.Hollister@Sun.COM 
149210696SDavid.Hollister@Sun.COM 		if (filter) {
149310696SDavid.Hollister@Sun.COM 			bufp = tbuf.buf;
149410696SDavid.Hollister@Sun.COM 			/* Skip the driver name */
149510696SDavid.Hollister@Sun.COM 			while (*bufp < '0' || *bufp > '9') {
149610696SDavid.Hollister@Sun.COM 				bufp++;
149710696SDavid.Hollister@Sun.COM 			}
149810696SDavid.Hollister@Sun.COM 
149910696SDavid.Hollister@Sun.COM 			ei_idx = 0;
150010696SDavid.Hollister@Sun.COM 			elem_inst[ei_idx++] = '0';
150110696SDavid.Hollister@Sun.COM 			elem_inst[ei_idx++] = 't';
150210696SDavid.Hollister@Sun.COM 			while (*bufp != ':' && ei_idx < (MAX_INST_STRLEN - 1)) {
150310696SDavid.Hollister@Sun.COM 				elem_inst[ei_idx++] = *bufp;
150410696SDavid.Hollister@Sun.COM 				bufp++;
150510696SDavid.Hollister@Sun.COM 			}
150610696SDavid.Hollister@Sun.COM 			elem_inst[ei_idx] = 0;
150710696SDavid.Hollister@Sun.COM 
150810696SDavid.Hollister@Sun.COM 			/* Get the instance */
150910696SDavid.Hollister@Sun.COM 			if ((int)mdb_strtoull(elem_inst) != instance) {
151010696SDavid.Hollister@Sun.COM 				elem_filtered = B_TRUE;
151110696SDavid.Hollister@Sun.COM 			}
151210696SDavid.Hollister@Sun.COM 		}
151310696SDavid.Hollister@Sun.COM 
151410696SDavid.Hollister@Sun.COM 		if (!elem_filtered) {
151510696SDavid.Hollister@Sun.COM 			mdb_printf("%Y.%09ld %s\n", tbuf.timestamp, tbuf.buf);
151610696SDavid.Hollister@Sun.COM 		}
151710696SDavid.Hollister@Sun.COM 
151810696SDavid.Hollister@Sun.COM 		--elems_to_print;
151910696SDavid.Hollister@Sun.COM 		if (++idx == tbuf_num_elems) {
152010696SDavid.Hollister@Sun.COM 			idx = 0;
152110696SDavid.Hollister@Sun.COM 		}
152210696SDavid.Hollister@Sun.COM 	}
152310696SDavid.Hollister@Sun.COM 
152410696SDavid.Hollister@Sun.COM 	return (DCMD_OK);
152510696SDavid.Hollister@Sun.COM }
152610696SDavid.Hollister@Sun.COM 
152710696SDavid.Hollister@Sun.COM /*
152810696SDavid.Hollister@Sun.COM  * Walkers
152910696SDavid.Hollister@Sun.COM  */
153010696SDavid.Hollister@Sun.COM static int
153110696SDavid.Hollister@Sun.COM targets_walk_i(mdb_walk_state_t *wsp)
153210696SDavid.Hollister@Sun.COM {
153310696SDavid.Hollister@Sun.COM 	if (wsp->walk_addr == NULL) {
153410696SDavid.Hollister@Sun.COM 		mdb_warn("Can not perform global walk\n");
153510696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
153610696SDavid.Hollister@Sun.COM 	}
153710696SDavid.Hollister@Sun.COM 
153810696SDavid.Hollister@Sun.COM 	/*
153910696SDavid.Hollister@Sun.COM 	 * Address provided belongs to HBA softstate.  Get the targets pointer
154010696SDavid.Hollister@Sun.COM 	 * to begin the walk.
154110696SDavid.Hollister@Sun.COM 	 */
154210696SDavid.Hollister@Sun.COM 	if (mdb_vread(&ss, sizeof (pmcs_hw_t), wsp->walk_addr) !=
154310696SDavid.Hollister@Sun.COM 	    sizeof (pmcs_hw_t)) {
154410696SDavid.Hollister@Sun.COM 		mdb_warn("Unable to read HBA softstate\n");
154510696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
154610696SDavid.Hollister@Sun.COM 	}
154710696SDavid.Hollister@Sun.COM 
154810696SDavid.Hollister@Sun.COM 	if (targets == NULL) {
154910696SDavid.Hollister@Sun.COM 		targets = mdb_alloc(sizeof (targets) * ss.max_dev, UM_SLEEP);
155010696SDavid.Hollister@Sun.COM 	}
155110696SDavid.Hollister@Sun.COM 
155210696SDavid.Hollister@Sun.COM 	if (MDB_RD(targets, sizeof (targets) * ss.max_dev, ss.targets) == -1) {
155310696SDavid.Hollister@Sun.COM 		NOREAD(targets, ss.targets);
155410696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
155510696SDavid.Hollister@Sun.COM 	}
155610696SDavid.Hollister@Sun.COM 
155710696SDavid.Hollister@Sun.COM 	target_idx = 0;
155810696SDavid.Hollister@Sun.COM 	wsp->walk_addr = (uintptr_t)(targets[0]);
155910696SDavid.Hollister@Sun.COM 	wsp->walk_data = mdb_alloc(sizeof (pmcs_xscsi_t), UM_SLEEP);
156010696SDavid.Hollister@Sun.COM 
156110696SDavid.Hollister@Sun.COM 	return (WALK_NEXT);
156210696SDavid.Hollister@Sun.COM }
156310696SDavid.Hollister@Sun.COM 
156410696SDavid.Hollister@Sun.COM static int
156510696SDavid.Hollister@Sun.COM targets_walk_s(mdb_walk_state_t *wsp)
156610696SDavid.Hollister@Sun.COM {
156710696SDavid.Hollister@Sun.COM 	int status;
156810696SDavid.Hollister@Sun.COM 
156910696SDavid.Hollister@Sun.COM 	if (target_idx == ss.max_dev) {
157010696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
157110696SDavid.Hollister@Sun.COM 	}
157210696SDavid.Hollister@Sun.COM 
157310696SDavid.Hollister@Sun.COM 	if (mdb_vread(wsp->walk_data, sizeof (pmcs_xscsi_t),
157410696SDavid.Hollister@Sun.COM 	    wsp->walk_addr) == -1) {
157510696SDavid.Hollister@Sun.COM 		mdb_warn("Failed to read target at %p", (void *)wsp->walk_addr);
157610696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
157710696SDavid.Hollister@Sun.COM 	}
157810696SDavid.Hollister@Sun.COM 
157910696SDavid.Hollister@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
158010696SDavid.Hollister@Sun.COM 	    wsp->walk_cbdata);
158110696SDavid.Hollister@Sun.COM 
158210696SDavid.Hollister@Sun.COM 	do {
158310696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)(targets[++target_idx]);
158410696SDavid.Hollister@Sun.COM 	} while ((wsp->walk_addr == NULL) && (target_idx < ss.max_dev));
158510696SDavid.Hollister@Sun.COM 
158610696SDavid.Hollister@Sun.COM 	if (target_idx == ss.max_dev) {
158710696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
158810696SDavid.Hollister@Sun.COM 	}
158910696SDavid.Hollister@Sun.COM 
159010696SDavid.Hollister@Sun.COM 	return (status);
159110696SDavid.Hollister@Sun.COM }
159210696SDavid.Hollister@Sun.COM 
159310696SDavid.Hollister@Sun.COM static void
159410696SDavid.Hollister@Sun.COM targets_walk_f(mdb_walk_state_t *wsp)
159510696SDavid.Hollister@Sun.COM {
159610696SDavid.Hollister@Sun.COM 	mdb_free(wsp->walk_data, sizeof (pmcs_xscsi_t));
159710696SDavid.Hollister@Sun.COM }
159810696SDavid.Hollister@Sun.COM 
159910696SDavid.Hollister@Sun.COM 
160010696SDavid.Hollister@Sun.COM static pmcs_phy_t *
160110696SDavid.Hollister@Sun.COM pmcs_next_sibling(pmcs_phy_t *phyp)
160210696SDavid.Hollister@Sun.COM {
160310696SDavid.Hollister@Sun.COM 	pmcs_phy_t parent;
160410696SDavid.Hollister@Sun.COM 
160510696SDavid.Hollister@Sun.COM 	/*
160610696SDavid.Hollister@Sun.COM 	 * First, if this is a root PHY, there are no more siblings
160710696SDavid.Hollister@Sun.COM 	 */
160810696SDavid.Hollister@Sun.COM 	if (phyp->level == 0) {
160910696SDavid.Hollister@Sun.COM 		return (NULL);
161010696SDavid.Hollister@Sun.COM 	}
161110696SDavid.Hollister@Sun.COM 
161210696SDavid.Hollister@Sun.COM 	/*
161310696SDavid.Hollister@Sun.COM 	 * Otherwise, next sibling is the parent's sibling
161410696SDavid.Hollister@Sun.COM 	 */
161510696SDavid.Hollister@Sun.COM 	while (phyp->level > 0) {
161610696SDavid.Hollister@Sun.COM 		if (mdb_vread(&parent, sizeof (pmcs_phy_t),
161710696SDavid.Hollister@Sun.COM 		    (uintptr_t)phyp->parent) == -1) {
161810696SDavid.Hollister@Sun.COM 			mdb_warn("pmcs_next_sibling: Failed to read PHY at %p",
161910696SDavid.Hollister@Sun.COM 			    (void *)phyp->parent);
162010696SDavid.Hollister@Sun.COM 			return (NULL);
162110696SDavid.Hollister@Sun.COM 		}
162210696SDavid.Hollister@Sun.COM 
162310696SDavid.Hollister@Sun.COM 		if (parent.sibling != NULL) {
162410696SDavid.Hollister@Sun.COM 			break;
162510696SDavid.Hollister@Sun.COM 		}
162610696SDavid.Hollister@Sun.COM 
162710696SDavid.Hollister@Sun.COM 		phyp = phyp->parent;
162810696SDavid.Hollister@Sun.COM 	}
162910696SDavid.Hollister@Sun.COM 
163010696SDavid.Hollister@Sun.COM 	return (parent.sibling);
163110696SDavid.Hollister@Sun.COM }
163210696SDavid.Hollister@Sun.COM 
163310696SDavid.Hollister@Sun.COM static int
163410696SDavid.Hollister@Sun.COM phy_walk_i(mdb_walk_state_t *wsp)
163510696SDavid.Hollister@Sun.COM {
163610696SDavid.Hollister@Sun.COM 	if (wsp->walk_addr == NULL) {
163710696SDavid.Hollister@Sun.COM 		mdb_warn("Can not perform global walk\n");
163810696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
163910696SDavid.Hollister@Sun.COM 	}
164010696SDavid.Hollister@Sun.COM 
164110696SDavid.Hollister@Sun.COM 	/*
164210696SDavid.Hollister@Sun.COM 	 * Address provided belongs to HBA softstate.  Get the targets pointer
164310696SDavid.Hollister@Sun.COM 	 * to begin the walk.
164410696SDavid.Hollister@Sun.COM 	 */
164510696SDavid.Hollister@Sun.COM 	if (mdb_vread(&ss, sizeof (pmcs_hw_t), wsp->walk_addr) !=
164610696SDavid.Hollister@Sun.COM 	    sizeof (pmcs_hw_t)) {
164710696SDavid.Hollister@Sun.COM 		mdb_warn("Unable to read HBA softstate\n");
164810696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
164910696SDavid.Hollister@Sun.COM 	}
165010696SDavid.Hollister@Sun.COM 
165110696SDavid.Hollister@Sun.COM 	wsp->walk_addr = (uintptr_t)(ss.root_phys);
165210696SDavid.Hollister@Sun.COM 	wsp->walk_data = mdb_alloc(sizeof (pmcs_phy_t), UM_SLEEP);
165310696SDavid.Hollister@Sun.COM 
165410696SDavid.Hollister@Sun.COM 	return (WALK_NEXT);
165510696SDavid.Hollister@Sun.COM }
165610696SDavid.Hollister@Sun.COM 
165710696SDavid.Hollister@Sun.COM static int
165810696SDavid.Hollister@Sun.COM phy_walk_s(mdb_walk_state_t *wsp)
165910696SDavid.Hollister@Sun.COM {
166010696SDavid.Hollister@Sun.COM 	pmcs_phy_t *phyp, *nphyp;
166110696SDavid.Hollister@Sun.COM 	int status;
166210696SDavid.Hollister@Sun.COM 
166310696SDavid.Hollister@Sun.COM 	if (mdb_vread(wsp->walk_data, sizeof (pmcs_phy_t),
166410696SDavid.Hollister@Sun.COM 	    wsp->walk_addr) == -1) {
166510696SDavid.Hollister@Sun.COM 		mdb_warn("phy_walk_s: Failed to read PHY at %p",
166610696SDavid.Hollister@Sun.COM 		    (void *)wsp->walk_addr);
166710696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
166810696SDavid.Hollister@Sun.COM 	}
166910696SDavid.Hollister@Sun.COM 
167010696SDavid.Hollister@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
167110696SDavid.Hollister@Sun.COM 	    wsp->walk_cbdata);
167210696SDavid.Hollister@Sun.COM 
167310696SDavid.Hollister@Sun.COM 	phyp = (pmcs_phy_t *)wsp->walk_data;
167410696SDavid.Hollister@Sun.COM 	if (phyp->children) {
167510696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)(phyp->children);
167610696SDavid.Hollister@Sun.COM 	} else {
167710696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)(phyp->sibling);
167810696SDavid.Hollister@Sun.COM 	}
167910696SDavid.Hollister@Sun.COM 
168010696SDavid.Hollister@Sun.COM 	if (wsp->walk_addr == NULL) {
168110696SDavid.Hollister@Sun.COM 		/*
168210696SDavid.Hollister@Sun.COM 		 * We reached the end of this sibling list.  Trudge back up
168310696SDavid.Hollister@Sun.COM 		 * to the parent and find the next sibling after the expander
168410696SDavid.Hollister@Sun.COM 		 * we just finished traversing, if there is one.
168510696SDavid.Hollister@Sun.COM 		 */
168610696SDavid.Hollister@Sun.COM 		nphyp = pmcs_next_sibling(phyp);
168710696SDavid.Hollister@Sun.COM 
168810696SDavid.Hollister@Sun.COM 		if (nphyp == NULL) {
168910696SDavid.Hollister@Sun.COM 			return (WALK_DONE);
169010696SDavid.Hollister@Sun.COM 		}
169110696SDavid.Hollister@Sun.COM 
169210696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)nphyp;
169310696SDavid.Hollister@Sun.COM 	}
169410696SDavid.Hollister@Sun.COM 
169510696SDavid.Hollister@Sun.COM 	return (status);
169610696SDavid.Hollister@Sun.COM }
169710696SDavid.Hollister@Sun.COM 
169810696SDavid.Hollister@Sun.COM static void
169910696SDavid.Hollister@Sun.COM phy_walk_f(mdb_walk_state_t *wsp)
170010696SDavid.Hollister@Sun.COM {
170110696SDavid.Hollister@Sun.COM 	mdb_free(wsp->walk_data, sizeof (pmcs_phy_t));
170210696SDavid.Hollister@Sun.COM }
170310696SDavid.Hollister@Sun.COM 
170410743SDavid.Hollister@Sun.COM static void
170510743SDavid.Hollister@Sun.COM display_matching_work(struct pmcs_hw ss, uintmax_t index, uintmax_t snum,
170610743SDavid.Hollister@Sun.COM     uintmax_t tag_type)
170710743SDavid.Hollister@Sun.COM {
170810743SDavid.Hollister@Sun.COM 	int		idx;
170910743SDavid.Hollister@Sun.COM 	pmcwork_t	work, *wp = &work;
171010743SDavid.Hollister@Sun.COM 	uintptr_t	_wp;
171110743SDavid.Hollister@Sun.COM 	boolean_t	printed_header = B_FALSE;
171210743SDavid.Hollister@Sun.COM 	uint32_t	mask, mask_val, match_val;
171310743SDavid.Hollister@Sun.COM 	char		*match_type;
171410743SDavid.Hollister@Sun.COM 
171510743SDavid.Hollister@Sun.COM 	if (index != UINT_MAX) {
171610743SDavid.Hollister@Sun.COM 		match_type = "index";
171710743SDavid.Hollister@Sun.COM 		mask = PMCS_TAG_INDEX_MASK;
171810743SDavid.Hollister@Sun.COM 		mask_val = index << PMCS_TAG_INDEX_SHIFT;
171910743SDavid.Hollister@Sun.COM 		match_val = index;
172010743SDavid.Hollister@Sun.COM 	} else if (snum != UINT_MAX) {
172110743SDavid.Hollister@Sun.COM 		match_type = "serial number";
172210743SDavid.Hollister@Sun.COM 		mask = PMCS_TAG_SERNO_MASK;
172310743SDavid.Hollister@Sun.COM 		mask_val = snum << PMCS_TAG_SERNO_SHIFT;
172410743SDavid.Hollister@Sun.COM 		match_val = snum;
172510743SDavid.Hollister@Sun.COM 	} else {
172610743SDavid.Hollister@Sun.COM 		switch (tag_type) {
172710743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_NONE:
172810743SDavid.Hollister@Sun.COM 			match_type = "tag type NONE";
172910743SDavid.Hollister@Sun.COM 			break;
173010743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_CBACK:
173110743SDavid.Hollister@Sun.COM 			match_type = "tag type CBACK";
173210743SDavid.Hollister@Sun.COM 			break;
173310743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_WAIT:
173410743SDavid.Hollister@Sun.COM 			match_type = "tag type WAIT";
173510743SDavid.Hollister@Sun.COM 			break;
173610743SDavid.Hollister@Sun.COM 		}
173710743SDavid.Hollister@Sun.COM 		mask = PMCS_TAG_TYPE_MASK;
173810743SDavid.Hollister@Sun.COM 		mask_val = tag_type << PMCS_TAG_TYPE_SHIFT;
173910743SDavid.Hollister@Sun.COM 		match_val = tag_type;
174010743SDavid.Hollister@Sun.COM 	}
174110743SDavid.Hollister@Sun.COM 
174210743SDavid.Hollister@Sun.COM 	_wp = (uintptr_t)ss.work;
174310743SDavid.Hollister@Sun.COM 
174410743SDavid.Hollister@Sun.COM 	for (idx = 0; idx < ss.max_cmd; idx++, _wp += sizeof (pmcwork_t)) {
174510743SDavid.Hollister@Sun.COM 		if (MDB_RD(&work, sizeof (pmcwork_t), _wp) == -1) {
174610743SDavid.Hollister@Sun.COM 			NOREAD(pmcwork_t, _wp);
174710743SDavid.Hollister@Sun.COM 			continue;
174810743SDavid.Hollister@Sun.COM 		}
174910743SDavid.Hollister@Sun.COM 
175010743SDavid.Hollister@Sun.COM 		if ((work.htag & mask) != mask_val) {
175110743SDavid.Hollister@Sun.COM 			continue;
175210743SDavid.Hollister@Sun.COM 		}
175310743SDavid.Hollister@Sun.COM 
175410743SDavid.Hollister@Sun.COM 		if (printed_header == B_FALSE) {
175510743SDavid.Hollister@Sun.COM 			if (tag_type) {
175610743SDavid.Hollister@Sun.COM 				mdb_printf("\nWork structures matching %s\n\n",
175710743SDavid.Hollister@Sun.COM 				    match_type, match_val);
175810743SDavid.Hollister@Sun.COM 			} else {
175910743SDavid.Hollister@Sun.COM 				mdb_printf("\nWork structures matching %s of "
176010743SDavid.Hollister@Sun.COM 				    "0x%x\n\n", match_type, match_val);
176110743SDavid.Hollister@Sun.COM 			}
176210743SDavid.Hollister@Sun.COM 			mdb_printf("%8s %10s %20s %8s %8s O D\n",
176310743SDavid.Hollister@Sun.COM 			    "HTag", "State", "Phy Path", "Target", "Timer");
176410743SDavid.Hollister@Sun.COM 			printed_header = B_TRUE;
176510743SDavid.Hollister@Sun.COM 		}
176610743SDavid.Hollister@Sun.COM 
176710743SDavid.Hollister@Sun.COM 		display_one_work(wp, 0, 0);
176810743SDavid.Hollister@Sun.COM 	}
176910743SDavid.Hollister@Sun.COM 
177010743SDavid.Hollister@Sun.COM 	if (!printed_header) {
177110743SDavid.Hollister@Sun.COM 		mdb_printf("No work structure matches found\n");
177210743SDavid.Hollister@Sun.COM 	}
177310743SDavid.Hollister@Sun.COM }
177410743SDavid.Hollister@Sun.COM 
177510743SDavid.Hollister@Sun.COM static int
177610743SDavid.Hollister@Sun.COM pmcs_tag(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
177710743SDavid.Hollister@Sun.COM {
177810743SDavid.Hollister@Sun.COM 	struct	pmcs_hw		ss;
177910743SDavid.Hollister@Sun.COM 	uintmax_t		tag_type = UINT_MAX;
178010743SDavid.Hollister@Sun.COM 	uintmax_t		snum = UINT_MAX;
178110743SDavid.Hollister@Sun.COM 	uintmax_t		index = UINT_MAX;
178210743SDavid.Hollister@Sun.COM 	int			args = 0;
178310743SDavid.Hollister@Sun.COM 	void			*pmcs_state;
178410743SDavid.Hollister@Sun.COM 	char			*state_str;
178510743SDavid.Hollister@Sun.COM 	struct dev_info		dip;
178610743SDavid.Hollister@Sun.COM 
178710743SDavid.Hollister@Sun.COM 	if (!(flags & DCMD_ADDRSPEC)) {
178810743SDavid.Hollister@Sun.COM 		pmcs_state = NULL;
178910743SDavid.Hollister@Sun.COM 		if (mdb_readvar(&pmcs_state, "pmcs_softc_state") == -1) {
179010743SDavid.Hollister@Sun.COM 			mdb_warn("can't read pmcs_softc_state");
179110743SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
179210743SDavid.Hollister@Sun.COM 		}
179310743SDavid.Hollister@Sun.COM 		if (mdb_pwalk_dcmd("genunix`softstate", "pmcs`pmcs_tag", argc,
179410743SDavid.Hollister@Sun.COM 		    argv, (uintptr_t)pmcs_state) == -1) {
179510743SDavid.Hollister@Sun.COM 			mdb_warn("mdb_pwalk_dcmd failed");
179610743SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
179710743SDavid.Hollister@Sun.COM 		}
179810743SDavid.Hollister@Sun.COM 		return (DCMD_OK);
179910743SDavid.Hollister@Sun.COM 	}
180010743SDavid.Hollister@Sun.COM 
180110743SDavid.Hollister@Sun.COM 	if (mdb_getopts(argc, argv,
180210743SDavid.Hollister@Sun.COM 	    'i', MDB_OPT_UINT64, &index,
180310743SDavid.Hollister@Sun.COM 	    's', MDB_OPT_UINT64, &snum,
180410743SDavid.Hollister@Sun.COM 	    't', MDB_OPT_UINT64, &tag_type) != argc)
180510743SDavid.Hollister@Sun.COM 		return (DCMD_USAGE);
180610743SDavid.Hollister@Sun.COM 
180710743SDavid.Hollister@Sun.COM 	/*
180810743SDavid.Hollister@Sun.COM 	 * Count the number of supplied options and make sure they are
180910743SDavid.Hollister@Sun.COM 	 * within appropriate ranges.  If they're set to UINT_MAX, that means
181010743SDavid.Hollister@Sun.COM 	 * they were not supplied, in which case reset them to 0.
181110743SDavid.Hollister@Sun.COM 	 */
181210743SDavid.Hollister@Sun.COM 	if (index != UINT_MAX) {
181310743SDavid.Hollister@Sun.COM 		args++;
181410743SDavid.Hollister@Sun.COM 		if (index > PMCS_TAG_INDEX_MASK) {
181510743SDavid.Hollister@Sun.COM 			mdb_warn("Index is out of range\n");
181610743SDavid.Hollister@Sun.COM 			return (DCMD_USAGE);
181710743SDavid.Hollister@Sun.COM 		}
181810743SDavid.Hollister@Sun.COM 	}
181910743SDavid.Hollister@Sun.COM 
182010743SDavid.Hollister@Sun.COM 	if (tag_type != UINT_MAX) {
182110743SDavid.Hollister@Sun.COM 		args++;
182210743SDavid.Hollister@Sun.COM 		switch (tag_type) {
182310743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_NONE:
182410743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_CBACK:
182510743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_WAIT:
182610743SDavid.Hollister@Sun.COM 			break;
182710743SDavid.Hollister@Sun.COM 		default:
182810743SDavid.Hollister@Sun.COM 			mdb_warn("Invalid tag type\n");
182910743SDavid.Hollister@Sun.COM 			return (DCMD_USAGE);
183010743SDavid.Hollister@Sun.COM 		}
183110743SDavid.Hollister@Sun.COM 	}
183210743SDavid.Hollister@Sun.COM 
183310743SDavid.Hollister@Sun.COM 	if (snum != UINT_MAX) {
183410743SDavid.Hollister@Sun.COM 		args++;
183510743SDavid.Hollister@Sun.COM 		if (snum > (PMCS_TAG_SERNO_MASK >> PMCS_TAG_SERNO_SHIFT)) {
183610743SDavid.Hollister@Sun.COM 			mdb_warn("Serial number is out of range\n");
183710743SDavid.Hollister@Sun.COM 			return (DCMD_USAGE);
183810743SDavid.Hollister@Sun.COM 		}
183910743SDavid.Hollister@Sun.COM 	}
184010743SDavid.Hollister@Sun.COM 
184110743SDavid.Hollister@Sun.COM 	/*
184210743SDavid.Hollister@Sun.COM 	 * Make sure 1 and only 1 option is specified
184310743SDavid.Hollister@Sun.COM 	 */
184410743SDavid.Hollister@Sun.COM 	if ((args == 0) || (args > 1)) {
184510743SDavid.Hollister@Sun.COM 		mdb_warn("Exactly one of -i, -s and -t must be specified\n");
184610743SDavid.Hollister@Sun.COM 		return (DCMD_USAGE);
184710743SDavid.Hollister@Sun.COM 	}
184810743SDavid.Hollister@Sun.COM 
184910743SDavid.Hollister@Sun.COM 	if (MDB_RD(&ss, sizeof (ss), addr) == -1) {
185010743SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
185110743SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
185210743SDavid.Hollister@Sun.COM 	}
185310743SDavid.Hollister@Sun.COM 
185410743SDavid.Hollister@Sun.COM 	if (MDB_RD(&dip, sizeof (struct dev_info), ss.dip) == -1) {
185510743SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
185610743SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
185710743SDavid.Hollister@Sun.COM 	}
185810743SDavid.Hollister@Sun.COM 
185910743SDavid.Hollister@Sun.COM 	/* processing completed */
186010743SDavid.Hollister@Sun.COM 
186110743SDavid.Hollister@Sun.COM 	if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) ||
186210743SDavid.Hollister@Sun.COM 	    (flags & DCMD_LOOPFIRST)) {
186310743SDavid.Hollister@Sun.COM 		if ((flags & DCMD_LOOP) && !(flags & DCMD_LOOPFIRST))
186410743SDavid.Hollister@Sun.COM 			mdb_printf("\n");
186510743SDavid.Hollister@Sun.COM 		mdb_printf("%16s %9s %4s B C  WorkFlags wserno DbgMsk %16s\n",
186610743SDavid.Hollister@Sun.COM 		    "Address", "State", "Inst", "DIP");
186710743SDavid.Hollister@Sun.COM 		mdb_printf("================================="
186810743SDavid.Hollister@Sun.COM 		    "============================================\n");
186910743SDavid.Hollister@Sun.COM 	}
187010743SDavid.Hollister@Sun.COM 
187110743SDavid.Hollister@Sun.COM 	switch (ss.state) {
187210743SDavid.Hollister@Sun.COM 	case STATE_NIL:
187310743SDavid.Hollister@Sun.COM 		state_str = "Invalid";
187410743SDavid.Hollister@Sun.COM 		break;
187510743SDavid.Hollister@Sun.COM 	case STATE_PROBING:
187610743SDavid.Hollister@Sun.COM 		state_str = "Probing";
187710743SDavid.Hollister@Sun.COM 		break;
187810743SDavid.Hollister@Sun.COM 	case STATE_RUNNING:
187910743SDavid.Hollister@Sun.COM 		state_str = "Running";
188010743SDavid.Hollister@Sun.COM 		break;
188110743SDavid.Hollister@Sun.COM 	case STATE_UNPROBING:
188210743SDavid.Hollister@Sun.COM 		state_str = "Unprobing";
188310743SDavid.Hollister@Sun.COM 		break;
188410743SDavid.Hollister@Sun.COM 	case STATE_DEAD:
188510743SDavid.Hollister@Sun.COM 		state_str = "Dead";
188610743SDavid.Hollister@Sun.COM 		break;
188710743SDavid.Hollister@Sun.COM 	}
188810743SDavid.Hollister@Sun.COM 
188910743SDavid.Hollister@Sun.COM 	mdb_printf("%16p %9s %4d %1d %1d 0x%08x 0x%04x 0x%04x %16p\n", addr,
189010743SDavid.Hollister@Sun.COM 	    state_str, dip.devi_instance, ss.blocked, ss.configuring,
189110743SDavid.Hollister@Sun.COM 	    ss.work_flags, ss.wserno, ss.debug_mask, ss.dip);
189210743SDavid.Hollister@Sun.COM 	mdb_printf("\n");
189310743SDavid.Hollister@Sun.COM 
189410743SDavid.Hollister@Sun.COM 	mdb_inc_indent(4);
189510743SDavid.Hollister@Sun.COM 	display_matching_work(ss, index, snum, tag_type);
189610743SDavid.Hollister@Sun.COM 	mdb_dec_indent(4);
189710743SDavid.Hollister@Sun.COM 	mdb_printf("\n");
189810743SDavid.Hollister@Sun.COM 
189910743SDavid.Hollister@Sun.COM 	return (DCMD_OK);
190010743SDavid.Hollister@Sun.COM }
190110743SDavid.Hollister@Sun.COM 
190210696SDavid.Hollister@Sun.COM static int
190310696SDavid.Hollister@Sun.COM pmcs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
190410696SDavid.Hollister@Sun.COM {
190510696SDavid.Hollister@Sun.COM 	struct	pmcs_hw		ss;
190610696SDavid.Hollister@Sun.COM 	uint_t			verbose = FALSE;
190710696SDavid.Hollister@Sun.COM 	uint_t			phy_info = FALSE;
190810696SDavid.Hollister@Sun.COM 	uint_t			hw_info = FALSE;
190910696SDavid.Hollister@Sun.COM 	uint_t			target_info = FALSE;
191010696SDavid.Hollister@Sun.COM 	uint_t			work_info = FALSE;
191110696SDavid.Hollister@Sun.COM 	uint_t			ic_info = FALSE;
191210696SDavid.Hollister@Sun.COM 	uint_t			iport_info = FALSE;
191310696SDavid.Hollister@Sun.COM 	uint_t			waitqs_info = FALSE;
191410696SDavid.Hollister@Sun.COM 	uint_t			tracelog = FALSE;
191510696SDavid.Hollister@Sun.COM 	uint_t			ibq = FALSE;
191610696SDavid.Hollister@Sun.COM 	uint_t			obq = FALSE;
191710696SDavid.Hollister@Sun.COM 	uint_t			tgt_phy_count = FALSE;
191810743SDavid.Hollister@Sun.COM 	uint_t			compq = FALSE;
191910696SDavid.Hollister@Sun.COM 	int			rv = DCMD_OK;
192010696SDavid.Hollister@Sun.COM 	void			*pmcs_state;
192110696SDavid.Hollister@Sun.COM 	char			*state_str;
192210696SDavid.Hollister@Sun.COM 	struct dev_info		dip;
192310696SDavid.Hollister@Sun.COM 
192410696SDavid.Hollister@Sun.COM 	if (!(flags & DCMD_ADDRSPEC)) {
192510696SDavid.Hollister@Sun.COM 		pmcs_state = NULL;
192610696SDavid.Hollister@Sun.COM 		if (mdb_readvar(&pmcs_state, "pmcs_softc_state") == -1) {
192710696SDavid.Hollister@Sun.COM 			mdb_warn("can't read pmcs_softc_state");
192810696SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
192910696SDavid.Hollister@Sun.COM 		}
193010696SDavid.Hollister@Sun.COM 		if (mdb_pwalk_dcmd("genunix`softstate", "pmcs`pmcs", argc, argv,
193110696SDavid.Hollister@Sun.COM 		    (uintptr_t)pmcs_state) == -1) {
193210696SDavid.Hollister@Sun.COM 			mdb_warn("mdb_pwalk_dcmd failed");
193310696SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
193410696SDavid.Hollister@Sun.COM 		}
193510696SDavid.Hollister@Sun.COM 		return (DCMD_OK);
193610696SDavid.Hollister@Sun.COM 	}
193710696SDavid.Hollister@Sun.COM 
193810696SDavid.Hollister@Sun.COM 	if (mdb_getopts(argc, argv,
193910743SDavid.Hollister@Sun.COM 	    'c', MDB_OPT_SETBITS, TRUE, &compq,
194010696SDavid.Hollister@Sun.COM 	    'h', MDB_OPT_SETBITS, TRUE, &hw_info,
194110696SDavid.Hollister@Sun.COM 	    'i', MDB_OPT_SETBITS, TRUE, &ic_info,
194210696SDavid.Hollister@Sun.COM 	    'I', MDB_OPT_SETBITS, TRUE, &iport_info,
194310696SDavid.Hollister@Sun.COM 	    'l', MDB_OPT_SETBITS, TRUE, &tracelog,
194410696SDavid.Hollister@Sun.COM 	    'p', MDB_OPT_SETBITS, TRUE, &phy_info,
194510696SDavid.Hollister@Sun.COM 	    'q', MDB_OPT_SETBITS, TRUE, &ibq,
194610696SDavid.Hollister@Sun.COM 	    'Q', MDB_OPT_SETBITS, TRUE, &obq,
194710696SDavid.Hollister@Sun.COM 	    't', MDB_OPT_SETBITS, TRUE, &target_info,
194810696SDavid.Hollister@Sun.COM 	    'T', MDB_OPT_SETBITS, TRUE, &tgt_phy_count,
194910696SDavid.Hollister@Sun.COM 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
195010696SDavid.Hollister@Sun.COM 	    'w', MDB_OPT_SETBITS, TRUE, &work_info,
195110696SDavid.Hollister@Sun.COM 	    'W', MDB_OPT_SETBITS, TRUE, &waitqs_info,
195210696SDavid.Hollister@Sun.COM 	    NULL) != argc)
195310696SDavid.Hollister@Sun.COM 		return (DCMD_USAGE);
195410696SDavid.Hollister@Sun.COM 
195510696SDavid.Hollister@Sun.COM 	if (MDB_RD(&ss, sizeof (ss), addr) == -1) {
195610696SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
195710696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
195810696SDavid.Hollister@Sun.COM 	}
195910696SDavid.Hollister@Sun.COM 
196010696SDavid.Hollister@Sun.COM 	if (MDB_RD(&dip, sizeof (struct dev_info), ss.dip) == -1) {
196110696SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
196210696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
196310696SDavid.Hollister@Sun.COM 	}
196410696SDavid.Hollister@Sun.COM 
196510696SDavid.Hollister@Sun.COM 	/*
196610696SDavid.Hollister@Sun.COM 	 * Dumping the trace log is special.  It's global, not per-HBA.
196710696SDavid.Hollister@Sun.COM 	 * Thus, a provided address is ignored.  In addition, other options
196810696SDavid.Hollister@Sun.COM 	 * cannot be specified at the same time.
196910696SDavid.Hollister@Sun.COM 	 */
197010696SDavid.Hollister@Sun.COM 	if (tracelog) {
197110696SDavid.Hollister@Sun.COM 		if (hw_info || ic_info || iport_info || phy_info || work_info ||
197210743SDavid.Hollister@Sun.COM 		    target_info || waitqs_info || ibq || obq || tgt_phy_count ||
197310743SDavid.Hollister@Sun.COM 		    compq) {
197410696SDavid.Hollister@Sun.COM 			return (DCMD_USAGE);
197510696SDavid.Hollister@Sun.COM 		}
197610696SDavid.Hollister@Sun.COM 
197710696SDavid.Hollister@Sun.COM 		if ((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) {
197810696SDavid.Hollister@Sun.COM 			return (pmcs_dump_tracelog(B_TRUE, dip.devi_instance));
197910696SDavid.Hollister@Sun.COM 		} else if (flags & DCMD_LOOPFIRST) {
198010696SDavid.Hollister@Sun.COM 			return (pmcs_dump_tracelog(B_FALSE, 0));
198110696SDavid.Hollister@Sun.COM 		} else {
198210696SDavid.Hollister@Sun.COM 			return (DCMD_OK);
198310696SDavid.Hollister@Sun.COM 		}
198410696SDavid.Hollister@Sun.COM 	}
198510696SDavid.Hollister@Sun.COM 
198610696SDavid.Hollister@Sun.COM 	/* processing completed */
198710696SDavid.Hollister@Sun.COM 
198810696SDavid.Hollister@Sun.COM 	if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) ||
198910696SDavid.Hollister@Sun.COM 	    (flags & DCMD_LOOPFIRST) || phy_info || target_info || hw_info ||
199010743SDavid.Hollister@Sun.COM 	    work_info || waitqs_info || ibq || obq || tgt_phy_count || compq) {
199110696SDavid.Hollister@Sun.COM 		if ((flags & DCMD_LOOP) && !(flags & DCMD_LOOPFIRST))
199210696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
199310696SDavid.Hollister@Sun.COM 		mdb_printf("%16s %9s %4s B C  WorkFlags wserno DbgMsk %16s\n",
199410696SDavid.Hollister@Sun.COM 		    "Address", "State", "Inst", "DIP");
199510696SDavid.Hollister@Sun.COM 		mdb_printf("================================="
199610696SDavid.Hollister@Sun.COM 		    "============================================\n");
199710696SDavid.Hollister@Sun.COM 	}
199810696SDavid.Hollister@Sun.COM 
199910696SDavid.Hollister@Sun.COM 	switch (ss.state) {
200010696SDavid.Hollister@Sun.COM 	case STATE_NIL:
200110696SDavid.Hollister@Sun.COM 		state_str = "Invalid";
200210696SDavid.Hollister@Sun.COM 		break;
200310696SDavid.Hollister@Sun.COM 	case STATE_PROBING:
200410696SDavid.Hollister@Sun.COM 		state_str = "Probing";
200510696SDavid.Hollister@Sun.COM 		break;
200610696SDavid.Hollister@Sun.COM 	case STATE_RUNNING:
200710696SDavid.Hollister@Sun.COM 		state_str = "Running";
200810696SDavid.Hollister@Sun.COM 		break;
200910696SDavid.Hollister@Sun.COM 	case STATE_UNPROBING:
201010696SDavid.Hollister@Sun.COM 		state_str = "Unprobing";
201110696SDavid.Hollister@Sun.COM 		break;
201210696SDavid.Hollister@Sun.COM 	case STATE_DEAD:
201310696SDavid.Hollister@Sun.COM 		state_str = "Dead";
201410696SDavid.Hollister@Sun.COM 		break;
201510696SDavid.Hollister@Sun.COM 	}
201610696SDavid.Hollister@Sun.COM 
201710696SDavid.Hollister@Sun.COM 	mdb_printf("%16p %9s %4d %1d %1d 0x%08x 0x%04x 0x%04x %16p\n", addr,
201810696SDavid.Hollister@Sun.COM 	    state_str, dip.devi_instance, ss.blocked, ss.configuring,
201910696SDavid.Hollister@Sun.COM 	    ss.work_flags, ss.wserno, ss.debug_mask, ss.dip);
202010696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
202110696SDavid.Hollister@Sun.COM 
202210696SDavid.Hollister@Sun.COM 	mdb_inc_indent(4);
202310696SDavid.Hollister@Sun.COM 
202410696SDavid.Hollister@Sun.COM 	if (waitqs_info)
202510696SDavid.Hollister@Sun.COM 		display_waitqs(ss, verbose);
202610696SDavid.Hollister@Sun.COM 
202710696SDavid.Hollister@Sun.COM 	if (hw_info)
202810696SDavid.Hollister@Sun.COM 		display_hwinfo(ss, verbose);
202910696SDavid.Hollister@Sun.COM 
203010696SDavid.Hollister@Sun.COM 	if (phy_info || tgt_phy_count)
203110696SDavid.Hollister@Sun.COM 		display_phys(ss, verbose, NULL, 0, tgt_phy_count);
203210696SDavid.Hollister@Sun.COM 
203310696SDavid.Hollister@Sun.COM 	if (target_info || tgt_phy_count)
203410696SDavid.Hollister@Sun.COM 		display_targets(ss, verbose, tgt_phy_count);
203510696SDavid.Hollister@Sun.COM 
203610696SDavid.Hollister@Sun.COM 	if (work_info)
203710696SDavid.Hollister@Sun.COM 		display_work(ss, verbose);
203810696SDavid.Hollister@Sun.COM 
203910696SDavid.Hollister@Sun.COM 	if (ic_info)
204010696SDavid.Hollister@Sun.COM 		display_ic(ss, verbose);
204110696SDavid.Hollister@Sun.COM 
204210696SDavid.Hollister@Sun.COM 	if (ibq)
204310696SDavid.Hollister@Sun.COM 		display_inbound_queues(ss, verbose);
204410696SDavid.Hollister@Sun.COM 
204510696SDavid.Hollister@Sun.COM 	if (obq)
204610696SDavid.Hollister@Sun.COM 		display_outbound_queues(ss, verbose);
204710696SDavid.Hollister@Sun.COM 
204810696SDavid.Hollister@Sun.COM 	if (iport_info)
204910696SDavid.Hollister@Sun.COM 		display_iport(ss, addr, verbose);
205010696SDavid.Hollister@Sun.COM 
205110743SDavid.Hollister@Sun.COM 	if (compq)
205210743SDavid.Hollister@Sun.COM 		display_completion_queue(ss);
205310743SDavid.Hollister@Sun.COM 
205410696SDavid.Hollister@Sun.COM 	mdb_dec_indent(4);
205510696SDavid.Hollister@Sun.COM 
205610696SDavid.Hollister@Sun.COM 	return (rv);
205710696SDavid.Hollister@Sun.COM }
205810696SDavid.Hollister@Sun.COM 
205910696SDavid.Hollister@Sun.COM void
206010696SDavid.Hollister@Sun.COM pmcs_help()
206110696SDavid.Hollister@Sun.COM {
206210696SDavid.Hollister@Sun.COM 	mdb_printf("Prints summary information about each pmcs instance.\n"
206310743SDavid.Hollister@Sun.COM 	    "    -c: Dump the completion queue\n"
206410696SDavid.Hollister@Sun.COM 	    "    -h: Print more detailed hardware information\n"
206510696SDavid.Hollister@Sun.COM 	    "    -i: Print interrupt coalescing information\n"
206610696SDavid.Hollister@Sun.COM 	    "    -I: Print information about each iport\n"
206710696SDavid.Hollister@Sun.COM 	    "    -l: Dump the trace log (cannot be used with other options)\n"
206810696SDavid.Hollister@Sun.COM 	    "    -p: Print information about each attached PHY\n"
206910696SDavid.Hollister@Sun.COM 	    "    -q: Dump inbound queues\n"
207010696SDavid.Hollister@Sun.COM 	    "    -Q: Dump outbound queues\n"
207110696SDavid.Hollister@Sun.COM 	    "    -t: Print information about each known target\n"
207210696SDavid.Hollister@Sun.COM 	    "    -T: Print target and PHY count summary\n"
207310696SDavid.Hollister@Sun.COM 	    "    -w: Dump work structures\n"
207410696SDavid.Hollister@Sun.COM 	    "    -W: List pmcs cmds waiting on various queues\n"
207510696SDavid.Hollister@Sun.COM 	    "    -v: Add verbosity to the above options\n");
207610696SDavid.Hollister@Sun.COM }
207710696SDavid.Hollister@Sun.COM 
207810743SDavid.Hollister@Sun.COM void
207910743SDavid.Hollister@Sun.COM pmcs_tag_help()
208010743SDavid.Hollister@Sun.COM {
208110743SDavid.Hollister@Sun.COM 	mdb_printf("Print all work structures by matching the tag.\n"
208210743SDavid.Hollister@Sun.COM 	    "    -i index:        Match tag index (0x000 - 0xfff)\n"
208310743SDavid.Hollister@Sun.COM 	    "    -s serialnumber: Match serial number (0x0000 - 0xffff)\n"
208410743SDavid.Hollister@Sun.COM 	    "    -t tagtype:      Match tag type [NONE(1), CBACK(2), "
208510743SDavid.Hollister@Sun.COM 	    "WAIT(3)]\n");
208610743SDavid.Hollister@Sun.COM }
208710743SDavid.Hollister@Sun.COM 
208810696SDavid.Hollister@Sun.COM static const mdb_dcmd_t dcmds[] = {
208910743SDavid.Hollister@Sun.COM 	{ "pmcs", "?[-chiIpQqtTwWv] | -l", "print pmcs information",
209010696SDavid.Hollister@Sun.COM 	    pmcs_dcmd, pmcs_help
209110696SDavid.Hollister@Sun.COM 	},
209210743SDavid.Hollister@Sun.COM 	{ "pmcs_tag", "?[-t tagtype|-s serialnum|-i index]",
209310743SDavid.Hollister@Sun.COM 	    "Find work structures by tag type, serial number or index",
209410743SDavid.Hollister@Sun.COM 	    pmcs_tag, pmcs_tag_help
209510743SDavid.Hollister@Sun.COM 	},
209610696SDavid.Hollister@Sun.COM 	{ NULL }
209710696SDavid.Hollister@Sun.COM };
209810696SDavid.Hollister@Sun.COM 
209910696SDavid.Hollister@Sun.COM static const mdb_walker_t walkers[] = {
210010696SDavid.Hollister@Sun.COM 	{ "pmcs_targets", "walk target structures",
210110696SDavid.Hollister@Sun.COM 		targets_walk_i, targets_walk_s, targets_walk_f },
210210696SDavid.Hollister@Sun.COM 	{ "pmcs_phys", "walk PHY structures",
210310696SDavid.Hollister@Sun.COM 		phy_walk_i, phy_walk_s, phy_walk_f },
210410696SDavid.Hollister@Sun.COM 	{ NULL }
210510696SDavid.Hollister@Sun.COM };
210610696SDavid.Hollister@Sun.COM 
210710696SDavid.Hollister@Sun.COM static const mdb_modinfo_t modinfo = {
210810696SDavid.Hollister@Sun.COM 	MDB_API_VERSION, dcmds, walkers
210910696SDavid.Hollister@Sun.COM };
211010696SDavid.Hollister@Sun.COM 
211110696SDavid.Hollister@Sun.COM const mdb_modinfo_t *
211210696SDavid.Hollister@Sun.COM _mdb_init(void)
211310696SDavid.Hollister@Sun.COM {
211410696SDavid.Hollister@Sun.COM 	return (&modinfo);
211510696SDavid.Hollister@Sun.COM }
2116