xref: /onnv-gate/usr/src/cmd/mdb/common/modules/pmcs/pmcs.c (revision 11980:1d26bfcee070)
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 /*
2211601SDavid.Hollister@Sun.COM  * Copyright 2010 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>
2811334SReed.Liu@Sun.COM #include <mdb/mdb_ctf.h>
2910696SDavid.Hollister@Sun.COM #include <sys/sysinfo.h>
3011048SDavid.Hollister@Sun.COM #include <sys/byteorder.h>
3111334SReed.Liu@Sun.COM #include <sys/nvpair.h>
3211334SReed.Liu@Sun.COM #include <sys/damap.h>
3310696SDavid.Hollister@Sun.COM #include <sys/scsi/scsi.h>
3410696SDavid.Hollister@Sun.COM #include <sys/scsi/adapters/pmcs/pmcs.h>
3511694SDavid.Hollister@Sun.COM #ifndef _KMDB
3611694SDavid.Hollister@Sun.COM #include <sys/types.h>
3711694SDavid.Hollister@Sun.COM #include <sys/stat.h>
3811694SDavid.Hollister@Sun.COM #include <fcntl.h>
3911694SDavid.Hollister@Sun.COM #include <unistd.h>
4011694SDavid.Hollister@Sun.COM #endif	/* _KMDB */
4110696SDavid.Hollister@Sun.COM 
4211334SReed.Liu@Sun.COM /*
4311334SReed.Liu@Sun.COM  * We need use this to pass the settings when display_iport
4411334SReed.Liu@Sun.COM  */
4511334SReed.Liu@Sun.COM typedef struct per_iport_setting {
4611334SReed.Liu@Sun.COM 	uint_t  pis_damap_info; /* -m: DAM/damap */
4711334SReed.Liu@Sun.COM 	uint_t  pis_dtc_info; /* -d: device tree children: dev_info/path_info */
4811334SReed.Liu@Sun.COM } per_iport_setting_t;
4911334SReed.Liu@Sun.COM 
5011334SReed.Liu@Sun.COM #define	MDB_RD(a, b, c)		mdb_vread(a, b, (uintptr_t)c)
5111334SReed.Liu@Sun.COM #define	NOREAD(a, b)		mdb_warn("could not read " #a " at 0x%p", b)
5210696SDavid.Hollister@Sun.COM 
5310696SDavid.Hollister@Sun.COM static pmcs_hw_t ss;
5410696SDavid.Hollister@Sun.COM static pmcs_xscsi_t **targets = NULL;
5510696SDavid.Hollister@Sun.COM static int target_idx;
5610696SDavid.Hollister@Sun.COM 
5710696SDavid.Hollister@Sun.COM static uint32_t	sas_phys, sata_phys, exp_phys, num_expanders, empty_phys;
5810696SDavid.Hollister@Sun.COM 
5910696SDavid.Hollister@Sun.COM static pmcs_phy_t *pmcs_next_sibling(pmcs_phy_t *phyp);
6010743SDavid.Hollister@Sun.COM static void display_one_work(pmcwork_t *wp, int verbose, int idx);
6110696SDavid.Hollister@Sun.COM 
6210696SDavid.Hollister@Sun.COM static void
6310696SDavid.Hollister@Sun.COM print_sas_address(pmcs_phy_t *phy)
6410696SDavid.Hollister@Sun.COM {
6510696SDavid.Hollister@Sun.COM 	int idx;
6610696SDavid.Hollister@Sun.COM 
6710696SDavid.Hollister@Sun.COM 	for (idx = 0; idx < 8; idx++) {
6810696SDavid.Hollister@Sun.COM 		mdb_printf("%02x", phy->sas_address[idx]);
6910696SDavid.Hollister@Sun.COM 	}
7010696SDavid.Hollister@Sun.COM }
7110696SDavid.Hollister@Sun.COM 
7210696SDavid.Hollister@Sun.COM /*ARGSUSED*/
7310696SDavid.Hollister@Sun.COM static void
7410696SDavid.Hollister@Sun.COM display_ic(struct pmcs_hw m, int verbose)
7510696SDavid.Hollister@Sun.COM {
7610696SDavid.Hollister@Sun.COM 	int msec_per_tick;
7710696SDavid.Hollister@Sun.COM 
7810696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&msec_per_tick, "msec_per_tick") == -1) {
7910696SDavid.Hollister@Sun.COM 		mdb_warn("can't read msec_per_tick");
8010696SDavid.Hollister@Sun.COM 		msec_per_tick = 0;
8110696SDavid.Hollister@Sun.COM 	}
8210696SDavid.Hollister@Sun.COM 
8310696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
8410696SDavid.Hollister@Sun.COM 	mdb_printf("Interrupt coalescing timer info\n");
8510696SDavid.Hollister@Sun.COM 	mdb_printf("-------------------------------\n");
8610696SDavid.Hollister@Sun.COM 	if (msec_per_tick == 0) {
8710696SDavid.Hollister@Sun.COM 		mdb_printf("Quantum                       : ?? ms\n");
8810696SDavid.Hollister@Sun.COM 	} else {
8910696SDavid.Hollister@Sun.COM 		mdb_printf("Quantum                       : %d ms\n",
9010696SDavid.Hollister@Sun.COM 		    m.io_intr_coal.quantum * msec_per_tick);
9110696SDavid.Hollister@Sun.COM 	}
9210696SDavid.Hollister@Sun.COM 	mdb_printf("Timer enabled                 : ");
9310696SDavid.Hollister@Sun.COM 	if (m.io_intr_coal.timer_on) {
9410696SDavid.Hollister@Sun.COM 		mdb_printf("Yes\n");
9510696SDavid.Hollister@Sun.COM 		mdb_printf("Coalescing timer value        : %d us\n",
9610696SDavid.Hollister@Sun.COM 		    m.io_intr_coal.intr_coal_timer);
9710696SDavid.Hollister@Sun.COM 	} else {
9810696SDavid.Hollister@Sun.COM 		mdb_printf("No\n");
9910696SDavid.Hollister@Sun.COM 	}
10010696SDavid.Hollister@Sun.COM 	mdb_printf("Total nsecs between interrupts: %ld\n",
10110696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.nsecs_between_intrs);
10210696SDavid.Hollister@Sun.COM 	mdb_printf("Time of last I/O interrupt    : %ld\n",
10310696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.last_io_comp);
10410696SDavid.Hollister@Sun.COM 	mdb_printf("Number of I/O interrupts      : %d\n",
10510696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.num_intrs);
10610696SDavid.Hollister@Sun.COM 	mdb_printf("Number of I/O completions     : %d\n",
10710696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.num_io_completions);
10810696SDavid.Hollister@Sun.COM 	mdb_printf("Max I/O completion interrupts : %d\n",
10910696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.max_io_completions);
11010696SDavid.Hollister@Sun.COM 	mdb_printf("Measured ECHO int latency     : %d ns\n",
11110696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.intr_latency);
11210696SDavid.Hollister@Sun.COM 	mdb_printf("Interrupt threshold           : %d\n",
11310696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.intr_threshold);
11410696SDavid.Hollister@Sun.COM }
11510696SDavid.Hollister@Sun.COM 
11610696SDavid.Hollister@Sun.COM /*ARGSUSED*/
11710696SDavid.Hollister@Sun.COM static int
11810696SDavid.Hollister@Sun.COM pmcs_iport_phy_walk_cb(uintptr_t addr, const void *wdata, void *priv)
11910696SDavid.Hollister@Sun.COM {
12010696SDavid.Hollister@Sun.COM 	struct pmcs_phy		phy;
12110696SDavid.Hollister@Sun.COM 
12210696SDavid.Hollister@Sun.COM 	if (mdb_vread(&phy, sizeof (struct pmcs_phy), addr) !=
12310696SDavid.Hollister@Sun.COM 	    sizeof (struct pmcs_phy)) {
12410696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
12510696SDavid.Hollister@Sun.COM 	}
12610696SDavid.Hollister@Sun.COM 
12710696SDavid.Hollister@Sun.COM 	mdb_printf("%16p %2d\n", addr, phy.phynum);
12810696SDavid.Hollister@Sun.COM 
12910696SDavid.Hollister@Sun.COM 	return (0);
13010696SDavid.Hollister@Sun.COM }
13110696SDavid.Hollister@Sun.COM 
13211334SReed.Liu@Sun.COM static int
13311334SReed.Liu@Sun.COM display_iport_damap(dev_info_t *pdip)
13411334SReed.Liu@Sun.COM {
13511334SReed.Liu@Sun.COM 	int rval = DCMD_ERR;
13611334SReed.Liu@Sun.COM 	struct dev_info dip;
13711334SReed.Liu@Sun.COM 	scsi_hba_tran_t sht;
13811334SReed.Liu@Sun.COM 	mdb_ctf_id_t istm_ctfid; /* impl_scsi_tgtmap_t ctf_id */
13911334SReed.Liu@Sun.COM 	ulong_t tmd_offset = 0; /* tgtmap_dam offset to impl_scsi_tgtmap_t */
14011334SReed.Liu@Sun.COM 	uintptr_t dam0;
14111334SReed.Liu@Sun.COM 	uintptr_t dam1;
14211334SReed.Liu@Sun.COM 
14311334SReed.Liu@Sun.COM 	if (mdb_vread(&dip, sizeof (struct dev_info), (uintptr_t)pdip) !=
14411334SReed.Liu@Sun.COM 	    sizeof (struct dev_info)) {
14511334SReed.Liu@Sun.COM 		return (rval);
14611334SReed.Liu@Sun.COM 	}
14711334SReed.Liu@Sun.COM 
14811334SReed.Liu@Sun.COM 	if (dip.devi_driver_data == NULL) {
14911334SReed.Liu@Sun.COM 		return (rval);
15011334SReed.Liu@Sun.COM 	}
15111334SReed.Liu@Sun.COM 
15211334SReed.Liu@Sun.COM 	if (mdb_vread(&sht, sizeof (scsi_hba_tran_t),
15311334SReed.Liu@Sun.COM 	    (uintptr_t)dip.devi_driver_data) != sizeof (scsi_hba_tran_t)) {
15411334SReed.Liu@Sun.COM 		return (rval);
15511334SReed.Liu@Sun.COM 	}
15611334SReed.Liu@Sun.COM 
15711334SReed.Liu@Sun.COM 	if (sht.tran_tgtmap == NULL) {
15811334SReed.Liu@Sun.COM 		return (rval);
15911334SReed.Liu@Sun.COM 	}
16011334SReed.Liu@Sun.COM 
16111334SReed.Liu@Sun.COM 	if (mdb_ctf_lookup_by_name("impl_scsi_tgtmap_t", &istm_ctfid) != 0) {
16211334SReed.Liu@Sun.COM 		return (rval);
16311334SReed.Liu@Sun.COM 	}
16411334SReed.Liu@Sun.COM 
16511334SReed.Liu@Sun.COM 	if (mdb_ctf_offsetof(istm_ctfid, "tgtmap_dam", &tmd_offset) != 0) {
16611334SReed.Liu@Sun.COM 		return (rval);
16711334SReed.Liu@Sun.COM 	}
16811334SReed.Liu@Sun.COM 
16911334SReed.Liu@Sun.COM 	tmd_offset /= NBBY;
17011334SReed.Liu@Sun.COM 	mdb_vread(&dam0, sizeof (dam0),
17111334SReed.Liu@Sun.COM 	    (uintptr_t)(tmd_offset + (char *)sht.tran_tgtmap));
17211334SReed.Liu@Sun.COM 	mdb_vread(&dam1, sizeof (dam1),
17311334SReed.Liu@Sun.COM 	    (uintptr_t)(sizeof (dam0) + tmd_offset + (char *)sht.tran_tgtmap));
17411334SReed.Liu@Sun.COM 
17511334SReed.Liu@Sun.COM 	if (dam0 != NULL) {
17611334SReed.Liu@Sun.COM 		rval = mdb_call_dcmd("damap", dam0, DCMD_ADDRSPEC, 0, NULL);
17711334SReed.Liu@Sun.COM 		mdb_printf("\n");
17811334SReed.Liu@Sun.COM 		if (rval != DCMD_OK) {
17911334SReed.Liu@Sun.COM 			return (rval);
18011334SReed.Liu@Sun.COM 		}
18111334SReed.Liu@Sun.COM 	}
18211334SReed.Liu@Sun.COM 
18311334SReed.Liu@Sun.COM 	if (dam1 != NULL) {
18411334SReed.Liu@Sun.COM 		rval = mdb_call_dcmd("damap", dam1, DCMD_ADDRSPEC, 0, NULL);
18511334SReed.Liu@Sun.COM 		mdb_printf("\n");
18611334SReed.Liu@Sun.COM 	}
18711334SReed.Liu@Sun.COM 
18811334SReed.Liu@Sun.COM 	return (rval);
18911334SReed.Liu@Sun.COM }
19011334SReed.Liu@Sun.COM 
19111334SReed.Liu@Sun.COM /* ARGSUSED */
19211334SReed.Liu@Sun.COM static int
19311334SReed.Liu@Sun.COM display_iport_di_cb(uintptr_t addr, const void *wdata, void *priv)
19411334SReed.Liu@Sun.COM {
19511334SReed.Liu@Sun.COM 	uint_t *idx = (uint_t *)priv;
19611334SReed.Liu@Sun.COM 	struct dev_info dip;
19711334SReed.Liu@Sun.COM 	char devi_name[MAXNAMELEN];
19811334SReed.Liu@Sun.COM 	char devi_addr[MAXNAMELEN];
19911334SReed.Liu@Sun.COM 
20011334SReed.Liu@Sun.COM 	if (mdb_vread(&dip, sizeof (struct dev_info), (uintptr_t)addr) !=
20111334SReed.Liu@Sun.COM 	    sizeof (struct dev_info)) {
20211334SReed.Liu@Sun.COM 		return (DCMD_ERR);
20311334SReed.Liu@Sun.COM 	}
20411334SReed.Liu@Sun.COM 
20511334SReed.Liu@Sun.COM 	if (mdb_readstr(devi_name, sizeof (devi_name),
20611334SReed.Liu@Sun.COM 	    (uintptr_t)dip.devi_node_name) == -1) {
20711334SReed.Liu@Sun.COM 		devi_name[0] = '?';
20811334SReed.Liu@Sun.COM 		devi_name[1] = '\0';
20911334SReed.Liu@Sun.COM 	}
21011334SReed.Liu@Sun.COM 
21111334SReed.Liu@Sun.COM 	if (mdb_readstr(devi_addr, sizeof (devi_addr),
21211334SReed.Liu@Sun.COM 	    (uintptr_t)dip.devi_addr) == -1) {
21311334SReed.Liu@Sun.COM 		devi_addr[0] = '?';
21411334SReed.Liu@Sun.COM 		devi_addr[1] = '\0';
21511334SReed.Liu@Sun.COM 	}
21611334SReed.Liu@Sun.COM 
21711334SReed.Liu@Sun.COM 	mdb_printf("  %3d: @%-21s%10s@\t%p::devinfo -s\n",
21811334SReed.Liu@Sun.COM 	    (*idx)++, devi_addr, devi_name, addr);
21911334SReed.Liu@Sun.COM 	return (DCMD_OK);
22011334SReed.Liu@Sun.COM }
22111334SReed.Liu@Sun.COM 
22211334SReed.Liu@Sun.COM /* ARGSUSED */
22311334SReed.Liu@Sun.COM static int
22411334SReed.Liu@Sun.COM display_iport_pi_cb(uintptr_t addr, const void *wdata, void *priv)
22511334SReed.Liu@Sun.COM {
22611334SReed.Liu@Sun.COM 	uint_t *idx = (uint_t *)priv;
22711334SReed.Liu@Sun.COM 	struct mdi_pathinfo mpi;
22811334SReed.Liu@Sun.COM 	char pi_addr[MAXNAMELEN];
22911334SReed.Liu@Sun.COM 
23011334SReed.Liu@Sun.COM 	if (mdb_vread(&mpi, sizeof (struct mdi_pathinfo), (uintptr_t)addr) !=
23111334SReed.Liu@Sun.COM 	    sizeof (struct mdi_pathinfo)) {
23211334SReed.Liu@Sun.COM 		return (DCMD_ERR);
23311334SReed.Liu@Sun.COM 	}
23411334SReed.Liu@Sun.COM 
23511334SReed.Liu@Sun.COM 	if (mdb_readstr(pi_addr, sizeof (pi_addr),
23611334SReed.Liu@Sun.COM 	    (uintptr_t)mpi.pi_addr) == -1) {
23711334SReed.Liu@Sun.COM 		pi_addr[0] = '?';
23811334SReed.Liu@Sun.COM 		pi_addr[1] = '\0';
23911334SReed.Liu@Sun.COM 	}
24011334SReed.Liu@Sun.COM 
24111334SReed.Liu@Sun.COM 	mdb_printf("  %3d: @%-21s %p::print struct mdi_pathinfo\n",
24211334SReed.Liu@Sun.COM 	    (*idx)++, pi_addr, addr);
24311334SReed.Liu@Sun.COM 	return (DCMD_OK);
24411334SReed.Liu@Sun.COM }
24511334SReed.Liu@Sun.COM 
24611334SReed.Liu@Sun.COM static int
24711334SReed.Liu@Sun.COM display_iport_dtc(dev_info_t *pdip)
24811334SReed.Liu@Sun.COM {
24911334SReed.Liu@Sun.COM 	int rval = DCMD_ERR;
25011334SReed.Liu@Sun.COM 	struct dev_info dip;
25111334SReed.Liu@Sun.COM 	struct mdi_phci phci;
25211334SReed.Liu@Sun.COM 	uint_t didx = 1;
25311334SReed.Liu@Sun.COM 	uint_t pidx = 1;
25411334SReed.Liu@Sun.COM 
25511334SReed.Liu@Sun.COM 	if (mdb_vread(&dip, sizeof (struct dev_info), (uintptr_t)pdip) !=
25611334SReed.Liu@Sun.COM 	    sizeof (struct dev_info)) {
25711334SReed.Liu@Sun.COM 		return (rval);
25811334SReed.Liu@Sun.COM 	}
25911334SReed.Liu@Sun.COM 
26011334SReed.Liu@Sun.COM 	mdb_printf("Device tree children - dev_info:\n");
26111334SReed.Liu@Sun.COM 	if (dip.devi_child == NULL) {
26211334SReed.Liu@Sun.COM 		mdb_printf("\tdevi_child is NULL, no dev_info\n\n");
26311334SReed.Liu@Sun.COM 		goto skip_di;
26411334SReed.Liu@Sun.COM 	}
26511334SReed.Liu@Sun.COM 
26611334SReed.Liu@Sun.COM 	/*
26711334SReed.Liu@Sun.COM 	 * First, we dump the iport's children dev_info node information.
26811334SReed.Liu@Sun.COM 	 * use existing walker: devinfo_siblings
26911334SReed.Liu@Sun.COM 	 */
27011334SReed.Liu@Sun.COM 	mdb_printf("\t#: @unit-address               name@\tdrill-down\n");
27111334SReed.Liu@Sun.COM 	rval = mdb_pwalk("devinfo_siblings", display_iport_di_cb,
27211334SReed.Liu@Sun.COM 	    (void *)&didx, (uintptr_t)dip.devi_child);
27311334SReed.Liu@Sun.COM 	mdb_printf("\n");
27411334SReed.Liu@Sun.COM 
27511334SReed.Liu@Sun.COM skip_di:
27611334SReed.Liu@Sun.COM 	/*
27711334SReed.Liu@Sun.COM 	 * Then we try to dump the iport's path_info node information.
27811334SReed.Liu@Sun.COM 	 * use existing walker: mdipi_phci_list
27911334SReed.Liu@Sun.COM 	 */
28011334SReed.Liu@Sun.COM 	mdb_printf("Device tree children - path_info:\n");
28111334SReed.Liu@Sun.COM 	if (mdb_vread(&phci, sizeof (struct mdi_phci),
28211334SReed.Liu@Sun.COM 	    (uintptr_t)dip.devi_mdi_xhci) != sizeof (struct mdi_phci)) {
28311334SReed.Liu@Sun.COM 		mdb_printf("\tdevi_mdi_xhci is NULL, no path_info\n\n");
28411334SReed.Liu@Sun.COM 		return (rval);
28511334SReed.Liu@Sun.COM 	}
28611334SReed.Liu@Sun.COM 
28711334SReed.Liu@Sun.COM 	if (phci.ph_path_head == NULL) {
28811334SReed.Liu@Sun.COM 		mdb_printf("\tph_path_head is NULL, no path_info\n\n");
28911334SReed.Liu@Sun.COM 		return (rval);
29011334SReed.Liu@Sun.COM 	}
29111334SReed.Liu@Sun.COM 
29211334SReed.Liu@Sun.COM 	mdb_printf("\t#: @unit-address          drill-down\n");
29311334SReed.Liu@Sun.COM 	rval = mdb_pwalk("mdipi_phci_list", display_iport_pi_cb,
29411334SReed.Liu@Sun.COM 	    (void *)&pidx, (uintptr_t)phci.ph_path_head);
29511334SReed.Liu@Sun.COM 	mdb_printf("\n");
29611334SReed.Liu@Sun.COM 	return (rval);
29711334SReed.Liu@Sun.COM }
29811334SReed.Liu@Sun.COM 
29911334SReed.Liu@Sun.COM static void
30011334SReed.Liu@Sun.COM display_iport_more(dev_info_t *dip, per_iport_setting_t *pis)
30111334SReed.Liu@Sun.COM {
30211334SReed.Liu@Sun.COM 	if (pis->pis_damap_info) {
30311334SReed.Liu@Sun.COM 		(void) display_iport_damap(dip);
30411334SReed.Liu@Sun.COM 	}
30511334SReed.Liu@Sun.COM 
30611334SReed.Liu@Sun.COM 	if (pis->pis_dtc_info) {
30711334SReed.Liu@Sun.COM 		(void) display_iport_dtc(dip);
30811334SReed.Liu@Sun.COM 	}
30911334SReed.Liu@Sun.COM }
31011334SReed.Liu@Sun.COM 
31110696SDavid.Hollister@Sun.COM /*ARGSUSED*/
31210696SDavid.Hollister@Sun.COM static int
31310696SDavid.Hollister@Sun.COM pmcs_iport_walk_cb(uintptr_t addr, const void *wdata, void *priv)
31410696SDavid.Hollister@Sun.COM {
31510696SDavid.Hollister@Sun.COM 	struct pmcs_iport	iport;
31610696SDavid.Hollister@Sun.COM 	uintptr_t		list_addr;
31710696SDavid.Hollister@Sun.COM 	char			*ua_state;
31810696SDavid.Hollister@Sun.COM 	char			portid[4];
31910696SDavid.Hollister@Sun.COM 	char			unit_address[34];
32011334SReed.Liu@Sun.COM 	per_iport_setting_t	*pis = (per_iport_setting_t *)priv;
32110696SDavid.Hollister@Sun.COM 
32210696SDavid.Hollister@Sun.COM 	if (mdb_vread(&iport, sizeof (struct pmcs_iport), addr) !=
32310696SDavid.Hollister@Sun.COM 	    sizeof (struct pmcs_iport)) {
32410696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
32510696SDavid.Hollister@Sun.COM 	}
32610696SDavid.Hollister@Sun.COM 
32710696SDavid.Hollister@Sun.COM 	if (mdb_readstr(unit_address, sizeof (unit_address),
32810696SDavid.Hollister@Sun.COM 	    (uintptr_t)(iport.ua)) == -1) {
32910696SDavid.Hollister@Sun.COM 		strncpy(unit_address, "Unset", sizeof (unit_address));
33010696SDavid.Hollister@Sun.COM 	}
33110696SDavid.Hollister@Sun.COM 
33210696SDavid.Hollister@Sun.COM 	if (iport.portid == 0xffff) {
33310696SDavid.Hollister@Sun.COM 		mdb_snprintf(portid, sizeof (portid), "%s", "-");
33411347SRamana.Srikanth@Sun.COM 	} else if (iport.portid == PMCS_IPORT_INVALID_PORT_ID) {
33511347SRamana.Srikanth@Sun.COM 		mdb_snprintf(portid, sizeof (portid), "%s", "N/A");
33610696SDavid.Hollister@Sun.COM 	} else {
33710696SDavid.Hollister@Sun.COM 		mdb_snprintf(portid, sizeof (portid), "%d", iport.portid);
33810696SDavid.Hollister@Sun.COM 	}
33910696SDavid.Hollister@Sun.COM 
34010696SDavid.Hollister@Sun.COM 	switch (iport.ua_state) {
34110696SDavid.Hollister@Sun.COM 	case UA_INACTIVE:
34210696SDavid.Hollister@Sun.COM 		ua_state = "Inactive";
34310696SDavid.Hollister@Sun.COM 		break;
34410696SDavid.Hollister@Sun.COM 	case UA_PEND_ACTIVATE:
34510696SDavid.Hollister@Sun.COM 		ua_state = "PendActivate";
34610696SDavid.Hollister@Sun.COM 		break;
34710696SDavid.Hollister@Sun.COM 	case UA_ACTIVE:
34810696SDavid.Hollister@Sun.COM 		ua_state = "Active";
34910696SDavid.Hollister@Sun.COM 		break;
35010696SDavid.Hollister@Sun.COM 	case UA_PEND_DEACTIVATE:
35110696SDavid.Hollister@Sun.COM 		ua_state = "PendDeactivate";
35210696SDavid.Hollister@Sun.COM 		break;
35310696SDavid.Hollister@Sun.COM 	default:
35410696SDavid.Hollister@Sun.COM 		ua_state = "Unknown";
35510696SDavid.Hollister@Sun.COM 	}
35610696SDavid.Hollister@Sun.COM 
35710696SDavid.Hollister@Sun.COM 	if (strlen(unit_address) < 3) {
35810696SDavid.Hollister@Sun.COM 		/* Standard iport unit address */
35910696SDavid.Hollister@Sun.COM 		mdb_printf("UA %-16s %16s %8s %8s %16s", "Iport", "UA State",
36010696SDavid.Hollister@Sun.COM 		    "PortID", "NumPhys", "DIP\n");
36110696SDavid.Hollister@Sun.COM 		mdb_printf("%2s %16p %16s %8s %8d %16p\n", unit_address, addr,
36210696SDavid.Hollister@Sun.COM 		    ua_state, portid, iport.nphy, iport.dip);
36310696SDavid.Hollister@Sun.COM 	} else {
36410696SDavid.Hollister@Sun.COM 		/* Temporary iport unit address */
36510696SDavid.Hollister@Sun.COM 		mdb_printf("%-32s %16s %20s %8s %8s %16s", "UA", "Iport",
36610696SDavid.Hollister@Sun.COM 		    "UA State", "PortID", "NumPhys", "DIP\n");
36710696SDavid.Hollister@Sun.COM 		mdb_printf("%32s %16p %20s %8s %8d %16p\n", unit_address, addr,
36810696SDavid.Hollister@Sun.COM 		    ua_state, portid, iport.nphy, iport.dip);
36910696SDavid.Hollister@Sun.COM 	}
37010696SDavid.Hollister@Sun.COM 
37110696SDavid.Hollister@Sun.COM 	if (iport.nphy > 0) {
37210696SDavid.Hollister@Sun.COM 		mdb_inc_indent(4);
37310696SDavid.Hollister@Sun.COM 		mdb_printf("%-18s %8s", "Phy", "PhyNum\n");
37410696SDavid.Hollister@Sun.COM 		mdb_inc_indent(2);
37510696SDavid.Hollister@Sun.COM 		list_addr =
37610696SDavid.Hollister@Sun.COM 		    (uintptr_t)(addr + offsetof(struct pmcs_iport, phys));
37710696SDavid.Hollister@Sun.COM 		if (mdb_pwalk("list", pmcs_iport_phy_walk_cb, NULL,
37810696SDavid.Hollister@Sun.COM 		    list_addr) == -1) {
37910696SDavid.Hollister@Sun.COM 			mdb_warn("pmcs iport walk failed");
38010696SDavid.Hollister@Sun.COM 		}
38110696SDavid.Hollister@Sun.COM 		mdb_dec_indent(6);
38210696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
38310696SDavid.Hollister@Sun.COM 	}
38410696SDavid.Hollister@Sun.COM 
38511334SReed.Liu@Sun.COM 	/*
38611334SReed.Liu@Sun.COM 	 * See if we need to show more information based on 'd' or 'm' options
38711334SReed.Liu@Sun.COM 	 */
38811334SReed.Liu@Sun.COM 	display_iport_more(iport.dip, pis);
38911334SReed.Liu@Sun.COM 
39010696SDavid.Hollister@Sun.COM 	return (0);
39110696SDavid.Hollister@Sun.COM }
39210696SDavid.Hollister@Sun.COM 
39310696SDavid.Hollister@Sun.COM /*ARGSUSED*/
39410696SDavid.Hollister@Sun.COM static void
39511334SReed.Liu@Sun.COM display_iport(struct pmcs_hw m, uintptr_t addr, int verbose,
39611334SReed.Liu@Sun.COM     per_iport_setting_t *pis)
39710696SDavid.Hollister@Sun.COM {
39810696SDavid.Hollister@Sun.COM 	uintptr_t	list_addr;
39910696SDavid.Hollister@Sun.COM 
40010696SDavid.Hollister@Sun.COM 	if (m.iports_attached) {
40110696SDavid.Hollister@Sun.COM 		mdb_printf("Iport information:\n");
40210696SDavid.Hollister@Sun.COM 		mdb_printf("-----------------\n");
40310696SDavid.Hollister@Sun.COM 	} else {
40410696SDavid.Hollister@Sun.COM 		mdb_printf("No Iports found.\n\n");
40510696SDavid.Hollister@Sun.COM 		return;
40610696SDavid.Hollister@Sun.COM 	}
40710696SDavid.Hollister@Sun.COM 
40810696SDavid.Hollister@Sun.COM 	list_addr = (uintptr_t)(addr + offsetof(struct pmcs_hw, iports));
40910696SDavid.Hollister@Sun.COM 
41011334SReed.Liu@Sun.COM 	if (mdb_pwalk("list", pmcs_iport_walk_cb, pis, list_addr) == -1) {
41110696SDavid.Hollister@Sun.COM 		mdb_warn("pmcs iport walk failed");
41210696SDavid.Hollister@Sun.COM 	}
41310696SDavid.Hollister@Sun.COM 
41410696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
41510696SDavid.Hollister@Sun.COM }
41610696SDavid.Hollister@Sun.COM 
41711048SDavid.Hollister@Sun.COM /* ARGSUSED */
41811048SDavid.Hollister@Sun.COM static int
41911048SDavid.Hollister@Sun.COM pmcs_utarget_walk_cb(uintptr_t addr, const void *wdata, void *priv)
42011048SDavid.Hollister@Sun.COM {
42111048SDavid.Hollister@Sun.COM 	pmcs_phy_t phy;
42211048SDavid.Hollister@Sun.COM 
42311048SDavid.Hollister@Sun.COM 	if (mdb_vread(&phy, sizeof (pmcs_phy_t), (uintptr_t)addr) == -1) {
42411048SDavid.Hollister@Sun.COM 		mdb_warn("pmcs_utarget_walk_cb: Failed to read PHY at %p",
42511048SDavid.Hollister@Sun.COM 		    (void *)addr);
42611048SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
42711048SDavid.Hollister@Sun.COM 	}
42811048SDavid.Hollister@Sun.COM 
42911048SDavid.Hollister@Sun.COM 	if (phy.configured && (phy.target == NULL)) {
43011048SDavid.Hollister@Sun.COM 		mdb_printf("SAS address: ");
43111048SDavid.Hollister@Sun.COM 		print_sas_address(&phy);
43211048SDavid.Hollister@Sun.COM 		mdb_printf("  DType: ");
43311048SDavid.Hollister@Sun.COM 		switch (phy.dtype) {
43411048SDavid.Hollister@Sun.COM 		case SAS:
43511048SDavid.Hollister@Sun.COM 			mdb_printf("%4s", "SAS");
43611048SDavid.Hollister@Sun.COM 			break;
43711048SDavid.Hollister@Sun.COM 		case SATA:
43811048SDavid.Hollister@Sun.COM 			mdb_printf("%4s", "SATA");
43911048SDavid.Hollister@Sun.COM 			break;
44011048SDavid.Hollister@Sun.COM 		case EXPANDER:
44111048SDavid.Hollister@Sun.COM 			mdb_printf("%4s", "SMP");
44211048SDavid.Hollister@Sun.COM 			break;
44311048SDavid.Hollister@Sun.COM 		default:
44411048SDavid.Hollister@Sun.COM 			mdb_printf("%4s", "N/A");
44511048SDavid.Hollister@Sun.COM 			break;
44611048SDavid.Hollister@Sun.COM 		}
44711048SDavid.Hollister@Sun.COM 		mdb_printf("  Path: %s\n", phy.path);
44811048SDavid.Hollister@Sun.COM 	}
44911048SDavid.Hollister@Sun.COM 
45011048SDavid.Hollister@Sun.COM 	return (0);
45111048SDavid.Hollister@Sun.COM }
45211048SDavid.Hollister@Sun.COM 
45311048SDavid.Hollister@Sun.COM static void
45411048SDavid.Hollister@Sun.COM display_unconfigured_targets(uintptr_t addr)
45511048SDavid.Hollister@Sun.COM {
45611048SDavid.Hollister@Sun.COM 	mdb_printf("Unconfigured target SAS address:\n\n");
45711048SDavid.Hollister@Sun.COM 
45811048SDavid.Hollister@Sun.COM 	if (mdb_pwalk("pmcs_phys", pmcs_utarget_walk_cb, NULL, addr) == -1) {
45911048SDavid.Hollister@Sun.COM 		mdb_warn("pmcs phys walk failed");
46011048SDavid.Hollister@Sun.COM 	}
46111048SDavid.Hollister@Sun.COM }
46211048SDavid.Hollister@Sun.COM 
46310743SDavid.Hollister@Sun.COM static void
46410743SDavid.Hollister@Sun.COM display_completion_queue(struct pmcs_hw ss)
46510743SDavid.Hollister@Sun.COM {
46610743SDavid.Hollister@Sun.COM 	pmcs_iocomp_cb_t ccb, *ccbp;
46710743SDavid.Hollister@Sun.COM 	pmcwork_t work;
46810743SDavid.Hollister@Sun.COM 
46910743SDavid.Hollister@Sun.COM 	if (ss.iocomp_cb_head == NULL) {
47010743SDavid.Hollister@Sun.COM 		mdb_printf("Completion queue is empty.\n");
47110743SDavid.Hollister@Sun.COM 		return;
47210743SDavid.Hollister@Sun.COM 	}
47310743SDavid.Hollister@Sun.COM 
47410743SDavid.Hollister@Sun.COM 	ccbp = ss.iocomp_cb_head;
47510743SDavid.Hollister@Sun.COM 	mdb_printf("%8s %10s %20s %8s %8s O D\n",
47610743SDavid.Hollister@Sun.COM 	    "HTag", "State", "Phy Path", "Target", "Timer");
47710743SDavid.Hollister@Sun.COM 
47810743SDavid.Hollister@Sun.COM 	while (ccbp) {
47910743SDavid.Hollister@Sun.COM 		if (mdb_vread(&ccb, sizeof (pmcs_iocomp_cb_t),
48010743SDavid.Hollister@Sun.COM 		    (uintptr_t)ccbp) != sizeof (pmcs_iocomp_cb_t)) {
48110743SDavid.Hollister@Sun.COM 			mdb_warn("Unable to read completion queue entry\n");
48210743SDavid.Hollister@Sun.COM 			return;
48310743SDavid.Hollister@Sun.COM 		}
48410743SDavid.Hollister@Sun.COM 
48510743SDavid.Hollister@Sun.COM 		if (mdb_vread(&work, sizeof (pmcwork_t), (uintptr_t)ccb.pwrk)
48610743SDavid.Hollister@Sun.COM 		    != sizeof (pmcwork_t)) {
48710743SDavid.Hollister@Sun.COM 			mdb_warn("Unable to read work structure\n");
48810743SDavid.Hollister@Sun.COM 			return;
48910743SDavid.Hollister@Sun.COM 		}
49010743SDavid.Hollister@Sun.COM 
49110743SDavid.Hollister@Sun.COM 		/*
49210743SDavid.Hollister@Sun.COM 		 * Only print the work structure if it's still active.  If
49310743SDavid.Hollister@Sun.COM 		 * it's not, it's been completed since we started looking at
49410743SDavid.Hollister@Sun.COM 		 * it.
49510743SDavid.Hollister@Sun.COM 		 */
49610743SDavid.Hollister@Sun.COM 		if (work.state != PMCS_WORK_STATE_NIL) {
49710743SDavid.Hollister@Sun.COM 			display_one_work(&work, 0, 0);
49810743SDavid.Hollister@Sun.COM 		}
49910743SDavid.Hollister@Sun.COM 		ccbp = ccb.next;
50010743SDavid.Hollister@Sun.COM 	}
50110743SDavid.Hollister@Sun.COM }
50210743SDavid.Hollister@Sun.COM 
50310696SDavid.Hollister@Sun.COM /*ARGSUSED*/
50410696SDavid.Hollister@Sun.COM static void
50510696SDavid.Hollister@Sun.COM display_hwinfo(struct pmcs_hw m, int verbose)
50610696SDavid.Hollister@Sun.COM {
50710696SDavid.Hollister@Sun.COM 	struct pmcs_hw	*mp = &m;
50810696SDavid.Hollister@Sun.COM 	char		*fwsupport;
50910696SDavid.Hollister@Sun.COM 
51010696SDavid.Hollister@Sun.COM 	switch (PMCS_FW_TYPE(mp)) {
51110696SDavid.Hollister@Sun.COM 	case PMCS_FW_TYPE_RELEASED:
51210696SDavid.Hollister@Sun.COM 		fwsupport = "Released";
51310696SDavid.Hollister@Sun.COM 		break;
51410696SDavid.Hollister@Sun.COM 	case PMCS_FW_TYPE_DEVELOPMENT:
51510696SDavid.Hollister@Sun.COM 		fwsupport = "Development";
51610696SDavid.Hollister@Sun.COM 		break;
51710696SDavid.Hollister@Sun.COM 	case PMCS_FW_TYPE_ALPHA:
51810696SDavid.Hollister@Sun.COM 		fwsupport = "Alpha";
51910696SDavid.Hollister@Sun.COM 		break;
52010696SDavid.Hollister@Sun.COM 	case PMCS_FW_TYPE_BETA:
52110696SDavid.Hollister@Sun.COM 		fwsupport = "Beta";
52210696SDavid.Hollister@Sun.COM 		break;
52310696SDavid.Hollister@Sun.COM 	default:
52410696SDavid.Hollister@Sun.COM 		fwsupport = "Special";
52510696SDavid.Hollister@Sun.COM 		break;
52610696SDavid.Hollister@Sun.COM 	}
52710696SDavid.Hollister@Sun.COM 
52810696SDavid.Hollister@Sun.COM 	mdb_printf("\nHardware information:\n");
52910696SDavid.Hollister@Sun.COM 	mdb_printf("---------------------\n");
53010696SDavid.Hollister@Sun.COM 
53110696SDavid.Hollister@Sun.COM 	mdb_printf("Chip revision:    %c\n", 'A' + m.chiprev);
53210696SDavid.Hollister@Sun.COM 	mdb_printf("SAS WWID:         %"PRIx64"\n", m.sas_wwns[0]);
53310696SDavid.Hollister@Sun.COM 	mdb_printf("Firmware version: %x.%x.%x (%s)\n",
53410696SDavid.Hollister@Sun.COM 	    PMCS_FW_MAJOR(mp), PMCS_FW_MINOR(mp), PMCS_FW_MICRO(mp),
53510696SDavid.Hollister@Sun.COM 	    fwsupport);
536*11980SDavid.Hollister@Sun.COM 	mdb_printf("ILA version:      %08x\n", m.ila_ver);
537*11980SDavid.Hollister@Sun.COM 	mdb_printf("Active f/w img:   %c\n", (m.fw_active_img) ? 'A' : 'B');
53810696SDavid.Hollister@Sun.COM 
53910696SDavid.Hollister@Sun.COM 	mdb_printf("Number of PHYs:   %d\n", m.nphy);
54010696SDavid.Hollister@Sun.COM 	mdb_printf("Maximum commands: %d\n", m.max_cmd);
54110696SDavid.Hollister@Sun.COM 	mdb_printf("Maximum devices:  %d\n", m.max_dev);
54210696SDavid.Hollister@Sun.COM 	mdb_printf("I/O queue depth:  %d\n", m.ioq_depth);
54310696SDavid.Hollister@Sun.COM 	if (m.fwlog == 0) {
54410696SDavid.Hollister@Sun.COM 		mdb_printf("Firmware logging: Disabled\n");
54510696SDavid.Hollister@Sun.COM 	} else {
54610696SDavid.Hollister@Sun.COM 		mdb_printf("Firmware logging: Enabled (%d)\n", m.fwlog);
54710696SDavid.Hollister@Sun.COM 	}
548*11980SDavid.Hollister@Sun.COM 	if (m.fwlog_file == 0) {
549*11980SDavid.Hollister@Sun.COM 		mdb_printf("Firmware logfile: Not configured\n");
550*11980SDavid.Hollister@Sun.COM 	} else {
551*11980SDavid.Hollister@Sun.COM 		mdb_printf("Firmware logfile: Configured\n");
552*11980SDavid.Hollister@Sun.COM 		mdb_inc_indent(2);
553*11980SDavid.Hollister@Sun.COM 		mdb_printf("AAP1 log file:  %s\n", m.fwlogfile_aap1);
554*11980SDavid.Hollister@Sun.COM 		mdb_printf("IOP logfile:    %s\n", m.fwlogfile_iop);
555*11980SDavid.Hollister@Sun.COM 		mdb_dec_indent(2);
556*11980SDavid.Hollister@Sun.COM 	}
55710696SDavid.Hollister@Sun.COM }
55810696SDavid.Hollister@Sun.COM 
55910696SDavid.Hollister@Sun.COM static void
56010696SDavid.Hollister@Sun.COM display_targets(struct pmcs_hw m, int verbose, int totals_only)
56110696SDavid.Hollister@Sun.COM {
56210696SDavid.Hollister@Sun.COM 	char		*dtype;
56310696SDavid.Hollister@Sun.COM 	pmcs_xscsi_t	xs;
56410696SDavid.Hollister@Sun.COM 	pmcs_phy_t	phy;
56510696SDavid.Hollister@Sun.COM 	uint16_t	max_dev, idx;
56610696SDavid.Hollister@Sun.COM 	uint32_t	sas_targets = 0, smp_targets = 0, sata_targets = 0;
56710696SDavid.Hollister@Sun.COM 
56810696SDavid.Hollister@Sun.COM 	max_dev = m.max_dev;
56910696SDavid.Hollister@Sun.COM 
57010696SDavid.Hollister@Sun.COM 	if (targets == NULL) {
57110696SDavid.Hollister@Sun.COM 		targets = mdb_alloc(sizeof (targets) * max_dev, UM_SLEEP);
57210696SDavid.Hollister@Sun.COM 	}
57310696SDavid.Hollister@Sun.COM 
57410696SDavid.Hollister@Sun.COM 	if (MDB_RD(targets, sizeof (targets) * max_dev, m.targets) == -1) {
57510696SDavid.Hollister@Sun.COM 		NOREAD(targets, m.targets);
57610696SDavid.Hollister@Sun.COM 		return;
57710696SDavid.Hollister@Sun.COM 	}
57810696SDavid.Hollister@Sun.COM 
57910696SDavid.Hollister@Sun.COM 	if (!totals_only) {
58010696SDavid.Hollister@Sun.COM 		mdb_printf("\nTarget information:\n");
58110696SDavid.Hollister@Sun.COM 		mdb_printf("---------------------------------------\n");
58211347SRamana.Srikanth@Sun.COM 		mdb_printf("VTGT %-16s %-16s %-5s %4s %6s %s", "SAS Address",
58311347SRamana.Srikanth@Sun.COM 		    "PHY Address", "DType", "Actv", "OnChip", "DS");
58410696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
58510696SDavid.Hollister@Sun.COM 	}
58610696SDavid.Hollister@Sun.COM 
58710696SDavid.Hollister@Sun.COM 	for (idx = 0; idx < max_dev; idx++) {
58810696SDavid.Hollister@Sun.COM 		if (targets[idx] == NULL) {
58910696SDavid.Hollister@Sun.COM 			continue;
59010696SDavid.Hollister@Sun.COM 		}
59110696SDavid.Hollister@Sun.COM 
59210696SDavid.Hollister@Sun.COM 		if (MDB_RD(&xs, sizeof (xs), targets[idx]) == -1) {
59310696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_xscsi_t, targets[idx]);
59410696SDavid.Hollister@Sun.COM 			continue;
59510696SDavid.Hollister@Sun.COM 		}
59610696SDavid.Hollister@Sun.COM 
59710696SDavid.Hollister@Sun.COM 		/*
59810755SJesse.Butler@Sun.COM 		 * It has to be new or assigned to be of interest.
59910696SDavid.Hollister@Sun.COM 		 */
60010755SJesse.Butler@Sun.COM 		if (xs.new == 0 && xs.assigned == 0) {
60110696SDavid.Hollister@Sun.COM 			continue;
60210696SDavid.Hollister@Sun.COM 		}
60310696SDavid.Hollister@Sun.COM 
60410696SDavid.Hollister@Sun.COM 		switch (xs.dtype) {
60510696SDavid.Hollister@Sun.COM 		case NOTHING:
60610696SDavid.Hollister@Sun.COM 			dtype = "None";
60710696SDavid.Hollister@Sun.COM 			break;
60810696SDavid.Hollister@Sun.COM 		case SATA:
60910696SDavid.Hollister@Sun.COM 			dtype = "SATA";
61010696SDavid.Hollister@Sun.COM 			sata_targets++;
61110696SDavid.Hollister@Sun.COM 			break;
61210696SDavid.Hollister@Sun.COM 		case SAS:
61310696SDavid.Hollister@Sun.COM 			dtype = "SAS";
61410696SDavid.Hollister@Sun.COM 			sas_targets++;
61510696SDavid.Hollister@Sun.COM 			break;
61610696SDavid.Hollister@Sun.COM 		case EXPANDER:
61710696SDavid.Hollister@Sun.COM 			dtype = "SMP";
61810696SDavid.Hollister@Sun.COM 			smp_targets++;
61910696SDavid.Hollister@Sun.COM 			break;
62010696SDavid.Hollister@Sun.COM 		}
62110696SDavid.Hollister@Sun.COM 
62210696SDavid.Hollister@Sun.COM 		if (totals_only) {
62310696SDavid.Hollister@Sun.COM 			continue;
62410696SDavid.Hollister@Sun.COM 		}
62510696SDavid.Hollister@Sun.COM 
62610696SDavid.Hollister@Sun.COM 		if (xs.phy) {
62710696SDavid.Hollister@Sun.COM 			if (MDB_RD(&phy, sizeof (phy), xs.phy) == -1) {
62810696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_phy_t, xs.phy);
62910696SDavid.Hollister@Sun.COM 				continue;
63010696SDavid.Hollister@Sun.COM 			}
63110696SDavid.Hollister@Sun.COM 			mdb_printf("%4d ", idx);
63210696SDavid.Hollister@Sun.COM 			print_sas_address(&phy);
63310696SDavid.Hollister@Sun.COM 			mdb_printf(" %16p", xs.phy);
63410696SDavid.Hollister@Sun.COM 		} else {
63510696SDavid.Hollister@Sun.COM 			mdb_printf("%4d %16s", idx, "<no phy avail>");
63610696SDavid.Hollister@Sun.COM 		}
63710696SDavid.Hollister@Sun.COM 		mdb_printf(" %5s", dtype);
63811347SRamana.Srikanth@Sun.COM 		mdb_printf(" %4d", xs.actv_pkts);
63911347SRamana.Srikanth@Sun.COM 		mdb_printf(" %6d", xs.actv_cnt);
64010696SDavid.Hollister@Sun.COM 		mdb_printf(" %2d", xs.dev_state);
64110696SDavid.Hollister@Sun.COM 
64210696SDavid.Hollister@Sun.COM 		if (verbose) {
64310696SDavid.Hollister@Sun.COM 			if (xs.new) {
64410696SDavid.Hollister@Sun.COM 				mdb_printf(" new");
64510755SJesse.Butler@Sun.COM 			}
64610755SJesse.Butler@Sun.COM 			if (xs.assigned) {
64710696SDavid.Hollister@Sun.COM 				mdb_printf(" assigned");
64810696SDavid.Hollister@Sun.COM 			}
64910696SDavid.Hollister@Sun.COM 			if (xs.draining) {
65010696SDavid.Hollister@Sun.COM 				mdb_printf(" draining");
65110696SDavid.Hollister@Sun.COM 			}
65210696SDavid.Hollister@Sun.COM 			if (xs.reset_wait) {
65310696SDavid.Hollister@Sun.COM 				mdb_printf(" reset_wait");
65410696SDavid.Hollister@Sun.COM 			}
65510696SDavid.Hollister@Sun.COM 			if (xs.resetting) {
65610696SDavid.Hollister@Sun.COM 				mdb_printf(" resetting");
65710696SDavid.Hollister@Sun.COM 			}
65810696SDavid.Hollister@Sun.COM 			if (xs.recover_wait) {
65910696SDavid.Hollister@Sun.COM 				mdb_printf(" recover_wait");
66010696SDavid.Hollister@Sun.COM 			}
66110696SDavid.Hollister@Sun.COM 			if (xs.recovering) {
66210696SDavid.Hollister@Sun.COM 				mdb_printf(" recovering");
66310696SDavid.Hollister@Sun.COM 			}
66410696SDavid.Hollister@Sun.COM 			if (xs.event_recovery) {
66510696SDavid.Hollister@Sun.COM 				mdb_printf(" event recovery");
66610696SDavid.Hollister@Sun.COM 			}
66710696SDavid.Hollister@Sun.COM 			if (xs.special_running) {
66810696SDavid.Hollister@Sun.COM 				mdb_printf(" special_active");
66910696SDavid.Hollister@Sun.COM 			}
67010696SDavid.Hollister@Sun.COM 			if (xs.ncq) {
67110696SDavid.Hollister@Sun.COM 				mdb_printf(" ncq_tagmap=0x%x qdepth=%d",
67210696SDavid.Hollister@Sun.COM 				    xs.tagmap, xs.qdepth);
67310696SDavid.Hollister@Sun.COM 			} else if (xs.pio) {
67410696SDavid.Hollister@Sun.COM 				mdb_printf(" pio");
67510696SDavid.Hollister@Sun.COM 			}
67610696SDavid.Hollister@Sun.COM 		}
67710696SDavid.Hollister@Sun.COM 
67810696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
67910696SDavid.Hollister@Sun.COM 	}
68010696SDavid.Hollister@Sun.COM 
68110696SDavid.Hollister@Sun.COM 	if (!totals_only) {
68210696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
68310696SDavid.Hollister@Sun.COM 	}
68410696SDavid.Hollister@Sun.COM 
68510696SDavid.Hollister@Sun.COM 	mdb_printf("%19s %d (%d SAS + %d SATA + %d SMP)\n",
68610696SDavid.Hollister@Sun.COM 	    "Configured targets:", (sas_targets + sata_targets + smp_targets),
68710696SDavid.Hollister@Sun.COM 	    sas_targets, sata_targets, smp_targets);
68810696SDavid.Hollister@Sun.COM }
68910696SDavid.Hollister@Sun.COM 
69010743SDavid.Hollister@Sun.COM static char *
69110743SDavid.Hollister@Sun.COM work_state_to_string(uint32_t state)
69210743SDavid.Hollister@Sun.COM {
69310743SDavid.Hollister@Sun.COM 	char *state_string;
69410743SDavid.Hollister@Sun.COM 
69510743SDavid.Hollister@Sun.COM 	switch (state) {
69610743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_NIL:
69710743SDavid.Hollister@Sun.COM 		state_string = "Free";
69810743SDavid.Hollister@Sun.COM 		break;
69910743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_READY:
70010743SDavid.Hollister@Sun.COM 		state_string = "Ready";
70110743SDavid.Hollister@Sun.COM 		break;
70210743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_ONCHIP:
70310743SDavid.Hollister@Sun.COM 		state_string = "On Chip";
70410743SDavid.Hollister@Sun.COM 		break;
70510743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_INTR:
70610743SDavid.Hollister@Sun.COM 		state_string = "In Intr";
70710743SDavid.Hollister@Sun.COM 		break;
70810743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_IOCOMPQ:
70910743SDavid.Hollister@Sun.COM 		state_string = "I/O Comp";
71010743SDavid.Hollister@Sun.COM 		break;
71110743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_ABORTED:
71210743SDavid.Hollister@Sun.COM 		state_string = "I/O Aborted";
71310743SDavid.Hollister@Sun.COM 		break;
71410743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_TIMED_OUT:
71510743SDavid.Hollister@Sun.COM 		state_string = "I/O Timed Out";
71610743SDavid.Hollister@Sun.COM 		break;
71710743SDavid.Hollister@Sun.COM 	default:
71810743SDavid.Hollister@Sun.COM 		state_string = "INVALID";
71910743SDavid.Hollister@Sun.COM 		break;
72010743SDavid.Hollister@Sun.COM 	}
72110743SDavid.Hollister@Sun.COM 
72210743SDavid.Hollister@Sun.COM 	return (state_string);
72310743SDavid.Hollister@Sun.COM }
72410743SDavid.Hollister@Sun.COM 
72510743SDavid.Hollister@Sun.COM static void
72610743SDavid.Hollister@Sun.COM display_one_work(pmcwork_t *wp, int verbose, int idx)
72710743SDavid.Hollister@Sun.COM {
72810743SDavid.Hollister@Sun.COM 	char		*state, *last_state;
72910743SDavid.Hollister@Sun.COM 	char		*path;
73010743SDavid.Hollister@Sun.COM 	pmcs_xscsi_t	xs;
73110743SDavid.Hollister@Sun.COM 	pmcs_phy_t	phy;
73210743SDavid.Hollister@Sun.COM 	int		tgt;
73310743SDavid.Hollister@Sun.COM 
73410743SDavid.Hollister@Sun.COM 	state = work_state_to_string(wp->state);
73510743SDavid.Hollister@Sun.COM 	last_state = work_state_to_string(wp->last_state);
73610743SDavid.Hollister@Sun.COM 
73710743SDavid.Hollister@Sun.COM 	if (wp->ssp_event && wp->ssp_event != 0xffffffff) {
73810743SDavid.Hollister@Sun.COM 		mdb_printf("SSP event 0x%x", wp->ssp_event);
73910743SDavid.Hollister@Sun.COM 	}
74010743SDavid.Hollister@Sun.COM 
74110743SDavid.Hollister@Sun.COM 	tgt = -1;
74210743SDavid.Hollister@Sun.COM 	if (wp->xp) {
74310743SDavid.Hollister@Sun.COM 		if (MDB_RD(&xs, sizeof (xs), wp->xp) == -1) {
74410743SDavid.Hollister@Sun.COM 			NOREAD(pmcs_xscsi_t, wp->xp);
74510743SDavid.Hollister@Sun.COM 		} else {
74610743SDavid.Hollister@Sun.COM 			tgt = xs.target_num;
74710743SDavid.Hollister@Sun.COM 		}
74810743SDavid.Hollister@Sun.COM 	}
74910743SDavid.Hollister@Sun.COM 	if (wp->phy) {
75010743SDavid.Hollister@Sun.COM 		if (MDB_RD(&phy, sizeof (phy), wp->phy) == -1) {
75110743SDavid.Hollister@Sun.COM 			NOREAD(pmcs_phy_t, wp->phy);
75210743SDavid.Hollister@Sun.COM 		}
75310743SDavid.Hollister@Sun.COM 		path = phy.path;
75410743SDavid.Hollister@Sun.COM 	} else {
75510743SDavid.Hollister@Sun.COM 		path = "N/A";
75610743SDavid.Hollister@Sun.COM 	}
75710743SDavid.Hollister@Sun.COM 
75810743SDavid.Hollister@Sun.COM 	if (verbose) {
75910743SDavid.Hollister@Sun.COM 		mdb_printf("%4d ", idx);
76010743SDavid.Hollister@Sun.COM 	}
76110743SDavid.Hollister@Sun.COM 	if (tgt == -1) {
76210743SDavid.Hollister@Sun.COM 		mdb_printf("%08x %10s %20s      N/A %8u %1d %1d ",
76310743SDavid.Hollister@Sun.COM 		    wp->htag, state, path, wp->timer,
76410743SDavid.Hollister@Sun.COM 		    wp->onwire, wp->dead);
76510743SDavid.Hollister@Sun.COM 	} else {
76610743SDavid.Hollister@Sun.COM 		mdb_printf("%08x %10s %20s %8d %8u %1d %1d ",
76710743SDavid.Hollister@Sun.COM 		    wp->htag, state, path, tgt, wp->timer,
76810743SDavid.Hollister@Sun.COM 		    wp->onwire, wp->dead);
76910743SDavid.Hollister@Sun.COM 	}
77010743SDavid.Hollister@Sun.COM 	if (verbose) {
77111601SDavid.Hollister@Sun.COM 		mdb_printf("%08x %10s 0x%016p 0x%016p 0x%016p\n",
77211601SDavid.Hollister@Sun.COM 		    wp->last_htag, last_state, wp->last_phy, wp->last_xp,
77311601SDavid.Hollister@Sun.COM 		    wp->last_arg);
77410743SDavid.Hollister@Sun.COM 	} else {
77510743SDavid.Hollister@Sun.COM 		mdb_printf("\n");
77610743SDavid.Hollister@Sun.COM 	}
77710743SDavid.Hollister@Sun.COM }
77810743SDavid.Hollister@Sun.COM 
77910696SDavid.Hollister@Sun.COM static void
78010696SDavid.Hollister@Sun.COM display_work(struct pmcs_hw m, int verbose)
78110696SDavid.Hollister@Sun.COM {
78210696SDavid.Hollister@Sun.COM 	int		idx;
78310743SDavid.Hollister@Sun.COM 	boolean_t	header_printed = B_FALSE;
78410696SDavid.Hollister@Sun.COM 	pmcwork_t	work, *wp = &work;
78510696SDavid.Hollister@Sun.COM 	uintptr_t	_wp;
78610696SDavid.Hollister@Sun.COM 
78710696SDavid.Hollister@Sun.COM 	mdb_printf("\nActive Work structure information:\n");
78810696SDavid.Hollister@Sun.COM 	mdb_printf("----------------------------------\n");
78910696SDavid.Hollister@Sun.COM 
79010696SDavid.Hollister@Sun.COM 	_wp = (uintptr_t)m.work;
79110696SDavid.Hollister@Sun.COM 
79210696SDavid.Hollister@Sun.COM 	for (idx = 0; idx < m.max_cmd; idx++, _wp += sizeof (pmcwork_t)) {
79310696SDavid.Hollister@Sun.COM 		if (MDB_RD(&work, sizeof (pmcwork_t), _wp) == -1) {
79410696SDavid.Hollister@Sun.COM 			NOREAD(pmcwork_t, _wp);
79510696SDavid.Hollister@Sun.COM 			continue;
79610696SDavid.Hollister@Sun.COM 		}
79710743SDavid.Hollister@Sun.COM 
79810743SDavid.Hollister@Sun.COM 		if (!verbose && (wp->htag == PMCS_TAG_TYPE_FREE)) {
79910696SDavid.Hollister@Sun.COM 			continue;
80010696SDavid.Hollister@Sun.COM 		}
80110743SDavid.Hollister@Sun.COM 
80210743SDavid.Hollister@Sun.COM 		if (header_printed == B_FALSE) {
80310743SDavid.Hollister@Sun.COM 			if (verbose) {
80410743SDavid.Hollister@Sun.COM 				mdb_printf("%4s ", "Idx");
80510743SDavid.Hollister@Sun.COM 			}
80610743SDavid.Hollister@Sun.COM 			mdb_printf("%8s %10s %20s %8s %8s O D ",
80710696SDavid.Hollister@Sun.COM 			    "HTag", "State", "Phy Path", "Target", "Timer");
80810743SDavid.Hollister@Sun.COM 			if (verbose) {
80911601SDavid.Hollister@Sun.COM 				mdb_printf("%8s %10s %18s %18s %18s\n",
81011601SDavid.Hollister@Sun.COM 				    "LastHTAG", "LastState", "LastPHY",
81111601SDavid.Hollister@Sun.COM 				    "LastTgt", "LastArg");
81210743SDavid.Hollister@Sun.COM 			} else {
81310743SDavid.Hollister@Sun.COM 				mdb_printf("\n");
81410743SDavid.Hollister@Sun.COM 			}
81510743SDavid.Hollister@Sun.COM 			header_printed = B_TRUE;
81610696SDavid.Hollister@Sun.COM 		}
81710743SDavid.Hollister@Sun.COM 
81810743SDavid.Hollister@Sun.COM 		display_one_work(wp, verbose, idx);
81910696SDavid.Hollister@Sun.COM 	}
82010696SDavid.Hollister@Sun.COM }
82110696SDavid.Hollister@Sun.COM 
82210696SDavid.Hollister@Sun.COM static void
82310743SDavid.Hollister@Sun.COM print_spcmd(pmcs_cmd_t *sp, void *kaddr, int printhdr, int verbose)
82410696SDavid.Hollister@Sun.COM {
82510743SDavid.Hollister@Sun.COM 	int cdb_size, idx;
82610743SDavid.Hollister@Sun.COM 	struct scsi_pkt pkt;
82710743SDavid.Hollister@Sun.COM 	uchar_t cdb[256];
82810743SDavid.Hollister@Sun.COM 
82910696SDavid.Hollister@Sun.COM 	if (printhdr) {
83010743SDavid.Hollister@Sun.COM 		if (verbose) {
83110743SDavid.Hollister@Sun.COM 			mdb_printf("%16s %16s %16s %8s %s CDB\n", "Command",
83210743SDavid.Hollister@Sun.COM 			    "SCSA pkt", "DMA Chunks", "HTAG", "SATL Tag");
83310743SDavid.Hollister@Sun.COM 		} else {
83410743SDavid.Hollister@Sun.COM 			mdb_printf("%16s %16s %16s %8s %s\n", "Command",
83510743SDavid.Hollister@Sun.COM 			    "SCSA pkt", "DMA Chunks", "HTAG", "SATL Tag");
83610743SDavid.Hollister@Sun.COM 		}
83710696SDavid.Hollister@Sun.COM 	}
83810743SDavid.Hollister@Sun.COM 
83910743SDavid.Hollister@Sun.COM 	mdb_printf("%16p %16p %16p %08x %08x ",
84010696SDavid.Hollister@Sun.COM 	    kaddr, sp->cmd_pkt, sp->cmd_clist, sp->cmd_tag, sp->cmd_satltag);
84110743SDavid.Hollister@Sun.COM 
84210743SDavid.Hollister@Sun.COM 	/*
84310743SDavid.Hollister@Sun.COM 	 * If we're printing verbose, dump the CDB as well.
84410743SDavid.Hollister@Sun.COM 	 */
84510743SDavid.Hollister@Sun.COM 	if (verbose) {
84610743SDavid.Hollister@Sun.COM 		if (sp->cmd_pkt) {
84710743SDavid.Hollister@Sun.COM 			if (mdb_vread(&pkt, sizeof (struct scsi_pkt),
84810743SDavid.Hollister@Sun.COM 			    (uintptr_t)sp->cmd_pkt) !=
84910743SDavid.Hollister@Sun.COM 			    sizeof (struct scsi_pkt)) {
85010743SDavid.Hollister@Sun.COM 				mdb_warn("Unable to read SCSI pkt\n");
85110743SDavid.Hollister@Sun.COM 				return;
85210743SDavid.Hollister@Sun.COM 			}
85310743SDavid.Hollister@Sun.COM 			cdb_size = pkt.pkt_cdblen;
85410743SDavid.Hollister@Sun.COM 			if (mdb_vread(&cdb[0], cdb_size,
85510743SDavid.Hollister@Sun.COM 			    (uintptr_t)pkt.pkt_cdbp) != cdb_size) {
85610743SDavid.Hollister@Sun.COM 				mdb_warn("Unable to read CDB\n");
85710743SDavid.Hollister@Sun.COM 				return;
85810743SDavid.Hollister@Sun.COM 			}
85910743SDavid.Hollister@Sun.COM 
86010743SDavid.Hollister@Sun.COM 			for (idx = 0; idx < cdb_size; idx++) {
86110743SDavid.Hollister@Sun.COM 				mdb_printf("%02x ", cdb[idx]);
86210743SDavid.Hollister@Sun.COM 			}
86310743SDavid.Hollister@Sun.COM 		} else {
86410743SDavid.Hollister@Sun.COM 			mdb_printf("N/A");
86510743SDavid.Hollister@Sun.COM 		}
86610743SDavid.Hollister@Sun.COM 
86710743SDavid.Hollister@Sun.COM 		mdb_printf("\n");
86810743SDavid.Hollister@Sun.COM 	} else {
86910743SDavid.Hollister@Sun.COM 		mdb_printf("\n");
87010743SDavid.Hollister@Sun.COM 	}
87110696SDavid.Hollister@Sun.COM }
87210696SDavid.Hollister@Sun.COM 
87310696SDavid.Hollister@Sun.COM /*ARGSUSED1*/
87410696SDavid.Hollister@Sun.COM static void
87510696SDavid.Hollister@Sun.COM display_waitqs(struct pmcs_hw m, int verbose)
87610696SDavid.Hollister@Sun.COM {
87710696SDavid.Hollister@Sun.COM 	pmcs_cmd_t	*sp, s;
87810696SDavid.Hollister@Sun.COM 	pmcs_xscsi_t	xs;
87910696SDavid.Hollister@Sun.COM 	int		first, i;
88010696SDavid.Hollister@Sun.COM 	int		max_dev = m.max_dev;
88110696SDavid.Hollister@Sun.COM 
88210696SDavid.Hollister@Sun.COM 	sp = m.dq.stqh_first;
88310696SDavid.Hollister@Sun.COM 	first = 1;
88410696SDavid.Hollister@Sun.COM 	while (sp) {
88510696SDavid.Hollister@Sun.COM 		if (first) {
88610696SDavid.Hollister@Sun.COM 			mdb_printf("\nDead Command Queue:\n");
88710696SDavid.Hollister@Sun.COM 			mdb_printf("---------------------------\n");
88810696SDavid.Hollister@Sun.COM 		}
88910696SDavid.Hollister@Sun.COM 		if (MDB_RD(&s, sizeof (s), sp) == -1) {
89010696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_cmd_t, sp);
89110696SDavid.Hollister@Sun.COM 			break;
89210696SDavid.Hollister@Sun.COM 		}
89310743SDavid.Hollister@Sun.COM 		print_spcmd(&s, sp, first, verbose);
89410696SDavid.Hollister@Sun.COM 		sp = s.cmd_next.stqe_next;
89510696SDavid.Hollister@Sun.COM 		first = 0;
89610696SDavid.Hollister@Sun.COM 	}
89710696SDavid.Hollister@Sun.COM 
89810696SDavid.Hollister@Sun.COM 	sp = m.cq.stqh_first;
89910696SDavid.Hollister@Sun.COM 	first = 1;
90010696SDavid.Hollister@Sun.COM 	while (sp) {
90110696SDavid.Hollister@Sun.COM 		if (first) {
90210696SDavid.Hollister@Sun.COM 			mdb_printf("\nCompletion Command Queue:\n");
90310696SDavid.Hollister@Sun.COM 			mdb_printf("---------------------------\n");
90410696SDavid.Hollister@Sun.COM 		}
90510696SDavid.Hollister@Sun.COM 		if (MDB_RD(&s, sizeof (s), sp) == -1) {
90610696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_cmd_t, sp);
90710696SDavid.Hollister@Sun.COM 			break;
90810696SDavid.Hollister@Sun.COM 		}
90910743SDavid.Hollister@Sun.COM 		print_spcmd(&s, sp, first, verbose);
91010696SDavid.Hollister@Sun.COM 		sp = s.cmd_next.stqe_next;
91110696SDavid.Hollister@Sun.COM 		first = 0;
91210696SDavid.Hollister@Sun.COM 	}
91310696SDavid.Hollister@Sun.COM 
91410696SDavid.Hollister@Sun.COM 
91510696SDavid.Hollister@Sun.COM 	if (targets == NULL) {
91610696SDavid.Hollister@Sun.COM 		targets = mdb_alloc(sizeof (targets) * max_dev, UM_SLEEP);
91710696SDavid.Hollister@Sun.COM 	}
91810696SDavid.Hollister@Sun.COM 
91910696SDavid.Hollister@Sun.COM 	if (MDB_RD(targets, sizeof (targets) * max_dev, m.targets) == -1) {
92010696SDavid.Hollister@Sun.COM 		NOREAD(targets, m.targets);
92110696SDavid.Hollister@Sun.COM 		return;
92210696SDavid.Hollister@Sun.COM 	}
92310696SDavid.Hollister@Sun.COM 
92410696SDavid.Hollister@Sun.COM 	for (i = 0; i < max_dev; i++) {
92510696SDavid.Hollister@Sun.COM 		if (targets[i] == NULL) {
92610696SDavid.Hollister@Sun.COM 			continue;
92710696SDavid.Hollister@Sun.COM 		}
92810696SDavid.Hollister@Sun.COM 		if (MDB_RD(&xs, sizeof (xs), targets[i]) == -1) {
92910696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_xscsi_t, targets[i]);
93010696SDavid.Hollister@Sun.COM 			continue;
93110696SDavid.Hollister@Sun.COM 		}
93210696SDavid.Hollister@Sun.COM 		sp = xs.wq.stqh_first;
93310696SDavid.Hollister@Sun.COM 		first = 1;
93410696SDavid.Hollister@Sun.COM 		while (sp) {
93510696SDavid.Hollister@Sun.COM 			if (first) {
93610696SDavid.Hollister@Sun.COM 				mdb_printf("\nTarget %u Wait Queue:\n",
93710696SDavid.Hollister@Sun.COM 				    xs.target_num);
93810696SDavid.Hollister@Sun.COM 				mdb_printf("---------------------------\n");
93910696SDavid.Hollister@Sun.COM 			}
94010696SDavid.Hollister@Sun.COM 			if (MDB_RD(&s, sizeof (s), sp) == -1) {
94110696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_cmd_t, sp);
94210696SDavid.Hollister@Sun.COM 				break;
94310696SDavid.Hollister@Sun.COM 			}
94410743SDavid.Hollister@Sun.COM 			print_spcmd(&s, sp, first, verbose);
94510696SDavid.Hollister@Sun.COM 			sp = s.cmd_next.stqe_next;
94610696SDavid.Hollister@Sun.COM 			first = 0;
94710696SDavid.Hollister@Sun.COM 		}
94810696SDavid.Hollister@Sun.COM 		sp = xs.aq.stqh_first;
94910696SDavid.Hollister@Sun.COM 		first = 1;
95010696SDavid.Hollister@Sun.COM 		while (sp) {
95110696SDavid.Hollister@Sun.COM 			if (first) {
95210696SDavid.Hollister@Sun.COM 				mdb_printf("\nTarget %u Active Queue:\n",
95310696SDavid.Hollister@Sun.COM 				    xs.target_num);
95410696SDavid.Hollister@Sun.COM 				mdb_printf("---------------------------\n");
95510696SDavid.Hollister@Sun.COM 			}
95610696SDavid.Hollister@Sun.COM 			if (MDB_RD(&s, sizeof (s), sp) == -1) {
95710696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_cmd_t, sp);
95810696SDavid.Hollister@Sun.COM 				break;
95910696SDavid.Hollister@Sun.COM 			}
96010743SDavid.Hollister@Sun.COM 			print_spcmd(&s, sp, first, verbose);
96110696SDavid.Hollister@Sun.COM 			sp = s.cmd_next.stqe_next;
96210696SDavid.Hollister@Sun.COM 			first = 0;
96310696SDavid.Hollister@Sun.COM 		}
96410696SDavid.Hollister@Sun.COM 		sp = xs.sq.stqh_first;
96510696SDavid.Hollister@Sun.COM 		first = 1;
96610696SDavid.Hollister@Sun.COM 		while (sp) {
96710696SDavid.Hollister@Sun.COM 			if (first) {
96810696SDavid.Hollister@Sun.COM 				mdb_printf("\nTarget %u Special Queue:\n",
96910696SDavid.Hollister@Sun.COM 				    xs.target_num);
97010696SDavid.Hollister@Sun.COM 				mdb_printf("---------------------------\n");
97110696SDavid.Hollister@Sun.COM 			}
97210696SDavid.Hollister@Sun.COM 			if (MDB_RD(&s, sizeof (s), sp) == -1) {
97310696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_cmd_t, sp);
97410696SDavid.Hollister@Sun.COM 				break;
97510696SDavid.Hollister@Sun.COM 			}
97610743SDavid.Hollister@Sun.COM 			print_spcmd(&s, sp, first, verbose);
97710696SDavid.Hollister@Sun.COM 			sp = s.cmd_next.stqe_next;
97810696SDavid.Hollister@Sun.COM 			first = 0;
97910696SDavid.Hollister@Sun.COM 		}
98010696SDavid.Hollister@Sun.COM 	}
98110696SDavid.Hollister@Sun.COM }
98210696SDavid.Hollister@Sun.COM 
98310696SDavid.Hollister@Sun.COM static char *
98410696SDavid.Hollister@Sun.COM ibq_type(int qnum)
98510696SDavid.Hollister@Sun.COM {
98610696SDavid.Hollister@Sun.COM 	if (qnum < 0 || qnum >= PMCS_NIQ) {
98710696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
98810696SDavid.Hollister@Sun.COM 	}
98910696SDavid.Hollister@Sun.COM 
99010696SDavid.Hollister@Sun.COM 	if (qnum < PMCS_IQ_OTHER) {
99110696SDavid.Hollister@Sun.COM 		return ("I/O");
99210696SDavid.Hollister@Sun.COM 	}
99310696SDavid.Hollister@Sun.COM 
99410696SDavid.Hollister@Sun.COM 	return ("Other");
99510696SDavid.Hollister@Sun.COM }
99610696SDavid.Hollister@Sun.COM 
99710696SDavid.Hollister@Sun.COM static char *
99810696SDavid.Hollister@Sun.COM obq_type(int qnum)
99910696SDavid.Hollister@Sun.COM {
100010696SDavid.Hollister@Sun.COM 	switch (qnum) {
100110696SDavid.Hollister@Sun.COM 	case PMCS_OQ_IODONE:
100210696SDavid.Hollister@Sun.COM 		return ("I/O");
100310696SDavid.Hollister@Sun.COM 		break;
100410696SDavid.Hollister@Sun.COM 	case PMCS_OQ_GENERAL:
100510696SDavid.Hollister@Sun.COM 		return ("General");
100610696SDavid.Hollister@Sun.COM 		break;
100710696SDavid.Hollister@Sun.COM 	case PMCS_OQ_EVENTS:
100810696SDavid.Hollister@Sun.COM 		return ("Events");
100910696SDavid.Hollister@Sun.COM 		break;
101010696SDavid.Hollister@Sun.COM 	default:
101110696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
101210696SDavid.Hollister@Sun.COM 	}
101310696SDavid.Hollister@Sun.COM }
101410696SDavid.Hollister@Sun.COM 
101510696SDavid.Hollister@Sun.COM static char *
101610696SDavid.Hollister@Sun.COM iomb_cat(uint32_t cat)
101710696SDavid.Hollister@Sun.COM {
101810696SDavid.Hollister@Sun.COM 	switch (cat) {
101910696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_NET:
102010696SDavid.Hollister@Sun.COM 		return ("NET");
102110696SDavid.Hollister@Sun.COM 		break;
102210696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_FC:
102310696SDavid.Hollister@Sun.COM 		return ("FC");
102410696SDavid.Hollister@Sun.COM 		break;
102510696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_SAS:
102610696SDavid.Hollister@Sun.COM 		return ("SAS");
102710696SDavid.Hollister@Sun.COM 		break;
102810696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_SCSI:
102910696SDavid.Hollister@Sun.COM 		return ("SCSI");
103010696SDavid.Hollister@Sun.COM 		break;
103110696SDavid.Hollister@Sun.COM 	default:
103210696SDavid.Hollister@Sun.COM 		return ("???");
103310696SDavid.Hollister@Sun.COM 	}
103410696SDavid.Hollister@Sun.COM }
103510696SDavid.Hollister@Sun.COM 
103610696SDavid.Hollister@Sun.COM static char *
103711601SDavid.Hollister@Sun.COM iomb_event(uint8_t event)
103811601SDavid.Hollister@Sun.COM {
103911601SDavid.Hollister@Sun.COM 	switch (event) {
104011601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PHY_STOP_STATUS:
104111601SDavid.Hollister@Sun.COM 		return ("PHY STOP");
104211601SDavid.Hollister@Sun.COM 		break;
104311601SDavid.Hollister@Sun.COM 	case IOP_EVENT_SAS_PHY_UP:
104411601SDavid.Hollister@Sun.COM 		return ("PHY UP");
104511601SDavid.Hollister@Sun.COM 		break;
104611601SDavid.Hollister@Sun.COM 	case IOP_EVENT_SATA_PHY_UP:
104711601SDavid.Hollister@Sun.COM 		return ("SATA PHY UP");
104811601SDavid.Hollister@Sun.COM 		break;
104911601SDavid.Hollister@Sun.COM 	case IOP_EVENT_SATA_SPINUP_HOLD:
105011601SDavid.Hollister@Sun.COM 		return ("SATA SPINUP HOLD");
105111601SDavid.Hollister@Sun.COM 		break;
105211601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PHY_DOWN:
105311601SDavid.Hollister@Sun.COM 		return ("PHY DOWN");
105411601SDavid.Hollister@Sun.COM 		break;
105511601SDavid.Hollister@Sun.COM 	case IOP_EVENT_BROADCAST_CHANGE:
105611601SDavid.Hollister@Sun.COM 		return ("BROADCAST CHANGE");
105711601SDavid.Hollister@Sun.COM 		break;
105811601SDavid.Hollister@Sun.COM 	case IOP_EVENT_BROADCAST_SES:
105911601SDavid.Hollister@Sun.COM 		return ("BROADCAST SES");
106011601SDavid.Hollister@Sun.COM 		break;
106111601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PHY_ERR_INBOUND_CRC:
106211601SDavid.Hollister@Sun.COM 		return ("INBOUND CRC ERROR");
106311601SDavid.Hollister@Sun.COM 		break;
106411601SDavid.Hollister@Sun.COM 	case IOP_EVENT_HARD_RESET_RECEIVED:
106511601SDavid.Hollister@Sun.COM 		return ("HARD RESET");
106611601SDavid.Hollister@Sun.COM 		break;
106711601SDavid.Hollister@Sun.COM 	case IOP_EVENT_EVENT_ID_FRAME_TIMO:
106811601SDavid.Hollister@Sun.COM 		return ("IDENTIFY FRAME TIMEOUT");
106911601SDavid.Hollister@Sun.COM 		break;
107011601SDavid.Hollister@Sun.COM 	case IOP_EVENT_BROADCAST_EXP:
107111601SDavid.Hollister@Sun.COM 		return ("BROADCAST EXPANDER");
107211601SDavid.Hollister@Sun.COM 		break;
107311601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PHY_START_STATUS:
107411601SDavid.Hollister@Sun.COM 		return ("PHY START");
107511601SDavid.Hollister@Sun.COM 		break;
107611601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PHY_ERR_INVALID_DWORD:
107711601SDavid.Hollister@Sun.COM 		return ("INVALID DWORD");
107811601SDavid.Hollister@Sun.COM 		break;
107911601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PHY_ERR_DISPARITY_ERROR:
108011601SDavid.Hollister@Sun.COM 		return ("DISPARITY ERROR");
108111601SDavid.Hollister@Sun.COM 		break;
108211601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PHY_ERR_CODE_VIOLATION:
108311601SDavid.Hollister@Sun.COM 		return ("CODE VIOLATION");
108411601SDavid.Hollister@Sun.COM 		break;
108511601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PHY_ERR_LOSS_OF_DWORD_SYN:
108611601SDavid.Hollister@Sun.COM 		return ("LOSS OF DWORD SYNC");
108711601SDavid.Hollister@Sun.COM 		break;
108811601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PHY_ERR_PHY_RESET_FAILD:
108911601SDavid.Hollister@Sun.COM 		return ("PHY RESET FAILED");
109011601SDavid.Hollister@Sun.COM 		break;
109111601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PORT_RECOVERY_TIMER_TMO:
109211601SDavid.Hollister@Sun.COM 		return ("PORT RECOVERY TIMEOUT");
109311601SDavid.Hollister@Sun.COM 		break;
109411601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PORT_RECOVER:
109511601SDavid.Hollister@Sun.COM 		return ("PORT RECOVERY");
109611601SDavid.Hollister@Sun.COM 		break;
109711601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PORT_RESET_TIMER_TMO:
109811601SDavid.Hollister@Sun.COM 		return ("PORT RESET TIMEOUT");
109911601SDavid.Hollister@Sun.COM 		break;
110011601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PORT_RESET_COMPLETE:
110111601SDavid.Hollister@Sun.COM 		return ("PORT RESET COMPLETE");
110211601SDavid.Hollister@Sun.COM 		break;
110311601SDavid.Hollister@Sun.COM 	case IOP_EVENT_BROADCAST_ASYNC_EVENT:
110411601SDavid.Hollister@Sun.COM 		return ("BROADCAST ASYNC");
110511601SDavid.Hollister@Sun.COM 		break;
110611601SDavid.Hollister@Sun.COM 	case IOP_EVENT_IT_NEXUS_LOSS:
110711601SDavid.Hollister@Sun.COM 		return ("I/T NEXUS LOSS");
110811601SDavid.Hollister@Sun.COM 		break;
110911601SDavid.Hollister@Sun.COM 	default:
111011601SDavid.Hollister@Sun.COM 		return ("Unknown Event");
111111601SDavid.Hollister@Sun.COM 	}
111211601SDavid.Hollister@Sun.COM }
111311601SDavid.Hollister@Sun.COM 
111411601SDavid.Hollister@Sun.COM static char *
111510696SDavid.Hollister@Sun.COM inbound_iomb_opcode(uint32_t opcode)
111610696SDavid.Hollister@Sun.COM {
111710696SDavid.Hollister@Sun.COM 	switch (opcode) {
111810696SDavid.Hollister@Sun.COM 	case PMCIN_ECHO:
111910696SDavid.Hollister@Sun.COM 		return ("ECHO");
112010696SDavid.Hollister@Sun.COM 		break;
112110696SDavid.Hollister@Sun.COM 	case PMCIN_GET_INFO:
112210696SDavid.Hollister@Sun.COM 		return ("GET_INFO");
112310696SDavid.Hollister@Sun.COM 		break;
112410696SDavid.Hollister@Sun.COM 	case PMCIN_GET_VPD:
112510696SDavid.Hollister@Sun.COM 		return ("GET_VPD");
112610696SDavid.Hollister@Sun.COM 		break;
112710696SDavid.Hollister@Sun.COM 	case PMCIN_PHY_START:
112810696SDavid.Hollister@Sun.COM 		return ("PHY_START");
112910696SDavid.Hollister@Sun.COM 		break;
113010696SDavid.Hollister@Sun.COM 	case PMCIN_PHY_STOP:
113110696SDavid.Hollister@Sun.COM 		return ("PHY_STOP");
113210696SDavid.Hollister@Sun.COM 		break;
113310696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_IO_START:
113410696SDavid.Hollister@Sun.COM 		return ("INI_IO_START");
113510696SDavid.Hollister@Sun.COM 		break;
113610696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_TM_START:
113710696SDavid.Hollister@Sun.COM 		return ("INI_TM_START");
113810696SDavid.Hollister@Sun.COM 		break;
113910696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_EXT_IO_START:
114010696SDavid.Hollister@Sun.COM 		return ("INI_EXT_IO_START");
114110696SDavid.Hollister@Sun.COM 		break;
114210696SDavid.Hollister@Sun.COM 	case PMCIN_DEVICE_HANDLE_ACCEPT:
114310696SDavid.Hollister@Sun.COM 		return ("DEVICE_HANDLE_ACCEPT");
114410696SDavid.Hollister@Sun.COM 		break;
114510696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_TGT_IO_START:
114610696SDavid.Hollister@Sun.COM 		return ("TGT_IO_START");
114710696SDavid.Hollister@Sun.COM 		break;
114810696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_TGT_RESPONSE_START:
114910696SDavid.Hollister@Sun.COM 		return ("TGT_RESPONSE_START");
115010696SDavid.Hollister@Sun.COM 		break;
115110696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_EDC_EXT_IO_START:
115210696SDavid.Hollister@Sun.COM 		return ("INI_EDC_EXT_IO_START");
115310696SDavid.Hollister@Sun.COM 		break;
115410696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_EDC_EXT_IO_START1:
115510696SDavid.Hollister@Sun.COM 		return ("INI_EDC_EXT_IO_START1");
115610696SDavid.Hollister@Sun.COM 		break;
115710696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_TGT_EDC_IO_START:
115810696SDavid.Hollister@Sun.COM 		return ("TGT_EDC_IO_START");
115910696SDavid.Hollister@Sun.COM 		break;
116010696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_ABORT:
116110696SDavid.Hollister@Sun.COM 		return ("SSP_ABORT");
116210696SDavid.Hollister@Sun.COM 		break;
116310696SDavid.Hollister@Sun.COM 	case PMCIN_DEREGISTER_DEVICE_HANDLE:
116410696SDavid.Hollister@Sun.COM 		return ("DEREGISTER_DEVICE_HANDLE");
116510696SDavid.Hollister@Sun.COM 		break;
116610696SDavid.Hollister@Sun.COM 	case PMCIN_GET_DEVICE_HANDLE:
116710696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_HANDLE");
116810696SDavid.Hollister@Sun.COM 		break;
116910696SDavid.Hollister@Sun.COM 	case PMCIN_SMP_REQUEST:
117010696SDavid.Hollister@Sun.COM 		return ("SMP_REQUEST");
117110696SDavid.Hollister@Sun.COM 		break;
117210696SDavid.Hollister@Sun.COM 	case PMCIN_SMP_RESPONSE:
117310696SDavid.Hollister@Sun.COM 		return ("SMP_RESPONSE");
117410696SDavid.Hollister@Sun.COM 		break;
117510696SDavid.Hollister@Sun.COM 	case PMCIN_SMP_ABORT:
117610696SDavid.Hollister@Sun.COM 		return ("SMP_ABORT");
117710696SDavid.Hollister@Sun.COM 		break;
117810696SDavid.Hollister@Sun.COM 	case PMCIN_ASSISTED_DISCOVERY:
117910696SDavid.Hollister@Sun.COM 		return ("ASSISTED_DISCOVERY");
118010696SDavid.Hollister@Sun.COM 		break;
118110696SDavid.Hollister@Sun.COM 	case PMCIN_REGISTER_DEVICE:
118210696SDavid.Hollister@Sun.COM 		return ("REGISTER_DEVICE");
118310696SDavid.Hollister@Sun.COM 		break;
118410696SDavid.Hollister@Sun.COM 	case PMCIN_SATA_HOST_IO_START:
118510696SDavid.Hollister@Sun.COM 		return ("SATA_HOST_IO_START");
118610696SDavid.Hollister@Sun.COM 		break;
118710696SDavid.Hollister@Sun.COM 	case PMCIN_SATA_ABORT:
118810696SDavid.Hollister@Sun.COM 		return ("SATA_ABORT");
118910696SDavid.Hollister@Sun.COM 		break;
119010696SDavid.Hollister@Sun.COM 	case PMCIN_LOCAL_PHY_CONTROL:
119110696SDavid.Hollister@Sun.COM 		return ("LOCAL_PHY_CONTROL");
119210696SDavid.Hollister@Sun.COM 		break;
119310696SDavid.Hollister@Sun.COM 	case PMCIN_GET_DEVICE_INFO:
119410696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_INFO");
119510696SDavid.Hollister@Sun.COM 		break;
119610696SDavid.Hollister@Sun.COM 	case PMCIN_TWI:
119710696SDavid.Hollister@Sun.COM 		return ("TWI");
119810696SDavid.Hollister@Sun.COM 		break;
119910696SDavid.Hollister@Sun.COM 	case PMCIN_FW_FLASH_UPDATE:
120010696SDavid.Hollister@Sun.COM 		return ("FW_FLASH_UPDATE");
120110696SDavid.Hollister@Sun.COM 		break;
120210696SDavid.Hollister@Sun.COM 	case PMCIN_SET_VPD:
120310696SDavid.Hollister@Sun.COM 		return ("SET_VPD");
120410696SDavid.Hollister@Sun.COM 		break;
120510696SDavid.Hollister@Sun.COM 	case PMCIN_GPIO:
120610696SDavid.Hollister@Sun.COM 		return ("GPIO");
120710696SDavid.Hollister@Sun.COM 		break;
120810696SDavid.Hollister@Sun.COM 	case PMCIN_SAS_DIAG_MODE_START_END:
120910696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_MODE_START_END");
121010696SDavid.Hollister@Sun.COM 		break;
121110696SDavid.Hollister@Sun.COM 	case PMCIN_SAS_DIAG_EXECUTE:
121210696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_EXECUTE");
121310696SDavid.Hollister@Sun.COM 		break;
121410696SDavid.Hollister@Sun.COM 	case PMCIN_SAW_HW_EVENT_ACK:
121510696SDavid.Hollister@Sun.COM 		return ("SAS_HW_EVENT_ACK");
121610696SDavid.Hollister@Sun.COM 		break;
121710696SDavid.Hollister@Sun.COM 	case PMCIN_GET_TIME_STAMP:
121810696SDavid.Hollister@Sun.COM 		return ("GET_TIME_STAMP");
121910696SDavid.Hollister@Sun.COM 		break;
122010696SDavid.Hollister@Sun.COM 	case PMCIN_PORT_CONTROL:
122110696SDavid.Hollister@Sun.COM 		return ("PORT_CONTROL");
122210696SDavid.Hollister@Sun.COM 		break;
122310696SDavid.Hollister@Sun.COM 	case PMCIN_GET_NVMD_DATA:
122410696SDavid.Hollister@Sun.COM 		return ("GET_NVMD_DATA");
122510696SDavid.Hollister@Sun.COM 		break;
122610696SDavid.Hollister@Sun.COM 	case PMCIN_SET_NVMD_DATA:
122710696SDavid.Hollister@Sun.COM 		return ("SET_NVMD_DATA");
122810696SDavid.Hollister@Sun.COM 		break;
122910696SDavid.Hollister@Sun.COM 	case PMCIN_SET_DEVICE_STATE:
123010696SDavid.Hollister@Sun.COM 		return ("SET_DEVICE_STATE");
123110696SDavid.Hollister@Sun.COM 		break;
123210696SDavid.Hollister@Sun.COM 	case PMCIN_GET_DEVICE_STATE:
123310696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_STATE");
123410696SDavid.Hollister@Sun.COM 		break;
123510696SDavid.Hollister@Sun.COM 	default:
123610696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
123710696SDavid.Hollister@Sun.COM 		break;
123810696SDavid.Hollister@Sun.COM 	}
123910696SDavid.Hollister@Sun.COM }
124010696SDavid.Hollister@Sun.COM 
124110696SDavid.Hollister@Sun.COM static char *
124210696SDavid.Hollister@Sun.COM outbound_iomb_opcode(uint32_t opcode)
124310696SDavid.Hollister@Sun.COM {
124410696SDavid.Hollister@Sun.COM 	switch (opcode) {
124510696SDavid.Hollister@Sun.COM 	case PMCOUT_ECHO:
124610696SDavid.Hollister@Sun.COM 		return ("ECHO");
124710696SDavid.Hollister@Sun.COM 		break;
124810696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_INFO:
124910696SDavid.Hollister@Sun.COM 		return ("GET_INFO");
125010696SDavid.Hollister@Sun.COM 		break;
125110696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_VPD:
125210696SDavid.Hollister@Sun.COM 		return ("GET_VPD");
125310696SDavid.Hollister@Sun.COM 		break;
125410696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_HW_EVENT:
125510696SDavid.Hollister@Sun.COM 		return ("SAS_HW_EVENT");
125610696SDavid.Hollister@Sun.COM 		break;
125710696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_COMPLETION:
125810696SDavid.Hollister@Sun.COM 		return ("SSP_COMPLETION");
125910696SDavid.Hollister@Sun.COM 		break;
126010696SDavid.Hollister@Sun.COM 	case PMCOUT_SMP_COMPLETION:
126110696SDavid.Hollister@Sun.COM 		return ("SMP_COMPLETION");
126210696SDavid.Hollister@Sun.COM 		break;
126310696SDavid.Hollister@Sun.COM 	case PMCOUT_LOCAL_PHY_CONTROL:
126410696SDavid.Hollister@Sun.COM 		return ("LOCAL_PHY_CONTROL");
126510696SDavid.Hollister@Sun.COM 		break;
126610696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_ASSISTED_DISCOVERY_EVENT:
126710696SDavid.Hollister@Sun.COM 		return ("SAS_ASSISTED_DISCOVERY_SENT");
126810696SDavid.Hollister@Sun.COM 		break;
126910696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_ASSISTED_DISCOVERY_EVENT:
127010696SDavid.Hollister@Sun.COM 		return ("SATA_ASSISTED_DISCOVERY_SENT");
127110696SDavid.Hollister@Sun.COM 		break;
127210696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_REGISTRATION:
127310696SDavid.Hollister@Sun.COM 		return ("DEVICE_REGISTRATION");
127410696SDavid.Hollister@Sun.COM 		break;
127510696SDavid.Hollister@Sun.COM 	case PMCOUT_DEREGISTER_DEVICE_HANDLE:
127610696SDavid.Hollister@Sun.COM 		return ("DEREGISTER_DEVICE_HANDLE");
127710696SDavid.Hollister@Sun.COM 		break;
127810696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_DEVICE_HANDLE:
127910696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_HANDLE");
128010696SDavid.Hollister@Sun.COM 		break;
128110696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_COMPLETION:
128210696SDavid.Hollister@Sun.COM 		return ("SATA_COMPLETION");
128310696SDavid.Hollister@Sun.COM 		break;
128410696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_EVENT:
128510696SDavid.Hollister@Sun.COM 		return ("SATA_EVENT");
128610696SDavid.Hollister@Sun.COM 		break;
128710696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_EVENT:
128810696SDavid.Hollister@Sun.COM 		return ("SSP_EVENT");
128910696SDavid.Hollister@Sun.COM 		break;
129010696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_HANDLE_ARRIVED:
129110696SDavid.Hollister@Sun.COM 		return ("DEVICE_HANDLE_ARRIVED");
129210696SDavid.Hollister@Sun.COM 		break;
129310696SDavid.Hollister@Sun.COM 	case PMCOUT_SMP_REQUEST_RECEIVED:
129410696SDavid.Hollister@Sun.COM 		return ("SMP_REQUEST_RECEIVED");
129510696SDavid.Hollister@Sun.COM 		break;
129610696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_REQUEST_RECEIVED:
129710696SDavid.Hollister@Sun.COM 		return ("SSP_REQUEST_RECEIVED");
129810696SDavid.Hollister@Sun.COM 		break;
129910696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_INFO:
130010696SDavid.Hollister@Sun.COM 		return ("DEVICE_INFO");
130110696SDavid.Hollister@Sun.COM 		break;
130210696SDavid.Hollister@Sun.COM 	case PMCOUT_FW_FLASH_UPDATE:
130310696SDavid.Hollister@Sun.COM 		return ("FW_FLASH_UPDATE");
130410696SDavid.Hollister@Sun.COM 		break;
130510696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_VPD:
130610696SDavid.Hollister@Sun.COM 		return ("SET_VPD");
130710696SDavid.Hollister@Sun.COM 		break;
130810696SDavid.Hollister@Sun.COM 	case PMCOUT_GPIO:
130910696SDavid.Hollister@Sun.COM 		return ("GPIO");
131010696SDavid.Hollister@Sun.COM 		break;
131110696SDavid.Hollister@Sun.COM 	case PMCOUT_GPIO_EVENT:
131210696SDavid.Hollister@Sun.COM 		return ("GPIO_EVENT");
131310696SDavid.Hollister@Sun.COM 		break;
131410696SDavid.Hollister@Sun.COM 	case PMCOUT_GENERAL_EVENT:
131510696SDavid.Hollister@Sun.COM 		return ("GENERAL_EVENT");
131610696SDavid.Hollister@Sun.COM 		break;
131710696SDavid.Hollister@Sun.COM 	case PMCOUT_TWI:
131810696SDavid.Hollister@Sun.COM 		return ("TWI");
131910696SDavid.Hollister@Sun.COM 		break;
132010696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_ABORT:
132110696SDavid.Hollister@Sun.COM 		return ("SSP_ABORT");
132210696SDavid.Hollister@Sun.COM 		break;
132310696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_ABORT:
132410696SDavid.Hollister@Sun.COM 		return ("SATA_ABORT");
132510696SDavid.Hollister@Sun.COM 		break;
132610696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_DIAG_MODE_START_END:
132710696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_MODE_START_END");
132810696SDavid.Hollister@Sun.COM 		break;
132910696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_DIAG_EXECUTE:
133010696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_EXECUTE");
133110696SDavid.Hollister@Sun.COM 		break;
133210696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_TIME_STAMP:
133310696SDavid.Hollister@Sun.COM 		return ("GET_TIME_STAMP");
133410696SDavid.Hollister@Sun.COM 		break;
133510696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_HW_EVENT_ACK_ACK:
133610696SDavid.Hollister@Sun.COM 		return ("SAS_HW_EVENT_ACK_ACK");
133710696SDavid.Hollister@Sun.COM 		break;
133810696SDavid.Hollister@Sun.COM 	case PMCOUT_PORT_CONTROL:
133910696SDavid.Hollister@Sun.COM 		return ("PORT_CONTROL");
134010696SDavid.Hollister@Sun.COM 		break;
134110696SDavid.Hollister@Sun.COM 	case PMCOUT_SKIP_ENTRIES:
134210696SDavid.Hollister@Sun.COM 		return ("SKIP_ENTRIES");
134310696SDavid.Hollister@Sun.COM 		break;
134410696SDavid.Hollister@Sun.COM 	case PMCOUT_SMP_ABORT:
134510696SDavid.Hollister@Sun.COM 		return ("SMP_ABORT");
134610696SDavid.Hollister@Sun.COM 		break;
134710696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_NVMD_DATA:
134810696SDavid.Hollister@Sun.COM 		return ("GET_NVMD_DATA");
134910696SDavid.Hollister@Sun.COM 		break;
135010696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_NVMD_DATA:
135110696SDavid.Hollister@Sun.COM 		return ("SET_NVMD_DATA");
135210696SDavid.Hollister@Sun.COM 		break;
135310696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_HANDLE_REMOVED:
135410696SDavid.Hollister@Sun.COM 		return ("DEVICE_HANDLE_REMOVED");
135510696SDavid.Hollister@Sun.COM 		break;
135610696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_DEVICE_STATE:
135710696SDavid.Hollister@Sun.COM 		return ("SET_DEVICE_STATE");
135810696SDavid.Hollister@Sun.COM 		break;
135910696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_DEVICE_STATE:
136010696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_STATE");
136110696SDavid.Hollister@Sun.COM 		break;
136210696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_DEVICE_INFO:
136310696SDavid.Hollister@Sun.COM 		return ("SET_DEVICE_INFO");
136410696SDavid.Hollister@Sun.COM 		break;
136510696SDavid.Hollister@Sun.COM 	default:
136610696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
136710696SDavid.Hollister@Sun.COM 		break;
136810696SDavid.Hollister@Sun.COM 	}
136910696SDavid.Hollister@Sun.COM }
137010696SDavid.Hollister@Sun.COM 
137110696SDavid.Hollister@Sun.COM static void
137210696SDavid.Hollister@Sun.COM dump_one_qentry_outbound(uint32_t *qentryp, int idx)
137310696SDavid.Hollister@Sun.COM {
137410696SDavid.Hollister@Sun.COM 	int qeidx;
137510696SDavid.Hollister@Sun.COM 	uint32_t word0 = LE_32(*qentryp);
137611601SDavid.Hollister@Sun.COM 	uint32_t word1 = LE_32(*(qentryp + 1));
137711601SDavid.Hollister@Sun.COM 	uint8_t iop_event;
137810696SDavid.Hollister@Sun.COM 
137910696SDavid.Hollister@Sun.COM 	mdb_printf("Entry #%02d\n", idx);
138010696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
138110696SDavid.Hollister@Sun.COM 
138210696SDavid.Hollister@Sun.COM 	mdb_printf("Header: 0x%08x (", word0);
138310696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_VALID) {
138410696SDavid.Hollister@Sun.COM 		mdb_printf("VALID, ");
138510696SDavid.Hollister@Sun.COM 	}
138610696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_HIPRI) {
138710696SDavid.Hollister@Sun.COM 		mdb_printf("HIPRI, ");
138810696SDavid.Hollister@Sun.COM 	}
138910696SDavid.Hollister@Sun.COM 	mdb_printf("OBID=%d, ",
139010696SDavid.Hollister@Sun.COM 	    (word0 & PMCS_IOMB_OBID_MASK) >> PMCS_IOMB_OBID_SHIFT);
139110696SDavid.Hollister@Sun.COM 	mdb_printf("CAT=%s, ",
139210696SDavid.Hollister@Sun.COM 	    iomb_cat((word0 & PMCS_IOMB_CAT_MASK) >> PMCS_IOMB_CAT_SHIFT));
139310696SDavid.Hollister@Sun.COM 	mdb_printf("OPCODE=%s",
139410696SDavid.Hollister@Sun.COM 	    outbound_iomb_opcode(word0 & PMCS_IOMB_OPCODE_MASK));
139511601SDavid.Hollister@Sun.COM 	if ((word0 & PMCS_IOMB_OPCODE_MASK) == PMCOUT_SAS_HW_EVENT) {
139611601SDavid.Hollister@Sun.COM 		iop_event = IOP_EVENT_EVENT(word1);
139711601SDavid.Hollister@Sun.COM 		mdb_printf(" <%s>", iomb_event(iop_event));
139811601SDavid.Hollister@Sun.COM 	}
139910696SDavid.Hollister@Sun.COM 	mdb_printf(")\n");
140010696SDavid.Hollister@Sun.COM 
140110696SDavid.Hollister@Sun.COM 	mdb_printf("Remaining Payload:\n");
140210696SDavid.Hollister@Sun.COM 
140310696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
140410696SDavid.Hollister@Sun.COM 	for (qeidx = 1; qeidx < (PMCS_QENTRY_SIZE / 4); qeidx++) {
140510696SDavid.Hollister@Sun.COM 		mdb_printf("%08x ", LE_32(*(qentryp + qeidx)));
140610696SDavid.Hollister@Sun.COM 	}
140710696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
140810696SDavid.Hollister@Sun.COM 	mdb_dec_indent(4);
140910696SDavid.Hollister@Sun.COM }
141010696SDavid.Hollister@Sun.COM 
141110696SDavid.Hollister@Sun.COM static void
141210696SDavid.Hollister@Sun.COM display_outbound_queues(struct pmcs_hw ss, uint_t verbose)
141310696SDavid.Hollister@Sun.COM {
141410696SDavid.Hollister@Sun.COM 	int		idx, qidx;
141510696SDavid.Hollister@Sun.COM 	uintptr_t	obqp;
141610696SDavid.Hollister@Sun.COM 	uint32_t	*cip;
141710696SDavid.Hollister@Sun.COM 	uint32_t	*qentryp = mdb_alloc(PMCS_QENTRY_SIZE, UM_SLEEP);
141810696SDavid.Hollister@Sun.COM 	uint32_t	last_consumed, oqpi;
141910696SDavid.Hollister@Sun.COM 
142010696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
142110696SDavid.Hollister@Sun.COM 	mdb_printf("Outbound Queues\n");
142210696SDavid.Hollister@Sun.COM 	mdb_printf("---------------\n");
142310696SDavid.Hollister@Sun.COM 
142410696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
142510696SDavid.Hollister@Sun.COM 
142610696SDavid.Hollister@Sun.COM 	for (qidx = 0; qidx < PMCS_NOQ; qidx++) {
142710696SDavid.Hollister@Sun.COM 		obqp = (uintptr_t)ss.oqp[qidx];
142810696SDavid.Hollister@Sun.COM 
142910696SDavid.Hollister@Sun.COM 		if (obqp == NULL) {
143010696SDavid.Hollister@Sun.COM 			mdb_printf("No outbound queue ptr for queue #%d\n",
143110696SDavid.Hollister@Sun.COM 			    qidx);
143210696SDavid.Hollister@Sun.COM 			continue;
143310696SDavid.Hollister@Sun.COM 		}
143410696SDavid.Hollister@Sun.COM 
143510696SDavid.Hollister@Sun.COM 		mdb_printf("Outbound Queue #%d (Queue Type = %s)\n", qidx,
143610696SDavid.Hollister@Sun.COM 		    obq_type(qidx));
143710696SDavid.Hollister@Sun.COM 		/*
143810696SDavid.Hollister@Sun.COM 		 * Chip is the producer, so read the actual producer index
143910696SDavid.Hollister@Sun.COM 		 * and not the driver's version
144010696SDavid.Hollister@Sun.COM 		 */
144110696SDavid.Hollister@Sun.COM 		cip = (uint32_t *)((void *)ss.cip);
144210696SDavid.Hollister@Sun.COM 		if (MDB_RD(&oqpi, 4, cip + OQPI_BASE_OFFSET +
144310696SDavid.Hollister@Sun.COM 		    (qidx * 4)) == -1) {
144410696SDavid.Hollister@Sun.COM 			mdb_warn("Couldn't read oqpi\n");
144510696SDavid.Hollister@Sun.COM 			break;
144610696SDavid.Hollister@Sun.COM 		}
144710696SDavid.Hollister@Sun.COM 
144810696SDavid.Hollister@Sun.COM 		mdb_printf("Producer index: %d  Consumer index: %d\n\n",
144910696SDavid.Hollister@Sun.COM 		    LE_32(oqpi), ss.oqci[qidx]);
145010696SDavid.Hollister@Sun.COM 		mdb_inc_indent(2);
145110696SDavid.Hollister@Sun.COM 
145210696SDavid.Hollister@Sun.COM 		if (ss.oqci[qidx] == 0) {
145310696SDavid.Hollister@Sun.COM 			last_consumed = ss.ioq_depth - 1;
145410696SDavid.Hollister@Sun.COM 		} else {
145510696SDavid.Hollister@Sun.COM 			last_consumed = ss.oqci[qidx] - 1;
145610696SDavid.Hollister@Sun.COM 		}
145710696SDavid.Hollister@Sun.COM 
145810696SDavid.Hollister@Sun.COM 
145910696SDavid.Hollister@Sun.COM 		if (!verbose) {
146010696SDavid.Hollister@Sun.COM 			mdb_printf("Last processed entry:\n");
146110696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
146210696SDavid.Hollister@Sun.COM 			    (obqp + (PMCS_QENTRY_SIZE * last_consumed)))
146310696SDavid.Hollister@Sun.COM 			    == -1) {
146410696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
146510696SDavid.Hollister@Sun.COM 				    (obqp + (PMCS_QENTRY_SIZE *
146610696SDavid.Hollister@Sun.COM 				    last_consumed)));
146710696SDavid.Hollister@Sun.COM 				break;
146810696SDavid.Hollister@Sun.COM 			}
146910696SDavid.Hollister@Sun.COM 			dump_one_qentry_outbound(qentryp, last_consumed);
147010696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
147110696SDavid.Hollister@Sun.COM 			mdb_dec_indent(2);
147210696SDavid.Hollister@Sun.COM 			continue;
147310696SDavid.Hollister@Sun.COM 		}
147410696SDavid.Hollister@Sun.COM 
147510696SDavid.Hollister@Sun.COM 		for (idx = 0; idx < ss.ioq_depth; idx++) {
147610696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
147710696SDavid.Hollister@Sun.COM 			    (obqp + (PMCS_QENTRY_SIZE * idx))) == -1) {
147810696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
147910696SDavid.Hollister@Sun.COM 				    (obqp + (PMCS_QENTRY_SIZE * idx)));
148010696SDavid.Hollister@Sun.COM 				break;
148110696SDavid.Hollister@Sun.COM 			}
148210696SDavid.Hollister@Sun.COM 			dump_one_qentry_outbound(qentryp, idx);
148310696SDavid.Hollister@Sun.COM 		}
148410696SDavid.Hollister@Sun.COM 
148510696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
148610696SDavid.Hollister@Sun.COM 		mdb_dec_indent(2);
148710696SDavid.Hollister@Sun.COM 	}
148810696SDavid.Hollister@Sun.COM 
148910696SDavid.Hollister@Sun.COM 	mdb_dec_indent(2);
149010696SDavid.Hollister@Sun.COM 	mdb_free(qentryp, PMCS_QENTRY_SIZE);
149110696SDavid.Hollister@Sun.COM }
149210696SDavid.Hollister@Sun.COM 
149310696SDavid.Hollister@Sun.COM static void
149410696SDavid.Hollister@Sun.COM dump_one_qentry_inbound(uint32_t *qentryp, int idx)
149510696SDavid.Hollister@Sun.COM {
149610696SDavid.Hollister@Sun.COM 	int qeidx;
149710696SDavid.Hollister@Sun.COM 	uint32_t word0 = LE_32(*qentryp);
149810696SDavid.Hollister@Sun.COM 
149910696SDavid.Hollister@Sun.COM 	mdb_printf("Entry #%02d\n", idx);
150010696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
150110696SDavid.Hollister@Sun.COM 
150210696SDavid.Hollister@Sun.COM 	mdb_printf("Header: 0x%08x (", word0);
150310696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_VALID) {
150410696SDavid.Hollister@Sun.COM 		mdb_printf("VALID, ");
150510696SDavid.Hollister@Sun.COM 	}
150610696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_HIPRI) {
150710696SDavid.Hollister@Sun.COM 		mdb_printf("HIPRI, ");
150810696SDavid.Hollister@Sun.COM 	}
150910696SDavid.Hollister@Sun.COM 	mdb_printf("OBID=%d, ",
151010696SDavid.Hollister@Sun.COM 	    (word0 & PMCS_IOMB_OBID_MASK) >> PMCS_IOMB_OBID_SHIFT);
151110696SDavid.Hollister@Sun.COM 	mdb_printf("CAT=%s, ",
151210696SDavid.Hollister@Sun.COM 	    iomb_cat((word0 & PMCS_IOMB_CAT_MASK) >> PMCS_IOMB_CAT_SHIFT));
151310696SDavid.Hollister@Sun.COM 	mdb_printf("OPCODE=%s",
151410696SDavid.Hollister@Sun.COM 	    inbound_iomb_opcode(word0 & PMCS_IOMB_OPCODE_MASK));
151510696SDavid.Hollister@Sun.COM 	mdb_printf(")\n");
151610696SDavid.Hollister@Sun.COM 
151710696SDavid.Hollister@Sun.COM 	mdb_printf("HTAG: 0x%08x\n", LE_32(*(qentryp + 1)));
151810696SDavid.Hollister@Sun.COM 	mdb_printf("Remaining Payload:\n");
151910696SDavid.Hollister@Sun.COM 
152010696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
152110696SDavid.Hollister@Sun.COM 	for (qeidx = 2; qeidx < (PMCS_QENTRY_SIZE / 4); qeidx++) {
152210696SDavid.Hollister@Sun.COM 		mdb_printf("%08x ", LE_32(*(qentryp + qeidx)));
152310696SDavid.Hollister@Sun.COM 	}
152410696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
152510696SDavid.Hollister@Sun.COM 	mdb_dec_indent(4);
152610696SDavid.Hollister@Sun.COM }
152710696SDavid.Hollister@Sun.COM 
152810696SDavid.Hollister@Sun.COM static void
152910696SDavid.Hollister@Sun.COM display_inbound_queues(struct pmcs_hw ss, uint_t verbose)
153010696SDavid.Hollister@Sun.COM {
153110696SDavid.Hollister@Sun.COM 	int		idx, qidx, iqci, last_consumed;
153210696SDavid.Hollister@Sun.COM 	uintptr_t	ibqp;
153310696SDavid.Hollister@Sun.COM 	uint32_t	*qentryp = mdb_alloc(PMCS_QENTRY_SIZE, UM_SLEEP);
153410696SDavid.Hollister@Sun.COM 	uint32_t	*cip;
153510696SDavid.Hollister@Sun.COM 
153610696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
153710696SDavid.Hollister@Sun.COM 	mdb_printf("Inbound Queues\n");
153810696SDavid.Hollister@Sun.COM 	mdb_printf("--------------\n");
153910696SDavid.Hollister@Sun.COM 
154010696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
154110696SDavid.Hollister@Sun.COM 
154210696SDavid.Hollister@Sun.COM 	for (qidx = 0; qidx < PMCS_NIQ; qidx++) {
154310696SDavid.Hollister@Sun.COM 		ibqp = (uintptr_t)ss.iqp[qidx];
154410696SDavid.Hollister@Sun.COM 
154510696SDavid.Hollister@Sun.COM 		if (ibqp == NULL) {
154610696SDavid.Hollister@Sun.COM 			mdb_printf("No inbound queue ptr for queue #%d\n",
154710696SDavid.Hollister@Sun.COM 			    qidx);
154810696SDavid.Hollister@Sun.COM 			continue;
154910696SDavid.Hollister@Sun.COM 		}
155010696SDavid.Hollister@Sun.COM 
155110696SDavid.Hollister@Sun.COM 		mdb_printf("Inbound Queue #%d (Queue Type = %s)\n", qidx,
155210696SDavid.Hollister@Sun.COM 		    ibq_type(qidx));
155310696SDavid.Hollister@Sun.COM 
155410696SDavid.Hollister@Sun.COM 		cip = (uint32_t *)((void *)ss.cip);
155510696SDavid.Hollister@Sun.COM 		if (MDB_RD(&iqci, 4, cip + (qidx * 4)) == -1) {
155610696SDavid.Hollister@Sun.COM 			mdb_warn("Couldn't read iqci\n");
155710696SDavid.Hollister@Sun.COM 			break;
155810696SDavid.Hollister@Sun.COM 		}
155910696SDavid.Hollister@Sun.COM 		iqci = LE_32(iqci);
156010696SDavid.Hollister@Sun.COM 
156110696SDavid.Hollister@Sun.COM 		mdb_printf("Producer index: %d  Consumer index: %d\n\n",
156210696SDavid.Hollister@Sun.COM 		    ss.shadow_iqpi[qidx], iqci);
156310696SDavid.Hollister@Sun.COM 		mdb_inc_indent(2);
156410696SDavid.Hollister@Sun.COM 
156510696SDavid.Hollister@Sun.COM 		if (iqci == 0) {
156610696SDavid.Hollister@Sun.COM 			last_consumed = ss.ioq_depth - 1;
156710696SDavid.Hollister@Sun.COM 		} else {
156810696SDavid.Hollister@Sun.COM 			last_consumed = iqci - 1;
156910696SDavid.Hollister@Sun.COM 		}
157010696SDavid.Hollister@Sun.COM 
157110696SDavid.Hollister@Sun.COM 		if (!verbose) {
157210696SDavid.Hollister@Sun.COM 			mdb_printf("Last processed entry:\n");
157310696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
157410696SDavid.Hollister@Sun.COM 			    (ibqp + (PMCS_QENTRY_SIZE * last_consumed)))
157510696SDavid.Hollister@Sun.COM 			    == -1) {
157610696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
157710696SDavid.Hollister@Sun.COM 				    (ibqp + (PMCS_QENTRY_SIZE *
157810696SDavid.Hollister@Sun.COM 				    last_consumed)));
157910696SDavid.Hollister@Sun.COM 				break;
158010696SDavid.Hollister@Sun.COM 			}
158110696SDavid.Hollister@Sun.COM 			dump_one_qentry_inbound(qentryp, last_consumed);
158210696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
158310696SDavid.Hollister@Sun.COM 			mdb_dec_indent(2);
158410696SDavid.Hollister@Sun.COM 			continue;
158510696SDavid.Hollister@Sun.COM 		}
158610696SDavid.Hollister@Sun.COM 
158710696SDavid.Hollister@Sun.COM 		for (idx = 0; idx < ss.ioq_depth; idx++) {
158810696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
158910696SDavid.Hollister@Sun.COM 			    (ibqp + (PMCS_QENTRY_SIZE * idx))) == -1) {
159010696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
159110696SDavid.Hollister@Sun.COM 				    (ibqp + (PMCS_QENTRY_SIZE * idx)));
159210696SDavid.Hollister@Sun.COM 				break;
159310696SDavid.Hollister@Sun.COM 			}
159410696SDavid.Hollister@Sun.COM 			dump_one_qentry_inbound(qentryp, idx);
159510696SDavid.Hollister@Sun.COM 		}
159610696SDavid.Hollister@Sun.COM 
159710696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
159810696SDavid.Hollister@Sun.COM 		mdb_dec_indent(2);
159910696SDavid.Hollister@Sun.COM 	}
160010696SDavid.Hollister@Sun.COM 
160110696SDavid.Hollister@Sun.COM 	mdb_dec_indent(2);
160210696SDavid.Hollister@Sun.COM 	mdb_free(qentryp, PMCS_QENTRY_SIZE);
160310696SDavid.Hollister@Sun.COM }
160410696SDavid.Hollister@Sun.COM 
160511601SDavid.Hollister@Sun.COM /*
160611601SDavid.Hollister@Sun.COM  * phy is our copy of the PHY structure.  phyp is the pointer to the actual
160711601SDavid.Hollister@Sun.COM  * kernel PHY data structure
160811601SDavid.Hollister@Sun.COM  */
160910696SDavid.Hollister@Sun.COM static void
161011601SDavid.Hollister@Sun.COM display_phy(struct pmcs_phy phy, struct pmcs_phy *phyp, int verbose,
161111601SDavid.Hollister@Sun.COM     int totals_only)
161210696SDavid.Hollister@Sun.COM {
161310696SDavid.Hollister@Sun.COM 	char		*dtype, *speed;
161410696SDavid.Hollister@Sun.COM 	char		*yes = "Yes";
161510696SDavid.Hollister@Sun.COM 	char		*no = "No";
161610696SDavid.Hollister@Sun.COM 	char		*cfgd = no;
161710696SDavid.Hollister@Sun.COM 	char		*apend = no;
161810696SDavid.Hollister@Sun.COM 	char		*asent = no;
161910696SDavid.Hollister@Sun.COM 	char		*dead = no;
162010696SDavid.Hollister@Sun.COM 	char		*changed = no;
162111601SDavid.Hollister@Sun.COM 	char		route_attr, route_method;
162210696SDavid.Hollister@Sun.COM 
162310696SDavid.Hollister@Sun.COM 	switch (phy.dtype) {
162410696SDavid.Hollister@Sun.COM 	case NOTHING:
162510696SDavid.Hollister@Sun.COM 		dtype = "None";
162610696SDavid.Hollister@Sun.COM 		break;
162710696SDavid.Hollister@Sun.COM 	case SATA:
162810696SDavid.Hollister@Sun.COM 		dtype = "SATA";
162910696SDavid.Hollister@Sun.COM 		if (phy.configured) {
163010696SDavid.Hollister@Sun.COM 			++sata_phys;
163110696SDavid.Hollister@Sun.COM 		}
163210696SDavid.Hollister@Sun.COM 		break;
163310696SDavid.Hollister@Sun.COM 	case SAS:
163410696SDavid.Hollister@Sun.COM 		dtype = "SAS";
163510696SDavid.Hollister@Sun.COM 		if (phy.configured) {
163610696SDavid.Hollister@Sun.COM 			++sas_phys;
163710696SDavid.Hollister@Sun.COM 		}
163810696SDavid.Hollister@Sun.COM 		break;
163910696SDavid.Hollister@Sun.COM 	case EXPANDER:
164010696SDavid.Hollister@Sun.COM 		dtype = "EXP";
164110696SDavid.Hollister@Sun.COM 		if (phy.configured) {
164210696SDavid.Hollister@Sun.COM 			++exp_phys;
164310696SDavid.Hollister@Sun.COM 		}
164410696SDavid.Hollister@Sun.COM 		break;
164510696SDavid.Hollister@Sun.COM 	}
164610696SDavid.Hollister@Sun.COM 
164710696SDavid.Hollister@Sun.COM 	if (phy.dtype == NOTHING) {
164810696SDavid.Hollister@Sun.COM 		empty_phys++;
164910696SDavid.Hollister@Sun.COM 	} else if ((phy.dtype == EXPANDER) && phy.configured) {
165010696SDavid.Hollister@Sun.COM 		num_expanders++;
165110696SDavid.Hollister@Sun.COM 	}
165210696SDavid.Hollister@Sun.COM 
165310696SDavid.Hollister@Sun.COM 	if (totals_only) {
165410696SDavid.Hollister@Sun.COM 		return;
165510696SDavid.Hollister@Sun.COM 	}
165610696SDavid.Hollister@Sun.COM 
165710696SDavid.Hollister@Sun.COM 	switch (phy.link_rate) {
165810696SDavid.Hollister@Sun.COM 	case SAS_LINK_RATE_1_5GBIT:
165910696SDavid.Hollister@Sun.COM 		speed = "1.5Gb/s";
166010696SDavid.Hollister@Sun.COM 		break;
166110696SDavid.Hollister@Sun.COM 	case SAS_LINK_RATE_3GBIT:
166210696SDavid.Hollister@Sun.COM 		speed = "3 Gb/s";
166310696SDavid.Hollister@Sun.COM 		break;
166410696SDavid.Hollister@Sun.COM 	case SAS_LINK_RATE_6GBIT:
166510696SDavid.Hollister@Sun.COM 		speed = "6 Gb/s";
166610696SDavid.Hollister@Sun.COM 		break;
166710696SDavid.Hollister@Sun.COM 	default:
166810696SDavid.Hollister@Sun.COM 		speed = "N/A";
166910696SDavid.Hollister@Sun.COM 		break;
167010696SDavid.Hollister@Sun.COM 	}
167110696SDavid.Hollister@Sun.COM 
167210696SDavid.Hollister@Sun.COM 	if ((phy.dtype != NOTHING) || verbose) {
167310696SDavid.Hollister@Sun.COM 		print_sas_address(&phy);
167410696SDavid.Hollister@Sun.COM 
167510696SDavid.Hollister@Sun.COM 		if (phy.device_id != PMCS_INVALID_DEVICE_ID) {
167610696SDavid.Hollister@Sun.COM 			mdb_printf(" %3d %4d %6s %4s ",
167710696SDavid.Hollister@Sun.COM 			    phy.device_id, phy.phynum, speed, dtype);
167810696SDavid.Hollister@Sun.COM 		} else {
167910696SDavid.Hollister@Sun.COM 			mdb_printf(" N/A %4d %6s %4s ",
168010696SDavid.Hollister@Sun.COM 			    phy.phynum, speed, dtype);
168110696SDavid.Hollister@Sun.COM 		}
168210696SDavid.Hollister@Sun.COM 
168310696SDavid.Hollister@Sun.COM 		if (verbose) {
168410696SDavid.Hollister@Sun.COM 			if (phy.abort_sent) {
168510696SDavid.Hollister@Sun.COM 				asent = yes;
168610696SDavid.Hollister@Sun.COM 			}
168710696SDavid.Hollister@Sun.COM 			if (phy.abort_pending) {
168810696SDavid.Hollister@Sun.COM 				apend = yes;
168910696SDavid.Hollister@Sun.COM 			}
169010696SDavid.Hollister@Sun.COM 			if (phy.configured) {
169110696SDavid.Hollister@Sun.COM 				cfgd = yes;
169210696SDavid.Hollister@Sun.COM 			}
169310696SDavid.Hollister@Sun.COM 			if (phy.dead) {
169410696SDavid.Hollister@Sun.COM 				dead = yes;
169510696SDavid.Hollister@Sun.COM 			}
169610696SDavid.Hollister@Sun.COM 			if (phy.changed) {
169710696SDavid.Hollister@Sun.COM 				changed = yes;
169810696SDavid.Hollister@Sun.COM 			}
169910696SDavid.Hollister@Sun.COM 
170011601SDavid.Hollister@Sun.COM 			switch (phy.routing_attr) {
170111601SDavid.Hollister@Sun.COM 			case SMP_ROUTING_DIRECT:
170211601SDavid.Hollister@Sun.COM 				route_attr = 'D';
170311601SDavid.Hollister@Sun.COM 				break;
170411601SDavid.Hollister@Sun.COM 			case SMP_ROUTING_SUBTRACTIVE:
170511601SDavid.Hollister@Sun.COM 				route_attr = 'S';
170611601SDavid.Hollister@Sun.COM 				break;
170711601SDavid.Hollister@Sun.COM 			case SMP_ROUTING_TABLE:
170811601SDavid.Hollister@Sun.COM 				route_attr = 'T';
170911601SDavid.Hollister@Sun.COM 				break;
171011601SDavid.Hollister@Sun.COM 			default:
171111601SDavid.Hollister@Sun.COM 				route_attr = '?';
171211601SDavid.Hollister@Sun.COM 				break;
171311601SDavid.Hollister@Sun.COM 			}
171411601SDavid.Hollister@Sun.COM 
171511601SDavid.Hollister@Sun.COM 			switch (phy.routing_method) {
171611601SDavid.Hollister@Sun.COM 			case SMP_ROUTING_DIRECT:
171711601SDavid.Hollister@Sun.COM 				route_method = 'D';
171811601SDavid.Hollister@Sun.COM 				break;
171911601SDavid.Hollister@Sun.COM 			case SMP_ROUTING_SUBTRACTIVE:
172011601SDavid.Hollister@Sun.COM 				route_method = 'S';
172111601SDavid.Hollister@Sun.COM 				break;
172211601SDavid.Hollister@Sun.COM 			case SMP_ROUTING_TABLE:
172311601SDavid.Hollister@Sun.COM 				route_method = 'T';
172411601SDavid.Hollister@Sun.COM 				break;
172511601SDavid.Hollister@Sun.COM 			default:
172611601SDavid.Hollister@Sun.COM 				route_attr = '?';
172711601SDavid.Hollister@Sun.COM 				break;
172811601SDavid.Hollister@Sun.COM 			}
172911601SDavid.Hollister@Sun.COM 
173011601SDavid.Hollister@Sun.COM 			mdb_printf("%-4s %-4s %-4s %-4s %-4s %3d %3c/%1c %3d "
173111601SDavid.Hollister@Sun.COM 			    "%1d 0x%p ", cfgd, apend, asent, changed, dead,
173211601SDavid.Hollister@Sun.COM 			    phy.ref_count, route_attr, route_method,
173311601SDavid.Hollister@Sun.COM 			    phy.enum_attempts, phy.reenumerate, phy.phy_lock);
173410696SDavid.Hollister@Sun.COM 		}
173510696SDavid.Hollister@Sun.COM 
173610696SDavid.Hollister@Sun.COM 		mdb_printf("Path: %s\n", phy.path);
173711601SDavid.Hollister@Sun.COM 
173811601SDavid.Hollister@Sun.COM 		/*
173911601SDavid.Hollister@Sun.COM 		 * In verbose mode, on the next line print the drill down
174011601SDavid.Hollister@Sun.COM 		 * info to see either the DISCOVER response or the REPORT
174111601SDavid.Hollister@Sun.COM 		 * GENERAL response depending on the PHY's dtype
174211601SDavid.Hollister@Sun.COM 		 */
174311601SDavid.Hollister@Sun.COM 		if (verbose) {
174411601SDavid.Hollister@Sun.COM 			uintptr_t tphyp = (uintptr_t)phyp;
174511601SDavid.Hollister@Sun.COM 
174611601SDavid.Hollister@Sun.COM 			mdb_inc_indent(4);
174711601SDavid.Hollister@Sun.COM 			switch (phy.dtype) {
174811601SDavid.Hollister@Sun.COM 			case EXPANDER:
174911601SDavid.Hollister@Sun.COM 				if (!phy.configured) {
175011601SDavid.Hollister@Sun.COM 					break;
175111601SDavid.Hollister@Sun.COM 				}
175211601SDavid.Hollister@Sun.COM 				mdb_printf("REPORT GENERAL response: %p::"
175311601SDavid.Hollister@Sun.COM 				    "print smp_report_general_resp_t\n",
175411601SDavid.Hollister@Sun.COM 				    (tphyp + offsetof(struct pmcs_phy,
175511601SDavid.Hollister@Sun.COM 				    rg_resp)));
175611601SDavid.Hollister@Sun.COM 				break;
175711601SDavid.Hollister@Sun.COM 			case SAS:
175811601SDavid.Hollister@Sun.COM 			case SATA:
175911601SDavid.Hollister@Sun.COM 				mdb_printf("DISCOVER response: %p::"
176011601SDavid.Hollister@Sun.COM 				    "print smp_discover_resp_t\n",
176111601SDavid.Hollister@Sun.COM 				    (tphyp + offsetof(struct pmcs_phy,
176211601SDavid.Hollister@Sun.COM 				    disc_resp)));
176311601SDavid.Hollister@Sun.COM 				break;
176411601SDavid.Hollister@Sun.COM 			default:
176511601SDavid.Hollister@Sun.COM 				break;
176611601SDavid.Hollister@Sun.COM 			}
176711601SDavid.Hollister@Sun.COM 			mdb_dec_indent(4);
176811601SDavid.Hollister@Sun.COM 		}
176910696SDavid.Hollister@Sun.COM 	}
177010696SDavid.Hollister@Sun.COM }
177110696SDavid.Hollister@Sun.COM 
177210696SDavid.Hollister@Sun.COM static void
177310696SDavid.Hollister@Sun.COM display_phys(struct pmcs_hw ss, int verbose, struct pmcs_phy *parent, int level,
177410696SDavid.Hollister@Sun.COM     int totals_only)
177510696SDavid.Hollister@Sun.COM {
177610696SDavid.Hollister@Sun.COM 	pmcs_phy_t	phy;
177710696SDavid.Hollister@Sun.COM 	pmcs_phy_t	*pphy = parent;
177810696SDavid.Hollister@Sun.COM 
177910696SDavid.Hollister@Sun.COM 	mdb_inc_indent(3);
178010696SDavid.Hollister@Sun.COM 
178110696SDavid.Hollister@Sun.COM 	if (parent == NULL) {
178210696SDavid.Hollister@Sun.COM 		pphy = (pmcs_phy_t *)ss.root_phys;
178310696SDavid.Hollister@Sun.COM 	} else {
178410696SDavid.Hollister@Sun.COM 		pphy = (pmcs_phy_t *)parent;
178510696SDavid.Hollister@Sun.COM 	}
178610696SDavid.Hollister@Sun.COM 
178710696SDavid.Hollister@Sun.COM 	if (level == 0) {
178810696SDavid.Hollister@Sun.COM 		sas_phys = 0;
178910696SDavid.Hollister@Sun.COM 		sata_phys = 0;
179010696SDavid.Hollister@Sun.COM 		exp_phys = 0;
179110696SDavid.Hollister@Sun.COM 		num_expanders = 0;
179210696SDavid.Hollister@Sun.COM 		empty_phys = 0;
179310696SDavid.Hollister@Sun.COM 	}
179410696SDavid.Hollister@Sun.COM 
179510696SDavid.Hollister@Sun.COM 	if (!totals_only) {
179610696SDavid.Hollister@Sun.COM 		if (level == 0) {
179710696SDavid.Hollister@Sun.COM 			mdb_printf("PHY information\n");
179810696SDavid.Hollister@Sun.COM 		}
179910696SDavid.Hollister@Sun.COM 		mdb_printf("--------\n");
180010696SDavid.Hollister@Sun.COM 		mdb_printf("Level %2d\n", level);
180110696SDavid.Hollister@Sun.COM 		mdb_printf("--------\n");
180210696SDavid.Hollister@Sun.COM 		mdb_printf("SAS Address      Hdl Phy#  Speed Type ");
180310696SDavid.Hollister@Sun.COM 
180410696SDavid.Hollister@Sun.COM 		if (verbose) {
180511601SDavid.Hollister@Sun.COM 			mdb_printf("Cfgd AbtP AbtS Chgd Dead Ref RtA/M Enm R "
180611601SDavid.Hollister@Sun.COM 			    "Lock\n");
180710696SDavid.Hollister@Sun.COM 		} else {
180810696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
180910696SDavid.Hollister@Sun.COM 		}
181010696SDavid.Hollister@Sun.COM 	}
181110696SDavid.Hollister@Sun.COM 
181210696SDavid.Hollister@Sun.COM 	while (pphy) {
181310696SDavid.Hollister@Sun.COM 		if (MDB_RD(&phy, sizeof (phy), (uintptr_t)pphy) == -1) {
181410696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_phy_t, phy);
181510696SDavid.Hollister@Sun.COM 			break;
181610696SDavid.Hollister@Sun.COM 		}
181710696SDavid.Hollister@Sun.COM 
181811601SDavid.Hollister@Sun.COM 		display_phy(phy, pphy, verbose, totals_only);
181910696SDavid.Hollister@Sun.COM 
182010696SDavid.Hollister@Sun.COM 		if (phy.children) {
182110696SDavid.Hollister@Sun.COM 			display_phys(ss, verbose, phy.children, level + 1,
182210696SDavid.Hollister@Sun.COM 			    totals_only);
182310696SDavid.Hollister@Sun.COM 			if (!totals_only) {
182410696SDavid.Hollister@Sun.COM 				mdb_printf("\n");
182510696SDavid.Hollister@Sun.COM 			}
182610696SDavid.Hollister@Sun.COM 		}
182710696SDavid.Hollister@Sun.COM 
182810696SDavid.Hollister@Sun.COM 		pphy = phy.sibling;
182910696SDavid.Hollister@Sun.COM 	}
183010696SDavid.Hollister@Sun.COM 
183110696SDavid.Hollister@Sun.COM 	mdb_dec_indent(3);
183210696SDavid.Hollister@Sun.COM 
183310696SDavid.Hollister@Sun.COM 	if (level == 0) {
183410696SDavid.Hollister@Sun.COM 		if (verbose) {
183510696SDavid.Hollister@Sun.COM 			mdb_printf("%19s %d (%d SAS + %d SATA + %d SMP) "
183610696SDavid.Hollister@Sun.COM 			    "(+%d subsidiary + %d empty)\n", "Occupied PHYs:",
183710696SDavid.Hollister@Sun.COM 			    (sas_phys + sata_phys + num_expanders),
183810696SDavid.Hollister@Sun.COM 			    sas_phys, sata_phys, num_expanders,
183910696SDavid.Hollister@Sun.COM 			    (exp_phys - num_expanders), empty_phys);
184010696SDavid.Hollister@Sun.COM 		} else {
184110696SDavid.Hollister@Sun.COM 			mdb_printf("%19s %d (%d SAS + %d SATA + %d SMP)\n",
184210696SDavid.Hollister@Sun.COM 			    "Occupied PHYs:",
184310696SDavid.Hollister@Sun.COM 			    (sas_phys + sata_phys + num_expanders),
184410696SDavid.Hollister@Sun.COM 			    sas_phys, sata_phys, num_expanders);
184510696SDavid.Hollister@Sun.COM 		}
184610696SDavid.Hollister@Sun.COM 	}
184710696SDavid.Hollister@Sun.COM }
184810696SDavid.Hollister@Sun.COM 
184910696SDavid.Hollister@Sun.COM /*
185011048SDavid.Hollister@Sun.COM  * filter is used to indicate whether we are filtering log messages based
185111048SDavid.Hollister@Sun.COM  * on "instance".  The other filtering (based on options) depends on the
185211048SDavid.Hollister@Sun.COM  * values that are passed in for "sas_addr" and "phy_path".
185311048SDavid.Hollister@Sun.COM  *
185410696SDavid.Hollister@Sun.COM  * MAX_INST_STRLEN is the largest string size from which we will attempt
185510696SDavid.Hollister@Sun.COM  * to convert to an instance number.  The string will be formed up as
185610696SDavid.Hollister@Sun.COM  * "0t<inst>\0" so that mdb_strtoull can parse it properly.
185710696SDavid.Hollister@Sun.COM  */
185810696SDavid.Hollister@Sun.COM #define	MAX_INST_STRLEN	8
185910696SDavid.Hollister@Sun.COM 
186010696SDavid.Hollister@Sun.COM static int
186111347SRamana.Srikanth@Sun.COM pmcs_dump_tracelog(boolean_t filter, int instance, uint64_t tail_lines,
186211347SRamana.Srikanth@Sun.COM     const char *phy_path, uint64_t sas_address)
186310696SDavid.Hollister@Sun.COM {
186410696SDavid.Hollister@Sun.COM 	pmcs_tbuf_t *tbuf_addr;
186510696SDavid.Hollister@Sun.COM 	uint_t tbuf_idx;
186610696SDavid.Hollister@Sun.COM 	pmcs_tbuf_t tbuf;
186710696SDavid.Hollister@Sun.COM 	boolean_t wrap, elem_filtered;
186810696SDavid.Hollister@Sun.COM 	uint_t start_idx, elems_to_print, idx, tbuf_num_elems;
186910696SDavid.Hollister@Sun.COM 	char *bufp;
187010696SDavid.Hollister@Sun.COM 	char elem_inst[MAX_INST_STRLEN], ei_idx;
187111048SDavid.Hollister@Sun.COM 	uint64_t sas_addr;
187211048SDavid.Hollister@Sun.COM 	uint8_t *sas_addressp;
187310696SDavid.Hollister@Sun.COM 
187410696SDavid.Hollister@Sun.COM 	/* Get the address of the first element */
187510696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&tbuf_addr, "pmcs_tbuf") == -1) {
187610696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf");
187710696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
187810696SDavid.Hollister@Sun.COM 	}
187910696SDavid.Hollister@Sun.COM 
188010696SDavid.Hollister@Sun.COM 	/* Get the total number */
188110696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&tbuf_num_elems, "pmcs_tbuf_num_elems") == -1) {
188210696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf_num_elems");
188310696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
188410696SDavid.Hollister@Sun.COM 	}
188510696SDavid.Hollister@Sun.COM 
188610696SDavid.Hollister@Sun.COM 	/* Get the current index */
188710696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&tbuf_idx, "pmcs_tbuf_idx") == -1) {
188810696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf_idx");
188910696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
189010696SDavid.Hollister@Sun.COM 	}
189110696SDavid.Hollister@Sun.COM 
189210696SDavid.Hollister@Sun.COM 	/* Indicator as to whether the buffer has wrapped */
189310696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&wrap, "pmcs_tbuf_wrap") == -1) {
189410696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf_wrap");
189510696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
189610696SDavid.Hollister@Sun.COM 	}
189710696SDavid.Hollister@Sun.COM 
189811048SDavid.Hollister@Sun.COM 	/*
189911048SDavid.Hollister@Sun.COM 	 * On little-endian systems, the SAS address passed in will be
190011048SDavid.Hollister@Sun.COM 	 * byte swapped.  Take care of that here.
190111048SDavid.Hollister@Sun.COM 	 */
190211048SDavid.Hollister@Sun.COM #if defined(_LITTLE_ENDIAN)
190311048SDavid.Hollister@Sun.COM 	sas_addr = ((sas_address << 56) |
190411048SDavid.Hollister@Sun.COM 	    ((sas_address << 40) & 0xff000000000000ULL) |
190511048SDavid.Hollister@Sun.COM 	    ((sas_address << 24) & 0xff0000000000ULL) |
190611048SDavid.Hollister@Sun.COM 	    ((sas_address << 8)  & 0xff00000000ULL) |
190711048SDavid.Hollister@Sun.COM 	    ((sas_address >> 8)  & 0xff000000ULL) |
190811048SDavid.Hollister@Sun.COM 	    ((sas_address >> 24) & 0xff0000ULL) |
190911048SDavid.Hollister@Sun.COM 	    ((sas_address >> 40) & 0xff00ULL) |
191011048SDavid.Hollister@Sun.COM 	    (sas_address  >> 56));
191111048SDavid.Hollister@Sun.COM #else
191211048SDavid.Hollister@Sun.COM 	sas_addr = sas_address;
191311048SDavid.Hollister@Sun.COM #endif
191411048SDavid.Hollister@Sun.COM 	sas_addressp = (uint8_t *)&sas_addr;
191511048SDavid.Hollister@Sun.COM 
191611347SRamana.Srikanth@Sun.COM 	/* Ensure the tail number isn't greater than the size of the log */
191711347SRamana.Srikanth@Sun.COM 	if (tail_lines > tbuf_num_elems) {
191811347SRamana.Srikanth@Sun.COM 		tail_lines = tbuf_num_elems;
191911347SRamana.Srikanth@Sun.COM 	}
192011347SRamana.Srikanth@Sun.COM 
192110696SDavid.Hollister@Sun.COM 	/* Figure out where we start and stop */
192210696SDavid.Hollister@Sun.COM 	if (wrap) {
192311347SRamana.Srikanth@Sun.COM 		if (tail_lines) {
192411347SRamana.Srikanth@Sun.COM 			/* Do we need to wrap backwards? */
192511347SRamana.Srikanth@Sun.COM 			if (tail_lines > tbuf_idx) {
192611347SRamana.Srikanth@Sun.COM 				start_idx = tbuf_num_elems - (tail_lines -
192711347SRamana.Srikanth@Sun.COM 				    tbuf_idx);
192811347SRamana.Srikanth@Sun.COM 			} else {
192911347SRamana.Srikanth@Sun.COM 				start_idx = tbuf_idx - tail_lines;
193011347SRamana.Srikanth@Sun.COM 			}
193111347SRamana.Srikanth@Sun.COM 			elems_to_print = tail_lines;
193211347SRamana.Srikanth@Sun.COM 		} else {
193311347SRamana.Srikanth@Sun.COM 			start_idx = tbuf_idx;
193411347SRamana.Srikanth@Sun.COM 			elems_to_print = tbuf_num_elems;
193511347SRamana.Srikanth@Sun.COM 		}
193610696SDavid.Hollister@Sun.COM 	} else {
193711347SRamana.Srikanth@Sun.COM 		if (tail_lines > tbuf_idx) {
193811347SRamana.Srikanth@Sun.COM 			tail_lines = tbuf_idx;
193911347SRamana.Srikanth@Sun.COM 		}
194011347SRamana.Srikanth@Sun.COM 		if (tail_lines) {
194111347SRamana.Srikanth@Sun.COM 			start_idx = tbuf_idx - tail_lines;
194211347SRamana.Srikanth@Sun.COM 			elems_to_print = tail_lines;
194311347SRamana.Srikanth@Sun.COM 		} else {
194411347SRamana.Srikanth@Sun.COM 			start_idx = 0;
194511347SRamana.Srikanth@Sun.COM 			elems_to_print = tbuf_idx;
194611347SRamana.Srikanth@Sun.COM 		}
194710696SDavid.Hollister@Sun.COM 	}
194810696SDavid.Hollister@Sun.COM 
194910696SDavid.Hollister@Sun.COM 	idx = start_idx;
195010696SDavid.Hollister@Sun.COM 
195110696SDavid.Hollister@Sun.COM 	/* Dump the buffer contents */
195210696SDavid.Hollister@Sun.COM 	while (elems_to_print != 0) {
195310696SDavid.Hollister@Sun.COM 		if (MDB_RD(&tbuf, sizeof (pmcs_tbuf_t), (tbuf_addr + idx))
195410696SDavid.Hollister@Sun.COM 		    == -1) {
195510696SDavid.Hollister@Sun.COM 			NOREAD(tbuf, (tbuf_addr + idx));
195610696SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
195710696SDavid.Hollister@Sun.COM 		}
195810696SDavid.Hollister@Sun.COM 
195911048SDavid.Hollister@Sun.COM 		/*
196011048SDavid.Hollister@Sun.COM 		 * Check for filtering on HBA instance
196111048SDavid.Hollister@Sun.COM 		 */
196210696SDavid.Hollister@Sun.COM 		elem_filtered = B_FALSE;
196310696SDavid.Hollister@Sun.COM 
196410696SDavid.Hollister@Sun.COM 		if (filter) {
196510696SDavid.Hollister@Sun.COM 			bufp = tbuf.buf;
196610696SDavid.Hollister@Sun.COM 			/* Skip the driver name */
196710696SDavid.Hollister@Sun.COM 			while (*bufp < '0' || *bufp > '9') {
196810696SDavid.Hollister@Sun.COM 				bufp++;
196910696SDavid.Hollister@Sun.COM 			}
197010696SDavid.Hollister@Sun.COM 
197110696SDavid.Hollister@Sun.COM 			ei_idx = 0;
197210696SDavid.Hollister@Sun.COM 			elem_inst[ei_idx++] = '0';
197310696SDavid.Hollister@Sun.COM 			elem_inst[ei_idx++] = 't';
197410696SDavid.Hollister@Sun.COM 			while (*bufp != ':' && ei_idx < (MAX_INST_STRLEN - 1)) {
197510696SDavid.Hollister@Sun.COM 				elem_inst[ei_idx++] = *bufp;
197610696SDavid.Hollister@Sun.COM 				bufp++;
197710696SDavid.Hollister@Sun.COM 			}
197810696SDavid.Hollister@Sun.COM 			elem_inst[ei_idx] = 0;
197910696SDavid.Hollister@Sun.COM 
198010696SDavid.Hollister@Sun.COM 			/* Get the instance */
198110696SDavid.Hollister@Sun.COM 			if ((int)mdb_strtoull(elem_inst) != instance) {
198210696SDavid.Hollister@Sun.COM 				elem_filtered = B_TRUE;
198310696SDavid.Hollister@Sun.COM 			}
198410696SDavid.Hollister@Sun.COM 		}
198510696SDavid.Hollister@Sun.COM 
198611048SDavid.Hollister@Sun.COM 		if (!elem_filtered && (phy_path || sas_address)) {
198711048SDavid.Hollister@Sun.COM 			/*
198811048SDavid.Hollister@Sun.COM 			 * This message is not being filtered by HBA instance.
198911048SDavid.Hollister@Sun.COM 			 * Now check to see if we're filtering based on
199011048SDavid.Hollister@Sun.COM 			 * PHY path or SAS address.
199111048SDavid.Hollister@Sun.COM 			 * Filtering is an "OR" operation.  So, if any of the
199211048SDavid.Hollister@Sun.COM 			 * criteria matches, this message will be printed.
199311048SDavid.Hollister@Sun.COM 			 */
199411048SDavid.Hollister@Sun.COM 			elem_filtered = B_TRUE;
199511048SDavid.Hollister@Sun.COM 
199611048SDavid.Hollister@Sun.COM 			if (phy_path != NULL) {
199711048SDavid.Hollister@Sun.COM 				if (strncmp(phy_path, tbuf.phy_path,
199811048SDavid.Hollister@Sun.COM 				    PMCS_TBUF_UA_MAX_SIZE) == 0) {
199911048SDavid.Hollister@Sun.COM 					elem_filtered = B_FALSE;
200011048SDavid.Hollister@Sun.COM 				}
200111048SDavid.Hollister@Sun.COM 			}
200211048SDavid.Hollister@Sun.COM 			if (sas_address != 0) {
200311048SDavid.Hollister@Sun.COM 				if (memcmp(sas_addressp, tbuf.phy_sas_address,
200411048SDavid.Hollister@Sun.COM 				    8) == 0) {
200511048SDavid.Hollister@Sun.COM 					elem_filtered = B_FALSE;
200611048SDavid.Hollister@Sun.COM 				}
200711048SDavid.Hollister@Sun.COM 			}
200811048SDavid.Hollister@Sun.COM 		}
200911048SDavid.Hollister@Sun.COM 
201010696SDavid.Hollister@Sun.COM 		if (!elem_filtered) {
201110696SDavid.Hollister@Sun.COM 			mdb_printf("%Y.%09ld %s\n", tbuf.timestamp, tbuf.buf);
201210696SDavid.Hollister@Sun.COM 		}
201310696SDavid.Hollister@Sun.COM 
201410696SDavid.Hollister@Sun.COM 		--elems_to_print;
201510696SDavid.Hollister@Sun.COM 		if (++idx == tbuf_num_elems) {
201610696SDavid.Hollister@Sun.COM 			idx = 0;
201710696SDavid.Hollister@Sun.COM 		}
201810696SDavid.Hollister@Sun.COM 	}
201910696SDavid.Hollister@Sun.COM 
202010696SDavid.Hollister@Sun.COM 	return (DCMD_OK);
202110696SDavid.Hollister@Sun.COM }
202210696SDavid.Hollister@Sun.COM 
202310696SDavid.Hollister@Sun.COM /*
202410696SDavid.Hollister@Sun.COM  * Walkers
202510696SDavid.Hollister@Sun.COM  */
202610696SDavid.Hollister@Sun.COM static int
202710696SDavid.Hollister@Sun.COM targets_walk_i(mdb_walk_state_t *wsp)
202810696SDavid.Hollister@Sun.COM {
202910696SDavid.Hollister@Sun.COM 	if (wsp->walk_addr == NULL) {
203010696SDavid.Hollister@Sun.COM 		mdb_warn("Can not perform global walk\n");
203110696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
203210696SDavid.Hollister@Sun.COM 	}
203310696SDavid.Hollister@Sun.COM 
203410696SDavid.Hollister@Sun.COM 	/*
203510696SDavid.Hollister@Sun.COM 	 * Address provided belongs to HBA softstate.  Get the targets pointer
203610696SDavid.Hollister@Sun.COM 	 * to begin the walk.
203710696SDavid.Hollister@Sun.COM 	 */
203810696SDavid.Hollister@Sun.COM 	if (mdb_vread(&ss, sizeof (pmcs_hw_t), wsp->walk_addr) !=
203910696SDavid.Hollister@Sun.COM 	    sizeof (pmcs_hw_t)) {
204010696SDavid.Hollister@Sun.COM 		mdb_warn("Unable to read HBA softstate\n");
204110696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
204210696SDavid.Hollister@Sun.COM 	}
204310696SDavid.Hollister@Sun.COM 
204410696SDavid.Hollister@Sun.COM 	if (targets == NULL) {
204510696SDavid.Hollister@Sun.COM 		targets = mdb_alloc(sizeof (targets) * ss.max_dev, UM_SLEEP);
204610696SDavid.Hollister@Sun.COM 	}
204710696SDavid.Hollister@Sun.COM 
204810696SDavid.Hollister@Sun.COM 	if (MDB_RD(targets, sizeof (targets) * ss.max_dev, ss.targets) == -1) {
204910696SDavid.Hollister@Sun.COM 		NOREAD(targets, ss.targets);
205010696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
205110696SDavid.Hollister@Sun.COM 	}
205210696SDavid.Hollister@Sun.COM 
205310696SDavid.Hollister@Sun.COM 	target_idx = 0;
205410696SDavid.Hollister@Sun.COM 	wsp->walk_addr = (uintptr_t)(targets[0]);
205510696SDavid.Hollister@Sun.COM 	wsp->walk_data = mdb_alloc(sizeof (pmcs_xscsi_t), UM_SLEEP);
205610696SDavid.Hollister@Sun.COM 
205710696SDavid.Hollister@Sun.COM 	return (WALK_NEXT);
205810696SDavid.Hollister@Sun.COM }
205910696SDavid.Hollister@Sun.COM 
206010696SDavid.Hollister@Sun.COM static int
206110696SDavid.Hollister@Sun.COM targets_walk_s(mdb_walk_state_t *wsp)
206210696SDavid.Hollister@Sun.COM {
206310696SDavid.Hollister@Sun.COM 	int status;
206410696SDavid.Hollister@Sun.COM 
206510696SDavid.Hollister@Sun.COM 	if (target_idx == ss.max_dev) {
206610696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
206710696SDavid.Hollister@Sun.COM 	}
206810696SDavid.Hollister@Sun.COM 
206910696SDavid.Hollister@Sun.COM 	if (mdb_vread(wsp->walk_data, sizeof (pmcs_xscsi_t),
207010696SDavid.Hollister@Sun.COM 	    wsp->walk_addr) == -1) {
207110696SDavid.Hollister@Sun.COM 		mdb_warn("Failed to read target at %p", (void *)wsp->walk_addr);
207210696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
207310696SDavid.Hollister@Sun.COM 	}
207410696SDavid.Hollister@Sun.COM 
207510696SDavid.Hollister@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
207610696SDavid.Hollister@Sun.COM 	    wsp->walk_cbdata);
207710696SDavid.Hollister@Sun.COM 
207810696SDavid.Hollister@Sun.COM 	do {
207910696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)(targets[++target_idx]);
208010696SDavid.Hollister@Sun.COM 	} while ((wsp->walk_addr == NULL) && (target_idx < ss.max_dev));
208110696SDavid.Hollister@Sun.COM 
208210696SDavid.Hollister@Sun.COM 	if (target_idx == ss.max_dev) {
208310696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
208410696SDavid.Hollister@Sun.COM 	}
208510696SDavid.Hollister@Sun.COM 
208610696SDavid.Hollister@Sun.COM 	return (status);
208710696SDavid.Hollister@Sun.COM }
208810696SDavid.Hollister@Sun.COM 
208910696SDavid.Hollister@Sun.COM static void
209010696SDavid.Hollister@Sun.COM targets_walk_f(mdb_walk_state_t *wsp)
209110696SDavid.Hollister@Sun.COM {
209210696SDavid.Hollister@Sun.COM 	mdb_free(wsp->walk_data, sizeof (pmcs_xscsi_t));
209310696SDavid.Hollister@Sun.COM }
209410696SDavid.Hollister@Sun.COM 
209510696SDavid.Hollister@Sun.COM 
209610696SDavid.Hollister@Sun.COM static pmcs_phy_t *
209710696SDavid.Hollister@Sun.COM pmcs_next_sibling(pmcs_phy_t *phyp)
209810696SDavid.Hollister@Sun.COM {
209910696SDavid.Hollister@Sun.COM 	pmcs_phy_t parent;
210010696SDavid.Hollister@Sun.COM 
210110696SDavid.Hollister@Sun.COM 	/*
210210696SDavid.Hollister@Sun.COM 	 * First, if this is a root PHY, there are no more siblings
210310696SDavid.Hollister@Sun.COM 	 */
210410696SDavid.Hollister@Sun.COM 	if (phyp->level == 0) {
210510696SDavid.Hollister@Sun.COM 		return (NULL);
210610696SDavid.Hollister@Sun.COM 	}
210710696SDavid.Hollister@Sun.COM 
210810696SDavid.Hollister@Sun.COM 	/*
210910696SDavid.Hollister@Sun.COM 	 * Otherwise, next sibling is the parent's sibling
211010696SDavid.Hollister@Sun.COM 	 */
211110696SDavid.Hollister@Sun.COM 	while (phyp->level > 0) {
211210696SDavid.Hollister@Sun.COM 		if (mdb_vread(&parent, sizeof (pmcs_phy_t),
211310696SDavid.Hollister@Sun.COM 		    (uintptr_t)phyp->parent) == -1) {
211410696SDavid.Hollister@Sun.COM 			mdb_warn("pmcs_next_sibling: Failed to read PHY at %p",
211510696SDavid.Hollister@Sun.COM 			    (void *)phyp->parent);
211610696SDavid.Hollister@Sun.COM 			return (NULL);
211710696SDavid.Hollister@Sun.COM 		}
211810696SDavid.Hollister@Sun.COM 
211910696SDavid.Hollister@Sun.COM 		if (parent.sibling != NULL) {
212010696SDavid.Hollister@Sun.COM 			break;
212110696SDavid.Hollister@Sun.COM 		}
212210696SDavid.Hollister@Sun.COM 
212311898SJesse.Butler@Sun.COM 		/*
212411898SJesse.Butler@Sun.COM 		 * If this PHY's sibling is NULL and it's a root phy,
212511898SJesse.Butler@Sun.COM 		 * we're done.
212611898SJesse.Butler@Sun.COM 		 */
212711898SJesse.Butler@Sun.COM 		if (parent.level == 0) {
212811898SJesse.Butler@Sun.COM 			return (NULL);
212911898SJesse.Butler@Sun.COM 		}
213011898SJesse.Butler@Sun.COM 
213110696SDavid.Hollister@Sun.COM 		phyp = phyp->parent;
213210696SDavid.Hollister@Sun.COM 	}
213310696SDavid.Hollister@Sun.COM 
213410696SDavid.Hollister@Sun.COM 	return (parent.sibling);
213510696SDavid.Hollister@Sun.COM }
213610696SDavid.Hollister@Sun.COM 
213710696SDavid.Hollister@Sun.COM static int
213810696SDavid.Hollister@Sun.COM phy_walk_i(mdb_walk_state_t *wsp)
213910696SDavid.Hollister@Sun.COM {
214010696SDavid.Hollister@Sun.COM 	if (wsp->walk_addr == NULL) {
214110696SDavid.Hollister@Sun.COM 		mdb_warn("Can not perform global walk\n");
214210696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
214310696SDavid.Hollister@Sun.COM 	}
214410696SDavid.Hollister@Sun.COM 
214510696SDavid.Hollister@Sun.COM 	/*
214610696SDavid.Hollister@Sun.COM 	 * Address provided belongs to HBA softstate.  Get the targets pointer
214710696SDavid.Hollister@Sun.COM 	 * to begin the walk.
214810696SDavid.Hollister@Sun.COM 	 */
214910696SDavid.Hollister@Sun.COM 	if (mdb_vread(&ss, sizeof (pmcs_hw_t), wsp->walk_addr) !=
215010696SDavid.Hollister@Sun.COM 	    sizeof (pmcs_hw_t)) {
215110696SDavid.Hollister@Sun.COM 		mdb_warn("Unable to read HBA softstate\n");
215210696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
215310696SDavid.Hollister@Sun.COM 	}
215410696SDavid.Hollister@Sun.COM 
215510696SDavid.Hollister@Sun.COM 	wsp->walk_addr = (uintptr_t)(ss.root_phys);
215610696SDavid.Hollister@Sun.COM 	wsp->walk_data = mdb_alloc(sizeof (pmcs_phy_t), UM_SLEEP);
215710696SDavid.Hollister@Sun.COM 
215810696SDavid.Hollister@Sun.COM 	return (WALK_NEXT);
215910696SDavid.Hollister@Sun.COM }
216010696SDavid.Hollister@Sun.COM 
216110696SDavid.Hollister@Sun.COM static int
216210696SDavid.Hollister@Sun.COM phy_walk_s(mdb_walk_state_t *wsp)
216310696SDavid.Hollister@Sun.COM {
216410696SDavid.Hollister@Sun.COM 	pmcs_phy_t *phyp, *nphyp;
216510696SDavid.Hollister@Sun.COM 	int status;
216610696SDavid.Hollister@Sun.COM 
216710696SDavid.Hollister@Sun.COM 	if (mdb_vread(wsp->walk_data, sizeof (pmcs_phy_t),
216810696SDavid.Hollister@Sun.COM 	    wsp->walk_addr) == -1) {
216910696SDavid.Hollister@Sun.COM 		mdb_warn("phy_walk_s: Failed to read PHY at %p",
217010696SDavid.Hollister@Sun.COM 		    (void *)wsp->walk_addr);
217110696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
217210696SDavid.Hollister@Sun.COM 	}
217310696SDavid.Hollister@Sun.COM 
217410696SDavid.Hollister@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
217510696SDavid.Hollister@Sun.COM 	    wsp->walk_cbdata);
217610696SDavid.Hollister@Sun.COM 
217710696SDavid.Hollister@Sun.COM 	phyp = (pmcs_phy_t *)wsp->walk_data;
217810696SDavid.Hollister@Sun.COM 	if (phyp->children) {
217910696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)(phyp->children);
218010696SDavid.Hollister@Sun.COM 	} else {
218110696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)(phyp->sibling);
218210696SDavid.Hollister@Sun.COM 	}
218310696SDavid.Hollister@Sun.COM 
218410696SDavid.Hollister@Sun.COM 	if (wsp->walk_addr == NULL) {
218510696SDavid.Hollister@Sun.COM 		/*
218610696SDavid.Hollister@Sun.COM 		 * We reached the end of this sibling list.  Trudge back up
218710696SDavid.Hollister@Sun.COM 		 * to the parent and find the next sibling after the expander
218810696SDavid.Hollister@Sun.COM 		 * we just finished traversing, if there is one.
218910696SDavid.Hollister@Sun.COM 		 */
219010696SDavid.Hollister@Sun.COM 		nphyp = pmcs_next_sibling(phyp);
219110696SDavid.Hollister@Sun.COM 
219210696SDavid.Hollister@Sun.COM 		if (nphyp == NULL) {
219310696SDavid.Hollister@Sun.COM 			return (WALK_DONE);
219410696SDavid.Hollister@Sun.COM 		}
219510696SDavid.Hollister@Sun.COM 
219610696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)nphyp;
219710696SDavid.Hollister@Sun.COM 	}
219810696SDavid.Hollister@Sun.COM 
219910696SDavid.Hollister@Sun.COM 	return (status);
220010696SDavid.Hollister@Sun.COM }
220110696SDavid.Hollister@Sun.COM 
220210696SDavid.Hollister@Sun.COM static void
220310696SDavid.Hollister@Sun.COM phy_walk_f(mdb_walk_state_t *wsp)
220410696SDavid.Hollister@Sun.COM {
220510696SDavid.Hollister@Sun.COM 	mdb_free(wsp->walk_data, sizeof (pmcs_phy_t));
220610696SDavid.Hollister@Sun.COM }
220710696SDavid.Hollister@Sun.COM 
220810743SDavid.Hollister@Sun.COM static void
220910743SDavid.Hollister@Sun.COM display_matching_work(struct pmcs_hw ss, uintmax_t index, uintmax_t snum,
221010743SDavid.Hollister@Sun.COM     uintmax_t tag_type)
221110743SDavid.Hollister@Sun.COM {
221210743SDavid.Hollister@Sun.COM 	int		idx;
221310743SDavid.Hollister@Sun.COM 	pmcwork_t	work, *wp = &work;
221410743SDavid.Hollister@Sun.COM 	uintptr_t	_wp;
221510743SDavid.Hollister@Sun.COM 	boolean_t	printed_header = B_FALSE;
221610743SDavid.Hollister@Sun.COM 	uint32_t	mask, mask_val, match_val;
221710743SDavid.Hollister@Sun.COM 	char		*match_type;
221810743SDavid.Hollister@Sun.COM 
221910743SDavid.Hollister@Sun.COM 	if (index != UINT_MAX) {
222010743SDavid.Hollister@Sun.COM 		match_type = "index";
222110743SDavid.Hollister@Sun.COM 		mask = PMCS_TAG_INDEX_MASK;
222210743SDavid.Hollister@Sun.COM 		mask_val = index << PMCS_TAG_INDEX_SHIFT;
222310743SDavid.Hollister@Sun.COM 		match_val = index;
222410743SDavid.Hollister@Sun.COM 	} else if (snum != UINT_MAX) {
222510743SDavid.Hollister@Sun.COM 		match_type = "serial number";
222610743SDavid.Hollister@Sun.COM 		mask = PMCS_TAG_SERNO_MASK;
222710743SDavid.Hollister@Sun.COM 		mask_val = snum << PMCS_TAG_SERNO_SHIFT;
222810743SDavid.Hollister@Sun.COM 		match_val = snum;
222910743SDavid.Hollister@Sun.COM 	} else {
223010743SDavid.Hollister@Sun.COM 		switch (tag_type) {
223110743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_NONE:
223210743SDavid.Hollister@Sun.COM 			match_type = "tag type NONE";
223310743SDavid.Hollister@Sun.COM 			break;
223410743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_CBACK:
223510743SDavid.Hollister@Sun.COM 			match_type = "tag type CBACK";
223610743SDavid.Hollister@Sun.COM 			break;
223710743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_WAIT:
223810743SDavid.Hollister@Sun.COM 			match_type = "tag type WAIT";
223910743SDavid.Hollister@Sun.COM 			break;
224010743SDavid.Hollister@Sun.COM 		}
224110743SDavid.Hollister@Sun.COM 		mask = PMCS_TAG_TYPE_MASK;
224210743SDavid.Hollister@Sun.COM 		mask_val = tag_type << PMCS_TAG_TYPE_SHIFT;
224310743SDavid.Hollister@Sun.COM 		match_val = tag_type;
224410743SDavid.Hollister@Sun.COM 	}
224510743SDavid.Hollister@Sun.COM 
224610743SDavid.Hollister@Sun.COM 	_wp = (uintptr_t)ss.work;
224710743SDavid.Hollister@Sun.COM 
224810743SDavid.Hollister@Sun.COM 	for (idx = 0; idx < ss.max_cmd; idx++, _wp += sizeof (pmcwork_t)) {
224910743SDavid.Hollister@Sun.COM 		if (MDB_RD(&work, sizeof (pmcwork_t), _wp) == -1) {
225010743SDavid.Hollister@Sun.COM 			NOREAD(pmcwork_t, _wp);
225110743SDavid.Hollister@Sun.COM 			continue;
225210743SDavid.Hollister@Sun.COM 		}
225310743SDavid.Hollister@Sun.COM 
225410743SDavid.Hollister@Sun.COM 		if ((work.htag & mask) != mask_val) {
225510743SDavid.Hollister@Sun.COM 			continue;
225610743SDavid.Hollister@Sun.COM 		}
225710743SDavid.Hollister@Sun.COM 
225810743SDavid.Hollister@Sun.COM 		if (printed_header == B_FALSE) {
225910743SDavid.Hollister@Sun.COM 			if (tag_type) {
226010743SDavid.Hollister@Sun.COM 				mdb_printf("\nWork structures matching %s\n\n",
226110743SDavid.Hollister@Sun.COM 				    match_type, match_val);
226210743SDavid.Hollister@Sun.COM 			} else {
226310743SDavid.Hollister@Sun.COM 				mdb_printf("\nWork structures matching %s of "
226410743SDavid.Hollister@Sun.COM 				    "0x%x\n\n", match_type, match_val);
226510743SDavid.Hollister@Sun.COM 			}
226610743SDavid.Hollister@Sun.COM 			mdb_printf("%8s %10s %20s %8s %8s O D\n",
226710743SDavid.Hollister@Sun.COM 			    "HTag", "State", "Phy Path", "Target", "Timer");
226810743SDavid.Hollister@Sun.COM 			printed_header = B_TRUE;
226910743SDavid.Hollister@Sun.COM 		}
227010743SDavid.Hollister@Sun.COM 
227110743SDavid.Hollister@Sun.COM 		display_one_work(wp, 0, 0);
227210743SDavid.Hollister@Sun.COM 	}
227310743SDavid.Hollister@Sun.COM 
227410743SDavid.Hollister@Sun.COM 	if (!printed_header) {
227510743SDavid.Hollister@Sun.COM 		mdb_printf("No work structure matches found\n");
227610743SDavid.Hollister@Sun.COM 	}
227710743SDavid.Hollister@Sun.COM }
227810743SDavid.Hollister@Sun.COM 
227910743SDavid.Hollister@Sun.COM static int
228010743SDavid.Hollister@Sun.COM pmcs_tag(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
228110743SDavid.Hollister@Sun.COM {
228210743SDavid.Hollister@Sun.COM 	struct	pmcs_hw		ss;
228310743SDavid.Hollister@Sun.COM 	uintmax_t		tag_type = UINT_MAX;
228410743SDavid.Hollister@Sun.COM 	uintmax_t		snum = UINT_MAX;
228510743SDavid.Hollister@Sun.COM 	uintmax_t		index = UINT_MAX;
228610743SDavid.Hollister@Sun.COM 	int			args = 0;
228710743SDavid.Hollister@Sun.COM 	void			*pmcs_state;
228810743SDavid.Hollister@Sun.COM 	char			*state_str;
228910743SDavid.Hollister@Sun.COM 	struct dev_info		dip;
229010743SDavid.Hollister@Sun.COM 
229110743SDavid.Hollister@Sun.COM 	if (!(flags & DCMD_ADDRSPEC)) {
229210743SDavid.Hollister@Sun.COM 		pmcs_state = NULL;
229310743SDavid.Hollister@Sun.COM 		if (mdb_readvar(&pmcs_state, "pmcs_softc_state") == -1) {
229410743SDavid.Hollister@Sun.COM 			mdb_warn("can't read pmcs_softc_state");
229510743SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
229610743SDavid.Hollister@Sun.COM 		}
229710743SDavid.Hollister@Sun.COM 		if (mdb_pwalk_dcmd("genunix`softstate", "pmcs`pmcs_tag", argc,
229810743SDavid.Hollister@Sun.COM 		    argv, (uintptr_t)pmcs_state) == -1) {
229910743SDavid.Hollister@Sun.COM 			mdb_warn("mdb_pwalk_dcmd failed");
230010743SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
230110743SDavid.Hollister@Sun.COM 		}
230210743SDavid.Hollister@Sun.COM 		return (DCMD_OK);
230310743SDavid.Hollister@Sun.COM 	}
230410743SDavid.Hollister@Sun.COM 
230510743SDavid.Hollister@Sun.COM 	if (mdb_getopts(argc, argv,
230610743SDavid.Hollister@Sun.COM 	    'i', MDB_OPT_UINT64, &index,
230710743SDavid.Hollister@Sun.COM 	    's', MDB_OPT_UINT64, &snum,
230810743SDavid.Hollister@Sun.COM 	    't', MDB_OPT_UINT64, &tag_type) != argc)
230910743SDavid.Hollister@Sun.COM 		return (DCMD_USAGE);
231010743SDavid.Hollister@Sun.COM 
231110743SDavid.Hollister@Sun.COM 	/*
231210743SDavid.Hollister@Sun.COM 	 * Count the number of supplied options and make sure they are
231310743SDavid.Hollister@Sun.COM 	 * within appropriate ranges.  If they're set to UINT_MAX, that means
231410743SDavid.Hollister@Sun.COM 	 * they were not supplied, in which case reset them to 0.
231510743SDavid.Hollister@Sun.COM 	 */
231610743SDavid.Hollister@Sun.COM 	if (index != UINT_MAX) {
231710743SDavid.Hollister@Sun.COM 		args++;
231810743SDavid.Hollister@Sun.COM 		if (index > PMCS_TAG_INDEX_MASK) {
231910743SDavid.Hollister@Sun.COM 			mdb_warn("Index is out of range\n");
232010743SDavid.Hollister@Sun.COM 			return (DCMD_USAGE);
232110743SDavid.Hollister@Sun.COM 		}
232210743SDavid.Hollister@Sun.COM 	}
232310743SDavid.Hollister@Sun.COM 
232410743SDavid.Hollister@Sun.COM 	if (tag_type != UINT_MAX) {
232510743SDavid.Hollister@Sun.COM 		args++;
232610743SDavid.Hollister@Sun.COM 		switch (tag_type) {
232710743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_NONE:
232810743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_CBACK:
232910743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_WAIT:
233010743SDavid.Hollister@Sun.COM 			break;
233110743SDavid.Hollister@Sun.COM 		default:
233210743SDavid.Hollister@Sun.COM 			mdb_warn("Invalid tag type\n");
233310743SDavid.Hollister@Sun.COM 			return (DCMD_USAGE);
233410743SDavid.Hollister@Sun.COM 		}
233510743SDavid.Hollister@Sun.COM 	}
233610743SDavid.Hollister@Sun.COM 
233710743SDavid.Hollister@Sun.COM 	if (snum != UINT_MAX) {
233810743SDavid.Hollister@Sun.COM 		args++;
233910743SDavid.Hollister@Sun.COM 		if (snum > (PMCS_TAG_SERNO_MASK >> PMCS_TAG_SERNO_SHIFT)) {
234010743SDavid.Hollister@Sun.COM 			mdb_warn("Serial number is out of range\n");
234110743SDavid.Hollister@Sun.COM 			return (DCMD_USAGE);
234210743SDavid.Hollister@Sun.COM 		}
234310743SDavid.Hollister@Sun.COM 	}
234410743SDavid.Hollister@Sun.COM 
234510743SDavid.Hollister@Sun.COM 	/*
234610743SDavid.Hollister@Sun.COM 	 * Make sure 1 and only 1 option is specified
234710743SDavid.Hollister@Sun.COM 	 */
234810743SDavid.Hollister@Sun.COM 	if ((args == 0) || (args > 1)) {
234910743SDavid.Hollister@Sun.COM 		mdb_warn("Exactly one of -i, -s and -t must be specified\n");
235010743SDavid.Hollister@Sun.COM 		return (DCMD_USAGE);
235110743SDavid.Hollister@Sun.COM 	}
235210743SDavid.Hollister@Sun.COM 
235310743SDavid.Hollister@Sun.COM 	if (MDB_RD(&ss, sizeof (ss), addr) == -1) {
235410743SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
235510743SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
235610743SDavid.Hollister@Sun.COM 	}
235710743SDavid.Hollister@Sun.COM 
235810743SDavid.Hollister@Sun.COM 	if (MDB_RD(&dip, sizeof (struct dev_info), ss.dip) == -1) {
235910743SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
236010743SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
236110743SDavid.Hollister@Sun.COM 	}
236210743SDavid.Hollister@Sun.COM 
236310743SDavid.Hollister@Sun.COM 	/* processing completed */
236410743SDavid.Hollister@Sun.COM 
236510743SDavid.Hollister@Sun.COM 	if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) ||
236610743SDavid.Hollister@Sun.COM 	    (flags & DCMD_LOOPFIRST)) {
236710743SDavid.Hollister@Sun.COM 		if ((flags & DCMD_LOOP) && !(flags & DCMD_LOOPFIRST))
236810743SDavid.Hollister@Sun.COM 			mdb_printf("\n");
236910743SDavid.Hollister@Sun.COM 		mdb_printf("%16s %9s %4s B C  WorkFlags wserno DbgMsk %16s\n",
237010743SDavid.Hollister@Sun.COM 		    "Address", "State", "Inst", "DIP");
237110743SDavid.Hollister@Sun.COM 		mdb_printf("================================="
237210743SDavid.Hollister@Sun.COM 		    "============================================\n");
237310743SDavid.Hollister@Sun.COM 	}
237410743SDavid.Hollister@Sun.COM 
237510743SDavid.Hollister@Sun.COM 	switch (ss.state) {
237610743SDavid.Hollister@Sun.COM 	case STATE_NIL:
237710743SDavid.Hollister@Sun.COM 		state_str = "Invalid";
237810743SDavid.Hollister@Sun.COM 		break;
237910743SDavid.Hollister@Sun.COM 	case STATE_PROBING:
238010743SDavid.Hollister@Sun.COM 		state_str = "Probing";
238110743SDavid.Hollister@Sun.COM 		break;
238210743SDavid.Hollister@Sun.COM 	case STATE_RUNNING:
238310743SDavid.Hollister@Sun.COM 		state_str = "Running";
238410743SDavid.Hollister@Sun.COM 		break;
238510743SDavid.Hollister@Sun.COM 	case STATE_UNPROBING:
238610743SDavid.Hollister@Sun.COM 		state_str = "Unprobing";
238710743SDavid.Hollister@Sun.COM 		break;
238810743SDavid.Hollister@Sun.COM 	case STATE_DEAD:
238910743SDavid.Hollister@Sun.COM 		state_str = "Dead";
239010743SDavid.Hollister@Sun.COM 		break;
239111692SJesse.Butler@Sun.COM 	case STATE_IN_RESET:
239211692SJesse.Butler@Sun.COM 		state_str = "In Reset";
239311692SJesse.Butler@Sun.COM 		break;
239410743SDavid.Hollister@Sun.COM 	}
239510743SDavid.Hollister@Sun.COM 
239610743SDavid.Hollister@Sun.COM 	mdb_printf("%16p %9s %4d %1d %1d 0x%08x 0x%04x 0x%04x %16p\n", addr,
239710743SDavid.Hollister@Sun.COM 	    state_str, dip.devi_instance, ss.blocked, ss.configuring,
239810743SDavid.Hollister@Sun.COM 	    ss.work_flags, ss.wserno, ss.debug_mask, ss.dip);
239910743SDavid.Hollister@Sun.COM 	mdb_printf("\n");
240010743SDavid.Hollister@Sun.COM 
240110743SDavid.Hollister@Sun.COM 	mdb_inc_indent(4);
240210743SDavid.Hollister@Sun.COM 	display_matching_work(ss, index, snum, tag_type);
240310743SDavid.Hollister@Sun.COM 	mdb_dec_indent(4);
240410743SDavid.Hollister@Sun.COM 	mdb_printf("\n");
240510743SDavid.Hollister@Sun.COM 
240610743SDavid.Hollister@Sun.COM 	return (DCMD_OK);
240710743SDavid.Hollister@Sun.COM }
240810743SDavid.Hollister@Sun.COM 
240911694SDavid.Hollister@Sun.COM #ifndef _KMDB
241011694SDavid.Hollister@Sun.COM static int
241111694SDavid.Hollister@Sun.COM pmcs_dump_fwlog(struct pmcs_hw *ss, int instance, const char *ofile)
241211694SDavid.Hollister@Sun.COM {
241311694SDavid.Hollister@Sun.COM 	uint8_t *fwlogp;
241411694SDavid.Hollister@Sun.COM 	int	ofilefd = -1;
241511694SDavid.Hollister@Sun.COM 	char	ofilename[MAXPATHLEN];
241611694SDavid.Hollister@Sun.COM 	int	rval = DCMD_OK;
241711694SDavid.Hollister@Sun.COM 
241811694SDavid.Hollister@Sun.COM 	if (ss->fwlogp == NULL) {
241911694SDavid.Hollister@Sun.COM 		mdb_warn("Firmware event log disabled for instance %d",
242011694SDavid.Hollister@Sun.COM 		    instance);
242111694SDavid.Hollister@Sun.COM 		return (DCMD_OK);
242211694SDavid.Hollister@Sun.COM 	}
242311694SDavid.Hollister@Sun.COM 
242411694SDavid.Hollister@Sun.COM 	if (snprintf(ofilename, MAXPATHLEN, "%s%d", ofile, instance) >
242511694SDavid.Hollister@Sun.COM 	    MAXPATHLEN) {
242611694SDavid.Hollister@Sun.COM 		mdb_warn("Output filename is too long for instance %d",
242711694SDavid.Hollister@Sun.COM 		    instance);
242811694SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
242911694SDavid.Hollister@Sun.COM 	}
243011694SDavid.Hollister@Sun.COM 
243111694SDavid.Hollister@Sun.COM 	fwlogp = mdb_alloc(PMCS_FWLOG_SIZE, UM_SLEEP);
243211694SDavid.Hollister@Sun.COM 
243311694SDavid.Hollister@Sun.COM 	if (MDB_RD(fwlogp, PMCS_FWLOG_SIZE, ss->fwlogp) == -1) {
243411694SDavid.Hollister@Sun.COM 		NOREAD(fwlogp, ss->fwlogp);
243511694SDavid.Hollister@Sun.COM 		rval = DCMD_ERR;
243611694SDavid.Hollister@Sun.COM 		goto cleanup;
243711694SDavid.Hollister@Sun.COM 	}
243811694SDavid.Hollister@Sun.COM 
243911694SDavid.Hollister@Sun.COM 	ofilefd = open(ofilename, O_WRONLY | O_CREAT,
244011694SDavid.Hollister@Sun.COM 	    S_IRUSR | S_IRGRP | S_IROTH);
244111694SDavid.Hollister@Sun.COM 	if (ofilefd < 0) {
244211694SDavid.Hollister@Sun.COM 		mdb_warn("Unable to open '%s' to dump instance %d event log",
244311694SDavid.Hollister@Sun.COM 		    ofilename, instance);
244411694SDavid.Hollister@Sun.COM 		rval = DCMD_ERR;
244511694SDavid.Hollister@Sun.COM 		goto cleanup;
244611694SDavid.Hollister@Sun.COM 	}
244711694SDavid.Hollister@Sun.COM 
244811694SDavid.Hollister@Sun.COM 	if (write(ofilefd, fwlogp, PMCS_FWLOG_SIZE) != PMCS_FWLOG_SIZE) {
244911694SDavid.Hollister@Sun.COM 		mdb_warn("Failed to write %d bytes to output file: instance %d",
245011694SDavid.Hollister@Sun.COM 		    PMCS_FWLOG_SIZE, instance);
245111694SDavid.Hollister@Sun.COM 		rval = DCMD_ERR;
245211694SDavid.Hollister@Sun.COM 		goto cleanup;
245311694SDavid.Hollister@Sun.COM 	}
245411694SDavid.Hollister@Sun.COM 
245511694SDavid.Hollister@Sun.COM 	mdb_printf("Event log for instance %d written to %s\n", instance,
245611694SDavid.Hollister@Sun.COM 	    ofilename);
245711694SDavid.Hollister@Sun.COM 
245811694SDavid.Hollister@Sun.COM cleanup:
245911694SDavid.Hollister@Sun.COM 	if (ofilefd >= 0) {
246011694SDavid.Hollister@Sun.COM 		close(ofilefd);
246111694SDavid.Hollister@Sun.COM 	}
246211694SDavid.Hollister@Sun.COM 	mdb_free(fwlogp, PMCS_FWLOG_SIZE);
246311694SDavid.Hollister@Sun.COM 	return (rval);
246411694SDavid.Hollister@Sun.COM }
246511694SDavid.Hollister@Sun.COM 
246611694SDavid.Hollister@Sun.COM static int
246711694SDavid.Hollister@Sun.COM pmcs_fwlog(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
246811694SDavid.Hollister@Sun.COM {
246911694SDavid.Hollister@Sun.COM 	void		*pmcs_state;
247011694SDavid.Hollister@Sun.COM 	const char	*ofile = NULL;
247111694SDavid.Hollister@Sun.COM 	struct pmcs_hw	ss;
247211694SDavid.Hollister@Sun.COM 	struct dev_info	dip;
247311694SDavid.Hollister@Sun.COM 
247411694SDavid.Hollister@Sun.COM 	if (mdb_getopts(argc, argv, 'o', MDB_OPT_STR, &ofile, NULL) != argc) {
247511694SDavid.Hollister@Sun.COM 		return (DCMD_USAGE);
247611694SDavid.Hollister@Sun.COM 	}
247711694SDavid.Hollister@Sun.COM 
247811694SDavid.Hollister@Sun.COM 	if (ofile == NULL) {
247911694SDavid.Hollister@Sun.COM 		mdb_printf("No output file specified\n");
248011694SDavid.Hollister@Sun.COM 		return (DCMD_USAGE);
248111694SDavid.Hollister@Sun.COM 	}
248211694SDavid.Hollister@Sun.COM 
248311694SDavid.Hollister@Sun.COM 	if (!(flags & DCMD_ADDRSPEC)) {
248411694SDavid.Hollister@Sun.COM 		pmcs_state = NULL;
248511694SDavid.Hollister@Sun.COM 		if (mdb_readvar(&pmcs_state, "pmcs_softc_state") == -1) {
248611694SDavid.Hollister@Sun.COM 			mdb_warn("can't read pmcs_softc_state");
248711694SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
248811694SDavid.Hollister@Sun.COM 		}
248911694SDavid.Hollister@Sun.COM 		if (mdb_pwalk_dcmd("genunix`softstate", "pmcs`pmcs_fwlog", argc,
249011694SDavid.Hollister@Sun.COM 		    argv, (uintptr_t)pmcs_state) == -1) {
249111694SDavid.Hollister@Sun.COM 			mdb_warn("mdb_pwalk_dcmd failed for pmcs_log");
249211694SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
249311694SDavid.Hollister@Sun.COM 		}
249411694SDavid.Hollister@Sun.COM 		return (DCMD_OK);
249511694SDavid.Hollister@Sun.COM 	}
249611694SDavid.Hollister@Sun.COM 
249711694SDavid.Hollister@Sun.COM 	if (MDB_RD(&ss, sizeof (ss), addr) == -1) {
249811694SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
249911694SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
250011694SDavid.Hollister@Sun.COM 	}
250111694SDavid.Hollister@Sun.COM 
250211694SDavid.Hollister@Sun.COM 	if (MDB_RD(&dip, sizeof (struct dev_info), ss.dip) == -1) {
250311694SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
250411694SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
250511694SDavid.Hollister@Sun.COM 	}
250611694SDavid.Hollister@Sun.COM 
250711694SDavid.Hollister@Sun.COM 	return (pmcs_dump_fwlog(&ss, dip.devi_instance, ofile));
250811694SDavid.Hollister@Sun.COM }
250911694SDavid.Hollister@Sun.COM #endif	/* _KMDB */
251011694SDavid.Hollister@Sun.COM 
251110696SDavid.Hollister@Sun.COM static int
251211048SDavid.Hollister@Sun.COM pmcs_log(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
251311048SDavid.Hollister@Sun.COM {
251411048SDavid.Hollister@Sun.COM 	void		*pmcs_state;
251511048SDavid.Hollister@Sun.COM 	struct pmcs_hw	ss;
251611048SDavid.Hollister@Sun.COM 	struct dev_info	dip;
251711048SDavid.Hollister@Sun.COM 	const char	*match_phy_path = NULL;
251811347SRamana.Srikanth@Sun.COM 	uint64_t 	match_sas_address = 0, tail_lines = 0;
251911048SDavid.Hollister@Sun.COM 
252011048SDavid.Hollister@Sun.COM 	if (!(flags & DCMD_ADDRSPEC)) {
252111048SDavid.Hollister@Sun.COM 		pmcs_state = NULL;
252211048SDavid.Hollister@Sun.COM 		if (mdb_readvar(&pmcs_state, "pmcs_softc_state") == -1) {
252311048SDavid.Hollister@Sun.COM 			mdb_warn("can't read pmcs_softc_state");
252411048SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
252511048SDavid.Hollister@Sun.COM 		}
252611048SDavid.Hollister@Sun.COM 		if (mdb_pwalk_dcmd("genunix`softstate", "pmcs`pmcs_log", argc,
252711048SDavid.Hollister@Sun.COM 		    argv, (uintptr_t)pmcs_state) == -1) {
252811048SDavid.Hollister@Sun.COM 			mdb_warn("mdb_pwalk_dcmd failed for pmcs_log");
252911048SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
253011048SDavid.Hollister@Sun.COM 		}
253111048SDavid.Hollister@Sun.COM 		return (DCMD_OK);
253211048SDavid.Hollister@Sun.COM 	}
253311048SDavid.Hollister@Sun.COM 
253411048SDavid.Hollister@Sun.COM 	if (mdb_getopts(argc, argv,
253511347SRamana.Srikanth@Sun.COM 	    'l', MDB_OPT_UINT64, &tail_lines,
253611048SDavid.Hollister@Sun.COM 	    'p', MDB_OPT_STR, &match_phy_path,
253711048SDavid.Hollister@Sun.COM 	    's', MDB_OPT_UINT64, &match_sas_address,
253811048SDavid.Hollister@Sun.COM 	    NULL) != argc) {
253911048SDavid.Hollister@Sun.COM 		return (DCMD_USAGE);
254011048SDavid.Hollister@Sun.COM 	}
254111048SDavid.Hollister@Sun.COM 
254211048SDavid.Hollister@Sun.COM 	if (MDB_RD(&ss, sizeof (ss), addr) == -1) {
254311048SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
254411048SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
254511048SDavid.Hollister@Sun.COM 	}
254611048SDavid.Hollister@Sun.COM 
254711048SDavid.Hollister@Sun.COM 	if (MDB_RD(&dip, sizeof (struct dev_info), ss.dip) == -1) {
254811048SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
254911048SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
255011048SDavid.Hollister@Sun.COM 	}
255111048SDavid.Hollister@Sun.COM 
255211048SDavid.Hollister@Sun.COM 	if (!(flags & DCMD_LOOP)) {
255311048SDavid.Hollister@Sun.COM 		return (pmcs_dump_tracelog(B_TRUE, dip.devi_instance,
255411347SRamana.Srikanth@Sun.COM 		    tail_lines, match_phy_path, match_sas_address));
255511048SDavid.Hollister@Sun.COM 	} else if (flags & DCMD_LOOPFIRST) {
255611347SRamana.Srikanth@Sun.COM 		return (pmcs_dump_tracelog(B_FALSE, 0, tail_lines,
255711347SRamana.Srikanth@Sun.COM 		    match_phy_path, match_sas_address));
255811048SDavid.Hollister@Sun.COM 	} else {
255911048SDavid.Hollister@Sun.COM 		return (DCMD_OK);
256011048SDavid.Hollister@Sun.COM 	}
256111048SDavid.Hollister@Sun.COM }
256211048SDavid.Hollister@Sun.COM 
256311048SDavid.Hollister@Sun.COM static int
256410696SDavid.Hollister@Sun.COM pmcs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
256510696SDavid.Hollister@Sun.COM {
256611048SDavid.Hollister@Sun.COM 	struct pmcs_hw		ss;
256710696SDavid.Hollister@Sun.COM 	uint_t			verbose = FALSE;
256810696SDavid.Hollister@Sun.COM 	uint_t			phy_info = FALSE;
256910696SDavid.Hollister@Sun.COM 	uint_t			hw_info = FALSE;
257010696SDavid.Hollister@Sun.COM 	uint_t			target_info = FALSE;
257110696SDavid.Hollister@Sun.COM 	uint_t			work_info = FALSE;
257210696SDavid.Hollister@Sun.COM 	uint_t			ic_info = FALSE;
257310696SDavid.Hollister@Sun.COM 	uint_t			iport_info = FALSE;
257410696SDavid.Hollister@Sun.COM 	uint_t			waitqs_info = FALSE;
257510696SDavid.Hollister@Sun.COM 	uint_t			ibq = FALSE;
257610696SDavid.Hollister@Sun.COM 	uint_t			obq = FALSE;
257710696SDavid.Hollister@Sun.COM 	uint_t			tgt_phy_count = FALSE;
257810743SDavid.Hollister@Sun.COM 	uint_t			compq = FALSE;
257911048SDavid.Hollister@Sun.COM 	uint_t			unconfigured = FALSE;
258011334SReed.Liu@Sun.COM 	uint_t			damap_info = FALSE;
258111334SReed.Liu@Sun.COM 	uint_t			dtc_info = FALSE;
258210696SDavid.Hollister@Sun.COM 	int			rv = DCMD_OK;
258310696SDavid.Hollister@Sun.COM 	void			*pmcs_state;
258410696SDavid.Hollister@Sun.COM 	char			*state_str;
258510696SDavid.Hollister@Sun.COM 	struct dev_info		dip;
258611334SReed.Liu@Sun.COM 	per_iport_setting_t	pis;
258710696SDavid.Hollister@Sun.COM 
258810696SDavid.Hollister@Sun.COM 	if (!(flags & DCMD_ADDRSPEC)) {
258910696SDavid.Hollister@Sun.COM 		pmcs_state = NULL;
259010696SDavid.Hollister@Sun.COM 		if (mdb_readvar(&pmcs_state, "pmcs_softc_state") == -1) {
259110696SDavid.Hollister@Sun.COM 			mdb_warn("can't read pmcs_softc_state");
259210696SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
259310696SDavid.Hollister@Sun.COM 		}
259410696SDavid.Hollister@Sun.COM 		if (mdb_pwalk_dcmd("genunix`softstate", "pmcs`pmcs", argc, argv,
259510696SDavid.Hollister@Sun.COM 		    (uintptr_t)pmcs_state) == -1) {
259610696SDavid.Hollister@Sun.COM 			mdb_warn("mdb_pwalk_dcmd failed");
259710696SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
259810696SDavid.Hollister@Sun.COM 		}
259910696SDavid.Hollister@Sun.COM 		return (DCMD_OK);
260010696SDavid.Hollister@Sun.COM 	}
260110696SDavid.Hollister@Sun.COM 
260210696SDavid.Hollister@Sun.COM 	if (mdb_getopts(argc, argv,
260310743SDavid.Hollister@Sun.COM 	    'c', MDB_OPT_SETBITS, TRUE, &compq,
260411334SReed.Liu@Sun.COM 	    'd', MDB_OPT_SETBITS, TRUE, &dtc_info,
260510696SDavid.Hollister@Sun.COM 	    'h', MDB_OPT_SETBITS, TRUE, &hw_info,
260610696SDavid.Hollister@Sun.COM 	    'i', MDB_OPT_SETBITS, TRUE, &ic_info,
260710696SDavid.Hollister@Sun.COM 	    'I', MDB_OPT_SETBITS, TRUE, &iport_info,
260811334SReed.Liu@Sun.COM 	    'm', MDB_OPT_SETBITS, TRUE, &damap_info,
260910696SDavid.Hollister@Sun.COM 	    'p', MDB_OPT_SETBITS, TRUE, &phy_info,
261010696SDavid.Hollister@Sun.COM 	    'q', MDB_OPT_SETBITS, TRUE, &ibq,
261110696SDavid.Hollister@Sun.COM 	    'Q', MDB_OPT_SETBITS, TRUE, &obq,
261210696SDavid.Hollister@Sun.COM 	    't', MDB_OPT_SETBITS, TRUE, &target_info,
261310696SDavid.Hollister@Sun.COM 	    'T', MDB_OPT_SETBITS, TRUE, &tgt_phy_count,
261411048SDavid.Hollister@Sun.COM 	    'u', MDB_OPT_SETBITS, TRUE, &unconfigured,
261510696SDavid.Hollister@Sun.COM 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
261610696SDavid.Hollister@Sun.COM 	    'w', MDB_OPT_SETBITS, TRUE, &work_info,
261710696SDavid.Hollister@Sun.COM 	    'W', MDB_OPT_SETBITS, TRUE, &waitqs_info,
261810696SDavid.Hollister@Sun.COM 	    NULL) != argc)
261910696SDavid.Hollister@Sun.COM 		return (DCMD_USAGE);
262010696SDavid.Hollister@Sun.COM 
262111334SReed.Liu@Sun.COM 	/*
262211334SReed.Liu@Sun.COM 	 * The 'd' and 'm' options implicitly enable the 'I' option
262311334SReed.Liu@Sun.COM 	 */
262411334SReed.Liu@Sun.COM 	pis.pis_damap_info = damap_info;
262511334SReed.Liu@Sun.COM 	pis.pis_dtc_info = dtc_info;
262611334SReed.Liu@Sun.COM 	if (damap_info || dtc_info) {
262711334SReed.Liu@Sun.COM 		iport_info = TRUE;
262811334SReed.Liu@Sun.COM 	}
262911334SReed.Liu@Sun.COM 
263010696SDavid.Hollister@Sun.COM 	if (MDB_RD(&ss, sizeof (ss), addr) == -1) {
263110696SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
263210696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
263310696SDavid.Hollister@Sun.COM 	}
263410696SDavid.Hollister@Sun.COM 
263510696SDavid.Hollister@Sun.COM 	if (MDB_RD(&dip, sizeof (struct dev_info), ss.dip) == -1) {
263610696SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
263710696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
263810696SDavid.Hollister@Sun.COM 	}
263910696SDavid.Hollister@Sun.COM 
264010696SDavid.Hollister@Sun.COM 	/* processing completed */
264110696SDavid.Hollister@Sun.COM 
264210696SDavid.Hollister@Sun.COM 	if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) ||
264310696SDavid.Hollister@Sun.COM 	    (flags & DCMD_LOOPFIRST) || phy_info || target_info || hw_info ||
264411048SDavid.Hollister@Sun.COM 	    work_info || waitqs_info || ibq || obq || tgt_phy_count || compq ||
264511048SDavid.Hollister@Sun.COM 	    unconfigured) {
264610696SDavid.Hollister@Sun.COM 		if ((flags & DCMD_LOOP) && !(flags & DCMD_LOOPFIRST))
264710696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
264810696SDavid.Hollister@Sun.COM 		mdb_printf("%16s %9s %4s B C  WorkFlags wserno DbgMsk %16s\n",
264910696SDavid.Hollister@Sun.COM 		    "Address", "State", "Inst", "DIP");
265010696SDavid.Hollister@Sun.COM 		mdb_printf("================================="
265110696SDavid.Hollister@Sun.COM 		    "============================================\n");
265210696SDavid.Hollister@Sun.COM 	}
265310696SDavid.Hollister@Sun.COM 
265410696SDavid.Hollister@Sun.COM 	switch (ss.state) {
265510696SDavid.Hollister@Sun.COM 	case STATE_NIL:
265610696SDavid.Hollister@Sun.COM 		state_str = "Invalid";
265710696SDavid.Hollister@Sun.COM 		break;
265810696SDavid.Hollister@Sun.COM 	case STATE_PROBING:
265910696SDavid.Hollister@Sun.COM 		state_str = "Probing";
266010696SDavid.Hollister@Sun.COM 		break;
266110696SDavid.Hollister@Sun.COM 	case STATE_RUNNING:
266210696SDavid.Hollister@Sun.COM 		state_str = "Running";
266310696SDavid.Hollister@Sun.COM 		break;
266410696SDavid.Hollister@Sun.COM 	case STATE_UNPROBING:
266510696SDavid.Hollister@Sun.COM 		state_str = "Unprobing";
266610696SDavid.Hollister@Sun.COM 		break;
266710696SDavid.Hollister@Sun.COM 	case STATE_DEAD:
266810696SDavid.Hollister@Sun.COM 		state_str = "Dead";
266910696SDavid.Hollister@Sun.COM 		break;
267011692SJesse.Butler@Sun.COM 	case STATE_IN_RESET:
267111692SJesse.Butler@Sun.COM 		state_str = "In Reset";
267211692SJesse.Butler@Sun.COM 		break;
267310696SDavid.Hollister@Sun.COM 	}
267410696SDavid.Hollister@Sun.COM 
267510696SDavid.Hollister@Sun.COM 	mdb_printf("%16p %9s %4d %1d %1d 0x%08x 0x%04x 0x%04x %16p\n", addr,
267610696SDavid.Hollister@Sun.COM 	    state_str, dip.devi_instance, ss.blocked, ss.configuring,
267710696SDavid.Hollister@Sun.COM 	    ss.work_flags, ss.wserno, ss.debug_mask, ss.dip);
267810696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
267910696SDavid.Hollister@Sun.COM 
268010696SDavid.Hollister@Sun.COM 	mdb_inc_indent(4);
268110696SDavid.Hollister@Sun.COM 
268210696SDavid.Hollister@Sun.COM 	if (waitqs_info)
268310696SDavid.Hollister@Sun.COM 		display_waitqs(ss, verbose);
268410696SDavid.Hollister@Sun.COM 
268510696SDavid.Hollister@Sun.COM 	if (hw_info)
268610696SDavid.Hollister@Sun.COM 		display_hwinfo(ss, verbose);
268710696SDavid.Hollister@Sun.COM 
268810696SDavid.Hollister@Sun.COM 	if (phy_info || tgt_phy_count)
268910696SDavid.Hollister@Sun.COM 		display_phys(ss, verbose, NULL, 0, tgt_phy_count);
269010696SDavid.Hollister@Sun.COM 
269110696SDavid.Hollister@Sun.COM 	if (target_info || tgt_phy_count)
269210696SDavid.Hollister@Sun.COM 		display_targets(ss, verbose, tgt_phy_count);
269310696SDavid.Hollister@Sun.COM 
269410696SDavid.Hollister@Sun.COM 	if (work_info)
269510696SDavid.Hollister@Sun.COM 		display_work(ss, verbose);
269610696SDavid.Hollister@Sun.COM 
269710696SDavid.Hollister@Sun.COM 	if (ic_info)
269810696SDavid.Hollister@Sun.COM 		display_ic(ss, verbose);
269910696SDavid.Hollister@Sun.COM 
270010696SDavid.Hollister@Sun.COM 	if (ibq)
270110696SDavid.Hollister@Sun.COM 		display_inbound_queues(ss, verbose);
270210696SDavid.Hollister@Sun.COM 
270310696SDavid.Hollister@Sun.COM 	if (obq)
270410696SDavid.Hollister@Sun.COM 		display_outbound_queues(ss, verbose);
270510696SDavid.Hollister@Sun.COM 
270610696SDavid.Hollister@Sun.COM 	if (iport_info)
270711334SReed.Liu@Sun.COM 		display_iport(ss, addr, verbose, &pis);
270810696SDavid.Hollister@Sun.COM 
270910743SDavid.Hollister@Sun.COM 	if (compq)
271010743SDavid.Hollister@Sun.COM 		display_completion_queue(ss);
271110743SDavid.Hollister@Sun.COM 
271211048SDavid.Hollister@Sun.COM 	if (unconfigured)
271311048SDavid.Hollister@Sun.COM 		display_unconfigured_targets(addr);
271411048SDavid.Hollister@Sun.COM 
271510696SDavid.Hollister@Sun.COM 	mdb_dec_indent(4);
271610696SDavid.Hollister@Sun.COM 
271710696SDavid.Hollister@Sun.COM 	return (rv);
271810696SDavid.Hollister@Sun.COM }
271910696SDavid.Hollister@Sun.COM 
272010696SDavid.Hollister@Sun.COM void
272110696SDavid.Hollister@Sun.COM pmcs_help()
272210696SDavid.Hollister@Sun.COM {
272310696SDavid.Hollister@Sun.COM 	mdb_printf("Prints summary information about each pmcs instance.\n"
272410743SDavid.Hollister@Sun.COM 	    "    -c: Dump the completion queue\n"
272511334SReed.Liu@Sun.COM 	    "    -d: Print per-iport information about device tree children\n"
272610696SDavid.Hollister@Sun.COM 	    "    -h: Print more detailed hardware information\n"
272710696SDavid.Hollister@Sun.COM 	    "    -i: Print interrupt coalescing information\n"
272810696SDavid.Hollister@Sun.COM 	    "    -I: Print information about each iport\n"
272911334SReed.Liu@Sun.COM 	    "    -m: Print per-iport information about DAM/damap state\n"
273010696SDavid.Hollister@Sun.COM 	    "    -p: Print information about each attached PHY\n"
273110696SDavid.Hollister@Sun.COM 	    "    -q: Dump inbound queues\n"
273210696SDavid.Hollister@Sun.COM 	    "    -Q: Dump outbound queues\n"
273311048SDavid.Hollister@Sun.COM 	    "    -t: Print information about each configured target\n"
273410696SDavid.Hollister@Sun.COM 	    "    -T: Print target and PHY count summary\n"
273511048SDavid.Hollister@Sun.COM 	    "    -u: Show SAS address of all unconfigured targets\n"
273610696SDavid.Hollister@Sun.COM 	    "    -w: Dump work structures\n"
273710696SDavid.Hollister@Sun.COM 	    "    -W: List pmcs cmds waiting on various queues\n"
273810696SDavid.Hollister@Sun.COM 	    "    -v: Add verbosity to the above options\n");
273910696SDavid.Hollister@Sun.COM }
274010696SDavid.Hollister@Sun.COM 
274110743SDavid.Hollister@Sun.COM void
274211048SDavid.Hollister@Sun.COM pmcs_log_help()
274311048SDavid.Hollister@Sun.COM {
274411048SDavid.Hollister@Sun.COM 	mdb_printf("Dump the pmcs log buffer, possibly with filtering.\n"
274511347SRamana.Srikanth@Sun.COM 	    "    -l TAIL_LINES:          Dump the last TAIL_LINES messages\n"
274611048SDavid.Hollister@Sun.COM 	    "    -p PHY_PATH:            Dump messages matching PHY_PATH\n"
274711048SDavid.Hollister@Sun.COM 	    "    -s SAS_ADDRESS:         Dump messages matching SAS_ADDRESS\n\n"
274811048SDavid.Hollister@Sun.COM 	    "Where: PHY_PATH can be found with ::pmcs -p (e.g. pp04.18.18.01)\n"
274911048SDavid.Hollister@Sun.COM 	    "       SAS_ADDRESS can be found with ::pmcs -t "
275011048SDavid.Hollister@Sun.COM 	    "(e.g. 5000c5000358c221)\n");
275111048SDavid.Hollister@Sun.COM }
275211048SDavid.Hollister@Sun.COM void
275310743SDavid.Hollister@Sun.COM pmcs_tag_help()
275410743SDavid.Hollister@Sun.COM {
275510743SDavid.Hollister@Sun.COM 	mdb_printf("Print all work structures by matching the tag.\n"
275610743SDavid.Hollister@Sun.COM 	    "    -i index:        Match tag index (0x000 - 0xfff)\n"
275710743SDavid.Hollister@Sun.COM 	    "    -s serialnumber: Match serial number (0x0000 - 0xffff)\n"
275810743SDavid.Hollister@Sun.COM 	    "    -t tagtype:      Match tag type [NONE(1), CBACK(2), "
275910743SDavid.Hollister@Sun.COM 	    "WAIT(3)]\n");
276010743SDavid.Hollister@Sun.COM }
276110743SDavid.Hollister@Sun.COM 
276210696SDavid.Hollister@Sun.COM static const mdb_dcmd_t dcmds[] = {
276311334SReed.Liu@Sun.COM 	{ "pmcs", "?[-cdhiImpQqtTuwWv]", "print pmcs information",
276410696SDavid.Hollister@Sun.COM 	    pmcs_dcmd, pmcs_help
276510696SDavid.Hollister@Sun.COM 	},
276611048SDavid.Hollister@Sun.COM 	{ "pmcs_log",
276711347SRamana.Srikanth@Sun.COM 	    "?[-p PHY_PATH | -s SAS_ADDRESS | -l TAIL_LINES]",
276811048SDavid.Hollister@Sun.COM 	    "dump pmcs log file", pmcs_log, pmcs_log_help
276911048SDavid.Hollister@Sun.COM 	},
277010743SDavid.Hollister@Sun.COM 	{ "pmcs_tag", "?[-t tagtype|-s serialnum|-i index]",
277110743SDavid.Hollister@Sun.COM 	    "Find work structures by tag type, serial number or index",
277210743SDavid.Hollister@Sun.COM 	    pmcs_tag, pmcs_tag_help
277310743SDavid.Hollister@Sun.COM 	},
277411694SDavid.Hollister@Sun.COM #ifndef _KMDB
277511694SDavid.Hollister@Sun.COM 	{ "pmcs_fwlog",
277611694SDavid.Hollister@Sun.COM 	    "?-o output_file",
277711694SDavid.Hollister@Sun.COM 	    "dump pmcs firmware event log to output_file", pmcs_fwlog, NULL
277811694SDavid.Hollister@Sun.COM 	},
277911694SDavid.Hollister@Sun.COM #endif	/* _KMDB */
278010696SDavid.Hollister@Sun.COM 	{ NULL }
278110696SDavid.Hollister@Sun.COM };
278210696SDavid.Hollister@Sun.COM 
278310696SDavid.Hollister@Sun.COM static const mdb_walker_t walkers[] = {
278410696SDavid.Hollister@Sun.COM 	{ "pmcs_targets", "walk target structures",
278510696SDavid.Hollister@Sun.COM 		targets_walk_i, targets_walk_s, targets_walk_f },
278610696SDavid.Hollister@Sun.COM 	{ "pmcs_phys", "walk PHY structures",
278710696SDavid.Hollister@Sun.COM 		phy_walk_i, phy_walk_s, phy_walk_f },
278810696SDavid.Hollister@Sun.COM 	{ NULL }
278910696SDavid.Hollister@Sun.COM };
279010696SDavid.Hollister@Sun.COM 
279110696SDavid.Hollister@Sun.COM static const mdb_modinfo_t modinfo = {
279210696SDavid.Hollister@Sun.COM 	MDB_API_VERSION, dcmds, walkers
279310696SDavid.Hollister@Sun.COM };
279410696SDavid.Hollister@Sun.COM 
279510696SDavid.Hollister@Sun.COM const mdb_modinfo_t *
279610696SDavid.Hollister@Sun.COM _mdb_init(void)
279710696SDavid.Hollister@Sun.COM {
279810696SDavid.Hollister@Sun.COM 	return (&modinfo);
279910696SDavid.Hollister@Sun.COM }
2800