xref: /onnv-gate/usr/src/cmd/mdb/common/modules/pmcs/pmcs.c (revision 12791:3e47de750570)
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 /*
2212060SDavid.Hollister@Sun.COM  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2310696SDavid.Hollister@Sun.COM  */
2410696SDavid.Hollister@Sun.COM 
2510696SDavid.Hollister@Sun.COM #include <limits.h>
2610696SDavid.Hollister@Sun.COM #include <sys/mdb_modapi.h>
2711334SReed.Liu@Sun.COM #include <mdb/mdb_ctf.h>
2810696SDavid.Hollister@Sun.COM #include <sys/sysinfo.h>
2911048SDavid.Hollister@Sun.COM #include <sys/byteorder.h>
3011334SReed.Liu@Sun.COM #include <sys/nvpair.h>
3111334SReed.Liu@Sun.COM #include <sys/damap.h>
3210696SDavid.Hollister@Sun.COM #include <sys/scsi/scsi.h>
3310696SDavid.Hollister@Sun.COM #include <sys/scsi/adapters/pmcs/pmcs.h>
3411694SDavid.Hollister@Sun.COM #ifndef _KMDB
3511694SDavid.Hollister@Sun.COM #include <sys/types.h>
3611694SDavid.Hollister@Sun.COM #include <sys/stat.h>
3711694SDavid.Hollister@Sun.COM #include <fcntl.h>
3811694SDavid.Hollister@Sun.COM #include <unistd.h>
3911694SDavid.Hollister@Sun.COM #endif	/* _KMDB */
4010696SDavid.Hollister@Sun.COM 
4111334SReed.Liu@Sun.COM /*
4211334SReed.Liu@Sun.COM  * We need use this to pass the settings when display_iport
4311334SReed.Liu@Sun.COM  */
4411334SReed.Liu@Sun.COM typedef struct per_iport_setting {
4511334SReed.Liu@Sun.COM 	uint_t  pis_damap_info; /* -m: DAM/damap */
4611334SReed.Liu@Sun.COM 	uint_t  pis_dtc_info; /* -d: device tree children: dev_info/path_info */
4711334SReed.Liu@Sun.COM } per_iport_setting_t;
4811334SReed.Liu@Sun.COM 
4912060SDavid.Hollister@Sun.COM /*
5012060SDavid.Hollister@Sun.COM  * This structure is used for sorting work structures by the wserno
5112060SDavid.Hollister@Sun.COM  */
5212060SDavid.Hollister@Sun.COM typedef struct wserno_list {
5312060SDavid.Hollister@Sun.COM 	int serno;
5412060SDavid.Hollister@Sun.COM 	int idx;
5512060SDavid.Hollister@Sun.COM 	struct wserno_list *next;
5612060SDavid.Hollister@Sun.COM 	struct wserno_list *prev;
5712060SDavid.Hollister@Sun.COM } wserno_list_t;
5812060SDavid.Hollister@Sun.COM 
5911334SReed.Liu@Sun.COM #define	MDB_RD(a, b, c)		mdb_vread(a, b, (uintptr_t)c)
6011334SReed.Liu@Sun.COM #define	NOREAD(a, b)		mdb_warn("could not read " #a " at 0x%p", b)
6110696SDavid.Hollister@Sun.COM 
6210696SDavid.Hollister@Sun.COM static pmcs_hw_t ss;
6310696SDavid.Hollister@Sun.COM static pmcs_xscsi_t **targets = NULL;
6410696SDavid.Hollister@Sun.COM static int target_idx;
6510696SDavid.Hollister@Sun.COM 
6610696SDavid.Hollister@Sun.COM static uint32_t	sas_phys, sata_phys, exp_phys, num_expanders, empty_phys;
6710696SDavid.Hollister@Sun.COM 
6810696SDavid.Hollister@Sun.COM static pmcs_phy_t *pmcs_next_sibling(pmcs_phy_t *phyp);
6910743SDavid.Hollister@Sun.COM static void display_one_work(pmcwork_t *wp, int verbose, int idx);
7010696SDavid.Hollister@Sun.COM 
7110696SDavid.Hollister@Sun.COM static void
print_sas_address(pmcs_phy_t * phy)7210696SDavid.Hollister@Sun.COM print_sas_address(pmcs_phy_t *phy)
7310696SDavid.Hollister@Sun.COM {
7410696SDavid.Hollister@Sun.COM 	int idx;
7510696SDavid.Hollister@Sun.COM 
7610696SDavid.Hollister@Sun.COM 	for (idx = 0; idx < 8; idx++) {
7710696SDavid.Hollister@Sun.COM 		mdb_printf("%02x", phy->sas_address[idx]);
7810696SDavid.Hollister@Sun.COM 	}
7910696SDavid.Hollister@Sun.COM }
8010696SDavid.Hollister@Sun.COM 
8112120SDavid.Hollister@Sun.COM static void
pmcs_fwtime_to_systime(struct pmcs_hw ss,uint32_t fw_hi,uint32_t fw_lo,struct timespec * stime)8212120SDavid.Hollister@Sun.COM pmcs_fwtime_to_systime(struct pmcs_hw ss, uint32_t fw_hi, uint32_t fw_lo,
8312120SDavid.Hollister@Sun.COM     struct timespec *stime)
8412120SDavid.Hollister@Sun.COM {
8512120SDavid.Hollister@Sun.COM 	uint64_t fwtime;
8612120SDavid.Hollister@Sun.COM 	time_t secs;
8712120SDavid.Hollister@Sun.COM 	long nsecs;
8812120SDavid.Hollister@Sun.COM 	boolean_t backward_time = B_FALSE;
8912120SDavid.Hollister@Sun.COM 
9012120SDavid.Hollister@Sun.COM 	fwtime = ((uint64_t)fw_hi << 32) | fw_lo;
9112120SDavid.Hollister@Sun.COM 
9212120SDavid.Hollister@Sun.COM 	/*
9312120SDavid.Hollister@Sun.COM 	 * If fwtime < ss.fw_timestamp, then we need to adjust the clock
9412120SDavid.Hollister@Sun.COM 	 * time backwards from ss.sys_timestamp.  Otherwise, the adjustment
9512120SDavid.Hollister@Sun.COM 	 * goes forward in time
9612120SDavid.Hollister@Sun.COM 	 */
9712120SDavid.Hollister@Sun.COM 	if (fwtime >= ss.fw_timestamp) {
9812120SDavid.Hollister@Sun.COM 		fwtime -= ss.fw_timestamp;
9912120SDavid.Hollister@Sun.COM 	} else {
10012120SDavid.Hollister@Sun.COM 		fwtime = ss.fw_timestamp - fwtime;
10112120SDavid.Hollister@Sun.COM 		backward_time = B_TRUE;
10212120SDavid.Hollister@Sun.COM 	}
10312120SDavid.Hollister@Sun.COM 
10412120SDavid.Hollister@Sun.COM 	secs = ((time_t)fwtime / NSECS_PER_SEC);
10512120SDavid.Hollister@Sun.COM 	nsecs = ((long)fwtime % NSECS_PER_SEC);
10612120SDavid.Hollister@Sun.COM 
10712120SDavid.Hollister@Sun.COM 	stime->tv_sec = ss.sys_timestamp.tv_sec;
10812120SDavid.Hollister@Sun.COM 	stime->tv_nsec = ss.sys_timestamp.tv_nsec;
10912120SDavid.Hollister@Sun.COM 
11012120SDavid.Hollister@Sun.COM 	if (backward_time) {
11112120SDavid.Hollister@Sun.COM 		if (stime->tv_nsec < nsecs) {
11212120SDavid.Hollister@Sun.COM 			stime->tv_sec--;
11312120SDavid.Hollister@Sun.COM 			stime->tv_nsec = stime->tv_nsec + NSECS_PER_SEC - nsecs;
11412120SDavid.Hollister@Sun.COM 		} else {
11512120SDavid.Hollister@Sun.COM 			stime->tv_nsec -= nsecs;
11612120SDavid.Hollister@Sun.COM 		}
11712120SDavid.Hollister@Sun.COM 		stime->tv_sec -= secs;
11812120SDavid.Hollister@Sun.COM 	} else {
11912120SDavid.Hollister@Sun.COM 		if (stime->tv_nsec + nsecs > NSECS_PER_SEC) {
12012120SDavid.Hollister@Sun.COM 			stime->tv_sec++;
12112120SDavid.Hollister@Sun.COM 		}
12212120SDavid.Hollister@Sun.COM 		stime->tv_nsec = (stime->tv_nsec + nsecs) % NSECS_PER_SEC;
12312120SDavid.Hollister@Sun.COM 		stime->tv_sec += secs;
12412120SDavid.Hollister@Sun.COM 	}
12512120SDavid.Hollister@Sun.COM }
12612120SDavid.Hollister@Sun.COM 
12710696SDavid.Hollister@Sun.COM /*ARGSUSED*/
12810696SDavid.Hollister@Sun.COM static void
display_ic(struct pmcs_hw m,int verbose)12910696SDavid.Hollister@Sun.COM display_ic(struct pmcs_hw m, int verbose)
13010696SDavid.Hollister@Sun.COM {
13110696SDavid.Hollister@Sun.COM 	int msec_per_tick;
13210696SDavid.Hollister@Sun.COM 
13310696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&msec_per_tick, "msec_per_tick") == -1) {
13410696SDavid.Hollister@Sun.COM 		mdb_warn("can't read msec_per_tick");
13510696SDavid.Hollister@Sun.COM 		msec_per_tick = 0;
13610696SDavid.Hollister@Sun.COM 	}
13710696SDavid.Hollister@Sun.COM 
13810696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
13910696SDavid.Hollister@Sun.COM 	mdb_printf("Interrupt coalescing timer info\n");
14010696SDavid.Hollister@Sun.COM 	mdb_printf("-------------------------------\n");
14110696SDavid.Hollister@Sun.COM 	if (msec_per_tick == 0) {
14210696SDavid.Hollister@Sun.COM 		mdb_printf("Quantum                       : ?? ms\n");
14310696SDavid.Hollister@Sun.COM 	} else {
14410696SDavid.Hollister@Sun.COM 		mdb_printf("Quantum                       : %d ms\n",
14510696SDavid.Hollister@Sun.COM 		    m.io_intr_coal.quantum * msec_per_tick);
14610696SDavid.Hollister@Sun.COM 	}
14710696SDavid.Hollister@Sun.COM 	mdb_printf("Timer enabled                 : ");
14810696SDavid.Hollister@Sun.COM 	if (m.io_intr_coal.timer_on) {
14910696SDavid.Hollister@Sun.COM 		mdb_printf("Yes\n");
15010696SDavid.Hollister@Sun.COM 		mdb_printf("Coalescing timer value        : %d us\n",
15110696SDavid.Hollister@Sun.COM 		    m.io_intr_coal.intr_coal_timer);
15210696SDavid.Hollister@Sun.COM 	} else {
15310696SDavid.Hollister@Sun.COM 		mdb_printf("No\n");
15410696SDavid.Hollister@Sun.COM 	}
15510696SDavid.Hollister@Sun.COM 	mdb_printf("Total nsecs between interrupts: %ld\n",
15610696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.nsecs_between_intrs);
15710696SDavid.Hollister@Sun.COM 	mdb_printf("Time of last I/O interrupt    : %ld\n",
15810696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.last_io_comp);
15910696SDavid.Hollister@Sun.COM 	mdb_printf("Number of I/O interrupts      : %d\n",
16010696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.num_intrs);
16110696SDavid.Hollister@Sun.COM 	mdb_printf("Number of I/O completions     : %d\n",
16210696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.num_io_completions);
16310696SDavid.Hollister@Sun.COM 	mdb_printf("Max I/O completion interrupts : %d\n",
16410696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.max_io_completions);
16510696SDavid.Hollister@Sun.COM 	mdb_printf("Measured ECHO int latency     : %d ns\n",
16610696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.intr_latency);
16710696SDavid.Hollister@Sun.COM 	mdb_printf("Interrupt threshold           : %d\n",
16810696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.intr_threshold);
16910696SDavid.Hollister@Sun.COM }
17010696SDavid.Hollister@Sun.COM 
17110696SDavid.Hollister@Sun.COM /*ARGSUSED*/
17210696SDavid.Hollister@Sun.COM static int
pmcs_iport_phy_walk_cb(uintptr_t addr,const void * wdata,void * priv)17310696SDavid.Hollister@Sun.COM pmcs_iport_phy_walk_cb(uintptr_t addr, const void *wdata, void *priv)
17410696SDavid.Hollister@Sun.COM {
17510696SDavid.Hollister@Sun.COM 	struct pmcs_phy		phy;
17610696SDavid.Hollister@Sun.COM 
17710696SDavid.Hollister@Sun.COM 	if (mdb_vread(&phy, sizeof (struct pmcs_phy), addr) !=
17810696SDavid.Hollister@Sun.COM 	    sizeof (struct pmcs_phy)) {
17910696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
18010696SDavid.Hollister@Sun.COM 	}
18110696SDavid.Hollister@Sun.COM 
18210696SDavid.Hollister@Sun.COM 	mdb_printf("%16p %2d\n", addr, phy.phynum);
18310696SDavid.Hollister@Sun.COM 
18410696SDavid.Hollister@Sun.COM 	return (0);
18510696SDavid.Hollister@Sun.COM }
18610696SDavid.Hollister@Sun.COM 
18711334SReed.Liu@Sun.COM static int
display_iport_damap(dev_info_t * pdip)18811334SReed.Liu@Sun.COM display_iport_damap(dev_info_t *pdip)
18911334SReed.Liu@Sun.COM {
19011334SReed.Liu@Sun.COM 	int rval = DCMD_ERR;
19111334SReed.Liu@Sun.COM 	struct dev_info dip;
19211334SReed.Liu@Sun.COM 	scsi_hba_tran_t sht;
19311334SReed.Liu@Sun.COM 	mdb_ctf_id_t istm_ctfid; /* impl_scsi_tgtmap_t ctf_id */
19411334SReed.Liu@Sun.COM 	ulong_t tmd_offset = 0; /* tgtmap_dam offset to impl_scsi_tgtmap_t */
19511334SReed.Liu@Sun.COM 	uintptr_t dam0;
19611334SReed.Liu@Sun.COM 	uintptr_t dam1;
19711334SReed.Liu@Sun.COM 
19811334SReed.Liu@Sun.COM 	if (mdb_vread(&dip, sizeof (struct dev_info), (uintptr_t)pdip) !=
19911334SReed.Liu@Sun.COM 	    sizeof (struct dev_info)) {
20011334SReed.Liu@Sun.COM 		return (rval);
20111334SReed.Liu@Sun.COM 	}
20211334SReed.Liu@Sun.COM 
20311334SReed.Liu@Sun.COM 	if (dip.devi_driver_data == NULL) {
20411334SReed.Liu@Sun.COM 		return (rval);
20511334SReed.Liu@Sun.COM 	}
20611334SReed.Liu@Sun.COM 
20711334SReed.Liu@Sun.COM 	if (mdb_vread(&sht, sizeof (scsi_hba_tran_t),
20811334SReed.Liu@Sun.COM 	    (uintptr_t)dip.devi_driver_data) != sizeof (scsi_hba_tran_t)) {
20911334SReed.Liu@Sun.COM 		return (rval);
21011334SReed.Liu@Sun.COM 	}
21111334SReed.Liu@Sun.COM 
21211334SReed.Liu@Sun.COM 	if (sht.tran_tgtmap == NULL) {
21311334SReed.Liu@Sun.COM 		return (rval);
21411334SReed.Liu@Sun.COM 	}
21511334SReed.Liu@Sun.COM 
21611334SReed.Liu@Sun.COM 	if (mdb_ctf_lookup_by_name("impl_scsi_tgtmap_t", &istm_ctfid) != 0) {
21711334SReed.Liu@Sun.COM 		return (rval);
21811334SReed.Liu@Sun.COM 	}
21911334SReed.Liu@Sun.COM 
22011334SReed.Liu@Sun.COM 	if (mdb_ctf_offsetof(istm_ctfid, "tgtmap_dam", &tmd_offset) != 0) {
22111334SReed.Liu@Sun.COM 		return (rval);
22211334SReed.Liu@Sun.COM 	}
22311334SReed.Liu@Sun.COM 
22411334SReed.Liu@Sun.COM 	tmd_offset /= NBBY;
22511334SReed.Liu@Sun.COM 	mdb_vread(&dam0, sizeof (dam0),
22611334SReed.Liu@Sun.COM 	    (uintptr_t)(tmd_offset + (char *)sht.tran_tgtmap));
22711334SReed.Liu@Sun.COM 	mdb_vread(&dam1, sizeof (dam1),
22811334SReed.Liu@Sun.COM 	    (uintptr_t)(sizeof (dam0) + tmd_offset + (char *)sht.tran_tgtmap));
22911334SReed.Liu@Sun.COM 
23011334SReed.Liu@Sun.COM 	if (dam0 != NULL) {
23111334SReed.Liu@Sun.COM 		rval = mdb_call_dcmd("damap", dam0, DCMD_ADDRSPEC, 0, NULL);
23211334SReed.Liu@Sun.COM 		mdb_printf("\n");
23311334SReed.Liu@Sun.COM 		if (rval != DCMD_OK) {
23411334SReed.Liu@Sun.COM 			return (rval);
23511334SReed.Liu@Sun.COM 		}
23611334SReed.Liu@Sun.COM 	}
23711334SReed.Liu@Sun.COM 
23811334SReed.Liu@Sun.COM 	if (dam1 != NULL) {
23911334SReed.Liu@Sun.COM 		rval = mdb_call_dcmd("damap", dam1, DCMD_ADDRSPEC, 0, NULL);
24011334SReed.Liu@Sun.COM 		mdb_printf("\n");
24111334SReed.Liu@Sun.COM 	}
24211334SReed.Liu@Sun.COM 
24311334SReed.Liu@Sun.COM 	return (rval);
24411334SReed.Liu@Sun.COM }
24511334SReed.Liu@Sun.COM 
24611334SReed.Liu@Sun.COM /* ARGSUSED */
24711334SReed.Liu@Sun.COM static int
display_iport_di_cb(uintptr_t addr,const void * wdata,void * priv)24811334SReed.Liu@Sun.COM display_iport_di_cb(uintptr_t addr, const void *wdata, void *priv)
24911334SReed.Liu@Sun.COM {
25011334SReed.Liu@Sun.COM 	uint_t *idx = (uint_t *)priv;
25111334SReed.Liu@Sun.COM 	struct dev_info dip;
25211334SReed.Liu@Sun.COM 	char devi_name[MAXNAMELEN];
25311334SReed.Liu@Sun.COM 	char devi_addr[MAXNAMELEN];
25411334SReed.Liu@Sun.COM 
25511334SReed.Liu@Sun.COM 	if (mdb_vread(&dip, sizeof (struct dev_info), (uintptr_t)addr) !=
25611334SReed.Liu@Sun.COM 	    sizeof (struct dev_info)) {
25711334SReed.Liu@Sun.COM 		return (DCMD_ERR);
25811334SReed.Liu@Sun.COM 	}
25911334SReed.Liu@Sun.COM 
26011334SReed.Liu@Sun.COM 	if (mdb_readstr(devi_name, sizeof (devi_name),
26111334SReed.Liu@Sun.COM 	    (uintptr_t)dip.devi_node_name) == -1) {
26211334SReed.Liu@Sun.COM 		devi_name[0] = '?';
26311334SReed.Liu@Sun.COM 		devi_name[1] = '\0';
26411334SReed.Liu@Sun.COM 	}
26511334SReed.Liu@Sun.COM 
26611334SReed.Liu@Sun.COM 	if (mdb_readstr(devi_addr, sizeof (devi_addr),
26711334SReed.Liu@Sun.COM 	    (uintptr_t)dip.devi_addr) == -1) {
26811334SReed.Liu@Sun.COM 		devi_addr[0] = '?';
26911334SReed.Liu@Sun.COM 		devi_addr[1] = '\0';
27011334SReed.Liu@Sun.COM 	}
27111334SReed.Liu@Sun.COM 
27211334SReed.Liu@Sun.COM 	mdb_printf("  %3d: @%-21s%10s@\t%p::devinfo -s\n",
27311334SReed.Liu@Sun.COM 	    (*idx)++, devi_addr, devi_name, addr);
27411334SReed.Liu@Sun.COM 	return (DCMD_OK);
27511334SReed.Liu@Sun.COM }
27611334SReed.Liu@Sun.COM 
27711334SReed.Liu@Sun.COM /* ARGSUSED */
27811334SReed.Liu@Sun.COM static int
display_iport_pi_cb(uintptr_t addr,const void * wdata,void * priv)27911334SReed.Liu@Sun.COM display_iport_pi_cb(uintptr_t addr, const void *wdata, void *priv)
28011334SReed.Liu@Sun.COM {
28111334SReed.Liu@Sun.COM 	uint_t *idx = (uint_t *)priv;
28211334SReed.Liu@Sun.COM 	struct mdi_pathinfo mpi;
28311334SReed.Liu@Sun.COM 	char pi_addr[MAXNAMELEN];
28411334SReed.Liu@Sun.COM 
28511334SReed.Liu@Sun.COM 	if (mdb_vread(&mpi, sizeof (struct mdi_pathinfo), (uintptr_t)addr) !=
28611334SReed.Liu@Sun.COM 	    sizeof (struct mdi_pathinfo)) {
28711334SReed.Liu@Sun.COM 		return (DCMD_ERR);
28811334SReed.Liu@Sun.COM 	}
28911334SReed.Liu@Sun.COM 
29011334SReed.Liu@Sun.COM 	if (mdb_readstr(pi_addr, sizeof (pi_addr),
29111334SReed.Liu@Sun.COM 	    (uintptr_t)mpi.pi_addr) == -1) {
29211334SReed.Liu@Sun.COM 		pi_addr[0] = '?';
29311334SReed.Liu@Sun.COM 		pi_addr[1] = '\0';
29411334SReed.Liu@Sun.COM 	}
29511334SReed.Liu@Sun.COM 
29611334SReed.Liu@Sun.COM 	mdb_printf("  %3d: @%-21s %p::print struct mdi_pathinfo\n",
29711334SReed.Liu@Sun.COM 	    (*idx)++, pi_addr, addr);
29811334SReed.Liu@Sun.COM 	return (DCMD_OK);
29911334SReed.Liu@Sun.COM }
30011334SReed.Liu@Sun.COM 
30111334SReed.Liu@Sun.COM static int
display_iport_dtc(dev_info_t * pdip)30211334SReed.Liu@Sun.COM display_iport_dtc(dev_info_t *pdip)
30311334SReed.Liu@Sun.COM {
30411334SReed.Liu@Sun.COM 	int rval = DCMD_ERR;
30511334SReed.Liu@Sun.COM 	struct dev_info dip;
30611334SReed.Liu@Sun.COM 	struct mdi_phci phci;
30711334SReed.Liu@Sun.COM 	uint_t didx = 1;
30811334SReed.Liu@Sun.COM 	uint_t pidx = 1;
30911334SReed.Liu@Sun.COM 
31011334SReed.Liu@Sun.COM 	if (mdb_vread(&dip, sizeof (struct dev_info), (uintptr_t)pdip) !=
31111334SReed.Liu@Sun.COM 	    sizeof (struct dev_info)) {
31211334SReed.Liu@Sun.COM 		return (rval);
31311334SReed.Liu@Sun.COM 	}
31411334SReed.Liu@Sun.COM 
31511334SReed.Liu@Sun.COM 	mdb_printf("Device tree children - dev_info:\n");
31611334SReed.Liu@Sun.COM 	if (dip.devi_child == NULL) {
31711334SReed.Liu@Sun.COM 		mdb_printf("\tdevi_child is NULL, no dev_info\n\n");
31811334SReed.Liu@Sun.COM 		goto skip_di;
31911334SReed.Liu@Sun.COM 	}
32011334SReed.Liu@Sun.COM 
32111334SReed.Liu@Sun.COM 	/*
32211334SReed.Liu@Sun.COM 	 * First, we dump the iport's children dev_info node information.
32311334SReed.Liu@Sun.COM 	 * use existing walker: devinfo_siblings
32411334SReed.Liu@Sun.COM 	 */
32511334SReed.Liu@Sun.COM 	mdb_printf("\t#: @unit-address               name@\tdrill-down\n");
32611334SReed.Liu@Sun.COM 	rval = mdb_pwalk("devinfo_siblings", display_iport_di_cb,
32711334SReed.Liu@Sun.COM 	    (void *)&didx, (uintptr_t)dip.devi_child);
32811334SReed.Liu@Sun.COM 	mdb_printf("\n");
32911334SReed.Liu@Sun.COM 
33011334SReed.Liu@Sun.COM skip_di:
33111334SReed.Liu@Sun.COM 	/*
33211334SReed.Liu@Sun.COM 	 * Then we try to dump the iport's path_info node information.
33311334SReed.Liu@Sun.COM 	 * use existing walker: mdipi_phci_list
33411334SReed.Liu@Sun.COM 	 */
33511334SReed.Liu@Sun.COM 	mdb_printf("Device tree children - path_info:\n");
33611334SReed.Liu@Sun.COM 	if (mdb_vread(&phci, sizeof (struct mdi_phci),
33711334SReed.Liu@Sun.COM 	    (uintptr_t)dip.devi_mdi_xhci) != sizeof (struct mdi_phci)) {
33811334SReed.Liu@Sun.COM 		mdb_printf("\tdevi_mdi_xhci is NULL, no path_info\n\n");
33911334SReed.Liu@Sun.COM 		return (rval);
34011334SReed.Liu@Sun.COM 	}
34111334SReed.Liu@Sun.COM 
34211334SReed.Liu@Sun.COM 	if (phci.ph_path_head == NULL) {
34311334SReed.Liu@Sun.COM 		mdb_printf("\tph_path_head is NULL, no path_info\n\n");
34411334SReed.Liu@Sun.COM 		return (rval);
34511334SReed.Liu@Sun.COM 	}
34611334SReed.Liu@Sun.COM 
34711334SReed.Liu@Sun.COM 	mdb_printf("\t#: @unit-address          drill-down\n");
34811334SReed.Liu@Sun.COM 	rval = mdb_pwalk("mdipi_phci_list", display_iport_pi_cb,
34911334SReed.Liu@Sun.COM 	    (void *)&pidx, (uintptr_t)phci.ph_path_head);
35011334SReed.Liu@Sun.COM 	mdb_printf("\n");
35111334SReed.Liu@Sun.COM 	return (rval);
35211334SReed.Liu@Sun.COM }
35311334SReed.Liu@Sun.COM 
35411334SReed.Liu@Sun.COM static void
display_iport_more(dev_info_t * dip,per_iport_setting_t * pis)35511334SReed.Liu@Sun.COM display_iport_more(dev_info_t *dip, per_iport_setting_t *pis)
35611334SReed.Liu@Sun.COM {
35711334SReed.Liu@Sun.COM 	if (pis->pis_damap_info) {
35811334SReed.Liu@Sun.COM 		(void) display_iport_damap(dip);
35911334SReed.Liu@Sun.COM 	}
36011334SReed.Liu@Sun.COM 
36111334SReed.Liu@Sun.COM 	if (pis->pis_dtc_info) {
36211334SReed.Liu@Sun.COM 		(void) display_iport_dtc(dip);
36311334SReed.Liu@Sun.COM 	}
36411334SReed.Liu@Sun.COM }
36511334SReed.Liu@Sun.COM 
36610696SDavid.Hollister@Sun.COM /*ARGSUSED*/
36710696SDavid.Hollister@Sun.COM static int
pmcs_iport_walk_cb(uintptr_t addr,const void * wdata,void * priv)36810696SDavid.Hollister@Sun.COM pmcs_iport_walk_cb(uintptr_t addr, const void *wdata, void *priv)
36910696SDavid.Hollister@Sun.COM {
37010696SDavid.Hollister@Sun.COM 	struct pmcs_iport	iport;
37110696SDavid.Hollister@Sun.COM 	uintptr_t		list_addr;
37210696SDavid.Hollister@Sun.COM 	char			*ua_state;
37310696SDavid.Hollister@Sun.COM 	char			portid[4];
37410696SDavid.Hollister@Sun.COM 	char			unit_address[34];
37511334SReed.Liu@Sun.COM 	per_iport_setting_t	*pis = (per_iport_setting_t *)priv;
37610696SDavid.Hollister@Sun.COM 
37710696SDavid.Hollister@Sun.COM 	if (mdb_vread(&iport, sizeof (struct pmcs_iport), addr) !=
37810696SDavid.Hollister@Sun.COM 	    sizeof (struct pmcs_iport)) {
37910696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
38010696SDavid.Hollister@Sun.COM 	}
38110696SDavid.Hollister@Sun.COM 
38210696SDavid.Hollister@Sun.COM 	if (mdb_readstr(unit_address, sizeof (unit_address),
38310696SDavid.Hollister@Sun.COM 	    (uintptr_t)(iport.ua)) == -1) {
38410696SDavid.Hollister@Sun.COM 		strncpy(unit_address, "Unset", sizeof (unit_address));
38510696SDavid.Hollister@Sun.COM 	}
38610696SDavid.Hollister@Sun.COM 
38710696SDavid.Hollister@Sun.COM 	if (iport.portid == 0xffff) {
38810696SDavid.Hollister@Sun.COM 		mdb_snprintf(portid, sizeof (portid), "%s", "-");
38911347SRamana.Srikanth@Sun.COM 	} else if (iport.portid == PMCS_IPORT_INVALID_PORT_ID) {
39011347SRamana.Srikanth@Sun.COM 		mdb_snprintf(portid, sizeof (portid), "%s", "N/A");
39110696SDavid.Hollister@Sun.COM 	} else {
39210696SDavid.Hollister@Sun.COM 		mdb_snprintf(portid, sizeof (portid), "%d", iport.portid);
39310696SDavid.Hollister@Sun.COM 	}
39410696SDavid.Hollister@Sun.COM 
39510696SDavid.Hollister@Sun.COM 	switch (iport.ua_state) {
39610696SDavid.Hollister@Sun.COM 	case UA_INACTIVE:
39710696SDavid.Hollister@Sun.COM 		ua_state = "Inactive";
39810696SDavid.Hollister@Sun.COM 		break;
39910696SDavid.Hollister@Sun.COM 	case UA_PEND_ACTIVATE:
40010696SDavid.Hollister@Sun.COM 		ua_state = "PendActivate";
40110696SDavid.Hollister@Sun.COM 		break;
40210696SDavid.Hollister@Sun.COM 	case UA_ACTIVE:
40310696SDavid.Hollister@Sun.COM 		ua_state = "Active";
40410696SDavid.Hollister@Sun.COM 		break;
40510696SDavid.Hollister@Sun.COM 	case UA_PEND_DEACTIVATE:
40610696SDavid.Hollister@Sun.COM 		ua_state = "PendDeactivate";
40710696SDavid.Hollister@Sun.COM 		break;
40810696SDavid.Hollister@Sun.COM 	default:
40910696SDavid.Hollister@Sun.COM 		ua_state = "Unknown";
41010696SDavid.Hollister@Sun.COM 	}
41110696SDavid.Hollister@Sun.COM 
41210696SDavid.Hollister@Sun.COM 	if (strlen(unit_address) < 3) {
41310696SDavid.Hollister@Sun.COM 		/* Standard iport unit address */
41410696SDavid.Hollister@Sun.COM 		mdb_printf("UA %-16s %16s %8s %8s %16s", "Iport", "UA State",
41510696SDavid.Hollister@Sun.COM 		    "PortID", "NumPhys", "DIP\n");
41610696SDavid.Hollister@Sun.COM 		mdb_printf("%2s %16p %16s %8s %8d %16p\n", unit_address, addr,
41710696SDavid.Hollister@Sun.COM 		    ua_state, portid, iport.nphy, iport.dip);
41810696SDavid.Hollister@Sun.COM 	} else {
41910696SDavid.Hollister@Sun.COM 		/* Temporary iport unit address */
42010696SDavid.Hollister@Sun.COM 		mdb_printf("%-32s %16s %20s %8s %8s %16s", "UA", "Iport",
42110696SDavid.Hollister@Sun.COM 		    "UA State", "PortID", "NumPhys", "DIP\n");
42210696SDavid.Hollister@Sun.COM 		mdb_printf("%32s %16p %20s %8s %8d %16p\n", unit_address, addr,
42310696SDavid.Hollister@Sun.COM 		    ua_state, portid, iport.nphy, iport.dip);
42410696SDavid.Hollister@Sun.COM 	}
42510696SDavid.Hollister@Sun.COM 
42610696SDavid.Hollister@Sun.COM 	if (iport.nphy > 0) {
42710696SDavid.Hollister@Sun.COM 		mdb_inc_indent(4);
42810696SDavid.Hollister@Sun.COM 		mdb_printf("%-18s %8s", "Phy", "PhyNum\n");
42910696SDavid.Hollister@Sun.COM 		mdb_inc_indent(2);
43010696SDavid.Hollister@Sun.COM 		list_addr =
43110696SDavid.Hollister@Sun.COM 		    (uintptr_t)(addr + offsetof(struct pmcs_iport, phys));
43210696SDavid.Hollister@Sun.COM 		if (mdb_pwalk("list", pmcs_iport_phy_walk_cb, NULL,
43310696SDavid.Hollister@Sun.COM 		    list_addr) == -1) {
43410696SDavid.Hollister@Sun.COM 			mdb_warn("pmcs iport walk failed");
43510696SDavid.Hollister@Sun.COM 		}
43610696SDavid.Hollister@Sun.COM 		mdb_dec_indent(6);
43710696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
43810696SDavid.Hollister@Sun.COM 	}
43910696SDavid.Hollister@Sun.COM 
44011334SReed.Liu@Sun.COM 	/*
44111334SReed.Liu@Sun.COM 	 * See if we need to show more information based on 'd' or 'm' options
44211334SReed.Liu@Sun.COM 	 */
44311334SReed.Liu@Sun.COM 	display_iport_more(iport.dip, pis);
44411334SReed.Liu@Sun.COM 
44510696SDavid.Hollister@Sun.COM 	return (0);
44610696SDavid.Hollister@Sun.COM }
44710696SDavid.Hollister@Sun.COM 
44810696SDavid.Hollister@Sun.COM /*ARGSUSED*/
44910696SDavid.Hollister@Sun.COM static void
display_iport(struct pmcs_hw m,uintptr_t addr,int verbose,per_iport_setting_t * pis)45011334SReed.Liu@Sun.COM display_iport(struct pmcs_hw m, uintptr_t addr, int verbose,
45111334SReed.Liu@Sun.COM     per_iport_setting_t *pis)
45210696SDavid.Hollister@Sun.COM {
45310696SDavid.Hollister@Sun.COM 	uintptr_t	list_addr;
45410696SDavid.Hollister@Sun.COM 
45510696SDavid.Hollister@Sun.COM 	if (m.iports_attached) {
45610696SDavid.Hollister@Sun.COM 		mdb_printf("Iport information:\n");
45710696SDavid.Hollister@Sun.COM 		mdb_printf("-----------------\n");
45810696SDavid.Hollister@Sun.COM 	} else {
45910696SDavid.Hollister@Sun.COM 		mdb_printf("No Iports found.\n\n");
46010696SDavid.Hollister@Sun.COM 		return;
46110696SDavid.Hollister@Sun.COM 	}
46210696SDavid.Hollister@Sun.COM 
46310696SDavid.Hollister@Sun.COM 	list_addr = (uintptr_t)(addr + offsetof(struct pmcs_hw, iports));
46410696SDavid.Hollister@Sun.COM 
46511334SReed.Liu@Sun.COM 	if (mdb_pwalk("list", pmcs_iport_walk_cb, pis, list_addr) == -1) {
46610696SDavid.Hollister@Sun.COM 		mdb_warn("pmcs iport walk failed");
46710696SDavid.Hollister@Sun.COM 	}
46810696SDavid.Hollister@Sun.COM 
46910696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
47010696SDavid.Hollister@Sun.COM }
47110696SDavid.Hollister@Sun.COM 
47211048SDavid.Hollister@Sun.COM /* ARGSUSED */
47311048SDavid.Hollister@Sun.COM static int
pmcs_utarget_walk_cb(uintptr_t addr,const void * wdata,void * priv)47411048SDavid.Hollister@Sun.COM pmcs_utarget_walk_cb(uintptr_t addr, const void *wdata, void *priv)
47511048SDavid.Hollister@Sun.COM {
47611048SDavid.Hollister@Sun.COM 	pmcs_phy_t phy;
47711048SDavid.Hollister@Sun.COM 
47811048SDavid.Hollister@Sun.COM 	if (mdb_vread(&phy, sizeof (pmcs_phy_t), (uintptr_t)addr) == -1) {
47911048SDavid.Hollister@Sun.COM 		mdb_warn("pmcs_utarget_walk_cb: Failed to read PHY at %p",
48011048SDavid.Hollister@Sun.COM 		    (void *)addr);
48111048SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
48211048SDavid.Hollister@Sun.COM 	}
48311048SDavid.Hollister@Sun.COM 
48411048SDavid.Hollister@Sun.COM 	if (phy.configured && (phy.target == NULL)) {
48511048SDavid.Hollister@Sun.COM 		mdb_printf("SAS address: ");
48611048SDavid.Hollister@Sun.COM 		print_sas_address(&phy);
48711048SDavid.Hollister@Sun.COM 		mdb_printf("  DType: ");
48811048SDavid.Hollister@Sun.COM 		switch (phy.dtype) {
48911048SDavid.Hollister@Sun.COM 		case SAS:
49011048SDavid.Hollister@Sun.COM 			mdb_printf("%4s", "SAS");
49111048SDavid.Hollister@Sun.COM 			break;
49211048SDavid.Hollister@Sun.COM 		case SATA:
49311048SDavid.Hollister@Sun.COM 			mdb_printf("%4s", "SATA");
49411048SDavid.Hollister@Sun.COM 			break;
49511048SDavid.Hollister@Sun.COM 		case EXPANDER:
49611048SDavid.Hollister@Sun.COM 			mdb_printf("%4s", "SMP");
49711048SDavid.Hollister@Sun.COM 			break;
49811048SDavid.Hollister@Sun.COM 		default:
49911048SDavid.Hollister@Sun.COM 			mdb_printf("%4s", "N/A");
50011048SDavid.Hollister@Sun.COM 			break;
50111048SDavid.Hollister@Sun.COM 		}
50211048SDavid.Hollister@Sun.COM 		mdb_printf("  Path: %s\n", phy.path);
50311048SDavid.Hollister@Sun.COM 	}
50411048SDavid.Hollister@Sun.COM 
50511048SDavid.Hollister@Sun.COM 	return (0);
50611048SDavid.Hollister@Sun.COM }
50711048SDavid.Hollister@Sun.COM 
50811048SDavid.Hollister@Sun.COM static void
display_unconfigured_targets(uintptr_t addr)50911048SDavid.Hollister@Sun.COM display_unconfigured_targets(uintptr_t addr)
51011048SDavid.Hollister@Sun.COM {
51111048SDavid.Hollister@Sun.COM 	mdb_printf("Unconfigured target SAS address:\n\n");
51211048SDavid.Hollister@Sun.COM 
51311048SDavid.Hollister@Sun.COM 	if (mdb_pwalk("pmcs_phys", pmcs_utarget_walk_cb, NULL, addr) == -1) {
51411048SDavid.Hollister@Sun.COM 		mdb_warn("pmcs phys walk failed");
51511048SDavid.Hollister@Sun.COM 	}
51611048SDavid.Hollister@Sun.COM }
51711048SDavid.Hollister@Sun.COM 
51810743SDavid.Hollister@Sun.COM static void
display_completion_queue(struct pmcs_hw ss)51910743SDavid.Hollister@Sun.COM display_completion_queue(struct pmcs_hw ss)
52010743SDavid.Hollister@Sun.COM {
52110743SDavid.Hollister@Sun.COM 	pmcs_iocomp_cb_t ccb, *ccbp;
52210743SDavid.Hollister@Sun.COM 	pmcwork_t work;
52310743SDavid.Hollister@Sun.COM 
52410743SDavid.Hollister@Sun.COM 	if (ss.iocomp_cb_head == NULL) {
52510743SDavid.Hollister@Sun.COM 		mdb_printf("Completion queue is empty.\n");
52610743SDavid.Hollister@Sun.COM 		return;
52710743SDavid.Hollister@Sun.COM 	}
52810743SDavid.Hollister@Sun.COM 
52910743SDavid.Hollister@Sun.COM 	ccbp = ss.iocomp_cb_head;
53010743SDavid.Hollister@Sun.COM 	mdb_printf("%8s %10s %20s %8s %8s O D\n",
53110743SDavid.Hollister@Sun.COM 	    "HTag", "State", "Phy Path", "Target", "Timer");
53210743SDavid.Hollister@Sun.COM 
53310743SDavid.Hollister@Sun.COM 	while (ccbp) {
53410743SDavid.Hollister@Sun.COM 		if (mdb_vread(&ccb, sizeof (pmcs_iocomp_cb_t),
53510743SDavid.Hollister@Sun.COM 		    (uintptr_t)ccbp) != sizeof (pmcs_iocomp_cb_t)) {
53610743SDavid.Hollister@Sun.COM 			mdb_warn("Unable to read completion queue entry\n");
53710743SDavid.Hollister@Sun.COM 			return;
53810743SDavid.Hollister@Sun.COM 		}
53910743SDavid.Hollister@Sun.COM 
54010743SDavid.Hollister@Sun.COM 		if (mdb_vread(&work, sizeof (pmcwork_t), (uintptr_t)ccb.pwrk)
54110743SDavid.Hollister@Sun.COM 		    != sizeof (pmcwork_t)) {
54210743SDavid.Hollister@Sun.COM 			mdb_warn("Unable to read work structure\n");
54310743SDavid.Hollister@Sun.COM 			return;
54410743SDavid.Hollister@Sun.COM 		}
54510743SDavid.Hollister@Sun.COM 
54610743SDavid.Hollister@Sun.COM 		/*
54710743SDavid.Hollister@Sun.COM 		 * Only print the work structure if it's still active.  If
54810743SDavid.Hollister@Sun.COM 		 * it's not, it's been completed since we started looking at
54910743SDavid.Hollister@Sun.COM 		 * it.
55010743SDavid.Hollister@Sun.COM 		 */
55110743SDavid.Hollister@Sun.COM 		if (work.state != PMCS_WORK_STATE_NIL) {
55210743SDavid.Hollister@Sun.COM 			display_one_work(&work, 0, 0);
55310743SDavid.Hollister@Sun.COM 		}
55410743SDavid.Hollister@Sun.COM 		ccbp = ccb.next;
55510743SDavid.Hollister@Sun.COM 	}
55610743SDavid.Hollister@Sun.COM }
55710743SDavid.Hollister@Sun.COM 
55812120SDavid.Hollister@Sun.COM static void
display_event_log(struct pmcs_hw ss)55912120SDavid.Hollister@Sun.COM display_event_log(struct pmcs_hw ss)
56012120SDavid.Hollister@Sun.COM {
56112120SDavid.Hollister@Sun.COM 	pmcs_fw_event_hdr_t fwhdr;
56212120SDavid.Hollister@Sun.COM 	char *header_id, *entry, *fwlogp;
56312120SDavid.Hollister@Sun.COM 	uint32_t total_size = PMCS_FWLOG_SIZE, log_size, index, *swapp, sidx;
56412120SDavid.Hollister@Sun.COM 	pmcs_fw_event_entry_t *fw_entryp;
56512120SDavid.Hollister@Sun.COM 	struct timespec systime;
56612120SDavid.Hollister@Sun.COM 
56712120SDavid.Hollister@Sun.COM 	if (ss.fwlogp == NULL) {
56812120SDavid.Hollister@Sun.COM 		mdb_printf("There is no firmware event log.\n");
56912120SDavid.Hollister@Sun.COM 		return;
57012120SDavid.Hollister@Sun.COM 	}
57112120SDavid.Hollister@Sun.COM 
57212120SDavid.Hollister@Sun.COM 	fwlogp = (char *)ss.fwlogp;
57312120SDavid.Hollister@Sun.COM 
57412120SDavid.Hollister@Sun.COM 	while (total_size != 0) {
57512120SDavid.Hollister@Sun.COM 		if (mdb_vread(&fwhdr, sizeof (pmcs_fw_event_hdr_t),
57612120SDavid.Hollister@Sun.COM 		    (uintptr_t)fwlogp) != sizeof (pmcs_fw_event_hdr_t)) {
57712120SDavid.Hollister@Sun.COM 			mdb_warn("Unable to read firmware event log header\n");
57812120SDavid.Hollister@Sun.COM 			return;
57912120SDavid.Hollister@Sun.COM 		}
58012120SDavid.Hollister@Sun.COM 
58112120SDavid.Hollister@Sun.COM 		/*
58212120SDavid.Hollister@Sun.COM 		 * Firmware event log is little-endian
58312120SDavid.Hollister@Sun.COM 		 */
58412120SDavid.Hollister@Sun.COM 		swapp = (uint32_t *)&fwhdr;
58512120SDavid.Hollister@Sun.COM 		for (sidx = 0; sidx < (sizeof (pmcs_fw_event_hdr_t) /
58612120SDavid.Hollister@Sun.COM 		    sizeof (uint32_t)); sidx++) {
58712120SDavid.Hollister@Sun.COM 			*swapp = LE_32(*swapp);
58812120SDavid.Hollister@Sun.COM 			swapp++;
58912120SDavid.Hollister@Sun.COM 		}
59012120SDavid.Hollister@Sun.COM 
59112120SDavid.Hollister@Sun.COM 		if (fwhdr.fw_el_signature == PMCS_FWLOG_AAP1_SIG) {
59212120SDavid.Hollister@Sun.COM 			header_id = "AAP1";
59312120SDavid.Hollister@Sun.COM 		} else if (fwhdr.fw_el_signature == PMCS_FWLOG_IOP_SIG) {
59412120SDavid.Hollister@Sun.COM 			header_id = "IOP";
59512120SDavid.Hollister@Sun.COM 		} else {
59612120SDavid.Hollister@Sun.COM 			mdb_warn("Invalid firmware event log signature\n");
59712120SDavid.Hollister@Sun.COM 			return;
59812120SDavid.Hollister@Sun.COM 		}
59912120SDavid.Hollister@Sun.COM 
60012120SDavid.Hollister@Sun.COM 		mdb_printf("Event Log:    %s\n", header_id);
60112120SDavid.Hollister@Sun.COM 		mdb_printf("Oldest entry: %d\n", fwhdr.fw_el_oldest_idx);
60212120SDavid.Hollister@Sun.COM 		mdb_printf("Latest entry: %d\n", fwhdr.fw_el_latest_idx);
60312120SDavid.Hollister@Sun.COM 
60412120SDavid.Hollister@Sun.COM 		entry = mdb_alloc(fwhdr.fw_el_entry_size, UM_SLEEP);
60512120SDavid.Hollister@Sun.COM 		fw_entryp = (pmcs_fw_event_entry_t *)((void *)entry);
60612120SDavid.Hollister@Sun.COM 		total_size -= sizeof (pmcs_fw_event_hdr_t);
60712120SDavid.Hollister@Sun.COM 		log_size = fwhdr.fw_el_buf_size;
60812120SDavid.Hollister@Sun.COM 		fwlogp += fwhdr.fw_el_entry_start_offset;
60912120SDavid.Hollister@Sun.COM 		swapp = (uint32_t *)((void *)entry);
61012120SDavid.Hollister@Sun.COM 		index = 0;
61112120SDavid.Hollister@Sun.COM 
61212120SDavid.Hollister@Sun.COM 		mdb_printf("%8s %16s %32s %8s %3s %8s %8s %8s %8s",
61312120SDavid.Hollister@Sun.COM 		    "Index", "Timestamp", "Time", "Seq Num", "Sev", "Word 0",
61412120SDavid.Hollister@Sun.COM 		    "Word 1", "Word 2", "Word 3");
61512120SDavid.Hollister@Sun.COM 		mdb_printf("\n");
61612120SDavid.Hollister@Sun.COM 
61712120SDavid.Hollister@Sun.COM 		while (log_size != 0) {
61812120SDavid.Hollister@Sun.COM 			if (mdb_vread(entry, fwhdr.fw_el_entry_size,
61912120SDavid.Hollister@Sun.COM 			    (uintptr_t)fwlogp) != fwhdr.fw_el_entry_size) {
62012120SDavid.Hollister@Sun.COM 				mdb_warn("Unable to read event log entry\n");
62112120SDavid.Hollister@Sun.COM 				goto bail_out;
62212120SDavid.Hollister@Sun.COM 			}
62312120SDavid.Hollister@Sun.COM 
62412120SDavid.Hollister@Sun.COM 			for (sidx = 0; sidx < (fwhdr.fw_el_entry_size /
62512120SDavid.Hollister@Sun.COM 			    sizeof (uint32_t)); sidx++) {
62612120SDavid.Hollister@Sun.COM 				*(swapp + sidx) = LE_32(*(swapp + sidx));
62712120SDavid.Hollister@Sun.COM 			}
62812120SDavid.Hollister@Sun.COM 
62912120SDavid.Hollister@Sun.COM 			if (fw_entryp->ts_upper || fw_entryp->ts_lower) {
63012120SDavid.Hollister@Sun.COM 				pmcs_fwtime_to_systime(ss, fw_entryp->ts_upper,
63112120SDavid.Hollister@Sun.COM 				    fw_entryp->ts_lower, &systime);
63212120SDavid.Hollister@Sun.COM 				mdb_printf("%8d %08x%08x [%Y.%09ld] %8d %3d "
63312120SDavid.Hollister@Sun.COM 				    "%08x %08x %08x %08x\n", index,
63412120SDavid.Hollister@Sun.COM 				    fw_entryp->ts_upper, fw_entryp->ts_lower,
63512120SDavid.Hollister@Sun.COM 				    systime, fw_entryp->seq_num,
63612120SDavid.Hollister@Sun.COM 				    fw_entryp->severity, fw_entryp->logw0,
63712120SDavid.Hollister@Sun.COM 				    fw_entryp->logw1, fw_entryp->logw2,
63812120SDavid.Hollister@Sun.COM 				    fw_entryp->logw3);
63912120SDavid.Hollister@Sun.COM 			}
64012120SDavid.Hollister@Sun.COM 
64112120SDavid.Hollister@Sun.COM 			fwlogp += fwhdr.fw_el_entry_size;
64212120SDavid.Hollister@Sun.COM 			total_size -= fwhdr.fw_el_entry_size;
64312120SDavid.Hollister@Sun.COM 			log_size -= fwhdr.fw_el_entry_size;
64412120SDavid.Hollister@Sun.COM 			index++;
64512120SDavid.Hollister@Sun.COM 		}
64612120SDavid.Hollister@Sun.COM 
64712120SDavid.Hollister@Sun.COM 		mdb_printf("\n");
64812120SDavid.Hollister@Sun.COM 	}
64912120SDavid.Hollister@Sun.COM 
65012120SDavid.Hollister@Sun.COM bail_out:
65112120SDavid.Hollister@Sun.COM 	mdb_free(entry, fwhdr.fw_el_entry_size);
65212120SDavid.Hollister@Sun.COM }
65312120SDavid.Hollister@Sun.COM 
65410696SDavid.Hollister@Sun.COM /*ARGSUSED*/
65510696SDavid.Hollister@Sun.COM static void
display_hwinfo(struct pmcs_hw m,int verbose)65610696SDavid.Hollister@Sun.COM display_hwinfo(struct pmcs_hw m, int verbose)
65710696SDavid.Hollister@Sun.COM {
65810696SDavid.Hollister@Sun.COM 	struct pmcs_hw	*mp = &m;
65910696SDavid.Hollister@Sun.COM 	char		*fwsupport;
66010696SDavid.Hollister@Sun.COM 
66110696SDavid.Hollister@Sun.COM 	switch (PMCS_FW_TYPE(mp)) {
66210696SDavid.Hollister@Sun.COM 	case PMCS_FW_TYPE_RELEASED:
66310696SDavid.Hollister@Sun.COM 		fwsupport = "Released";
66410696SDavid.Hollister@Sun.COM 		break;
66510696SDavid.Hollister@Sun.COM 	case PMCS_FW_TYPE_DEVELOPMENT:
66610696SDavid.Hollister@Sun.COM 		fwsupport = "Development";
66710696SDavid.Hollister@Sun.COM 		break;
66810696SDavid.Hollister@Sun.COM 	case PMCS_FW_TYPE_ALPHA:
66910696SDavid.Hollister@Sun.COM 		fwsupport = "Alpha";
67010696SDavid.Hollister@Sun.COM 		break;
67110696SDavid.Hollister@Sun.COM 	case PMCS_FW_TYPE_BETA:
67210696SDavid.Hollister@Sun.COM 		fwsupport = "Beta";
67310696SDavid.Hollister@Sun.COM 		break;
67410696SDavid.Hollister@Sun.COM 	default:
67510696SDavid.Hollister@Sun.COM 		fwsupport = "Special";
67610696SDavid.Hollister@Sun.COM 		break;
67710696SDavid.Hollister@Sun.COM 	}
67810696SDavid.Hollister@Sun.COM 
67910696SDavid.Hollister@Sun.COM 	mdb_printf("\nHardware information:\n");
68010696SDavid.Hollister@Sun.COM 	mdb_printf("---------------------\n");
68110696SDavid.Hollister@Sun.COM 
68210696SDavid.Hollister@Sun.COM 	mdb_printf("Chip revision:    %c\n", 'A' + m.chiprev);
68310696SDavid.Hollister@Sun.COM 	mdb_printf("SAS WWID:         %"PRIx64"\n", m.sas_wwns[0]);
68410696SDavid.Hollister@Sun.COM 	mdb_printf("Firmware version: %x.%x.%x (%s)\n",
68510696SDavid.Hollister@Sun.COM 	    PMCS_FW_MAJOR(mp), PMCS_FW_MINOR(mp), PMCS_FW_MICRO(mp),
68610696SDavid.Hollister@Sun.COM 	    fwsupport);
68711980SDavid.Hollister@Sun.COM 	mdb_printf("ILA version:      %08x\n", m.ila_ver);
68811980SDavid.Hollister@Sun.COM 	mdb_printf("Active f/w img:   %c\n", (m.fw_active_img) ? 'A' : 'B');
68910696SDavid.Hollister@Sun.COM 
69010696SDavid.Hollister@Sun.COM 	mdb_printf("Number of PHYs:   %d\n", m.nphy);
69110696SDavid.Hollister@Sun.COM 	mdb_printf("Maximum commands: %d\n", m.max_cmd);
69210696SDavid.Hollister@Sun.COM 	mdb_printf("Maximum devices:  %d\n", m.max_dev);
69310696SDavid.Hollister@Sun.COM 	mdb_printf("I/O queue depth:  %d\n", m.ioq_depth);
69412060SDavid.Hollister@Sun.COM 	mdb_printf("Open retry intvl: %d usecs\n", m.open_retry_interval);
69510696SDavid.Hollister@Sun.COM 	if (m.fwlog == 0) {
69610696SDavid.Hollister@Sun.COM 		mdb_printf("Firmware logging: Disabled\n");
69710696SDavid.Hollister@Sun.COM 	} else {
69810696SDavid.Hollister@Sun.COM 		mdb_printf("Firmware logging: Enabled (%d)\n", m.fwlog);
69910696SDavid.Hollister@Sun.COM 	}
70011980SDavid.Hollister@Sun.COM 	if (m.fwlog_file == 0) {
70111980SDavid.Hollister@Sun.COM 		mdb_printf("Firmware logfile: Not configured\n");
70211980SDavid.Hollister@Sun.COM 	} else {
70311980SDavid.Hollister@Sun.COM 		mdb_printf("Firmware logfile: Configured\n");
70411980SDavid.Hollister@Sun.COM 		mdb_inc_indent(2);
70511980SDavid.Hollister@Sun.COM 		mdb_printf("AAP1 log file:  %s\n", m.fwlogfile_aap1);
70611980SDavid.Hollister@Sun.COM 		mdb_printf("IOP logfile:    %s\n", m.fwlogfile_iop);
70711980SDavid.Hollister@Sun.COM 		mdb_dec_indent(2);
70811980SDavid.Hollister@Sun.COM 	}
70910696SDavid.Hollister@Sun.COM }
71010696SDavid.Hollister@Sun.COM 
71110696SDavid.Hollister@Sun.COM static void
display_targets(struct pmcs_hw m,int verbose,int totals_only)71210696SDavid.Hollister@Sun.COM display_targets(struct pmcs_hw m, int verbose, int totals_only)
71310696SDavid.Hollister@Sun.COM {
71410696SDavid.Hollister@Sun.COM 	char		*dtype;
71510696SDavid.Hollister@Sun.COM 	pmcs_xscsi_t	xs;
71610696SDavid.Hollister@Sun.COM 	pmcs_phy_t	phy;
71710696SDavid.Hollister@Sun.COM 	uint16_t	max_dev, idx;
71810696SDavid.Hollister@Sun.COM 	uint32_t	sas_targets = 0, smp_targets = 0, sata_targets = 0;
71910696SDavid.Hollister@Sun.COM 
72010696SDavid.Hollister@Sun.COM 	max_dev = m.max_dev;
72110696SDavid.Hollister@Sun.COM 
72210696SDavid.Hollister@Sun.COM 	if (targets == NULL) {
72310696SDavid.Hollister@Sun.COM 		targets = mdb_alloc(sizeof (targets) * max_dev, UM_SLEEP);
72410696SDavid.Hollister@Sun.COM 	}
72510696SDavid.Hollister@Sun.COM 
72610696SDavid.Hollister@Sun.COM 	if (MDB_RD(targets, sizeof (targets) * max_dev, m.targets) == -1) {
72710696SDavid.Hollister@Sun.COM 		NOREAD(targets, m.targets);
72810696SDavid.Hollister@Sun.COM 		return;
72910696SDavid.Hollister@Sun.COM 	}
73010696SDavid.Hollister@Sun.COM 
73110696SDavid.Hollister@Sun.COM 	if (!totals_only) {
73210696SDavid.Hollister@Sun.COM 		mdb_printf("\nTarget information:\n");
73310696SDavid.Hollister@Sun.COM 		mdb_printf("---------------------------------------\n");
73411347SRamana.Srikanth@Sun.COM 		mdb_printf("VTGT %-16s %-16s %-5s %4s %6s %s", "SAS Address",
73511347SRamana.Srikanth@Sun.COM 		    "PHY Address", "DType", "Actv", "OnChip", "DS");
73610696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
73710696SDavid.Hollister@Sun.COM 	}
73810696SDavid.Hollister@Sun.COM 
73910696SDavid.Hollister@Sun.COM 	for (idx = 0; idx < max_dev; idx++) {
74010696SDavid.Hollister@Sun.COM 		if (targets[idx] == NULL) {
74110696SDavid.Hollister@Sun.COM 			continue;
74210696SDavid.Hollister@Sun.COM 		}
74310696SDavid.Hollister@Sun.COM 
74410696SDavid.Hollister@Sun.COM 		if (MDB_RD(&xs, sizeof (xs), targets[idx]) == -1) {
74510696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_xscsi_t, targets[idx]);
74610696SDavid.Hollister@Sun.COM 			continue;
74710696SDavid.Hollister@Sun.COM 		}
74810696SDavid.Hollister@Sun.COM 
74910696SDavid.Hollister@Sun.COM 		/*
75010755SJesse.Butler@Sun.COM 		 * It has to be new or assigned to be of interest.
75110696SDavid.Hollister@Sun.COM 		 */
75210755SJesse.Butler@Sun.COM 		if (xs.new == 0 && xs.assigned == 0) {
75310696SDavid.Hollister@Sun.COM 			continue;
75410696SDavid.Hollister@Sun.COM 		}
75510696SDavid.Hollister@Sun.COM 
75610696SDavid.Hollister@Sun.COM 		switch (xs.dtype) {
75710696SDavid.Hollister@Sun.COM 		case NOTHING:
75810696SDavid.Hollister@Sun.COM 			dtype = "None";
75910696SDavid.Hollister@Sun.COM 			break;
76010696SDavid.Hollister@Sun.COM 		case SATA:
76110696SDavid.Hollister@Sun.COM 			dtype = "SATA";
76210696SDavid.Hollister@Sun.COM 			sata_targets++;
76310696SDavid.Hollister@Sun.COM 			break;
76410696SDavid.Hollister@Sun.COM 		case SAS:
76510696SDavid.Hollister@Sun.COM 			dtype = "SAS";
76610696SDavid.Hollister@Sun.COM 			sas_targets++;
76710696SDavid.Hollister@Sun.COM 			break;
76810696SDavid.Hollister@Sun.COM 		case EXPANDER:
76910696SDavid.Hollister@Sun.COM 			dtype = "SMP";
77010696SDavid.Hollister@Sun.COM 			smp_targets++;
77110696SDavid.Hollister@Sun.COM 			break;
77210696SDavid.Hollister@Sun.COM 		}
77310696SDavid.Hollister@Sun.COM 
77410696SDavid.Hollister@Sun.COM 		if (totals_only) {
77510696SDavid.Hollister@Sun.COM 			continue;
77610696SDavid.Hollister@Sun.COM 		}
77710696SDavid.Hollister@Sun.COM 
77810696SDavid.Hollister@Sun.COM 		if (xs.phy) {
77910696SDavid.Hollister@Sun.COM 			if (MDB_RD(&phy, sizeof (phy), xs.phy) == -1) {
78010696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_phy_t, xs.phy);
78110696SDavid.Hollister@Sun.COM 				continue;
78210696SDavid.Hollister@Sun.COM 			}
78310696SDavid.Hollister@Sun.COM 			mdb_printf("%4d ", idx);
78410696SDavid.Hollister@Sun.COM 			print_sas_address(&phy);
78510696SDavid.Hollister@Sun.COM 			mdb_printf(" %16p", xs.phy);
78610696SDavid.Hollister@Sun.COM 		} else {
78710696SDavid.Hollister@Sun.COM 			mdb_printf("%4d %16s", idx, "<no phy avail>");
78810696SDavid.Hollister@Sun.COM 		}
78910696SDavid.Hollister@Sun.COM 		mdb_printf(" %5s", dtype);
79011347SRamana.Srikanth@Sun.COM 		mdb_printf(" %4d", xs.actv_pkts);
79111347SRamana.Srikanth@Sun.COM 		mdb_printf(" %6d", xs.actv_cnt);
79210696SDavid.Hollister@Sun.COM 		mdb_printf(" %2d", xs.dev_state);
79310696SDavid.Hollister@Sun.COM 
79410696SDavid.Hollister@Sun.COM 		if (verbose) {
79510696SDavid.Hollister@Sun.COM 			if (xs.new) {
79610696SDavid.Hollister@Sun.COM 				mdb_printf(" new");
79710755SJesse.Butler@Sun.COM 			}
79810755SJesse.Butler@Sun.COM 			if (xs.assigned) {
79910696SDavid.Hollister@Sun.COM 				mdb_printf(" assigned");
80010696SDavid.Hollister@Sun.COM 			}
80110696SDavid.Hollister@Sun.COM 			if (xs.draining) {
80210696SDavid.Hollister@Sun.COM 				mdb_printf(" draining");
80310696SDavid.Hollister@Sun.COM 			}
80410696SDavid.Hollister@Sun.COM 			if (xs.reset_wait) {
80510696SDavid.Hollister@Sun.COM 				mdb_printf(" reset_wait");
80610696SDavid.Hollister@Sun.COM 			}
80710696SDavid.Hollister@Sun.COM 			if (xs.resetting) {
80810696SDavid.Hollister@Sun.COM 				mdb_printf(" resetting");
80910696SDavid.Hollister@Sun.COM 			}
81010696SDavid.Hollister@Sun.COM 			if (xs.recover_wait) {
81110696SDavid.Hollister@Sun.COM 				mdb_printf(" recover_wait");
81210696SDavid.Hollister@Sun.COM 			}
81310696SDavid.Hollister@Sun.COM 			if (xs.recovering) {
81410696SDavid.Hollister@Sun.COM 				mdb_printf(" recovering");
81510696SDavid.Hollister@Sun.COM 			}
81610696SDavid.Hollister@Sun.COM 			if (xs.event_recovery) {
81710696SDavid.Hollister@Sun.COM 				mdb_printf(" event recovery");
81810696SDavid.Hollister@Sun.COM 			}
81910696SDavid.Hollister@Sun.COM 			if (xs.special_running) {
82010696SDavid.Hollister@Sun.COM 				mdb_printf(" special_active");
82110696SDavid.Hollister@Sun.COM 			}
82210696SDavid.Hollister@Sun.COM 			if (xs.ncq) {
82310696SDavid.Hollister@Sun.COM 				mdb_printf(" ncq_tagmap=0x%x qdepth=%d",
82410696SDavid.Hollister@Sun.COM 				    xs.tagmap, xs.qdepth);
82510696SDavid.Hollister@Sun.COM 			} else if (xs.pio) {
82610696SDavid.Hollister@Sun.COM 				mdb_printf(" pio");
82710696SDavid.Hollister@Sun.COM 			}
82810696SDavid.Hollister@Sun.COM 		}
82910696SDavid.Hollister@Sun.COM 
83010696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
83110696SDavid.Hollister@Sun.COM 	}
83210696SDavid.Hollister@Sun.COM 
83310696SDavid.Hollister@Sun.COM 	if (!totals_only) {
83410696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
83510696SDavid.Hollister@Sun.COM 	}
83610696SDavid.Hollister@Sun.COM 
83710696SDavid.Hollister@Sun.COM 	mdb_printf("%19s %d (%d SAS + %d SATA + %d SMP)\n",
83810696SDavid.Hollister@Sun.COM 	    "Configured targets:", (sas_targets + sata_targets + smp_targets),
83910696SDavid.Hollister@Sun.COM 	    sas_targets, sata_targets, smp_targets);
84010696SDavid.Hollister@Sun.COM }
84110696SDavid.Hollister@Sun.COM 
84210743SDavid.Hollister@Sun.COM static char *
work_state_to_string(uint32_t state)84310743SDavid.Hollister@Sun.COM work_state_to_string(uint32_t state)
84410743SDavid.Hollister@Sun.COM {
84510743SDavid.Hollister@Sun.COM 	char *state_string;
84610743SDavid.Hollister@Sun.COM 
84710743SDavid.Hollister@Sun.COM 	switch (state) {
84810743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_NIL:
84910743SDavid.Hollister@Sun.COM 		state_string = "Free";
85010743SDavid.Hollister@Sun.COM 		break;
85110743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_READY:
85210743SDavid.Hollister@Sun.COM 		state_string = "Ready";
85310743SDavid.Hollister@Sun.COM 		break;
85410743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_ONCHIP:
85510743SDavid.Hollister@Sun.COM 		state_string = "On Chip";
85610743SDavid.Hollister@Sun.COM 		break;
85710743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_INTR:
85810743SDavid.Hollister@Sun.COM 		state_string = "In Intr";
85910743SDavid.Hollister@Sun.COM 		break;
86010743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_IOCOMPQ:
86110743SDavid.Hollister@Sun.COM 		state_string = "I/O Comp";
86210743SDavid.Hollister@Sun.COM 		break;
86310743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_ABORTED:
86410743SDavid.Hollister@Sun.COM 		state_string = "I/O Aborted";
86510743SDavid.Hollister@Sun.COM 		break;
86610743SDavid.Hollister@Sun.COM 	case PMCS_WORK_STATE_TIMED_OUT:
86710743SDavid.Hollister@Sun.COM 		state_string = "I/O Timed Out";
86810743SDavid.Hollister@Sun.COM 		break;
86910743SDavid.Hollister@Sun.COM 	default:
87010743SDavid.Hollister@Sun.COM 		state_string = "INVALID";
87110743SDavid.Hollister@Sun.COM 		break;
87210743SDavid.Hollister@Sun.COM 	}
87310743SDavid.Hollister@Sun.COM 
87410743SDavid.Hollister@Sun.COM 	return (state_string);
87510743SDavid.Hollister@Sun.COM }
87610743SDavid.Hollister@Sun.COM 
87710743SDavid.Hollister@Sun.COM static void
display_one_work(pmcwork_t * wp,int verbose,int idx)87810743SDavid.Hollister@Sun.COM display_one_work(pmcwork_t *wp, int verbose, int idx)
87910743SDavid.Hollister@Sun.COM {
88010743SDavid.Hollister@Sun.COM 	char		*state, *last_state;
88110743SDavid.Hollister@Sun.COM 	char		*path;
88210743SDavid.Hollister@Sun.COM 	pmcs_xscsi_t	xs;
88310743SDavid.Hollister@Sun.COM 	pmcs_phy_t	phy;
88410743SDavid.Hollister@Sun.COM 	int		tgt;
88510743SDavid.Hollister@Sun.COM 
88610743SDavid.Hollister@Sun.COM 	state = work_state_to_string(wp->state);
88710743SDavid.Hollister@Sun.COM 	last_state = work_state_to_string(wp->last_state);
88810743SDavid.Hollister@Sun.COM 
88910743SDavid.Hollister@Sun.COM 	if (wp->ssp_event && wp->ssp_event != 0xffffffff) {
89010743SDavid.Hollister@Sun.COM 		mdb_printf("SSP event 0x%x", wp->ssp_event);
89110743SDavid.Hollister@Sun.COM 	}
89210743SDavid.Hollister@Sun.COM 
89310743SDavid.Hollister@Sun.COM 	tgt = -1;
89410743SDavid.Hollister@Sun.COM 	if (wp->xp) {
89510743SDavid.Hollister@Sun.COM 		if (MDB_RD(&xs, sizeof (xs), wp->xp) == -1) {
89610743SDavid.Hollister@Sun.COM 			NOREAD(pmcs_xscsi_t, wp->xp);
89710743SDavid.Hollister@Sun.COM 		} else {
89810743SDavid.Hollister@Sun.COM 			tgt = xs.target_num;
89910743SDavid.Hollister@Sun.COM 		}
90010743SDavid.Hollister@Sun.COM 	}
90110743SDavid.Hollister@Sun.COM 	if (wp->phy) {
90210743SDavid.Hollister@Sun.COM 		if (MDB_RD(&phy, sizeof (phy), wp->phy) == -1) {
90310743SDavid.Hollister@Sun.COM 			NOREAD(pmcs_phy_t, wp->phy);
90410743SDavid.Hollister@Sun.COM 		}
90510743SDavid.Hollister@Sun.COM 		path = phy.path;
90610743SDavid.Hollister@Sun.COM 	} else {
90710743SDavid.Hollister@Sun.COM 		path = "N/A";
90810743SDavid.Hollister@Sun.COM 	}
90910743SDavid.Hollister@Sun.COM 
91010743SDavid.Hollister@Sun.COM 	if (verbose) {
91110743SDavid.Hollister@Sun.COM 		mdb_printf("%4d ", idx);
91210743SDavid.Hollister@Sun.COM 	}
91310743SDavid.Hollister@Sun.COM 	if (tgt == -1) {
91410743SDavid.Hollister@Sun.COM 		mdb_printf("%08x %10s %20s      N/A %8u %1d %1d ",
91510743SDavid.Hollister@Sun.COM 		    wp->htag, state, path, wp->timer,
91610743SDavid.Hollister@Sun.COM 		    wp->onwire, wp->dead);
91710743SDavid.Hollister@Sun.COM 	} else {
91810743SDavid.Hollister@Sun.COM 		mdb_printf("%08x %10s %20s %8d %8u %1d %1d ",
91910743SDavid.Hollister@Sun.COM 		    wp->htag, state, path, tgt, wp->timer,
92010743SDavid.Hollister@Sun.COM 		    wp->onwire, wp->dead);
92110743SDavid.Hollister@Sun.COM 	}
92210743SDavid.Hollister@Sun.COM 	if (verbose) {
92311601SDavid.Hollister@Sun.COM 		mdb_printf("%08x %10s 0x%016p 0x%016p 0x%016p\n",
92411601SDavid.Hollister@Sun.COM 		    wp->last_htag, last_state, wp->last_phy, wp->last_xp,
92511601SDavid.Hollister@Sun.COM 		    wp->last_arg);
92610743SDavid.Hollister@Sun.COM 	} else {
92710743SDavid.Hollister@Sun.COM 		mdb_printf("\n");
92810743SDavid.Hollister@Sun.COM 	}
92910743SDavid.Hollister@Sun.COM }
93010743SDavid.Hollister@Sun.COM 
93110696SDavid.Hollister@Sun.COM static void
display_work(struct pmcs_hw m,int verbose,int wserno)93212060SDavid.Hollister@Sun.COM display_work(struct pmcs_hw m, int verbose, int wserno)
93310696SDavid.Hollister@Sun.COM {
93410696SDavid.Hollister@Sun.COM 	int		idx;
93510743SDavid.Hollister@Sun.COM 	boolean_t	header_printed = B_FALSE;
93612060SDavid.Hollister@Sun.COM 	pmcwork_t	*wp;
93712060SDavid.Hollister@Sun.COM 	wserno_list_t	*sernop, *sp, *newsp, *sphead = NULL;
93810696SDavid.Hollister@Sun.COM 	uintptr_t	_wp;
93912060SDavid.Hollister@Sun.COM 	int		serno;
94012060SDavid.Hollister@Sun.COM 
94112060SDavid.Hollister@Sun.COM 	wp = mdb_alloc(sizeof (pmcwork_t) * m.max_cmd, UM_SLEEP);
94212060SDavid.Hollister@Sun.COM 	_wp = (uintptr_t)m.work;
94312060SDavid.Hollister@Sun.COM 	sernop = mdb_alloc(sizeof (wserno_list_t) * m.max_cmd, UM_SLEEP);
94412060SDavid.Hollister@Sun.COM 	bzero(sernop, sizeof (wserno_list_t) * m.max_cmd);
94510696SDavid.Hollister@Sun.COM 
94610696SDavid.Hollister@Sun.COM 	mdb_printf("\nActive Work structure information:\n");
94710696SDavid.Hollister@Sun.COM 	mdb_printf("----------------------------------\n");
94810696SDavid.Hollister@Sun.COM 
94912060SDavid.Hollister@Sun.COM 	/*
95012060SDavid.Hollister@Sun.COM 	 * Read in all the work structures
95112060SDavid.Hollister@Sun.COM 	 */
95210696SDavid.Hollister@Sun.COM 	for (idx = 0; idx < m.max_cmd; idx++, _wp += sizeof (pmcwork_t)) {
95312060SDavid.Hollister@Sun.COM 		if (MDB_RD(wp + idx, sizeof (pmcwork_t), _wp) == -1) {
95410696SDavid.Hollister@Sun.COM 			NOREAD(pmcwork_t, _wp);
95510696SDavid.Hollister@Sun.COM 			continue;
95610696SDavid.Hollister@Sun.COM 		}
95712060SDavid.Hollister@Sun.COM 	}
95810743SDavid.Hollister@Sun.COM 
95912060SDavid.Hollister@Sun.COM 	/*
96012060SDavid.Hollister@Sun.COM 	 * Sort by serial number?
96112060SDavid.Hollister@Sun.COM 	 */
96212060SDavid.Hollister@Sun.COM 	if (wserno) {
96312060SDavid.Hollister@Sun.COM 		for (idx = 0; idx < m.max_cmd; idx++) {
96412060SDavid.Hollister@Sun.COM 			if ((wp + idx)->htag == 0) {
96512060SDavid.Hollister@Sun.COM 				serno = PMCS_TAG_SERNO((wp + idx)->last_htag);
96612060SDavid.Hollister@Sun.COM 			} else {
96712060SDavid.Hollister@Sun.COM 				serno = PMCS_TAG_SERNO((wp + idx)->htag);
96812060SDavid.Hollister@Sun.COM 			}
96912060SDavid.Hollister@Sun.COM 
97012060SDavid.Hollister@Sun.COM 			/* Start at the beginning of the list */
97112060SDavid.Hollister@Sun.COM 			sp = sphead;
97212060SDavid.Hollister@Sun.COM 			newsp = sernop + idx;
97312060SDavid.Hollister@Sun.COM 			/* If this is the first entry, just add it */
97412060SDavid.Hollister@Sun.COM 			if (sphead == NULL) {
97512060SDavid.Hollister@Sun.COM 				sphead = sernop;
97612060SDavid.Hollister@Sun.COM 				sphead->serno = serno;
97712060SDavid.Hollister@Sun.COM 				sphead->idx = idx;
97812060SDavid.Hollister@Sun.COM 				sphead->next = NULL;
97912060SDavid.Hollister@Sun.COM 				sphead->prev = NULL;
98012060SDavid.Hollister@Sun.COM 				continue;
98112060SDavid.Hollister@Sun.COM 			}
98212060SDavid.Hollister@Sun.COM 
98312060SDavid.Hollister@Sun.COM 			newsp->serno = serno;
98412060SDavid.Hollister@Sun.COM 			newsp->idx = idx;
98512060SDavid.Hollister@Sun.COM 
98612060SDavid.Hollister@Sun.COM 			/* Find out where in the list this goes */
98712060SDavid.Hollister@Sun.COM 			while (sp) {
98812060SDavid.Hollister@Sun.COM 				/* This item goes before sp */
98912060SDavid.Hollister@Sun.COM 				if (serno < sp->serno) {
99012060SDavid.Hollister@Sun.COM 					newsp->next = sp;
99112060SDavid.Hollister@Sun.COM 					newsp->prev = sp->prev;
99212060SDavid.Hollister@Sun.COM 					if (newsp->prev == NULL) {
99312060SDavid.Hollister@Sun.COM 						sphead = newsp;
99412060SDavid.Hollister@Sun.COM 					} else {
99512060SDavid.Hollister@Sun.COM 						newsp->prev->next = newsp;
99612060SDavid.Hollister@Sun.COM 					}
99712060SDavid.Hollister@Sun.COM 					sp->prev = newsp;
99812060SDavid.Hollister@Sun.COM 					break;
99912060SDavid.Hollister@Sun.COM 				}
100012060SDavid.Hollister@Sun.COM 
100112060SDavid.Hollister@Sun.COM 				/*
100212060SDavid.Hollister@Sun.COM 				 * If sp->next is NULL, this entry goes at the
100312060SDavid.Hollister@Sun.COM 				 * end of the list
100412060SDavid.Hollister@Sun.COM 				 */
100512060SDavid.Hollister@Sun.COM 				if (sp->next == NULL) {
100612060SDavid.Hollister@Sun.COM 					sp->next = newsp;
100712060SDavid.Hollister@Sun.COM 					newsp->next = NULL;
100812060SDavid.Hollister@Sun.COM 					newsp->prev = sp;
100912060SDavid.Hollister@Sun.COM 					break;
101012060SDavid.Hollister@Sun.COM 				}
101112060SDavid.Hollister@Sun.COM 
101212060SDavid.Hollister@Sun.COM 				sp = sp->next;
101312060SDavid.Hollister@Sun.COM 			}
101412060SDavid.Hollister@Sun.COM 		}
101512060SDavid.Hollister@Sun.COM 
101612060SDavid.Hollister@Sun.COM 		/*
101712060SDavid.Hollister@Sun.COM 		 * Now print the sorted list
101812060SDavid.Hollister@Sun.COM 		 */
101912060SDavid.Hollister@Sun.COM 		mdb_printf(" Idx %8s %10s %20s %8s %8s O D ",
102012060SDavid.Hollister@Sun.COM 		    "HTag", "State", "Phy Path", "Target", "Timer");
102112060SDavid.Hollister@Sun.COM 		mdb_printf("%8s %10s %18s %18s %18s\n", "LastHTAG",
102212060SDavid.Hollister@Sun.COM 		    "LastState", "LastPHY", "LastTgt", "LastArg");
102312060SDavid.Hollister@Sun.COM 
102412060SDavid.Hollister@Sun.COM 		sp = sphead;
102512060SDavid.Hollister@Sun.COM 		while (sp) {
102612060SDavid.Hollister@Sun.COM 			display_one_work(wp + sp->idx, 1, sp->idx);
102712060SDavid.Hollister@Sun.COM 			sp = sp->next;
102812060SDavid.Hollister@Sun.COM 		}
102912060SDavid.Hollister@Sun.COM 
103012060SDavid.Hollister@Sun.COM 		goto out;
103112060SDavid.Hollister@Sun.COM 	}
103212060SDavid.Hollister@Sun.COM 
103312060SDavid.Hollister@Sun.COM 	/*
103412060SDavid.Hollister@Sun.COM 	 * Now print the list, sorted by index
103512060SDavid.Hollister@Sun.COM 	 */
103612060SDavid.Hollister@Sun.COM 	for (idx = 0; idx < m.max_cmd; idx++) {
103712060SDavid.Hollister@Sun.COM 		if (!verbose && ((wp + idx)->htag == PMCS_TAG_TYPE_FREE)) {
103810696SDavid.Hollister@Sun.COM 			continue;
103910696SDavid.Hollister@Sun.COM 		}
104010743SDavid.Hollister@Sun.COM 
104110743SDavid.Hollister@Sun.COM 		if (header_printed == B_FALSE) {
104210743SDavid.Hollister@Sun.COM 			if (verbose) {
104310743SDavid.Hollister@Sun.COM 				mdb_printf("%4s ", "Idx");
104410743SDavid.Hollister@Sun.COM 			}
104510743SDavid.Hollister@Sun.COM 			mdb_printf("%8s %10s %20s %8s %8s O D ",
104610696SDavid.Hollister@Sun.COM 			    "HTag", "State", "Phy Path", "Target", "Timer");
104710743SDavid.Hollister@Sun.COM 			if (verbose) {
104811601SDavid.Hollister@Sun.COM 				mdb_printf("%8s %10s %18s %18s %18s\n",
104911601SDavid.Hollister@Sun.COM 				    "LastHTAG", "LastState", "LastPHY",
105011601SDavid.Hollister@Sun.COM 				    "LastTgt", "LastArg");
105110743SDavid.Hollister@Sun.COM 			} else {
105210743SDavid.Hollister@Sun.COM 				mdb_printf("\n");
105310743SDavid.Hollister@Sun.COM 			}
105410743SDavid.Hollister@Sun.COM 			header_printed = B_TRUE;
105510696SDavid.Hollister@Sun.COM 		}
105610743SDavid.Hollister@Sun.COM 
105712060SDavid.Hollister@Sun.COM 		display_one_work(wp + idx, verbose, idx);
105810696SDavid.Hollister@Sun.COM 	}
105912060SDavid.Hollister@Sun.COM 
106012060SDavid.Hollister@Sun.COM out:
106112060SDavid.Hollister@Sun.COM 	mdb_free(wp, sizeof (pmcwork_t) * m.max_cmd);
106212060SDavid.Hollister@Sun.COM 	mdb_free(sernop, sizeof (wserno_list_t) * m.max_cmd);
106310696SDavid.Hollister@Sun.COM }
106410696SDavid.Hollister@Sun.COM 
106510696SDavid.Hollister@Sun.COM static void
print_spcmd(pmcs_cmd_t * sp,void * kaddr,int printhdr,int verbose)106610743SDavid.Hollister@Sun.COM print_spcmd(pmcs_cmd_t *sp, void *kaddr, int printhdr, int verbose)
106710696SDavid.Hollister@Sun.COM {
106810743SDavid.Hollister@Sun.COM 	int cdb_size, idx;
106910743SDavid.Hollister@Sun.COM 	struct scsi_pkt pkt;
107010743SDavid.Hollister@Sun.COM 	uchar_t cdb[256];
107110743SDavid.Hollister@Sun.COM 
107210696SDavid.Hollister@Sun.COM 	if (printhdr) {
107310743SDavid.Hollister@Sun.COM 		if (verbose) {
107410743SDavid.Hollister@Sun.COM 			mdb_printf("%16s %16s %16s %8s %s CDB\n", "Command",
107510743SDavid.Hollister@Sun.COM 			    "SCSA pkt", "DMA Chunks", "HTAG", "SATL Tag");
107610743SDavid.Hollister@Sun.COM 		} else {
107710743SDavid.Hollister@Sun.COM 			mdb_printf("%16s %16s %16s %8s %s\n", "Command",
107810743SDavid.Hollister@Sun.COM 			    "SCSA pkt", "DMA Chunks", "HTAG", "SATL Tag");
107910743SDavid.Hollister@Sun.COM 		}
108010696SDavid.Hollister@Sun.COM 	}
108110743SDavid.Hollister@Sun.COM 
108210743SDavid.Hollister@Sun.COM 	mdb_printf("%16p %16p %16p %08x %08x ",
108310696SDavid.Hollister@Sun.COM 	    kaddr, sp->cmd_pkt, sp->cmd_clist, sp->cmd_tag, sp->cmd_satltag);
108410743SDavid.Hollister@Sun.COM 
108510743SDavid.Hollister@Sun.COM 	/*
108610743SDavid.Hollister@Sun.COM 	 * If we're printing verbose, dump the CDB as well.
108710743SDavid.Hollister@Sun.COM 	 */
108810743SDavid.Hollister@Sun.COM 	if (verbose) {
108910743SDavid.Hollister@Sun.COM 		if (sp->cmd_pkt) {
109010743SDavid.Hollister@Sun.COM 			if (mdb_vread(&pkt, sizeof (struct scsi_pkt),
109110743SDavid.Hollister@Sun.COM 			    (uintptr_t)sp->cmd_pkt) !=
109210743SDavid.Hollister@Sun.COM 			    sizeof (struct scsi_pkt)) {
109310743SDavid.Hollister@Sun.COM 				mdb_warn("Unable to read SCSI pkt\n");
109410743SDavid.Hollister@Sun.COM 				return;
109510743SDavid.Hollister@Sun.COM 			}
109610743SDavid.Hollister@Sun.COM 			cdb_size = pkt.pkt_cdblen;
109710743SDavid.Hollister@Sun.COM 			if (mdb_vread(&cdb[0], cdb_size,
109810743SDavid.Hollister@Sun.COM 			    (uintptr_t)pkt.pkt_cdbp) != cdb_size) {
109910743SDavid.Hollister@Sun.COM 				mdb_warn("Unable to read CDB\n");
110010743SDavid.Hollister@Sun.COM 				return;
110110743SDavid.Hollister@Sun.COM 			}
110210743SDavid.Hollister@Sun.COM 
110310743SDavid.Hollister@Sun.COM 			for (idx = 0; idx < cdb_size; idx++) {
110410743SDavid.Hollister@Sun.COM 				mdb_printf("%02x ", cdb[idx]);
110510743SDavid.Hollister@Sun.COM 			}
110610743SDavid.Hollister@Sun.COM 		} else {
110710743SDavid.Hollister@Sun.COM 			mdb_printf("N/A");
110810743SDavid.Hollister@Sun.COM 		}
110910743SDavid.Hollister@Sun.COM 
111010743SDavid.Hollister@Sun.COM 		mdb_printf("\n");
111110743SDavid.Hollister@Sun.COM 	} else {
111210743SDavid.Hollister@Sun.COM 		mdb_printf("\n");
111310743SDavid.Hollister@Sun.COM 	}
111410696SDavid.Hollister@Sun.COM }
111510696SDavid.Hollister@Sun.COM 
111610696SDavid.Hollister@Sun.COM /*ARGSUSED1*/
111710696SDavid.Hollister@Sun.COM static void
display_waitqs(struct pmcs_hw m,int verbose)111810696SDavid.Hollister@Sun.COM display_waitqs(struct pmcs_hw m, int verbose)
111910696SDavid.Hollister@Sun.COM {
112010696SDavid.Hollister@Sun.COM 	pmcs_cmd_t	*sp, s;
112110696SDavid.Hollister@Sun.COM 	pmcs_xscsi_t	xs;
112210696SDavid.Hollister@Sun.COM 	int		first, i;
112310696SDavid.Hollister@Sun.COM 	int		max_dev = m.max_dev;
112410696SDavid.Hollister@Sun.COM 
112510696SDavid.Hollister@Sun.COM 	sp = m.dq.stqh_first;
112610696SDavid.Hollister@Sun.COM 	first = 1;
112710696SDavid.Hollister@Sun.COM 	while (sp) {
112810696SDavid.Hollister@Sun.COM 		if (first) {
112910696SDavid.Hollister@Sun.COM 			mdb_printf("\nDead Command Queue:\n");
113010696SDavid.Hollister@Sun.COM 			mdb_printf("---------------------------\n");
113110696SDavid.Hollister@Sun.COM 		}
113210696SDavid.Hollister@Sun.COM 		if (MDB_RD(&s, sizeof (s), sp) == -1) {
113310696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_cmd_t, sp);
113410696SDavid.Hollister@Sun.COM 			break;
113510696SDavid.Hollister@Sun.COM 		}
113610743SDavid.Hollister@Sun.COM 		print_spcmd(&s, sp, first, verbose);
113710696SDavid.Hollister@Sun.COM 		sp = s.cmd_next.stqe_next;
113810696SDavid.Hollister@Sun.COM 		first = 0;
113910696SDavid.Hollister@Sun.COM 	}
114010696SDavid.Hollister@Sun.COM 
114110696SDavid.Hollister@Sun.COM 	sp = m.cq.stqh_first;
114210696SDavid.Hollister@Sun.COM 	first = 1;
114310696SDavid.Hollister@Sun.COM 	while (sp) {
114410696SDavid.Hollister@Sun.COM 		if (first) {
114510696SDavid.Hollister@Sun.COM 			mdb_printf("\nCompletion Command Queue:\n");
114610696SDavid.Hollister@Sun.COM 			mdb_printf("---------------------------\n");
114710696SDavid.Hollister@Sun.COM 		}
114810696SDavid.Hollister@Sun.COM 		if (MDB_RD(&s, sizeof (s), sp) == -1) {
114910696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_cmd_t, sp);
115010696SDavid.Hollister@Sun.COM 			break;
115110696SDavid.Hollister@Sun.COM 		}
115210743SDavid.Hollister@Sun.COM 		print_spcmd(&s, sp, first, verbose);
115310696SDavid.Hollister@Sun.COM 		sp = s.cmd_next.stqe_next;
115410696SDavid.Hollister@Sun.COM 		first = 0;
115510696SDavid.Hollister@Sun.COM 	}
115610696SDavid.Hollister@Sun.COM 
115710696SDavid.Hollister@Sun.COM 
115810696SDavid.Hollister@Sun.COM 	if (targets == NULL) {
115910696SDavid.Hollister@Sun.COM 		targets = mdb_alloc(sizeof (targets) * max_dev, UM_SLEEP);
116010696SDavid.Hollister@Sun.COM 	}
116110696SDavid.Hollister@Sun.COM 
116210696SDavid.Hollister@Sun.COM 	if (MDB_RD(targets, sizeof (targets) * max_dev, m.targets) == -1) {
116310696SDavid.Hollister@Sun.COM 		NOREAD(targets, m.targets);
116410696SDavid.Hollister@Sun.COM 		return;
116510696SDavid.Hollister@Sun.COM 	}
116610696SDavid.Hollister@Sun.COM 
116710696SDavid.Hollister@Sun.COM 	for (i = 0; i < max_dev; i++) {
116810696SDavid.Hollister@Sun.COM 		if (targets[i] == NULL) {
116910696SDavid.Hollister@Sun.COM 			continue;
117010696SDavid.Hollister@Sun.COM 		}
117110696SDavid.Hollister@Sun.COM 		if (MDB_RD(&xs, sizeof (xs), targets[i]) == -1) {
117210696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_xscsi_t, targets[i]);
117310696SDavid.Hollister@Sun.COM 			continue;
117410696SDavid.Hollister@Sun.COM 		}
117510696SDavid.Hollister@Sun.COM 		sp = xs.wq.stqh_first;
117610696SDavid.Hollister@Sun.COM 		first = 1;
117710696SDavid.Hollister@Sun.COM 		while (sp) {
117810696SDavid.Hollister@Sun.COM 			if (first) {
117910696SDavid.Hollister@Sun.COM 				mdb_printf("\nTarget %u Wait Queue:\n",
118010696SDavid.Hollister@Sun.COM 				    xs.target_num);
118110696SDavid.Hollister@Sun.COM 				mdb_printf("---------------------------\n");
118210696SDavid.Hollister@Sun.COM 			}
118310696SDavid.Hollister@Sun.COM 			if (MDB_RD(&s, sizeof (s), sp) == -1) {
118410696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_cmd_t, sp);
118510696SDavid.Hollister@Sun.COM 				break;
118610696SDavid.Hollister@Sun.COM 			}
118710743SDavid.Hollister@Sun.COM 			print_spcmd(&s, sp, first, verbose);
118810696SDavid.Hollister@Sun.COM 			sp = s.cmd_next.stqe_next;
118910696SDavid.Hollister@Sun.COM 			first = 0;
119010696SDavid.Hollister@Sun.COM 		}
119110696SDavid.Hollister@Sun.COM 		sp = xs.aq.stqh_first;
119210696SDavid.Hollister@Sun.COM 		first = 1;
119310696SDavid.Hollister@Sun.COM 		while (sp) {
119410696SDavid.Hollister@Sun.COM 			if (first) {
119510696SDavid.Hollister@Sun.COM 				mdb_printf("\nTarget %u Active Queue:\n",
119610696SDavid.Hollister@Sun.COM 				    xs.target_num);
119710696SDavid.Hollister@Sun.COM 				mdb_printf("---------------------------\n");
119810696SDavid.Hollister@Sun.COM 			}
119910696SDavid.Hollister@Sun.COM 			if (MDB_RD(&s, sizeof (s), sp) == -1) {
120010696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_cmd_t, sp);
120110696SDavid.Hollister@Sun.COM 				break;
120210696SDavid.Hollister@Sun.COM 			}
120310743SDavid.Hollister@Sun.COM 			print_spcmd(&s, sp, first, verbose);
120410696SDavid.Hollister@Sun.COM 			sp = s.cmd_next.stqe_next;
120510696SDavid.Hollister@Sun.COM 			first = 0;
120610696SDavid.Hollister@Sun.COM 		}
120710696SDavid.Hollister@Sun.COM 		sp = xs.sq.stqh_first;
120810696SDavid.Hollister@Sun.COM 		first = 1;
120910696SDavid.Hollister@Sun.COM 		while (sp) {
121010696SDavid.Hollister@Sun.COM 			if (first) {
121110696SDavid.Hollister@Sun.COM 				mdb_printf("\nTarget %u Special Queue:\n",
121210696SDavid.Hollister@Sun.COM 				    xs.target_num);
121310696SDavid.Hollister@Sun.COM 				mdb_printf("---------------------------\n");
121410696SDavid.Hollister@Sun.COM 			}
121510696SDavid.Hollister@Sun.COM 			if (MDB_RD(&s, sizeof (s), sp) == -1) {
121610696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_cmd_t, sp);
121710696SDavid.Hollister@Sun.COM 				break;
121810696SDavid.Hollister@Sun.COM 			}
121910743SDavid.Hollister@Sun.COM 			print_spcmd(&s, sp, first, verbose);
122010696SDavid.Hollister@Sun.COM 			sp = s.cmd_next.stqe_next;
122110696SDavid.Hollister@Sun.COM 			first = 0;
122210696SDavid.Hollister@Sun.COM 		}
122310696SDavid.Hollister@Sun.COM 	}
122410696SDavid.Hollister@Sun.COM }
122510696SDavid.Hollister@Sun.COM 
122610696SDavid.Hollister@Sun.COM static char *
ibq_type(int qnum)122710696SDavid.Hollister@Sun.COM ibq_type(int qnum)
122810696SDavid.Hollister@Sun.COM {
122910696SDavid.Hollister@Sun.COM 	if (qnum < 0 || qnum >= PMCS_NIQ) {
123010696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
123110696SDavid.Hollister@Sun.COM 	}
123210696SDavid.Hollister@Sun.COM 
123310696SDavid.Hollister@Sun.COM 	if (qnum < PMCS_IQ_OTHER) {
123410696SDavid.Hollister@Sun.COM 		return ("I/O");
123510696SDavid.Hollister@Sun.COM 	}
123610696SDavid.Hollister@Sun.COM 
123710696SDavid.Hollister@Sun.COM 	return ("Other");
123810696SDavid.Hollister@Sun.COM }
123910696SDavid.Hollister@Sun.COM 
124010696SDavid.Hollister@Sun.COM static char *
obq_type(int qnum)124110696SDavid.Hollister@Sun.COM obq_type(int qnum)
124210696SDavid.Hollister@Sun.COM {
124310696SDavid.Hollister@Sun.COM 	switch (qnum) {
124410696SDavid.Hollister@Sun.COM 	case PMCS_OQ_IODONE:
124510696SDavid.Hollister@Sun.COM 		return ("I/O");
124610696SDavid.Hollister@Sun.COM 		break;
124710696SDavid.Hollister@Sun.COM 	case PMCS_OQ_GENERAL:
124810696SDavid.Hollister@Sun.COM 		return ("General");
124910696SDavid.Hollister@Sun.COM 		break;
125010696SDavid.Hollister@Sun.COM 	case PMCS_OQ_EVENTS:
125110696SDavid.Hollister@Sun.COM 		return ("Events");
125210696SDavid.Hollister@Sun.COM 		break;
125310696SDavid.Hollister@Sun.COM 	default:
125410696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
125510696SDavid.Hollister@Sun.COM 	}
125610696SDavid.Hollister@Sun.COM }
125710696SDavid.Hollister@Sun.COM 
125810696SDavid.Hollister@Sun.COM static char *
iomb_cat(uint32_t cat)125910696SDavid.Hollister@Sun.COM iomb_cat(uint32_t cat)
126010696SDavid.Hollister@Sun.COM {
126110696SDavid.Hollister@Sun.COM 	switch (cat) {
126210696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_NET:
126310696SDavid.Hollister@Sun.COM 		return ("NET");
126410696SDavid.Hollister@Sun.COM 		break;
126510696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_FC:
126610696SDavid.Hollister@Sun.COM 		return ("FC");
126710696SDavid.Hollister@Sun.COM 		break;
126810696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_SAS:
126910696SDavid.Hollister@Sun.COM 		return ("SAS");
127010696SDavid.Hollister@Sun.COM 		break;
127110696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_SCSI:
127210696SDavid.Hollister@Sun.COM 		return ("SCSI");
127310696SDavid.Hollister@Sun.COM 		break;
127410696SDavid.Hollister@Sun.COM 	default:
127510696SDavid.Hollister@Sun.COM 		return ("???");
127610696SDavid.Hollister@Sun.COM 	}
127710696SDavid.Hollister@Sun.COM }
127810696SDavid.Hollister@Sun.COM 
127910696SDavid.Hollister@Sun.COM static char *
iomb_event(uint8_t event)128011601SDavid.Hollister@Sun.COM iomb_event(uint8_t event)
128111601SDavid.Hollister@Sun.COM {
128211601SDavid.Hollister@Sun.COM 	switch (event) {
128311601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PHY_STOP_STATUS:
128411601SDavid.Hollister@Sun.COM 		return ("PHY STOP");
128511601SDavid.Hollister@Sun.COM 		break;
128611601SDavid.Hollister@Sun.COM 	case IOP_EVENT_SAS_PHY_UP:
128711601SDavid.Hollister@Sun.COM 		return ("PHY UP");
128811601SDavid.Hollister@Sun.COM 		break;
128911601SDavid.Hollister@Sun.COM 	case IOP_EVENT_SATA_PHY_UP:
129011601SDavid.Hollister@Sun.COM 		return ("SATA PHY UP");
129111601SDavid.Hollister@Sun.COM 		break;
129211601SDavid.Hollister@Sun.COM 	case IOP_EVENT_SATA_SPINUP_HOLD:
129311601SDavid.Hollister@Sun.COM 		return ("SATA SPINUP HOLD");
129411601SDavid.Hollister@Sun.COM 		break;
129511601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PHY_DOWN:
129611601SDavid.Hollister@Sun.COM 		return ("PHY DOWN");
129711601SDavid.Hollister@Sun.COM 		break;
129811601SDavid.Hollister@Sun.COM 	case IOP_EVENT_BROADCAST_CHANGE:
129911601SDavid.Hollister@Sun.COM 		return ("BROADCAST CHANGE");
130011601SDavid.Hollister@Sun.COM 		break;
130111601SDavid.Hollister@Sun.COM 	case IOP_EVENT_BROADCAST_SES:
130211601SDavid.Hollister@Sun.COM 		return ("BROADCAST SES");
130311601SDavid.Hollister@Sun.COM 		break;
130411601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PHY_ERR_INBOUND_CRC:
130511601SDavid.Hollister@Sun.COM 		return ("INBOUND CRC ERROR");
130611601SDavid.Hollister@Sun.COM 		break;
130711601SDavid.Hollister@Sun.COM 	case IOP_EVENT_HARD_RESET_RECEIVED:
130811601SDavid.Hollister@Sun.COM 		return ("HARD RESET");
130911601SDavid.Hollister@Sun.COM 		break;
131011601SDavid.Hollister@Sun.COM 	case IOP_EVENT_EVENT_ID_FRAME_TIMO:
131111601SDavid.Hollister@Sun.COM 		return ("IDENTIFY FRAME TIMEOUT");
131211601SDavid.Hollister@Sun.COM 		break;
131311601SDavid.Hollister@Sun.COM 	case IOP_EVENT_BROADCAST_EXP:
131411601SDavid.Hollister@Sun.COM 		return ("BROADCAST EXPANDER");
131511601SDavid.Hollister@Sun.COM 		break;
131611601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PHY_START_STATUS:
131711601SDavid.Hollister@Sun.COM 		return ("PHY START");
131811601SDavid.Hollister@Sun.COM 		break;
131911601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PHY_ERR_INVALID_DWORD:
132011601SDavid.Hollister@Sun.COM 		return ("INVALID DWORD");
132111601SDavid.Hollister@Sun.COM 		break;
132211601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PHY_ERR_DISPARITY_ERROR:
132311601SDavid.Hollister@Sun.COM 		return ("DISPARITY ERROR");
132411601SDavid.Hollister@Sun.COM 		break;
132511601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PHY_ERR_CODE_VIOLATION:
132611601SDavid.Hollister@Sun.COM 		return ("CODE VIOLATION");
132711601SDavid.Hollister@Sun.COM 		break;
132811601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PHY_ERR_LOSS_OF_DWORD_SYN:
132911601SDavid.Hollister@Sun.COM 		return ("LOSS OF DWORD SYNC");
133011601SDavid.Hollister@Sun.COM 		break;
133111601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PHY_ERR_PHY_RESET_FAILD:
133211601SDavid.Hollister@Sun.COM 		return ("PHY RESET FAILED");
133311601SDavid.Hollister@Sun.COM 		break;
133411601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PORT_RECOVERY_TIMER_TMO:
133511601SDavid.Hollister@Sun.COM 		return ("PORT RECOVERY TIMEOUT");
133611601SDavid.Hollister@Sun.COM 		break;
133711601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PORT_RECOVER:
133811601SDavid.Hollister@Sun.COM 		return ("PORT RECOVERY");
133911601SDavid.Hollister@Sun.COM 		break;
134011601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PORT_RESET_TIMER_TMO:
134111601SDavid.Hollister@Sun.COM 		return ("PORT RESET TIMEOUT");
134211601SDavid.Hollister@Sun.COM 		break;
134311601SDavid.Hollister@Sun.COM 	case IOP_EVENT_PORT_RESET_COMPLETE:
134411601SDavid.Hollister@Sun.COM 		return ("PORT RESET COMPLETE");
134511601SDavid.Hollister@Sun.COM 		break;
134611601SDavid.Hollister@Sun.COM 	case IOP_EVENT_BROADCAST_ASYNC_EVENT:
134711601SDavid.Hollister@Sun.COM 		return ("BROADCAST ASYNC");
134811601SDavid.Hollister@Sun.COM 		break;
134911601SDavid.Hollister@Sun.COM 	case IOP_EVENT_IT_NEXUS_LOSS:
135011601SDavid.Hollister@Sun.COM 		return ("I/T NEXUS LOSS");
135111601SDavid.Hollister@Sun.COM 		break;
135211601SDavid.Hollister@Sun.COM 	default:
135311601SDavid.Hollister@Sun.COM 		return ("Unknown Event");
135411601SDavid.Hollister@Sun.COM 	}
135511601SDavid.Hollister@Sun.COM }
135611601SDavid.Hollister@Sun.COM 
135711601SDavid.Hollister@Sun.COM static char *
inbound_iomb_opcode(uint32_t opcode)135810696SDavid.Hollister@Sun.COM inbound_iomb_opcode(uint32_t opcode)
135910696SDavid.Hollister@Sun.COM {
136010696SDavid.Hollister@Sun.COM 	switch (opcode) {
136110696SDavid.Hollister@Sun.COM 	case PMCIN_ECHO:
136210696SDavid.Hollister@Sun.COM 		return ("ECHO");
136310696SDavid.Hollister@Sun.COM 		break;
136410696SDavid.Hollister@Sun.COM 	case PMCIN_GET_INFO:
136510696SDavid.Hollister@Sun.COM 		return ("GET_INFO");
136610696SDavid.Hollister@Sun.COM 		break;
136710696SDavid.Hollister@Sun.COM 	case PMCIN_GET_VPD:
136810696SDavid.Hollister@Sun.COM 		return ("GET_VPD");
136910696SDavid.Hollister@Sun.COM 		break;
137010696SDavid.Hollister@Sun.COM 	case PMCIN_PHY_START:
137110696SDavid.Hollister@Sun.COM 		return ("PHY_START");
137210696SDavid.Hollister@Sun.COM 		break;
137310696SDavid.Hollister@Sun.COM 	case PMCIN_PHY_STOP:
137410696SDavid.Hollister@Sun.COM 		return ("PHY_STOP");
137510696SDavid.Hollister@Sun.COM 		break;
137610696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_IO_START:
137710696SDavid.Hollister@Sun.COM 		return ("INI_IO_START");
137810696SDavid.Hollister@Sun.COM 		break;
137910696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_TM_START:
138010696SDavid.Hollister@Sun.COM 		return ("INI_TM_START");
138110696SDavid.Hollister@Sun.COM 		break;
138210696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_EXT_IO_START:
138310696SDavid.Hollister@Sun.COM 		return ("INI_EXT_IO_START");
138410696SDavid.Hollister@Sun.COM 		break;
138510696SDavid.Hollister@Sun.COM 	case PMCIN_DEVICE_HANDLE_ACCEPT:
138610696SDavid.Hollister@Sun.COM 		return ("DEVICE_HANDLE_ACCEPT");
138710696SDavid.Hollister@Sun.COM 		break;
138810696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_TGT_IO_START:
138910696SDavid.Hollister@Sun.COM 		return ("TGT_IO_START");
139010696SDavid.Hollister@Sun.COM 		break;
139110696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_TGT_RESPONSE_START:
139210696SDavid.Hollister@Sun.COM 		return ("TGT_RESPONSE_START");
139310696SDavid.Hollister@Sun.COM 		break;
139410696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_EDC_EXT_IO_START:
139510696SDavid.Hollister@Sun.COM 		return ("INI_EDC_EXT_IO_START");
139610696SDavid.Hollister@Sun.COM 		break;
139710696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_EDC_EXT_IO_START1:
139810696SDavid.Hollister@Sun.COM 		return ("INI_EDC_EXT_IO_START1");
139910696SDavid.Hollister@Sun.COM 		break;
140010696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_TGT_EDC_IO_START:
140110696SDavid.Hollister@Sun.COM 		return ("TGT_EDC_IO_START");
140210696SDavid.Hollister@Sun.COM 		break;
140310696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_ABORT:
140410696SDavid.Hollister@Sun.COM 		return ("SSP_ABORT");
140510696SDavid.Hollister@Sun.COM 		break;
140610696SDavid.Hollister@Sun.COM 	case PMCIN_DEREGISTER_DEVICE_HANDLE:
140710696SDavid.Hollister@Sun.COM 		return ("DEREGISTER_DEVICE_HANDLE");
140810696SDavid.Hollister@Sun.COM 		break;
140910696SDavid.Hollister@Sun.COM 	case PMCIN_GET_DEVICE_HANDLE:
141010696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_HANDLE");
141110696SDavid.Hollister@Sun.COM 		break;
141210696SDavid.Hollister@Sun.COM 	case PMCIN_SMP_REQUEST:
141310696SDavid.Hollister@Sun.COM 		return ("SMP_REQUEST");
141410696SDavid.Hollister@Sun.COM 		break;
141510696SDavid.Hollister@Sun.COM 	case PMCIN_SMP_RESPONSE:
141610696SDavid.Hollister@Sun.COM 		return ("SMP_RESPONSE");
141710696SDavid.Hollister@Sun.COM 		break;
141810696SDavid.Hollister@Sun.COM 	case PMCIN_SMP_ABORT:
141910696SDavid.Hollister@Sun.COM 		return ("SMP_ABORT");
142010696SDavid.Hollister@Sun.COM 		break;
142110696SDavid.Hollister@Sun.COM 	case PMCIN_ASSISTED_DISCOVERY:
142210696SDavid.Hollister@Sun.COM 		return ("ASSISTED_DISCOVERY");
142310696SDavid.Hollister@Sun.COM 		break;
142410696SDavid.Hollister@Sun.COM 	case PMCIN_REGISTER_DEVICE:
142510696SDavid.Hollister@Sun.COM 		return ("REGISTER_DEVICE");
142610696SDavid.Hollister@Sun.COM 		break;
142710696SDavid.Hollister@Sun.COM 	case PMCIN_SATA_HOST_IO_START:
142810696SDavid.Hollister@Sun.COM 		return ("SATA_HOST_IO_START");
142910696SDavid.Hollister@Sun.COM 		break;
143010696SDavid.Hollister@Sun.COM 	case PMCIN_SATA_ABORT:
143110696SDavid.Hollister@Sun.COM 		return ("SATA_ABORT");
143210696SDavid.Hollister@Sun.COM 		break;
143310696SDavid.Hollister@Sun.COM 	case PMCIN_LOCAL_PHY_CONTROL:
143410696SDavid.Hollister@Sun.COM 		return ("LOCAL_PHY_CONTROL");
143510696SDavid.Hollister@Sun.COM 		break;
143610696SDavid.Hollister@Sun.COM 	case PMCIN_GET_DEVICE_INFO:
143710696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_INFO");
143810696SDavid.Hollister@Sun.COM 		break;
143910696SDavid.Hollister@Sun.COM 	case PMCIN_TWI:
144010696SDavid.Hollister@Sun.COM 		return ("TWI");
144110696SDavid.Hollister@Sun.COM 		break;
144210696SDavid.Hollister@Sun.COM 	case PMCIN_FW_FLASH_UPDATE:
144310696SDavid.Hollister@Sun.COM 		return ("FW_FLASH_UPDATE");
144410696SDavid.Hollister@Sun.COM 		break;
144510696SDavid.Hollister@Sun.COM 	case PMCIN_SET_VPD:
144610696SDavid.Hollister@Sun.COM 		return ("SET_VPD");
144710696SDavid.Hollister@Sun.COM 		break;
144810696SDavid.Hollister@Sun.COM 	case PMCIN_GPIO:
144910696SDavid.Hollister@Sun.COM 		return ("GPIO");
145010696SDavid.Hollister@Sun.COM 		break;
145110696SDavid.Hollister@Sun.COM 	case PMCIN_SAS_DIAG_MODE_START_END:
145210696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_MODE_START_END");
145310696SDavid.Hollister@Sun.COM 		break;
145410696SDavid.Hollister@Sun.COM 	case PMCIN_SAS_DIAG_EXECUTE:
145510696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_EXECUTE");
145610696SDavid.Hollister@Sun.COM 		break;
145712258Ssrikanth.suravajhala@oracle.com 	case PMCIN_SAS_HW_EVENT_ACK:
145810696SDavid.Hollister@Sun.COM 		return ("SAS_HW_EVENT_ACK");
145910696SDavid.Hollister@Sun.COM 		break;
146010696SDavid.Hollister@Sun.COM 	case PMCIN_GET_TIME_STAMP:
146110696SDavid.Hollister@Sun.COM 		return ("GET_TIME_STAMP");
146210696SDavid.Hollister@Sun.COM 		break;
146310696SDavid.Hollister@Sun.COM 	case PMCIN_PORT_CONTROL:
146410696SDavid.Hollister@Sun.COM 		return ("PORT_CONTROL");
146510696SDavid.Hollister@Sun.COM 		break;
146610696SDavid.Hollister@Sun.COM 	case PMCIN_GET_NVMD_DATA:
146710696SDavid.Hollister@Sun.COM 		return ("GET_NVMD_DATA");
146810696SDavid.Hollister@Sun.COM 		break;
146910696SDavid.Hollister@Sun.COM 	case PMCIN_SET_NVMD_DATA:
147010696SDavid.Hollister@Sun.COM 		return ("SET_NVMD_DATA");
147110696SDavid.Hollister@Sun.COM 		break;
147210696SDavid.Hollister@Sun.COM 	case PMCIN_SET_DEVICE_STATE:
147310696SDavid.Hollister@Sun.COM 		return ("SET_DEVICE_STATE");
147410696SDavid.Hollister@Sun.COM 		break;
147510696SDavid.Hollister@Sun.COM 	case PMCIN_GET_DEVICE_STATE:
147610696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_STATE");
147710696SDavid.Hollister@Sun.COM 		break;
147810696SDavid.Hollister@Sun.COM 	default:
147910696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
148010696SDavid.Hollister@Sun.COM 		break;
148110696SDavid.Hollister@Sun.COM 	}
148210696SDavid.Hollister@Sun.COM }
148310696SDavid.Hollister@Sun.COM 
148410696SDavid.Hollister@Sun.COM static char *
outbound_iomb_opcode(uint32_t opcode)148510696SDavid.Hollister@Sun.COM outbound_iomb_opcode(uint32_t opcode)
148610696SDavid.Hollister@Sun.COM {
148710696SDavid.Hollister@Sun.COM 	switch (opcode) {
148810696SDavid.Hollister@Sun.COM 	case PMCOUT_ECHO:
148910696SDavid.Hollister@Sun.COM 		return ("ECHO");
149010696SDavid.Hollister@Sun.COM 		break;
149110696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_INFO:
149210696SDavid.Hollister@Sun.COM 		return ("GET_INFO");
149310696SDavid.Hollister@Sun.COM 		break;
149410696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_VPD:
149510696SDavid.Hollister@Sun.COM 		return ("GET_VPD");
149610696SDavid.Hollister@Sun.COM 		break;
149710696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_HW_EVENT:
149810696SDavid.Hollister@Sun.COM 		return ("SAS_HW_EVENT");
149910696SDavid.Hollister@Sun.COM 		break;
150010696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_COMPLETION:
150110696SDavid.Hollister@Sun.COM 		return ("SSP_COMPLETION");
150210696SDavid.Hollister@Sun.COM 		break;
150310696SDavid.Hollister@Sun.COM 	case PMCOUT_SMP_COMPLETION:
150410696SDavid.Hollister@Sun.COM 		return ("SMP_COMPLETION");
150510696SDavid.Hollister@Sun.COM 		break;
150610696SDavid.Hollister@Sun.COM 	case PMCOUT_LOCAL_PHY_CONTROL:
150710696SDavid.Hollister@Sun.COM 		return ("LOCAL_PHY_CONTROL");
150810696SDavid.Hollister@Sun.COM 		break;
150910696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_ASSISTED_DISCOVERY_EVENT:
151010696SDavid.Hollister@Sun.COM 		return ("SAS_ASSISTED_DISCOVERY_SENT");
151110696SDavid.Hollister@Sun.COM 		break;
151210696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_ASSISTED_DISCOVERY_EVENT:
151310696SDavid.Hollister@Sun.COM 		return ("SATA_ASSISTED_DISCOVERY_SENT");
151410696SDavid.Hollister@Sun.COM 		break;
151510696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_REGISTRATION:
151610696SDavid.Hollister@Sun.COM 		return ("DEVICE_REGISTRATION");
151710696SDavid.Hollister@Sun.COM 		break;
151810696SDavid.Hollister@Sun.COM 	case PMCOUT_DEREGISTER_DEVICE_HANDLE:
151910696SDavid.Hollister@Sun.COM 		return ("DEREGISTER_DEVICE_HANDLE");
152010696SDavid.Hollister@Sun.COM 		break;
152110696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_DEVICE_HANDLE:
152210696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_HANDLE");
152310696SDavid.Hollister@Sun.COM 		break;
152410696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_COMPLETION:
152510696SDavid.Hollister@Sun.COM 		return ("SATA_COMPLETION");
152610696SDavid.Hollister@Sun.COM 		break;
152710696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_EVENT:
152810696SDavid.Hollister@Sun.COM 		return ("SATA_EVENT");
152910696SDavid.Hollister@Sun.COM 		break;
153010696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_EVENT:
153110696SDavid.Hollister@Sun.COM 		return ("SSP_EVENT");
153210696SDavid.Hollister@Sun.COM 		break;
153310696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_HANDLE_ARRIVED:
153410696SDavid.Hollister@Sun.COM 		return ("DEVICE_HANDLE_ARRIVED");
153510696SDavid.Hollister@Sun.COM 		break;
153610696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_REQUEST_RECEIVED:
153710696SDavid.Hollister@Sun.COM 		return ("SSP_REQUEST_RECEIVED");
153810696SDavid.Hollister@Sun.COM 		break;
153910696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_INFO:
154010696SDavid.Hollister@Sun.COM 		return ("DEVICE_INFO");
154110696SDavid.Hollister@Sun.COM 		break;
154210696SDavid.Hollister@Sun.COM 	case PMCOUT_FW_FLASH_UPDATE:
154310696SDavid.Hollister@Sun.COM 		return ("FW_FLASH_UPDATE");
154410696SDavid.Hollister@Sun.COM 		break;
154510696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_VPD:
154610696SDavid.Hollister@Sun.COM 		return ("SET_VPD");
154710696SDavid.Hollister@Sun.COM 		break;
154810696SDavid.Hollister@Sun.COM 	case PMCOUT_GPIO:
154910696SDavid.Hollister@Sun.COM 		return ("GPIO");
155010696SDavid.Hollister@Sun.COM 		break;
155110696SDavid.Hollister@Sun.COM 	case PMCOUT_GPIO_EVENT:
155210696SDavid.Hollister@Sun.COM 		return ("GPIO_EVENT");
155310696SDavid.Hollister@Sun.COM 		break;
155410696SDavid.Hollister@Sun.COM 	case PMCOUT_GENERAL_EVENT:
155510696SDavid.Hollister@Sun.COM 		return ("GENERAL_EVENT");
155610696SDavid.Hollister@Sun.COM 		break;
155710696SDavid.Hollister@Sun.COM 	case PMCOUT_TWI:
155810696SDavid.Hollister@Sun.COM 		return ("TWI");
155910696SDavid.Hollister@Sun.COM 		break;
156010696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_ABORT:
156110696SDavid.Hollister@Sun.COM 		return ("SSP_ABORT");
156210696SDavid.Hollister@Sun.COM 		break;
156310696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_ABORT:
156410696SDavid.Hollister@Sun.COM 		return ("SATA_ABORT");
156510696SDavid.Hollister@Sun.COM 		break;
156610696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_DIAG_MODE_START_END:
156710696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_MODE_START_END");
156810696SDavid.Hollister@Sun.COM 		break;
156910696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_DIAG_EXECUTE:
157010696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_EXECUTE");
157110696SDavid.Hollister@Sun.COM 		break;
157210696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_TIME_STAMP:
157310696SDavid.Hollister@Sun.COM 		return ("GET_TIME_STAMP");
157410696SDavid.Hollister@Sun.COM 		break;
157510696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_HW_EVENT_ACK_ACK:
157610696SDavid.Hollister@Sun.COM 		return ("SAS_HW_EVENT_ACK_ACK");
157710696SDavid.Hollister@Sun.COM 		break;
157810696SDavid.Hollister@Sun.COM 	case PMCOUT_PORT_CONTROL:
157910696SDavid.Hollister@Sun.COM 		return ("PORT_CONTROL");
158010696SDavid.Hollister@Sun.COM 		break;
158110696SDavid.Hollister@Sun.COM 	case PMCOUT_SKIP_ENTRIES:
158210696SDavid.Hollister@Sun.COM 		return ("SKIP_ENTRIES");
158310696SDavid.Hollister@Sun.COM 		break;
158410696SDavid.Hollister@Sun.COM 	case PMCOUT_SMP_ABORT:
158510696SDavid.Hollister@Sun.COM 		return ("SMP_ABORT");
158610696SDavid.Hollister@Sun.COM 		break;
158710696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_NVMD_DATA:
158810696SDavid.Hollister@Sun.COM 		return ("GET_NVMD_DATA");
158910696SDavid.Hollister@Sun.COM 		break;
159010696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_NVMD_DATA:
159110696SDavid.Hollister@Sun.COM 		return ("SET_NVMD_DATA");
159210696SDavid.Hollister@Sun.COM 		break;
159310696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_HANDLE_REMOVED:
159410696SDavid.Hollister@Sun.COM 		return ("DEVICE_HANDLE_REMOVED");
159510696SDavid.Hollister@Sun.COM 		break;
159610696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_DEVICE_STATE:
159710696SDavid.Hollister@Sun.COM 		return ("SET_DEVICE_STATE");
159810696SDavid.Hollister@Sun.COM 		break;
159910696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_DEVICE_STATE:
160010696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_STATE");
160110696SDavid.Hollister@Sun.COM 		break;
160210696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_DEVICE_INFO:
160310696SDavid.Hollister@Sun.COM 		return ("SET_DEVICE_INFO");
160410696SDavid.Hollister@Sun.COM 		break;
160510696SDavid.Hollister@Sun.COM 	default:
160610696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
160710696SDavid.Hollister@Sun.COM 		break;
160810696SDavid.Hollister@Sun.COM 	}
160910696SDavid.Hollister@Sun.COM }
161010696SDavid.Hollister@Sun.COM 
1611*12791Sdavid.hollister@oracle.com static uint32_t
get_devid_from_ob_iomb(struct pmcs_hw ss,uint32_t * qentryp,uint16_t opcode)1612*12791Sdavid.hollister@oracle.com get_devid_from_ob_iomb(struct pmcs_hw ss, uint32_t *qentryp, uint16_t opcode)
1613*12791Sdavid.hollister@oracle.com {
1614*12791Sdavid.hollister@oracle.com 	uint32_t devid = PMCS_INVALID_DEVICE_ID;
1615*12791Sdavid.hollister@oracle.com 
1616*12791Sdavid.hollister@oracle.com 	switch (opcode) {
1617*12791Sdavid.hollister@oracle.com 	/*
1618*12791Sdavid.hollister@oracle.com 	 * These are obtained via the HTAG which is in word 1
1619*12791Sdavid.hollister@oracle.com 	 */
1620*12791Sdavid.hollister@oracle.com 	case PMCOUT_SSP_COMPLETION:
1621*12791Sdavid.hollister@oracle.com 	case PMCOUT_SMP_COMPLETION:
1622*12791Sdavid.hollister@oracle.com 	case PMCOUT_DEREGISTER_DEVICE_HANDLE:
1623*12791Sdavid.hollister@oracle.com 	case PMCOUT_GET_DEVICE_HANDLE:
1624*12791Sdavid.hollister@oracle.com 	case PMCOUT_SATA_COMPLETION:
1625*12791Sdavid.hollister@oracle.com 	case PMCOUT_SSP_ABORT:
1626*12791Sdavid.hollister@oracle.com 	case PMCOUT_SATA_ABORT:
1627*12791Sdavid.hollister@oracle.com 	case PMCOUT_SMP_ABORT:
1628*12791Sdavid.hollister@oracle.com 	case PMCOUT_SAS_HW_EVENT_ACK_ACK: {
1629*12791Sdavid.hollister@oracle.com 		uint32_t	htag;
1630*12791Sdavid.hollister@oracle.com 		pmcwork_t	*wp;
1631*12791Sdavid.hollister@oracle.com 		pmcs_phy_t	*phy;
1632*12791Sdavid.hollister@oracle.com 		uintptr_t	_wp, _phy;
1633*12791Sdavid.hollister@oracle.com 		uint16_t	index;
1634*12791Sdavid.hollister@oracle.com 
1635*12791Sdavid.hollister@oracle.com 		htag = LE_32(*(qentryp + 1));
1636*12791Sdavid.hollister@oracle.com 		index = htag & PMCS_TAG_INDEX_MASK;
1637*12791Sdavid.hollister@oracle.com 
1638*12791Sdavid.hollister@oracle.com 		wp = mdb_alloc(sizeof (pmcwork_t), UM_SLEEP);
1639*12791Sdavid.hollister@oracle.com 		_wp = (uintptr_t)ss.work + (sizeof (pmcwork_t) * index);
1640*12791Sdavid.hollister@oracle.com 
1641*12791Sdavid.hollister@oracle.com 		if (MDB_RD(wp, sizeof (pmcwork_t), _wp) == -1) {
1642*12791Sdavid.hollister@oracle.com 			NOREAD(pmcwork_t, _wp);
1643*12791Sdavid.hollister@oracle.com 			mdb_free(wp, sizeof (pmcwork_t));
1644*12791Sdavid.hollister@oracle.com 			break;
1645*12791Sdavid.hollister@oracle.com 		}
1646*12791Sdavid.hollister@oracle.com 
1647*12791Sdavid.hollister@oracle.com 		phy = mdb_alloc(sizeof (pmcs_phy_t), UM_SLEEP);
1648*12791Sdavid.hollister@oracle.com 		if (wp->phy == NULL) {
1649*12791Sdavid.hollister@oracle.com 			_phy = (uintptr_t)wp->last_phy;
1650*12791Sdavid.hollister@oracle.com 		} else {
1651*12791Sdavid.hollister@oracle.com 			_phy = (uintptr_t)wp->phy;
1652*12791Sdavid.hollister@oracle.com 		}
1653*12791Sdavid.hollister@oracle.com 
1654*12791Sdavid.hollister@oracle.com 		/*
1655*12791Sdavid.hollister@oracle.com 		 * If we have a PHY, read it in and get it's handle
1656*12791Sdavid.hollister@oracle.com 		 */
1657*12791Sdavid.hollister@oracle.com 		if (_phy != NULL) {
1658*12791Sdavid.hollister@oracle.com 			if (MDB_RD(phy, sizeof (*phy), _phy) == -1) {
1659*12791Sdavid.hollister@oracle.com 				NOREAD(pmcs_phy_t, phy);
1660*12791Sdavid.hollister@oracle.com 			} else {
1661*12791Sdavid.hollister@oracle.com 				devid = phy->device_id;
1662*12791Sdavid.hollister@oracle.com 			}
1663*12791Sdavid.hollister@oracle.com 		}
1664*12791Sdavid.hollister@oracle.com 
1665*12791Sdavid.hollister@oracle.com 		mdb_free(phy, sizeof (pmcs_phy_t));
1666*12791Sdavid.hollister@oracle.com 		mdb_free(wp, sizeof (pmcwork_t));
1667*12791Sdavid.hollister@oracle.com 		break;
1668*12791Sdavid.hollister@oracle.com 	}
1669*12791Sdavid.hollister@oracle.com 
1670*12791Sdavid.hollister@oracle.com 	/*
1671*12791Sdavid.hollister@oracle.com 	 * The device ID is in the outbound IOMB at word 1
1672*12791Sdavid.hollister@oracle.com 	 */
1673*12791Sdavid.hollister@oracle.com 	case PMCOUT_SSP_REQUEST_RECEIVED:
1674*12791Sdavid.hollister@oracle.com 		devid = LE_32(*(qentryp + 1)) & PMCS_DEVICE_ID_MASK;
1675*12791Sdavid.hollister@oracle.com 		break;
1676*12791Sdavid.hollister@oracle.com 
1677*12791Sdavid.hollister@oracle.com 	/*
1678*12791Sdavid.hollister@oracle.com 	 * The device ID is in the outbound IOMB at word 2
1679*12791Sdavid.hollister@oracle.com 	 */
1680*12791Sdavid.hollister@oracle.com 	case PMCOUT_DEVICE_HANDLE_ARRIVED:
1681*12791Sdavid.hollister@oracle.com 	case PMCOUT_DEVICE_HANDLE_REMOVED:
1682*12791Sdavid.hollister@oracle.com 		devid = LE_32(*(qentryp + 2)) & PMCS_DEVICE_ID_MASK;
1683*12791Sdavid.hollister@oracle.com 		break;
1684*12791Sdavid.hollister@oracle.com 
1685*12791Sdavid.hollister@oracle.com 	/*
1686*12791Sdavid.hollister@oracle.com 	 * In this (very rare - never seen it) state, the device ID
1687*12791Sdavid.hollister@oracle.com 	 * comes from the HTAG in the inbound IOMB, which would be word
1688*12791Sdavid.hollister@oracle.com 	 * 3 in the outbound IOMB
1689*12791Sdavid.hollister@oracle.com 	 */
1690*12791Sdavid.hollister@oracle.com 	case PMCOUT_GENERAL_EVENT:
1691*12791Sdavid.hollister@oracle.com 	/*
1692*12791Sdavid.hollister@oracle.com 	 * The device ID is in the outbound IOMB at word 3
1693*12791Sdavid.hollister@oracle.com 	 */
1694*12791Sdavid.hollister@oracle.com 	case PMCOUT_DEVICE_REGISTRATION:
1695*12791Sdavid.hollister@oracle.com 	case PMCOUT_DEVICE_INFO:
1696*12791Sdavid.hollister@oracle.com 	case PMCOUT_SET_DEVICE_STATE:
1697*12791Sdavid.hollister@oracle.com 	case PMCOUT_GET_DEVICE_STATE:
1698*12791Sdavid.hollister@oracle.com 	case PMCOUT_SET_DEVICE_INFO:
1699*12791Sdavid.hollister@oracle.com 		devid = LE_32(*(qentryp + 3)) & PMCS_DEVICE_ID_MASK;
1700*12791Sdavid.hollister@oracle.com 		break;
1701*12791Sdavid.hollister@oracle.com 
1702*12791Sdavid.hollister@oracle.com 	/*
1703*12791Sdavid.hollister@oracle.com 	 * Device ID is in the outbound IOMB at word 4
1704*12791Sdavid.hollister@oracle.com 	 */
1705*12791Sdavid.hollister@oracle.com 	case PMCOUT_SATA_EVENT:
1706*12791Sdavid.hollister@oracle.com 	case PMCOUT_SSP_EVENT:
1707*12791Sdavid.hollister@oracle.com 		devid = LE_32(*(qentryp + 4)) & PMCS_DEVICE_ID_MASK;
1708*12791Sdavid.hollister@oracle.com 		break;
1709*12791Sdavid.hollister@oracle.com 	}
1710*12791Sdavid.hollister@oracle.com 
1711*12791Sdavid.hollister@oracle.com 	return (devid);
1712*12791Sdavid.hollister@oracle.com }
1713*12791Sdavid.hollister@oracle.com 
1714*12791Sdavid.hollister@oracle.com static boolean_t
iomb_is_dev_hdl_specific(uint32_t word0,boolean_t inbound)1715*12791Sdavid.hollister@oracle.com iomb_is_dev_hdl_specific(uint32_t word0, boolean_t inbound)
1716*12791Sdavid.hollister@oracle.com {
1717*12791Sdavid.hollister@oracle.com 	uint16_t opcode = word0 & PMCS_IOMB_OPCODE_MASK;
1718*12791Sdavid.hollister@oracle.com 
1719*12791Sdavid.hollister@oracle.com 	if (inbound) {
1720*12791Sdavid.hollister@oracle.com 		switch (opcode) {
1721*12791Sdavid.hollister@oracle.com 		case PMCIN_SSP_INI_IO_START:
1722*12791Sdavid.hollister@oracle.com 		case PMCIN_SSP_INI_TM_START:
1723*12791Sdavid.hollister@oracle.com 		case PMCIN_SSP_INI_EXT_IO_START:
1724*12791Sdavid.hollister@oracle.com 		case PMCIN_SSP_TGT_IO_START:
1725*12791Sdavid.hollister@oracle.com 		case PMCIN_SSP_TGT_RESPONSE_START:
1726*12791Sdavid.hollister@oracle.com 		case PMCIN_SSP_ABORT:
1727*12791Sdavid.hollister@oracle.com 		case PMCIN_DEREGISTER_DEVICE_HANDLE:
1728*12791Sdavid.hollister@oracle.com 		case PMCIN_SMP_REQUEST:
1729*12791Sdavid.hollister@oracle.com 		case PMCIN_SMP_RESPONSE:
1730*12791Sdavid.hollister@oracle.com 		case PMCIN_SMP_ABORT:
1731*12791Sdavid.hollister@oracle.com 		case PMCIN_ASSISTED_DISCOVERY:
1732*12791Sdavid.hollister@oracle.com 		case PMCIN_SATA_HOST_IO_START:
1733*12791Sdavid.hollister@oracle.com 		case PMCIN_SATA_ABORT:
1734*12791Sdavid.hollister@oracle.com 		case PMCIN_GET_DEVICE_INFO:
1735*12791Sdavid.hollister@oracle.com 		case PMCIN_SET_DEVICE_STATE:
1736*12791Sdavid.hollister@oracle.com 		case PMCIN_GET_DEVICE_STATE:
1737*12791Sdavid.hollister@oracle.com 			return (B_TRUE);
1738*12791Sdavid.hollister@oracle.com 		}
1739*12791Sdavid.hollister@oracle.com 
1740*12791Sdavid.hollister@oracle.com 		return (B_FALSE);
1741*12791Sdavid.hollister@oracle.com 	}
1742*12791Sdavid.hollister@oracle.com 
1743*12791Sdavid.hollister@oracle.com 	switch (opcode) {
1744*12791Sdavid.hollister@oracle.com 	case PMCOUT_SSP_COMPLETION:
1745*12791Sdavid.hollister@oracle.com 	case PMCOUT_SMP_COMPLETION:
1746*12791Sdavid.hollister@oracle.com 	case PMCOUT_DEVICE_REGISTRATION:
1747*12791Sdavid.hollister@oracle.com 	case PMCOUT_DEREGISTER_DEVICE_HANDLE:
1748*12791Sdavid.hollister@oracle.com 	case PMCOUT_GET_DEVICE_HANDLE:
1749*12791Sdavid.hollister@oracle.com 	case PMCOUT_SATA_COMPLETION:
1750*12791Sdavid.hollister@oracle.com 	case PMCOUT_SATA_EVENT:
1751*12791Sdavid.hollister@oracle.com 	case PMCOUT_SSP_EVENT:
1752*12791Sdavid.hollister@oracle.com 	case PMCOUT_DEVICE_HANDLE_ARRIVED:
1753*12791Sdavid.hollister@oracle.com 	case PMCOUT_SSP_REQUEST_RECEIVED:
1754*12791Sdavid.hollister@oracle.com 	case PMCOUT_DEVICE_INFO:
1755*12791Sdavid.hollister@oracle.com 	case PMCOUT_FW_FLASH_UPDATE:
1756*12791Sdavid.hollister@oracle.com 	case PMCOUT_GENERAL_EVENT:
1757*12791Sdavid.hollister@oracle.com 	case PMCOUT_SSP_ABORT:
1758*12791Sdavid.hollister@oracle.com 	case PMCOUT_SATA_ABORT:
1759*12791Sdavid.hollister@oracle.com 	case PMCOUT_SAS_HW_EVENT_ACK_ACK:
1760*12791Sdavid.hollister@oracle.com 	case PMCOUT_SMP_ABORT:
1761*12791Sdavid.hollister@oracle.com 	case PMCOUT_DEVICE_HANDLE_REMOVED:
1762*12791Sdavid.hollister@oracle.com 	case PMCOUT_SET_DEVICE_STATE:
1763*12791Sdavid.hollister@oracle.com 	case PMCOUT_GET_DEVICE_STATE:
1764*12791Sdavid.hollister@oracle.com 	case PMCOUT_SET_DEVICE_INFO:
1765*12791Sdavid.hollister@oracle.com 		return (B_TRUE);
1766*12791Sdavid.hollister@oracle.com 	}
1767*12791Sdavid.hollister@oracle.com 
1768*12791Sdavid.hollister@oracle.com 	return (B_FALSE);
1769*12791Sdavid.hollister@oracle.com }
1770*12791Sdavid.hollister@oracle.com 
177110696SDavid.Hollister@Sun.COM static void
dump_one_qentry_outbound(struct pmcs_hw ss,uint32_t * qentryp,int idx,uint64_t devid_filter)1772*12791Sdavid.hollister@oracle.com dump_one_qentry_outbound(struct pmcs_hw ss, uint32_t *qentryp, int idx,
1773*12791Sdavid.hollister@oracle.com     uint64_t devid_filter)
177410696SDavid.Hollister@Sun.COM {
177510696SDavid.Hollister@Sun.COM 	int qeidx;
177610696SDavid.Hollister@Sun.COM 	uint32_t word0 = LE_32(*qentryp);
177711601SDavid.Hollister@Sun.COM 	uint32_t word1 = LE_32(*(qentryp + 1));
177811601SDavid.Hollister@Sun.COM 	uint8_t iop_event;
1779*12791Sdavid.hollister@oracle.com 	uint32_t devid;
1780*12791Sdavid.hollister@oracle.com 
1781*12791Sdavid.hollister@oracle.com 	/*
1782*12791Sdavid.hollister@oracle.com 	 * Check to see if we're filtering on a device ID
1783*12791Sdavid.hollister@oracle.com 	 */
1784*12791Sdavid.hollister@oracle.com 	if (devid_filter != PMCS_INVALID_DEVICE_ID) {
1785*12791Sdavid.hollister@oracle.com 		if (!iomb_is_dev_hdl_specific(word0, B_FALSE)) {
1786*12791Sdavid.hollister@oracle.com 			return;
1787*12791Sdavid.hollister@oracle.com 		}
1788*12791Sdavid.hollister@oracle.com 
1789*12791Sdavid.hollister@oracle.com 		/*
1790*12791Sdavid.hollister@oracle.com 		 * Go find the device id.  It might be in the outbound
1791*12791Sdavid.hollister@oracle.com 		 * IOMB or we may have to go find the work structure and
1792*12791Sdavid.hollister@oracle.com 		 * get it from there.
1793*12791Sdavid.hollister@oracle.com 		 */
1794*12791Sdavid.hollister@oracle.com 		devid = get_devid_from_ob_iomb(ss, qentryp,
1795*12791Sdavid.hollister@oracle.com 		    word0 & PMCS_IOMB_OPCODE_MASK);
1796*12791Sdavid.hollister@oracle.com 		if ((devid == PMCS_INVALID_DEVICE_ID) ||
1797*12791Sdavid.hollister@oracle.com 		    (devid_filter != devid)) {
1798*12791Sdavid.hollister@oracle.com 			return;
1799*12791Sdavid.hollister@oracle.com 		}
1800*12791Sdavid.hollister@oracle.com 	}
180110696SDavid.Hollister@Sun.COM 
180210696SDavid.Hollister@Sun.COM 	mdb_printf("Entry #%02d\n", idx);
180310696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
180410696SDavid.Hollister@Sun.COM 
180510696SDavid.Hollister@Sun.COM 	mdb_printf("Header: 0x%08x (", word0);
180610696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_VALID) {
180710696SDavid.Hollister@Sun.COM 		mdb_printf("VALID, ");
180810696SDavid.Hollister@Sun.COM 	}
180910696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_HIPRI) {
181010696SDavid.Hollister@Sun.COM 		mdb_printf("HIPRI, ");
181110696SDavid.Hollister@Sun.COM 	}
181210696SDavid.Hollister@Sun.COM 	mdb_printf("OBID=%d, ",
181310696SDavid.Hollister@Sun.COM 	    (word0 & PMCS_IOMB_OBID_MASK) >> PMCS_IOMB_OBID_SHIFT);
181410696SDavid.Hollister@Sun.COM 	mdb_printf("CAT=%s, ",
181510696SDavid.Hollister@Sun.COM 	    iomb_cat((word0 & PMCS_IOMB_CAT_MASK) >> PMCS_IOMB_CAT_SHIFT));
181610696SDavid.Hollister@Sun.COM 	mdb_printf("OPCODE=%s",
181710696SDavid.Hollister@Sun.COM 	    outbound_iomb_opcode(word0 & PMCS_IOMB_OPCODE_MASK));
181811601SDavid.Hollister@Sun.COM 	if ((word0 & PMCS_IOMB_OPCODE_MASK) == PMCOUT_SAS_HW_EVENT) {
181911601SDavid.Hollister@Sun.COM 		iop_event = IOP_EVENT_EVENT(word1);
182011601SDavid.Hollister@Sun.COM 		mdb_printf(" <%s>", iomb_event(iop_event));
182111601SDavid.Hollister@Sun.COM 	}
182210696SDavid.Hollister@Sun.COM 	mdb_printf(")\n");
182310696SDavid.Hollister@Sun.COM 
182410696SDavid.Hollister@Sun.COM 	mdb_printf("Remaining Payload:\n");
182510696SDavid.Hollister@Sun.COM 
182610696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
182710696SDavid.Hollister@Sun.COM 	for (qeidx = 1; qeidx < (PMCS_QENTRY_SIZE / 4); qeidx++) {
182810696SDavid.Hollister@Sun.COM 		mdb_printf("%08x ", LE_32(*(qentryp + qeidx)));
182910696SDavid.Hollister@Sun.COM 	}
183010696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
183110696SDavid.Hollister@Sun.COM 	mdb_dec_indent(4);
183210696SDavid.Hollister@Sun.COM }
183310696SDavid.Hollister@Sun.COM 
183410696SDavid.Hollister@Sun.COM static void
display_outbound_queues(struct pmcs_hw ss,uint64_t devid_filter,uint_t verbose)1835*12791Sdavid.hollister@oracle.com display_outbound_queues(struct pmcs_hw ss, uint64_t devid_filter,
1836*12791Sdavid.hollister@oracle.com     uint_t verbose)
183710696SDavid.Hollister@Sun.COM {
183810696SDavid.Hollister@Sun.COM 	int		idx, qidx;
183910696SDavid.Hollister@Sun.COM 	uintptr_t	obqp;
184010696SDavid.Hollister@Sun.COM 	uint32_t	*cip;
184110696SDavid.Hollister@Sun.COM 	uint32_t	*qentryp = mdb_alloc(PMCS_QENTRY_SIZE, UM_SLEEP);
184210696SDavid.Hollister@Sun.COM 	uint32_t	last_consumed, oqpi;
184310696SDavid.Hollister@Sun.COM 
184410696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
184510696SDavid.Hollister@Sun.COM 	mdb_printf("Outbound Queues\n");
184610696SDavid.Hollister@Sun.COM 	mdb_printf("---------------\n");
184710696SDavid.Hollister@Sun.COM 
184810696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
184910696SDavid.Hollister@Sun.COM 
185010696SDavid.Hollister@Sun.COM 	for (qidx = 0; qidx < PMCS_NOQ; qidx++) {
185110696SDavid.Hollister@Sun.COM 		obqp = (uintptr_t)ss.oqp[qidx];
185210696SDavid.Hollister@Sun.COM 
185310696SDavid.Hollister@Sun.COM 		if (obqp == NULL) {
185410696SDavid.Hollister@Sun.COM 			mdb_printf("No outbound queue ptr for queue #%d\n",
185510696SDavid.Hollister@Sun.COM 			    qidx);
185610696SDavid.Hollister@Sun.COM 			continue;
185710696SDavid.Hollister@Sun.COM 		}
185810696SDavid.Hollister@Sun.COM 
185910696SDavid.Hollister@Sun.COM 		mdb_printf("Outbound Queue #%d (Queue Type = %s)\n", qidx,
186010696SDavid.Hollister@Sun.COM 		    obq_type(qidx));
186110696SDavid.Hollister@Sun.COM 		/*
186210696SDavid.Hollister@Sun.COM 		 * Chip is the producer, so read the actual producer index
186310696SDavid.Hollister@Sun.COM 		 * and not the driver's version
186410696SDavid.Hollister@Sun.COM 		 */
186510696SDavid.Hollister@Sun.COM 		cip = (uint32_t *)((void *)ss.cip);
186610696SDavid.Hollister@Sun.COM 		if (MDB_RD(&oqpi, 4, cip + OQPI_BASE_OFFSET +
186710696SDavid.Hollister@Sun.COM 		    (qidx * 4)) == -1) {
186810696SDavid.Hollister@Sun.COM 			mdb_warn("Couldn't read oqpi\n");
186910696SDavid.Hollister@Sun.COM 			break;
187010696SDavid.Hollister@Sun.COM 		}
187110696SDavid.Hollister@Sun.COM 
187210696SDavid.Hollister@Sun.COM 		mdb_printf("Producer index: %d  Consumer index: %d\n\n",
187310696SDavid.Hollister@Sun.COM 		    LE_32(oqpi), ss.oqci[qidx]);
187410696SDavid.Hollister@Sun.COM 		mdb_inc_indent(2);
187510696SDavid.Hollister@Sun.COM 
187610696SDavid.Hollister@Sun.COM 		if (ss.oqci[qidx] == 0) {
187710696SDavid.Hollister@Sun.COM 			last_consumed = ss.ioq_depth - 1;
187810696SDavid.Hollister@Sun.COM 		} else {
187910696SDavid.Hollister@Sun.COM 			last_consumed = ss.oqci[qidx] - 1;
188010696SDavid.Hollister@Sun.COM 		}
188110696SDavid.Hollister@Sun.COM 
188210696SDavid.Hollister@Sun.COM 
188310696SDavid.Hollister@Sun.COM 		if (!verbose) {
188410696SDavid.Hollister@Sun.COM 			mdb_printf("Last processed entry:\n");
188510696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
188610696SDavid.Hollister@Sun.COM 			    (obqp + (PMCS_QENTRY_SIZE * last_consumed)))
188710696SDavid.Hollister@Sun.COM 			    == -1) {
188810696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
188910696SDavid.Hollister@Sun.COM 				    (obqp + (PMCS_QENTRY_SIZE *
189010696SDavid.Hollister@Sun.COM 				    last_consumed)));
189110696SDavid.Hollister@Sun.COM 				break;
189210696SDavid.Hollister@Sun.COM 			}
1893*12791Sdavid.hollister@oracle.com 			dump_one_qentry_outbound(ss, qentryp, last_consumed,
1894*12791Sdavid.hollister@oracle.com 			    devid_filter);
189510696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
189610696SDavid.Hollister@Sun.COM 			mdb_dec_indent(2);
189710696SDavid.Hollister@Sun.COM 			continue;
189810696SDavid.Hollister@Sun.COM 		}
189910696SDavid.Hollister@Sun.COM 
190010696SDavid.Hollister@Sun.COM 		for (idx = 0; idx < ss.ioq_depth; idx++) {
190110696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
190210696SDavid.Hollister@Sun.COM 			    (obqp + (PMCS_QENTRY_SIZE * idx))) == -1) {
190310696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
190410696SDavid.Hollister@Sun.COM 				    (obqp + (PMCS_QENTRY_SIZE * idx)));
190510696SDavid.Hollister@Sun.COM 				break;
190610696SDavid.Hollister@Sun.COM 			}
1907*12791Sdavid.hollister@oracle.com 			dump_one_qentry_outbound(ss, qentryp, idx,
1908*12791Sdavid.hollister@oracle.com 			    devid_filter);
190910696SDavid.Hollister@Sun.COM 		}
191010696SDavid.Hollister@Sun.COM 
191110696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
191210696SDavid.Hollister@Sun.COM 		mdb_dec_indent(2);
191310696SDavid.Hollister@Sun.COM 	}
191410696SDavid.Hollister@Sun.COM 
191510696SDavid.Hollister@Sun.COM 	mdb_dec_indent(2);
191610696SDavid.Hollister@Sun.COM 	mdb_free(qentryp, PMCS_QENTRY_SIZE);
191710696SDavid.Hollister@Sun.COM }
191810696SDavid.Hollister@Sun.COM 
191910696SDavid.Hollister@Sun.COM static void
dump_one_qentry_inbound(uint32_t * qentryp,int idx,uint64_t devid_filter)1920*12791Sdavid.hollister@oracle.com dump_one_qentry_inbound(uint32_t *qentryp, int idx, uint64_t devid_filter)
192110696SDavid.Hollister@Sun.COM {
192210696SDavid.Hollister@Sun.COM 	int qeidx;
192310696SDavid.Hollister@Sun.COM 	uint32_t word0 = LE_32(*qentryp);
1924*12791Sdavid.hollister@oracle.com 	uint32_t devid = LE_32(*(qentryp + 2));
1925*12791Sdavid.hollister@oracle.com 
1926*12791Sdavid.hollister@oracle.com 	/*
1927*12791Sdavid.hollister@oracle.com 	 * Check to see if we're filtering on a device ID
1928*12791Sdavid.hollister@oracle.com 	 */
1929*12791Sdavid.hollister@oracle.com 	if (devid_filter != PMCS_INVALID_DEVICE_ID) {
1930*12791Sdavid.hollister@oracle.com 		if (iomb_is_dev_hdl_specific(word0, B_TRUE)) {
1931*12791Sdavid.hollister@oracle.com 			if (devid_filter != devid) {
1932*12791Sdavid.hollister@oracle.com 				return;
1933*12791Sdavid.hollister@oracle.com 			}
1934*12791Sdavid.hollister@oracle.com 		} else {
1935*12791Sdavid.hollister@oracle.com 			return;
1936*12791Sdavid.hollister@oracle.com 		}
1937*12791Sdavid.hollister@oracle.com 	}
193810696SDavid.Hollister@Sun.COM 
193910696SDavid.Hollister@Sun.COM 	mdb_printf("Entry #%02d\n", idx);
194010696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
194110696SDavid.Hollister@Sun.COM 
194210696SDavid.Hollister@Sun.COM 	mdb_printf("Header: 0x%08x (", word0);
194310696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_VALID) {
194410696SDavid.Hollister@Sun.COM 		mdb_printf("VALID, ");
194510696SDavid.Hollister@Sun.COM 	}
194610696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_HIPRI) {
194710696SDavid.Hollister@Sun.COM 		mdb_printf("HIPRI, ");
194810696SDavid.Hollister@Sun.COM 	}
194910696SDavid.Hollister@Sun.COM 	mdb_printf("OBID=%d, ",
195010696SDavid.Hollister@Sun.COM 	    (word0 & PMCS_IOMB_OBID_MASK) >> PMCS_IOMB_OBID_SHIFT);
195110696SDavid.Hollister@Sun.COM 	mdb_printf("CAT=%s, ",
195210696SDavid.Hollister@Sun.COM 	    iomb_cat((word0 & PMCS_IOMB_CAT_MASK) >> PMCS_IOMB_CAT_SHIFT));
195310696SDavid.Hollister@Sun.COM 	mdb_printf("OPCODE=%s",
195410696SDavid.Hollister@Sun.COM 	    inbound_iomb_opcode(word0 & PMCS_IOMB_OPCODE_MASK));
195510696SDavid.Hollister@Sun.COM 	mdb_printf(")\n");
195610696SDavid.Hollister@Sun.COM 
195710696SDavid.Hollister@Sun.COM 	mdb_printf("HTAG: 0x%08x\n", LE_32(*(qentryp + 1)));
195810696SDavid.Hollister@Sun.COM 	mdb_printf("Remaining Payload:\n");
195910696SDavid.Hollister@Sun.COM 
196010696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
196110696SDavid.Hollister@Sun.COM 	for (qeidx = 2; qeidx < (PMCS_QENTRY_SIZE / 4); qeidx++) {
196210696SDavid.Hollister@Sun.COM 		mdb_printf("%08x ", LE_32(*(qentryp + qeidx)));
196310696SDavid.Hollister@Sun.COM 	}
196410696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
196510696SDavid.Hollister@Sun.COM 	mdb_dec_indent(4);
196610696SDavid.Hollister@Sun.COM }
196710696SDavid.Hollister@Sun.COM 
196810696SDavid.Hollister@Sun.COM static void
display_inbound_queues(struct pmcs_hw ss,uint64_t devid_filter,uint_t verbose)1969*12791Sdavid.hollister@oracle.com display_inbound_queues(struct pmcs_hw ss, uint64_t devid_filter, uint_t verbose)
197010696SDavid.Hollister@Sun.COM {
197110696SDavid.Hollister@Sun.COM 	int		idx, qidx, iqci, last_consumed;
197210696SDavid.Hollister@Sun.COM 	uintptr_t	ibqp;
197310696SDavid.Hollister@Sun.COM 	uint32_t	*qentryp = mdb_alloc(PMCS_QENTRY_SIZE, UM_SLEEP);
197410696SDavid.Hollister@Sun.COM 	uint32_t	*cip;
197510696SDavid.Hollister@Sun.COM 
197610696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
197710696SDavid.Hollister@Sun.COM 	mdb_printf("Inbound Queues\n");
197810696SDavid.Hollister@Sun.COM 	mdb_printf("--------------\n");
197910696SDavid.Hollister@Sun.COM 
198010696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
198110696SDavid.Hollister@Sun.COM 
198210696SDavid.Hollister@Sun.COM 	for (qidx = 0; qidx < PMCS_NIQ; qidx++) {
198310696SDavid.Hollister@Sun.COM 		ibqp = (uintptr_t)ss.iqp[qidx];
198410696SDavid.Hollister@Sun.COM 
198510696SDavid.Hollister@Sun.COM 		if (ibqp == NULL) {
198610696SDavid.Hollister@Sun.COM 			mdb_printf("No inbound queue ptr for queue #%d\n",
198710696SDavid.Hollister@Sun.COM 			    qidx);
198810696SDavid.Hollister@Sun.COM 			continue;
198910696SDavid.Hollister@Sun.COM 		}
199010696SDavid.Hollister@Sun.COM 
199110696SDavid.Hollister@Sun.COM 		mdb_printf("Inbound Queue #%d (Queue Type = %s)\n", qidx,
199210696SDavid.Hollister@Sun.COM 		    ibq_type(qidx));
199310696SDavid.Hollister@Sun.COM 
199410696SDavid.Hollister@Sun.COM 		cip = (uint32_t *)((void *)ss.cip);
199510696SDavid.Hollister@Sun.COM 		if (MDB_RD(&iqci, 4, cip + (qidx * 4)) == -1) {
199610696SDavid.Hollister@Sun.COM 			mdb_warn("Couldn't read iqci\n");
199710696SDavid.Hollister@Sun.COM 			break;
199810696SDavid.Hollister@Sun.COM 		}
199910696SDavid.Hollister@Sun.COM 		iqci = LE_32(iqci);
200010696SDavid.Hollister@Sun.COM 
200110696SDavid.Hollister@Sun.COM 		mdb_printf("Producer index: %d  Consumer index: %d\n\n",
200210696SDavid.Hollister@Sun.COM 		    ss.shadow_iqpi[qidx], iqci);
200310696SDavid.Hollister@Sun.COM 		mdb_inc_indent(2);
200410696SDavid.Hollister@Sun.COM 
200510696SDavid.Hollister@Sun.COM 		if (iqci == 0) {
200610696SDavid.Hollister@Sun.COM 			last_consumed = ss.ioq_depth - 1;
200710696SDavid.Hollister@Sun.COM 		} else {
200810696SDavid.Hollister@Sun.COM 			last_consumed = iqci - 1;
200910696SDavid.Hollister@Sun.COM 		}
201010696SDavid.Hollister@Sun.COM 
201110696SDavid.Hollister@Sun.COM 		if (!verbose) {
201210696SDavid.Hollister@Sun.COM 			mdb_printf("Last processed entry:\n");
201310696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
201410696SDavid.Hollister@Sun.COM 			    (ibqp + (PMCS_QENTRY_SIZE * last_consumed)))
201510696SDavid.Hollister@Sun.COM 			    == -1) {
201610696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
201710696SDavid.Hollister@Sun.COM 				    (ibqp + (PMCS_QENTRY_SIZE *
201810696SDavid.Hollister@Sun.COM 				    last_consumed)));
201910696SDavid.Hollister@Sun.COM 				break;
202010696SDavid.Hollister@Sun.COM 			}
2021*12791Sdavid.hollister@oracle.com 			dump_one_qentry_inbound(qentryp, last_consumed,
2022*12791Sdavid.hollister@oracle.com 			    devid_filter);
202310696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
202410696SDavid.Hollister@Sun.COM 			mdb_dec_indent(2);
202510696SDavid.Hollister@Sun.COM 			continue;
202610696SDavid.Hollister@Sun.COM 		}
202710696SDavid.Hollister@Sun.COM 
202810696SDavid.Hollister@Sun.COM 		for (idx = 0; idx < ss.ioq_depth; idx++) {
202910696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
203010696SDavid.Hollister@Sun.COM 			    (ibqp + (PMCS_QENTRY_SIZE * idx))) == -1) {
203110696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
203210696SDavid.Hollister@Sun.COM 				    (ibqp + (PMCS_QENTRY_SIZE * idx)));
203310696SDavid.Hollister@Sun.COM 				break;
203410696SDavid.Hollister@Sun.COM 			}
2035*12791Sdavid.hollister@oracle.com 			dump_one_qentry_inbound(qentryp, idx, devid_filter);
203610696SDavid.Hollister@Sun.COM 		}
203710696SDavid.Hollister@Sun.COM 
203810696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
203910696SDavid.Hollister@Sun.COM 		mdb_dec_indent(2);
204010696SDavid.Hollister@Sun.COM 	}
204110696SDavid.Hollister@Sun.COM 
204210696SDavid.Hollister@Sun.COM 	mdb_dec_indent(2);
204310696SDavid.Hollister@Sun.COM 	mdb_free(qentryp, PMCS_QENTRY_SIZE);
204410696SDavid.Hollister@Sun.COM }
204510696SDavid.Hollister@Sun.COM 
204611601SDavid.Hollister@Sun.COM /*
204711601SDavid.Hollister@Sun.COM  * phy is our copy of the PHY structure.  phyp is the pointer to the actual
204811601SDavid.Hollister@Sun.COM  * kernel PHY data structure
204911601SDavid.Hollister@Sun.COM  */
205010696SDavid.Hollister@Sun.COM static void
display_phy(struct pmcs_phy phy,struct pmcs_phy * phyp,int verbose,int totals_only)205111601SDavid.Hollister@Sun.COM display_phy(struct pmcs_phy phy, struct pmcs_phy *phyp, int verbose,
205211601SDavid.Hollister@Sun.COM     int totals_only)
205310696SDavid.Hollister@Sun.COM {
205410696SDavid.Hollister@Sun.COM 	char		*dtype, *speed;
205510696SDavid.Hollister@Sun.COM 	char		*yes = "Yes";
205610696SDavid.Hollister@Sun.COM 	char		*no = "No";
205710696SDavid.Hollister@Sun.COM 	char		*cfgd = no;
205810696SDavid.Hollister@Sun.COM 	char		*apend = no;
205910696SDavid.Hollister@Sun.COM 	char		*asent = no;
206010696SDavid.Hollister@Sun.COM 	char		*dead = no;
206110696SDavid.Hollister@Sun.COM 	char		*changed = no;
206211601SDavid.Hollister@Sun.COM 	char		route_attr, route_method;
206310696SDavid.Hollister@Sun.COM 
206410696SDavid.Hollister@Sun.COM 	switch (phy.dtype) {
206510696SDavid.Hollister@Sun.COM 	case NOTHING:
206610696SDavid.Hollister@Sun.COM 		dtype = "None";
206710696SDavid.Hollister@Sun.COM 		break;
206810696SDavid.Hollister@Sun.COM 	case SATA:
206910696SDavid.Hollister@Sun.COM 		dtype = "SATA";
207010696SDavid.Hollister@Sun.COM 		if (phy.configured) {
207110696SDavid.Hollister@Sun.COM 			++sata_phys;
207210696SDavid.Hollister@Sun.COM 		}
207310696SDavid.Hollister@Sun.COM 		break;
207410696SDavid.Hollister@Sun.COM 	case SAS:
207510696SDavid.Hollister@Sun.COM 		dtype = "SAS";
207610696SDavid.Hollister@Sun.COM 		if (phy.configured) {
207710696SDavid.Hollister@Sun.COM 			++sas_phys;
207810696SDavid.Hollister@Sun.COM 		}
207910696SDavid.Hollister@Sun.COM 		break;
208010696SDavid.Hollister@Sun.COM 	case EXPANDER:
208110696SDavid.Hollister@Sun.COM 		dtype = "EXP";
208210696SDavid.Hollister@Sun.COM 		if (phy.configured) {
208310696SDavid.Hollister@Sun.COM 			++exp_phys;
208410696SDavid.Hollister@Sun.COM 		}
208510696SDavid.Hollister@Sun.COM 		break;
208610696SDavid.Hollister@Sun.COM 	}
208710696SDavid.Hollister@Sun.COM 
208810696SDavid.Hollister@Sun.COM 	if (phy.dtype == NOTHING) {
208910696SDavid.Hollister@Sun.COM 		empty_phys++;
209010696SDavid.Hollister@Sun.COM 	} else if ((phy.dtype == EXPANDER) && phy.configured) {
209110696SDavid.Hollister@Sun.COM 		num_expanders++;
209210696SDavid.Hollister@Sun.COM 	}
209310696SDavid.Hollister@Sun.COM 
209410696SDavid.Hollister@Sun.COM 	if (totals_only) {
209510696SDavid.Hollister@Sun.COM 		return;
209610696SDavid.Hollister@Sun.COM 	}
209710696SDavid.Hollister@Sun.COM 
209810696SDavid.Hollister@Sun.COM 	switch (phy.link_rate) {
209910696SDavid.Hollister@Sun.COM 	case SAS_LINK_RATE_1_5GBIT:
210010696SDavid.Hollister@Sun.COM 		speed = "1.5Gb/s";
210110696SDavid.Hollister@Sun.COM 		break;
210210696SDavid.Hollister@Sun.COM 	case SAS_LINK_RATE_3GBIT:
210310696SDavid.Hollister@Sun.COM 		speed = "3 Gb/s";
210410696SDavid.Hollister@Sun.COM 		break;
210510696SDavid.Hollister@Sun.COM 	case SAS_LINK_RATE_6GBIT:
210610696SDavid.Hollister@Sun.COM 		speed = "6 Gb/s";
210710696SDavid.Hollister@Sun.COM 		break;
210810696SDavid.Hollister@Sun.COM 	default:
210910696SDavid.Hollister@Sun.COM 		speed = "N/A";
211010696SDavid.Hollister@Sun.COM 		break;
211110696SDavid.Hollister@Sun.COM 	}
211210696SDavid.Hollister@Sun.COM 
211310696SDavid.Hollister@Sun.COM 	if ((phy.dtype != NOTHING) || verbose) {
211410696SDavid.Hollister@Sun.COM 		print_sas_address(&phy);
211510696SDavid.Hollister@Sun.COM 
211610696SDavid.Hollister@Sun.COM 		if (phy.device_id != PMCS_INVALID_DEVICE_ID) {
211710696SDavid.Hollister@Sun.COM 			mdb_printf(" %3d %4d %6s %4s ",
211810696SDavid.Hollister@Sun.COM 			    phy.device_id, phy.phynum, speed, dtype);
211910696SDavid.Hollister@Sun.COM 		} else {
212010696SDavid.Hollister@Sun.COM 			mdb_printf(" N/A %4d %6s %4s ",
212110696SDavid.Hollister@Sun.COM 			    phy.phynum, speed, dtype);
212210696SDavid.Hollister@Sun.COM 		}
212310696SDavid.Hollister@Sun.COM 
212410696SDavid.Hollister@Sun.COM 		if (verbose) {
212510696SDavid.Hollister@Sun.COM 			if (phy.abort_sent) {
212610696SDavid.Hollister@Sun.COM 				asent = yes;
212710696SDavid.Hollister@Sun.COM 			}
212810696SDavid.Hollister@Sun.COM 			if (phy.abort_pending) {
212910696SDavid.Hollister@Sun.COM 				apend = yes;
213010696SDavid.Hollister@Sun.COM 			}
213110696SDavid.Hollister@Sun.COM 			if (phy.configured) {
213210696SDavid.Hollister@Sun.COM 				cfgd = yes;
213310696SDavid.Hollister@Sun.COM 			}
213410696SDavid.Hollister@Sun.COM 			if (phy.dead) {
213510696SDavid.Hollister@Sun.COM 				dead = yes;
213610696SDavid.Hollister@Sun.COM 			}
213710696SDavid.Hollister@Sun.COM 			if (phy.changed) {
213810696SDavid.Hollister@Sun.COM 				changed = yes;
213910696SDavid.Hollister@Sun.COM 			}
214010696SDavid.Hollister@Sun.COM 
214111601SDavid.Hollister@Sun.COM 			switch (phy.routing_attr) {
214211601SDavid.Hollister@Sun.COM 			case SMP_ROUTING_DIRECT:
214311601SDavid.Hollister@Sun.COM 				route_attr = 'D';
214411601SDavid.Hollister@Sun.COM 				break;
214511601SDavid.Hollister@Sun.COM 			case SMP_ROUTING_SUBTRACTIVE:
214611601SDavid.Hollister@Sun.COM 				route_attr = 'S';
214711601SDavid.Hollister@Sun.COM 				break;
214811601SDavid.Hollister@Sun.COM 			case SMP_ROUTING_TABLE:
214911601SDavid.Hollister@Sun.COM 				route_attr = 'T';
215011601SDavid.Hollister@Sun.COM 				break;
215111601SDavid.Hollister@Sun.COM 			default:
215211601SDavid.Hollister@Sun.COM 				route_attr = '?';
215311601SDavid.Hollister@Sun.COM 				break;
215411601SDavid.Hollister@Sun.COM 			}
215511601SDavid.Hollister@Sun.COM 
215611601SDavid.Hollister@Sun.COM 			switch (phy.routing_method) {
215711601SDavid.Hollister@Sun.COM 			case SMP_ROUTING_DIRECT:
215811601SDavid.Hollister@Sun.COM 				route_method = 'D';
215911601SDavid.Hollister@Sun.COM 				break;
216011601SDavid.Hollister@Sun.COM 			case SMP_ROUTING_SUBTRACTIVE:
216111601SDavid.Hollister@Sun.COM 				route_method = 'S';
216211601SDavid.Hollister@Sun.COM 				break;
216311601SDavid.Hollister@Sun.COM 			case SMP_ROUTING_TABLE:
216411601SDavid.Hollister@Sun.COM 				route_method = 'T';
216511601SDavid.Hollister@Sun.COM 				break;
216611601SDavid.Hollister@Sun.COM 			default:
216711601SDavid.Hollister@Sun.COM 				route_attr = '?';
216811601SDavid.Hollister@Sun.COM 				break;
216911601SDavid.Hollister@Sun.COM 			}
217011601SDavid.Hollister@Sun.COM 
217111601SDavid.Hollister@Sun.COM 			mdb_printf("%-4s %-4s %-4s %-4s %-4s %3d %3c/%1c %3d "
217211601SDavid.Hollister@Sun.COM 			    "%1d 0x%p ", cfgd, apend, asent, changed, dead,
217311601SDavid.Hollister@Sun.COM 			    phy.ref_count, route_attr, route_method,
217411601SDavid.Hollister@Sun.COM 			    phy.enum_attempts, phy.reenumerate, phy.phy_lock);
217510696SDavid.Hollister@Sun.COM 		}
217610696SDavid.Hollister@Sun.COM 
217710696SDavid.Hollister@Sun.COM 		mdb_printf("Path: %s\n", phy.path);
217811601SDavid.Hollister@Sun.COM 
217911601SDavid.Hollister@Sun.COM 		/*
218011601SDavid.Hollister@Sun.COM 		 * In verbose mode, on the next line print the drill down
218111601SDavid.Hollister@Sun.COM 		 * info to see either the DISCOVER response or the REPORT
218211601SDavid.Hollister@Sun.COM 		 * GENERAL response depending on the PHY's dtype
218311601SDavid.Hollister@Sun.COM 		 */
218411601SDavid.Hollister@Sun.COM 		if (verbose) {
218511601SDavid.Hollister@Sun.COM 			uintptr_t tphyp = (uintptr_t)phyp;
218611601SDavid.Hollister@Sun.COM 
218711601SDavid.Hollister@Sun.COM 			mdb_inc_indent(4);
218811601SDavid.Hollister@Sun.COM 			switch (phy.dtype) {
218911601SDavid.Hollister@Sun.COM 			case EXPANDER:
219011601SDavid.Hollister@Sun.COM 				if (!phy.configured) {
219111601SDavid.Hollister@Sun.COM 					break;
219211601SDavid.Hollister@Sun.COM 				}
219311601SDavid.Hollister@Sun.COM 				mdb_printf("REPORT GENERAL response: %p::"
219411601SDavid.Hollister@Sun.COM 				    "print smp_report_general_resp_t\n",
219511601SDavid.Hollister@Sun.COM 				    (tphyp + offsetof(struct pmcs_phy,
219611601SDavid.Hollister@Sun.COM 				    rg_resp)));
219711601SDavid.Hollister@Sun.COM 				break;
219811601SDavid.Hollister@Sun.COM 			case SAS:
219911601SDavid.Hollister@Sun.COM 			case SATA:
220011601SDavid.Hollister@Sun.COM 				mdb_printf("DISCOVER response: %p::"
220111601SDavid.Hollister@Sun.COM 				    "print smp_discover_resp_t\n",
220211601SDavid.Hollister@Sun.COM 				    (tphyp + offsetof(struct pmcs_phy,
220311601SDavid.Hollister@Sun.COM 				    disc_resp)));
220411601SDavid.Hollister@Sun.COM 				break;
220511601SDavid.Hollister@Sun.COM 			default:
220611601SDavid.Hollister@Sun.COM 				break;
220711601SDavid.Hollister@Sun.COM 			}
220811601SDavid.Hollister@Sun.COM 			mdb_dec_indent(4);
220911601SDavid.Hollister@Sun.COM 		}
221010696SDavid.Hollister@Sun.COM 	}
221110696SDavid.Hollister@Sun.COM }
221210696SDavid.Hollister@Sun.COM 
221310696SDavid.Hollister@Sun.COM static void
display_phys(struct pmcs_hw ss,int verbose,struct pmcs_phy * parent,int level,int totals_only)221410696SDavid.Hollister@Sun.COM display_phys(struct pmcs_hw ss, int verbose, struct pmcs_phy *parent, int level,
221510696SDavid.Hollister@Sun.COM     int totals_only)
221610696SDavid.Hollister@Sun.COM {
221710696SDavid.Hollister@Sun.COM 	pmcs_phy_t	phy;
221810696SDavid.Hollister@Sun.COM 	pmcs_phy_t	*pphy = parent;
221910696SDavid.Hollister@Sun.COM 
222010696SDavid.Hollister@Sun.COM 	mdb_inc_indent(3);
222110696SDavid.Hollister@Sun.COM 
222210696SDavid.Hollister@Sun.COM 	if (parent == NULL) {
222310696SDavid.Hollister@Sun.COM 		pphy = (pmcs_phy_t *)ss.root_phys;
222410696SDavid.Hollister@Sun.COM 	} else {
222510696SDavid.Hollister@Sun.COM 		pphy = (pmcs_phy_t *)parent;
222610696SDavid.Hollister@Sun.COM 	}
222710696SDavid.Hollister@Sun.COM 
222810696SDavid.Hollister@Sun.COM 	if (level == 0) {
222910696SDavid.Hollister@Sun.COM 		sas_phys = 0;
223010696SDavid.Hollister@Sun.COM 		sata_phys = 0;
223110696SDavid.Hollister@Sun.COM 		exp_phys = 0;
223210696SDavid.Hollister@Sun.COM 		num_expanders = 0;
223310696SDavid.Hollister@Sun.COM 		empty_phys = 0;
223410696SDavid.Hollister@Sun.COM 	}
223510696SDavid.Hollister@Sun.COM 
223610696SDavid.Hollister@Sun.COM 	if (!totals_only) {
223710696SDavid.Hollister@Sun.COM 		if (level == 0) {
223810696SDavid.Hollister@Sun.COM 			mdb_printf("PHY information\n");
223910696SDavid.Hollister@Sun.COM 		}
224010696SDavid.Hollister@Sun.COM 		mdb_printf("--------\n");
224110696SDavid.Hollister@Sun.COM 		mdb_printf("Level %2d\n", level);
224210696SDavid.Hollister@Sun.COM 		mdb_printf("--------\n");
224310696SDavid.Hollister@Sun.COM 		mdb_printf("SAS Address      Hdl Phy#  Speed Type ");
224410696SDavid.Hollister@Sun.COM 
224510696SDavid.Hollister@Sun.COM 		if (verbose) {
224611601SDavid.Hollister@Sun.COM 			mdb_printf("Cfgd AbtP AbtS Chgd Dead Ref RtA/M Enm R "
224711601SDavid.Hollister@Sun.COM 			    "Lock\n");
224810696SDavid.Hollister@Sun.COM 		} else {
224910696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
225010696SDavid.Hollister@Sun.COM 		}
225110696SDavid.Hollister@Sun.COM 	}
225210696SDavid.Hollister@Sun.COM 
225310696SDavid.Hollister@Sun.COM 	while (pphy) {
225410696SDavid.Hollister@Sun.COM 		if (MDB_RD(&phy, sizeof (phy), (uintptr_t)pphy) == -1) {
225510696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_phy_t, phy);
225610696SDavid.Hollister@Sun.COM 			break;
225710696SDavid.Hollister@Sun.COM 		}
225810696SDavid.Hollister@Sun.COM 
225911601SDavid.Hollister@Sun.COM 		display_phy(phy, pphy, verbose, totals_only);
226010696SDavid.Hollister@Sun.COM 
226110696SDavid.Hollister@Sun.COM 		if (phy.children) {
226210696SDavid.Hollister@Sun.COM 			display_phys(ss, verbose, phy.children, level + 1,
226310696SDavid.Hollister@Sun.COM 			    totals_only);
226410696SDavid.Hollister@Sun.COM 			if (!totals_only) {
226510696SDavid.Hollister@Sun.COM 				mdb_printf("\n");
226610696SDavid.Hollister@Sun.COM 			}
226710696SDavid.Hollister@Sun.COM 		}
226810696SDavid.Hollister@Sun.COM 
226910696SDavid.Hollister@Sun.COM 		pphy = phy.sibling;
227010696SDavid.Hollister@Sun.COM 	}
227110696SDavid.Hollister@Sun.COM 
227210696SDavid.Hollister@Sun.COM 	mdb_dec_indent(3);
227310696SDavid.Hollister@Sun.COM 
227410696SDavid.Hollister@Sun.COM 	if (level == 0) {
227510696SDavid.Hollister@Sun.COM 		if (verbose) {
227610696SDavid.Hollister@Sun.COM 			mdb_printf("%19s %d (%d SAS + %d SATA + %d SMP) "
227710696SDavid.Hollister@Sun.COM 			    "(+%d subsidiary + %d empty)\n", "Occupied PHYs:",
227810696SDavid.Hollister@Sun.COM 			    (sas_phys + sata_phys + num_expanders),
227910696SDavid.Hollister@Sun.COM 			    sas_phys, sata_phys, num_expanders,
228010696SDavid.Hollister@Sun.COM 			    (exp_phys - num_expanders), empty_phys);
228110696SDavid.Hollister@Sun.COM 		} else {
228210696SDavid.Hollister@Sun.COM 			mdb_printf("%19s %d (%d SAS + %d SATA + %d SMP)\n",
228310696SDavid.Hollister@Sun.COM 			    "Occupied PHYs:",
228410696SDavid.Hollister@Sun.COM 			    (sas_phys + sata_phys + num_expanders),
228510696SDavid.Hollister@Sun.COM 			    sas_phys, sata_phys, num_expanders);
228610696SDavid.Hollister@Sun.COM 		}
228710696SDavid.Hollister@Sun.COM 	}
228810696SDavid.Hollister@Sun.COM }
228910696SDavid.Hollister@Sun.COM 
229010696SDavid.Hollister@Sun.COM /*
229111048SDavid.Hollister@Sun.COM  * filter is used to indicate whether we are filtering log messages based
229211048SDavid.Hollister@Sun.COM  * on "instance".  The other filtering (based on options) depends on the
229311048SDavid.Hollister@Sun.COM  * values that are passed in for "sas_addr" and "phy_path".
229411048SDavid.Hollister@Sun.COM  *
229510696SDavid.Hollister@Sun.COM  * MAX_INST_STRLEN is the largest string size from which we will attempt
229610696SDavid.Hollister@Sun.COM  * to convert to an instance number.  The string will be formed up as
229710696SDavid.Hollister@Sun.COM  * "0t<inst>\0" so that mdb_strtoull can parse it properly.
229810696SDavid.Hollister@Sun.COM  */
229910696SDavid.Hollister@Sun.COM #define	MAX_INST_STRLEN	8
230010696SDavid.Hollister@Sun.COM 
230110696SDavid.Hollister@Sun.COM static int
pmcs_dump_tracelog(boolean_t filter,int instance,uint64_t tail_lines,const char * phy_path,uint64_t sas_address,uint64_t verbose)230211347SRamana.Srikanth@Sun.COM pmcs_dump_tracelog(boolean_t filter, int instance, uint64_t tail_lines,
230312120SDavid.Hollister@Sun.COM     const char *phy_path, uint64_t sas_address, uint64_t verbose)
230410696SDavid.Hollister@Sun.COM {
230510696SDavid.Hollister@Sun.COM 	pmcs_tbuf_t *tbuf_addr;
230610696SDavid.Hollister@Sun.COM 	uint_t tbuf_idx;
230710696SDavid.Hollister@Sun.COM 	pmcs_tbuf_t tbuf;
230810696SDavid.Hollister@Sun.COM 	boolean_t wrap, elem_filtered;
230910696SDavid.Hollister@Sun.COM 	uint_t start_idx, elems_to_print, idx, tbuf_num_elems;
231010696SDavid.Hollister@Sun.COM 	char *bufp;
231110696SDavid.Hollister@Sun.COM 	char elem_inst[MAX_INST_STRLEN], ei_idx;
231211048SDavid.Hollister@Sun.COM 	uint64_t sas_addr;
231311048SDavid.Hollister@Sun.COM 	uint8_t *sas_addressp;
231410696SDavid.Hollister@Sun.COM 
231510696SDavid.Hollister@Sun.COM 	/* Get the address of the first element */
231610696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&tbuf_addr, "pmcs_tbuf") == -1) {
231710696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf");
231810696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
231910696SDavid.Hollister@Sun.COM 	}
232010696SDavid.Hollister@Sun.COM 
232110696SDavid.Hollister@Sun.COM 	/* Get the total number */
232210696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&tbuf_num_elems, "pmcs_tbuf_num_elems") == -1) {
232310696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf_num_elems");
232410696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
232510696SDavid.Hollister@Sun.COM 	}
232610696SDavid.Hollister@Sun.COM 
232710696SDavid.Hollister@Sun.COM 	/* Get the current index */
232810696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&tbuf_idx, "pmcs_tbuf_idx") == -1) {
232910696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf_idx");
233010696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
233110696SDavid.Hollister@Sun.COM 	}
233210696SDavid.Hollister@Sun.COM 
233310696SDavid.Hollister@Sun.COM 	/* Indicator as to whether the buffer has wrapped */
233410696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&wrap, "pmcs_tbuf_wrap") == -1) {
233510696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf_wrap");
233610696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
233710696SDavid.Hollister@Sun.COM 	}
233810696SDavid.Hollister@Sun.COM 
233911048SDavid.Hollister@Sun.COM 	/*
234011048SDavid.Hollister@Sun.COM 	 * On little-endian systems, the SAS address passed in will be
234111048SDavid.Hollister@Sun.COM 	 * byte swapped.  Take care of that here.
234211048SDavid.Hollister@Sun.COM 	 */
234311048SDavid.Hollister@Sun.COM #if defined(_LITTLE_ENDIAN)
234411048SDavid.Hollister@Sun.COM 	sas_addr = ((sas_address << 56) |
234511048SDavid.Hollister@Sun.COM 	    ((sas_address << 40) & 0xff000000000000ULL) |
234611048SDavid.Hollister@Sun.COM 	    ((sas_address << 24) & 0xff0000000000ULL) |
234711048SDavid.Hollister@Sun.COM 	    ((sas_address << 8)  & 0xff00000000ULL) |
234811048SDavid.Hollister@Sun.COM 	    ((sas_address >> 8)  & 0xff000000ULL) |
234911048SDavid.Hollister@Sun.COM 	    ((sas_address >> 24) & 0xff0000ULL) |
235011048SDavid.Hollister@Sun.COM 	    ((sas_address >> 40) & 0xff00ULL) |
235111048SDavid.Hollister@Sun.COM 	    (sas_address  >> 56));
235211048SDavid.Hollister@Sun.COM #else
235311048SDavid.Hollister@Sun.COM 	sas_addr = sas_address;
235411048SDavid.Hollister@Sun.COM #endif
235511048SDavid.Hollister@Sun.COM 	sas_addressp = (uint8_t *)&sas_addr;
235611048SDavid.Hollister@Sun.COM 
235711347SRamana.Srikanth@Sun.COM 	/* Ensure the tail number isn't greater than the size of the log */
235811347SRamana.Srikanth@Sun.COM 	if (tail_lines > tbuf_num_elems) {
235911347SRamana.Srikanth@Sun.COM 		tail_lines = tbuf_num_elems;
236011347SRamana.Srikanth@Sun.COM 	}
236111347SRamana.Srikanth@Sun.COM 
236210696SDavid.Hollister@Sun.COM 	/* Figure out where we start and stop */
236310696SDavid.Hollister@Sun.COM 	if (wrap) {
236411347SRamana.Srikanth@Sun.COM 		if (tail_lines) {
236511347SRamana.Srikanth@Sun.COM 			/* Do we need to wrap backwards? */
236611347SRamana.Srikanth@Sun.COM 			if (tail_lines > tbuf_idx) {
236711347SRamana.Srikanth@Sun.COM 				start_idx = tbuf_num_elems - (tail_lines -
236811347SRamana.Srikanth@Sun.COM 				    tbuf_idx);
236911347SRamana.Srikanth@Sun.COM 			} else {
237011347SRamana.Srikanth@Sun.COM 				start_idx = tbuf_idx - tail_lines;
237111347SRamana.Srikanth@Sun.COM 			}
237211347SRamana.Srikanth@Sun.COM 			elems_to_print = tail_lines;
237311347SRamana.Srikanth@Sun.COM 		} else {
237411347SRamana.Srikanth@Sun.COM 			start_idx = tbuf_idx;
237511347SRamana.Srikanth@Sun.COM 			elems_to_print = tbuf_num_elems;
237611347SRamana.Srikanth@Sun.COM 		}
237710696SDavid.Hollister@Sun.COM 	} else {
237811347SRamana.Srikanth@Sun.COM 		if (tail_lines > tbuf_idx) {
237911347SRamana.Srikanth@Sun.COM 			tail_lines = tbuf_idx;
238011347SRamana.Srikanth@Sun.COM 		}
238111347SRamana.Srikanth@Sun.COM 		if (tail_lines) {
238211347SRamana.Srikanth@Sun.COM 			start_idx = tbuf_idx - tail_lines;
238311347SRamana.Srikanth@Sun.COM 			elems_to_print = tail_lines;
238411347SRamana.Srikanth@Sun.COM 		} else {
238511347SRamana.Srikanth@Sun.COM 			start_idx = 0;
238611347SRamana.Srikanth@Sun.COM 			elems_to_print = tbuf_idx;
238711347SRamana.Srikanth@Sun.COM 		}
238810696SDavid.Hollister@Sun.COM 	}
238910696SDavid.Hollister@Sun.COM 
239010696SDavid.Hollister@Sun.COM 	idx = start_idx;
239110696SDavid.Hollister@Sun.COM 
239210696SDavid.Hollister@Sun.COM 	/* Dump the buffer contents */
239310696SDavid.Hollister@Sun.COM 	while (elems_to_print != 0) {
239410696SDavid.Hollister@Sun.COM 		if (MDB_RD(&tbuf, sizeof (pmcs_tbuf_t), (tbuf_addr + idx))
239510696SDavid.Hollister@Sun.COM 		    == -1) {
239610696SDavid.Hollister@Sun.COM 			NOREAD(tbuf, (tbuf_addr + idx));
239710696SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
239810696SDavid.Hollister@Sun.COM 		}
239910696SDavid.Hollister@Sun.COM 
240011048SDavid.Hollister@Sun.COM 		/*
240111048SDavid.Hollister@Sun.COM 		 * Check for filtering on HBA instance
240211048SDavid.Hollister@Sun.COM 		 */
240310696SDavid.Hollister@Sun.COM 		elem_filtered = B_FALSE;
240410696SDavid.Hollister@Sun.COM 
240510696SDavid.Hollister@Sun.COM 		if (filter) {
240610696SDavid.Hollister@Sun.COM 			bufp = tbuf.buf;
240710696SDavid.Hollister@Sun.COM 			/* Skip the driver name */
240810696SDavid.Hollister@Sun.COM 			while (*bufp < '0' || *bufp > '9') {
240910696SDavid.Hollister@Sun.COM 				bufp++;
241010696SDavid.Hollister@Sun.COM 			}
241110696SDavid.Hollister@Sun.COM 
241210696SDavid.Hollister@Sun.COM 			ei_idx = 0;
241310696SDavid.Hollister@Sun.COM 			elem_inst[ei_idx++] = '0';
241410696SDavid.Hollister@Sun.COM 			elem_inst[ei_idx++] = 't';
241510696SDavid.Hollister@Sun.COM 			while (*bufp != ':' && ei_idx < (MAX_INST_STRLEN - 1)) {
241610696SDavid.Hollister@Sun.COM 				elem_inst[ei_idx++] = *bufp;
241710696SDavid.Hollister@Sun.COM 				bufp++;
241810696SDavid.Hollister@Sun.COM 			}
241910696SDavid.Hollister@Sun.COM 			elem_inst[ei_idx] = 0;
242010696SDavid.Hollister@Sun.COM 
242110696SDavid.Hollister@Sun.COM 			/* Get the instance */
242210696SDavid.Hollister@Sun.COM 			if ((int)mdb_strtoull(elem_inst) != instance) {
242310696SDavid.Hollister@Sun.COM 				elem_filtered = B_TRUE;
242410696SDavid.Hollister@Sun.COM 			}
242510696SDavid.Hollister@Sun.COM 		}
242610696SDavid.Hollister@Sun.COM 
242711048SDavid.Hollister@Sun.COM 		if (!elem_filtered && (phy_path || sas_address)) {
242811048SDavid.Hollister@Sun.COM 			/*
242911048SDavid.Hollister@Sun.COM 			 * This message is not being filtered by HBA instance.
243011048SDavid.Hollister@Sun.COM 			 * Now check to see if we're filtering based on
243111048SDavid.Hollister@Sun.COM 			 * PHY path or SAS address.
243211048SDavid.Hollister@Sun.COM 			 * Filtering is an "OR" operation.  So, if any of the
243311048SDavid.Hollister@Sun.COM 			 * criteria matches, this message will be printed.
243411048SDavid.Hollister@Sun.COM 			 */
243511048SDavid.Hollister@Sun.COM 			elem_filtered = B_TRUE;
243611048SDavid.Hollister@Sun.COM 
243711048SDavid.Hollister@Sun.COM 			if (phy_path != NULL) {
243811048SDavid.Hollister@Sun.COM 				if (strncmp(phy_path, tbuf.phy_path,
243911048SDavid.Hollister@Sun.COM 				    PMCS_TBUF_UA_MAX_SIZE) == 0) {
244011048SDavid.Hollister@Sun.COM 					elem_filtered = B_FALSE;
244111048SDavid.Hollister@Sun.COM 				}
244211048SDavid.Hollister@Sun.COM 			}
244311048SDavid.Hollister@Sun.COM 			if (sas_address != 0) {
244411048SDavid.Hollister@Sun.COM 				if (memcmp(sas_addressp, tbuf.phy_sas_address,
244511048SDavid.Hollister@Sun.COM 				    8) == 0) {
244611048SDavid.Hollister@Sun.COM 					elem_filtered = B_FALSE;
244711048SDavid.Hollister@Sun.COM 				}
244811048SDavid.Hollister@Sun.COM 			}
244911048SDavid.Hollister@Sun.COM 		}
245011048SDavid.Hollister@Sun.COM 
245110696SDavid.Hollister@Sun.COM 		if (!elem_filtered) {
245212120SDavid.Hollister@Sun.COM 			/*
245312120SDavid.Hollister@Sun.COM 			 * If the -v flag was given, print the firmware
245412120SDavid.Hollister@Sun.COM 			 * timestamp along with the clock time
245512120SDavid.Hollister@Sun.COM 			 */
245612120SDavid.Hollister@Sun.COM 			mdb_printf("%Y.%09ld ", tbuf.timestamp);
245712120SDavid.Hollister@Sun.COM 			if (verbose) {
245812120SDavid.Hollister@Sun.COM 				mdb_printf("(0x%" PRIx64 ") ",
245912120SDavid.Hollister@Sun.COM 				    tbuf.fw_timestamp);
246012120SDavid.Hollister@Sun.COM 			}
246112120SDavid.Hollister@Sun.COM 			mdb_printf("%s\n", tbuf.buf);
246210696SDavid.Hollister@Sun.COM 		}
246310696SDavid.Hollister@Sun.COM 
246410696SDavid.Hollister@Sun.COM 		--elems_to_print;
246510696SDavid.Hollister@Sun.COM 		if (++idx == tbuf_num_elems) {
246610696SDavid.Hollister@Sun.COM 			idx = 0;
246710696SDavid.Hollister@Sun.COM 		}
246810696SDavid.Hollister@Sun.COM 	}
246910696SDavid.Hollister@Sun.COM 
247010696SDavid.Hollister@Sun.COM 	return (DCMD_OK);
247110696SDavid.Hollister@Sun.COM }
247210696SDavid.Hollister@Sun.COM 
247310696SDavid.Hollister@Sun.COM /*
247410696SDavid.Hollister@Sun.COM  * Walkers
247510696SDavid.Hollister@Sun.COM  */
247610696SDavid.Hollister@Sun.COM static int
targets_walk_i(mdb_walk_state_t * wsp)247710696SDavid.Hollister@Sun.COM targets_walk_i(mdb_walk_state_t *wsp)
247810696SDavid.Hollister@Sun.COM {
247910696SDavid.Hollister@Sun.COM 	if (wsp->walk_addr == NULL) {
248010696SDavid.Hollister@Sun.COM 		mdb_warn("Can not perform global walk\n");
248110696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
248210696SDavid.Hollister@Sun.COM 	}
248310696SDavid.Hollister@Sun.COM 
248410696SDavid.Hollister@Sun.COM 	/*
248510696SDavid.Hollister@Sun.COM 	 * Address provided belongs to HBA softstate.  Get the targets pointer
248610696SDavid.Hollister@Sun.COM 	 * to begin the walk.
248710696SDavid.Hollister@Sun.COM 	 */
248810696SDavid.Hollister@Sun.COM 	if (mdb_vread(&ss, sizeof (pmcs_hw_t), wsp->walk_addr) !=
248910696SDavid.Hollister@Sun.COM 	    sizeof (pmcs_hw_t)) {
249010696SDavid.Hollister@Sun.COM 		mdb_warn("Unable to read HBA softstate\n");
249110696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
249210696SDavid.Hollister@Sun.COM 	}
249310696SDavid.Hollister@Sun.COM 
249410696SDavid.Hollister@Sun.COM 	if (targets == NULL) {
249510696SDavid.Hollister@Sun.COM 		targets = mdb_alloc(sizeof (targets) * ss.max_dev, UM_SLEEP);
249610696SDavid.Hollister@Sun.COM 	}
249710696SDavid.Hollister@Sun.COM 
249810696SDavid.Hollister@Sun.COM 	if (MDB_RD(targets, sizeof (targets) * ss.max_dev, ss.targets) == -1) {
249910696SDavid.Hollister@Sun.COM 		NOREAD(targets, ss.targets);
250010696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
250110696SDavid.Hollister@Sun.COM 	}
250210696SDavid.Hollister@Sun.COM 
250310696SDavid.Hollister@Sun.COM 	target_idx = 0;
250410696SDavid.Hollister@Sun.COM 	wsp->walk_addr = (uintptr_t)(targets[0]);
250510696SDavid.Hollister@Sun.COM 	wsp->walk_data = mdb_alloc(sizeof (pmcs_xscsi_t), UM_SLEEP);
250610696SDavid.Hollister@Sun.COM 
250710696SDavid.Hollister@Sun.COM 	return (WALK_NEXT);
250810696SDavid.Hollister@Sun.COM }
250910696SDavid.Hollister@Sun.COM 
251010696SDavid.Hollister@Sun.COM static int
targets_walk_s(mdb_walk_state_t * wsp)251110696SDavid.Hollister@Sun.COM targets_walk_s(mdb_walk_state_t *wsp)
251210696SDavid.Hollister@Sun.COM {
251310696SDavid.Hollister@Sun.COM 	int status;
251410696SDavid.Hollister@Sun.COM 
251510696SDavid.Hollister@Sun.COM 	if (target_idx == ss.max_dev) {
251610696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
251710696SDavid.Hollister@Sun.COM 	}
251810696SDavid.Hollister@Sun.COM 
251910696SDavid.Hollister@Sun.COM 	if (mdb_vread(wsp->walk_data, sizeof (pmcs_xscsi_t),
252010696SDavid.Hollister@Sun.COM 	    wsp->walk_addr) == -1) {
252110696SDavid.Hollister@Sun.COM 		mdb_warn("Failed to read target at %p", (void *)wsp->walk_addr);
252210696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
252310696SDavid.Hollister@Sun.COM 	}
252410696SDavid.Hollister@Sun.COM 
252510696SDavid.Hollister@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
252610696SDavid.Hollister@Sun.COM 	    wsp->walk_cbdata);
252710696SDavid.Hollister@Sun.COM 
252810696SDavid.Hollister@Sun.COM 	do {
252910696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)(targets[++target_idx]);
253010696SDavid.Hollister@Sun.COM 	} while ((wsp->walk_addr == NULL) && (target_idx < ss.max_dev));
253110696SDavid.Hollister@Sun.COM 
253210696SDavid.Hollister@Sun.COM 	if (target_idx == ss.max_dev) {
253310696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
253410696SDavid.Hollister@Sun.COM 	}
253510696SDavid.Hollister@Sun.COM 
253610696SDavid.Hollister@Sun.COM 	return (status);
253710696SDavid.Hollister@Sun.COM }
253810696SDavid.Hollister@Sun.COM 
253910696SDavid.Hollister@Sun.COM static void
targets_walk_f(mdb_walk_state_t * wsp)254010696SDavid.Hollister@Sun.COM targets_walk_f(mdb_walk_state_t *wsp)
254110696SDavid.Hollister@Sun.COM {
254210696SDavid.Hollister@Sun.COM 	mdb_free(wsp->walk_data, sizeof (pmcs_xscsi_t));
254310696SDavid.Hollister@Sun.COM }
254410696SDavid.Hollister@Sun.COM 
254510696SDavid.Hollister@Sun.COM 
254610696SDavid.Hollister@Sun.COM static pmcs_phy_t *
pmcs_next_sibling(pmcs_phy_t * phyp)254710696SDavid.Hollister@Sun.COM pmcs_next_sibling(pmcs_phy_t *phyp)
254810696SDavid.Hollister@Sun.COM {
254910696SDavid.Hollister@Sun.COM 	pmcs_phy_t parent;
255010696SDavid.Hollister@Sun.COM 
255110696SDavid.Hollister@Sun.COM 	/*
255210696SDavid.Hollister@Sun.COM 	 * First, if this is a root PHY, there are no more siblings
255310696SDavid.Hollister@Sun.COM 	 */
255410696SDavid.Hollister@Sun.COM 	if (phyp->level == 0) {
255510696SDavid.Hollister@Sun.COM 		return (NULL);
255610696SDavid.Hollister@Sun.COM 	}
255710696SDavid.Hollister@Sun.COM 
255810696SDavid.Hollister@Sun.COM 	/*
255910696SDavid.Hollister@Sun.COM 	 * Otherwise, next sibling is the parent's sibling
256010696SDavid.Hollister@Sun.COM 	 */
256110696SDavid.Hollister@Sun.COM 	while (phyp->level > 0) {
256210696SDavid.Hollister@Sun.COM 		if (mdb_vread(&parent, sizeof (pmcs_phy_t),
256310696SDavid.Hollister@Sun.COM 		    (uintptr_t)phyp->parent) == -1) {
256410696SDavid.Hollister@Sun.COM 			mdb_warn("pmcs_next_sibling: Failed to read PHY at %p",
256510696SDavid.Hollister@Sun.COM 			    (void *)phyp->parent);
256610696SDavid.Hollister@Sun.COM 			return (NULL);
256710696SDavid.Hollister@Sun.COM 		}
256810696SDavid.Hollister@Sun.COM 
256910696SDavid.Hollister@Sun.COM 		if (parent.sibling != NULL) {
257010696SDavid.Hollister@Sun.COM 			break;
257110696SDavid.Hollister@Sun.COM 		}
257210696SDavid.Hollister@Sun.COM 
257311898SJesse.Butler@Sun.COM 		/*
257411898SJesse.Butler@Sun.COM 		 * If this PHY's sibling is NULL and it's a root phy,
257511898SJesse.Butler@Sun.COM 		 * we're done.
257611898SJesse.Butler@Sun.COM 		 */
257711898SJesse.Butler@Sun.COM 		if (parent.level == 0) {
257811898SJesse.Butler@Sun.COM 			return (NULL);
257911898SJesse.Butler@Sun.COM 		}
258011898SJesse.Butler@Sun.COM 
258110696SDavid.Hollister@Sun.COM 		phyp = phyp->parent;
258210696SDavid.Hollister@Sun.COM 	}
258310696SDavid.Hollister@Sun.COM 
258410696SDavid.Hollister@Sun.COM 	return (parent.sibling);
258510696SDavid.Hollister@Sun.COM }
258610696SDavid.Hollister@Sun.COM 
258710696SDavid.Hollister@Sun.COM static int
phy_walk_i(mdb_walk_state_t * wsp)258810696SDavid.Hollister@Sun.COM phy_walk_i(mdb_walk_state_t *wsp)
258910696SDavid.Hollister@Sun.COM {
259010696SDavid.Hollister@Sun.COM 	if (wsp->walk_addr == NULL) {
259110696SDavid.Hollister@Sun.COM 		mdb_warn("Can not perform global walk\n");
259210696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
259310696SDavid.Hollister@Sun.COM 	}
259410696SDavid.Hollister@Sun.COM 
259510696SDavid.Hollister@Sun.COM 	/*
259610696SDavid.Hollister@Sun.COM 	 * Address provided belongs to HBA softstate.  Get the targets pointer
259710696SDavid.Hollister@Sun.COM 	 * to begin the walk.
259810696SDavid.Hollister@Sun.COM 	 */
259910696SDavid.Hollister@Sun.COM 	if (mdb_vread(&ss, sizeof (pmcs_hw_t), wsp->walk_addr) !=
260010696SDavid.Hollister@Sun.COM 	    sizeof (pmcs_hw_t)) {
260110696SDavid.Hollister@Sun.COM 		mdb_warn("Unable to read HBA softstate\n");
260210696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
260310696SDavid.Hollister@Sun.COM 	}
260410696SDavid.Hollister@Sun.COM 
260510696SDavid.Hollister@Sun.COM 	wsp->walk_addr = (uintptr_t)(ss.root_phys);
260610696SDavid.Hollister@Sun.COM 	wsp->walk_data = mdb_alloc(sizeof (pmcs_phy_t), UM_SLEEP);
260710696SDavid.Hollister@Sun.COM 
260810696SDavid.Hollister@Sun.COM 	return (WALK_NEXT);
260910696SDavid.Hollister@Sun.COM }
261010696SDavid.Hollister@Sun.COM 
261110696SDavid.Hollister@Sun.COM static int
phy_walk_s(mdb_walk_state_t * wsp)261210696SDavid.Hollister@Sun.COM phy_walk_s(mdb_walk_state_t *wsp)
261310696SDavid.Hollister@Sun.COM {
261410696SDavid.Hollister@Sun.COM 	pmcs_phy_t *phyp, *nphyp;
261510696SDavid.Hollister@Sun.COM 	int status;
261610696SDavid.Hollister@Sun.COM 
261710696SDavid.Hollister@Sun.COM 	if (mdb_vread(wsp->walk_data, sizeof (pmcs_phy_t),
261810696SDavid.Hollister@Sun.COM 	    wsp->walk_addr) == -1) {
261910696SDavid.Hollister@Sun.COM 		mdb_warn("phy_walk_s: Failed to read PHY at %p",
262010696SDavid.Hollister@Sun.COM 		    (void *)wsp->walk_addr);
262110696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
262210696SDavid.Hollister@Sun.COM 	}
262310696SDavid.Hollister@Sun.COM 
262410696SDavid.Hollister@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
262510696SDavid.Hollister@Sun.COM 	    wsp->walk_cbdata);
262610696SDavid.Hollister@Sun.COM 
262710696SDavid.Hollister@Sun.COM 	phyp = (pmcs_phy_t *)wsp->walk_data;
262810696SDavid.Hollister@Sun.COM 	if (phyp->children) {
262910696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)(phyp->children);
263010696SDavid.Hollister@Sun.COM 	} else {
263110696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)(phyp->sibling);
263210696SDavid.Hollister@Sun.COM 	}
263310696SDavid.Hollister@Sun.COM 
263410696SDavid.Hollister@Sun.COM 	if (wsp->walk_addr == NULL) {
263510696SDavid.Hollister@Sun.COM 		/*
263610696SDavid.Hollister@Sun.COM 		 * We reached the end of this sibling list.  Trudge back up
263710696SDavid.Hollister@Sun.COM 		 * to the parent and find the next sibling after the expander
263810696SDavid.Hollister@Sun.COM 		 * we just finished traversing, if there is one.
263910696SDavid.Hollister@Sun.COM 		 */
264010696SDavid.Hollister@Sun.COM 		nphyp = pmcs_next_sibling(phyp);
264110696SDavid.Hollister@Sun.COM 
264210696SDavid.Hollister@Sun.COM 		if (nphyp == NULL) {
264310696SDavid.Hollister@Sun.COM 			return (WALK_DONE);
264410696SDavid.Hollister@Sun.COM 		}
264510696SDavid.Hollister@Sun.COM 
264610696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)nphyp;
264710696SDavid.Hollister@Sun.COM 	}
264810696SDavid.Hollister@Sun.COM 
264910696SDavid.Hollister@Sun.COM 	return (status);
265010696SDavid.Hollister@Sun.COM }
265110696SDavid.Hollister@Sun.COM 
265210696SDavid.Hollister@Sun.COM static void
phy_walk_f(mdb_walk_state_t * wsp)265310696SDavid.Hollister@Sun.COM phy_walk_f(mdb_walk_state_t *wsp)
265410696SDavid.Hollister@Sun.COM {
265510696SDavid.Hollister@Sun.COM 	mdb_free(wsp->walk_data, sizeof (pmcs_phy_t));
265610696SDavid.Hollister@Sun.COM }
265710696SDavid.Hollister@Sun.COM 
265810743SDavid.Hollister@Sun.COM static void
display_matching_work(struct pmcs_hw ss,uintmax_t index,uintmax_t snum,uintmax_t tag_type)265910743SDavid.Hollister@Sun.COM display_matching_work(struct pmcs_hw ss, uintmax_t index, uintmax_t snum,
266010743SDavid.Hollister@Sun.COM     uintmax_t tag_type)
266110743SDavid.Hollister@Sun.COM {
266210743SDavid.Hollister@Sun.COM 	int		idx;
266310743SDavid.Hollister@Sun.COM 	pmcwork_t	work, *wp = &work;
266410743SDavid.Hollister@Sun.COM 	uintptr_t	_wp;
266510743SDavid.Hollister@Sun.COM 	boolean_t	printed_header = B_FALSE;
266610743SDavid.Hollister@Sun.COM 	uint32_t	mask, mask_val, match_val;
266710743SDavid.Hollister@Sun.COM 	char		*match_type;
266810743SDavid.Hollister@Sun.COM 
266910743SDavid.Hollister@Sun.COM 	if (index != UINT_MAX) {
267010743SDavid.Hollister@Sun.COM 		match_type = "index";
267110743SDavid.Hollister@Sun.COM 		mask = PMCS_TAG_INDEX_MASK;
267210743SDavid.Hollister@Sun.COM 		mask_val = index << PMCS_TAG_INDEX_SHIFT;
267310743SDavid.Hollister@Sun.COM 		match_val = index;
267410743SDavid.Hollister@Sun.COM 	} else if (snum != UINT_MAX) {
267510743SDavid.Hollister@Sun.COM 		match_type = "serial number";
267610743SDavid.Hollister@Sun.COM 		mask = PMCS_TAG_SERNO_MASK;
267710743SDavid.Hollister@Sun.COM 		mask_val = snum << PMCS_TAG_SERNO_SHIFT;
267810743SDavid.Hollister@Sun.COM 		match_val = snum;
267910743SDavid.Hollister@Sun.COM 	} else {
268010743SDavid.Hollister@Sun.COM 		switch (tag_type) {
268110743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_NONE:
268210743SDavid.Hollister@Sun.COM 			match_type = "tag type NONE";
268310743SDavid.Hollister@Sun.COM 			break;
268410743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_CBACK:
268510743SDavid.Hollister@Sun.COM 			match_type = "tag type CBACK";
268610743SDavid.Hollister@Sun.COM 			break;
268710743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_WAIT:
268810743SDavid.Hollister@Sun.COM 			match_type = "tag type WAIT";
268910743SDavid.Hollister@Sun.COM 			break;
269010743SDavid.Hollister@Sun.COM 		}
269110743SDavid.Hollister@Sun.COM 		mask = PMCS_TAG_TYPE_MASK;
269210743SDavid.Hollister@Sun.COM 		mask_val = tag_type << PMCS_TAG_TYPE_SHIFT;
269310743SDavid.Hollister@Sun.COM 		match_val = tag_type;
269410743SDavid.Hollister@Sun.COM 	}
269510743SDavid.Hollister@Sun.COM 
269610743SDavid.Hollister@Sun.COM 	_wp = (uintptr_t)ss.work;
269710743SDavid.Hollister@Sun.COM 
269810743SDavid.Hollister@Sun.COM 	for (idx = 0; idx < ss.max_cmd; idx++, _wp += sizeof (pmcwork_t)) {
269910743SDavid.Hollister@Sun.COM 		if (MDB_RD(&work, sizeof (pmcwork_t), _wp) == -1) {
270010743SDavid.Hollister@Sun.COM 			NOREAD(pmcwork_t, _wp);
270110743SDavid.Hollister@Sun.COM 			continue;
270210743SDavid.Hollister@Sun.COM 		}
270310743SDavid.Hollister@Sun.COM 
270410743SDavid.Hollister@Sun.COM 		if ((work.htag & mask) != mask_val) {
270510743SDavid.Hollister@Sun.COM 			continue;
270610743SDavid.Hollister@Sun.COM 		}
270710743SDavid.Hollister@Sun.COM 
270810743SDavid.Hollister@Sun.COM 		if (printed_header == B_FALSE) {
270910743SDavid.Hollister@Sun.COM 			if (tag_type) {
271010743SDavid.Hollister@Sun.COM 				mdb_printf("\nWork structures matching %s\n\n",
271110743SDavid.Hollister@Sun.COM 				    match_type, match_val);
271210743SDavid.Hollister@Sun.COM 			} else {
271310743SDavid.Hollister@Sun.COM 				mdb_printf("\nWork structures matching %s of "
271410743SDavid.Hollister@Sun.COM 				    "0x%x\n\n", match_type, match_val);
271510743SDavid.Hollister@Sun.COM 			}
271610743SDavid.Hollister@Sun.COM 			mdb_printf("%8s %10s %20s %8s %8s O D\n",
271710743SDavid.Hollister@Sun.COM 			    "HTag", "State", "Phy Path", "Target", "Timer");
271810743SDavid.Hollister@Sun.COM 			printed_header = B_TRUE;
271910743SDavid.Hollister@Sun.COM 		}
272010743SDavid.Hollister@Sun.COM 
272110743SDavid.Hollister@Sun.COM 		display_one_work(wp, 0, 0);
272210743SDavid.Hollister@Sun.COM 	}
272310743SDavid.Hollister@Sun.COM 
272410743SDavid.Hollister@Sun.COM 	if (!printed_header) {
272510743SDavid.Hollister@Sun.COM 		mdb_printf("No work structure matches found\n");
272610743SDavid.Hollister@Sun.COM 	}
272710743SDavid.Hollister@Sun.COM }
272810743SDavid.Hollister@Sun.COM 
272910743SDavid.Hollister@Sun.COM static int
pmcs_tag(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)273010743SDavid.Hollister@Sun.COM pmcs_tag(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
273110743SDavid.Hollister@Sun.COM {
273210743SDavid.Hollister@Sun.COM 	struct	pmcs_hw		ss;
273310743SDavid.Hollister@Sun.COM 	uintmax_t		tag_type = UINT_MAX;
273410743SDavid.Hollister@Sun.COM 	uintmax_t		snum = UINT_MAX;
273510743SDavid.Hollister@Sun.COM 	uintmax_t		index = UINT_MAX;
273610743SDavid.Hollister@Sun.COM 	int			args = 0;
273710743SDavid.Hollister@Sun.COM 	void			*pmcs_state;
273810743SDavid.Hollister@Sun.COM 	char			*state_str;
273910743SDavid.Hollister@Sun.COM 	struct dev_info		dip;
274010743SDavid.Hollister@Sun.COM 
274110743SDavid.Hollister@Sun.COM 	if (!(flags & DCMD_ADDRSPEC)) {
274210743SDavid.Hollister@Sun.COM 		pmcs_state = NULL;
274310743SDavid.Hollister@Sun.COM 		if (mdb_readvar(&pmcs_state, "pmcs_softc_state") == -1) {
274410743SDavid.Hollister@Sun.COM 			mdb_warn("can't read pmcs_softc_state");
274510743SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
274610743SDavid.Hollister@Sun.COM 		}
274710743SDavid.Hollister@Sun.COM 		if (mdb_pwalk_dcmd("genunix`softstate", "pmcs`pmcs_tag", argc,
274810743SDavid.Hollister@Sun.COM 		    argv, (uintptr_t)pmcs_state) == -1) {
274910743SDavid.Hollister@Sun.COM 			mdb_warn("mdb_pwalk_dcmd failed");
275010743SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
275110743SDavid.Hollister@Sun.COM 		}
275210743SDavid.Hollister@Sun.COM 		return (DCMD_OK);
275310743SDavid.Hollister@Sun.COM 	}
275410743SDavid.Hollister@Sun.COM 
275510743SDavid.Hollister@Sun.COM 	if (mdb_getopts(argc, argv,
275610743SDavid.Hollister@Sun.COM 	    'i', MDB_OPT_UINT64, &index,
275710743SDavid.Hollister@Sun.COM 	    's', MDB_OPT_UINT64, &snum,
275810743SDavid.Hollister@Sun.COM 	    't', MDB_OPT_UINT64, &tag_type) != argc)
275910743SDavid.Hollister@Sun.COM 		return (DCMD_USAGE);
276010743SDavid.Hollister@Sun.COM 
276110743SDavid.Hollister@Sun.COM 	/*
276210743SDavid.Hollister@Sun.COM 	 * Count the number of supplied options and make sure they are
276310743SDavid.Hollister@Sun.COM 	 * within appropriate ranges.  If they're set to UINT_MAX, that means
276410743SDavid.Hollister@Sun.COM 	 * they were not supplied, in which case reset them to 0.
276510743SDavid.Hollister@Sun.COM 	 */
276610743SDavid.Hollister@Sun.COM 	if (index != UINT_MAX) {
276710743SDavid.Hollister@Sun.COM 		args++;
276810743SDavid.Hollister@Sun.COM 		if (index > PMCS_TAG_INDEX_MASK) {
276910743SDavid.Hollister@Sun.COM 			mdb_warn("Index is out of range\n");
277010743SDavid.Hollister@Sun.COM 			return (DCMD_USAGE);
277110743SDavid.Hollister@Sun.COM 		}
277210743SDavid.Hollister@Sun.COM 	}
277310743SDavid.Hollister@Sun.COM 
277410743SDavid.Hollister@Sun.COM 	if (tag_type != UINT_MAX) {
277510743SDavid.Hollister@Sun.COM 		args++;
277610743SDavid.Hollister@Sun.COM 		switch (tag_type) {
277710743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_NONE:
277810743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_CBACK:
277910743SDavid.Hollister@Sun.COM 		case PMCS_TAG_TYPE_WAIT:
278010743SDavid.Hollister@Sun.COM 			break;
278110743SDavid.Hollister@Sun.COM 		default:
278210743SDavid.Hollister@Sun.COM 			mdb_warn("Invalid tag type\n");
278310743SDavid.Hollister@Sun.COM 			return (DCMD_USAGE);
278410743SDavid.Hollister@Sun.COM 		}
278510743SDavid.Hollister@Sun.COM 	}
278610743SDavid.Hollister@Sun.COM 
278710743SDavid.Hollister@Sun.COM 	if (snum != UINT_MAX) {
278810743SDavid.Hollister@Sun.COM 		args++;
278910743SDavid.Hollister@Sun.COM 		if (snum > (PMCS_TAG_SERNO_MASK >> PMCS_TAG_SERNO_SHIFT)) {
279010743SDavid.Hollister@Sun.COM 			mdb_warn("Serial number is out of range\n");
279110743SDavid.Hollister@Sun.COM 			return (DCMD_USAGE);
279210743SDavid.Hollister@Sun.COM 		}
279310743SDavid.Hollister@Sun.COM 	}
279410743SDavid.Hollister@Sun.COM 
279510743SDavid.Hollister@Sun.COM 	/*
279610743SDavid.Hollister@Sun.COM 	 * Make sure 1 and only 1 option is specified
279710743SDavid.Hollister@Sun.COM 	 */
279810743SDavid.Hollister@Sun.COM 	if ((args == 0) || (args > 1)) {
279910743SDavid.Hollister@Sun.COM 		mdb_warn("Exactly one of -i, -s and -t must be specified\n");
280010743SDavid.Hollister@Sun.COM 		return (DCMD_USAGE);
280110743SDavid.Hollister@Sun.COM 	}
280210743SDavid.Hollister@Sun.COM 
280310743SDavid.Hollister@Sun.COM 	if (MDB_RD(&ss, sizeof (ss), addr) == -1) {
280410743SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
280510743SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
280610743SDavid.Hollister@Sun.COM 	}
280710743SDavid.Hollister@Sun.COM 
280810743SDavid.Hollister@Sun.COM 	if (MDB_RD(&dip, sizeof (struct dev_info), ss.dip) == -1) {
280910743SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
281010743SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
281110743SDavid.Hollister@Sun.COM 	}
281210743SDavid.Hollister@Sun.COM 
281310743SDavid.Hollister@Sun.COM 	/* processing completed */
281410743SDavid.Hollister@Sun.COM 
281510743SDavid.Hollister@Sun.COM 	if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) ||
281610743SDavid.Hollister@Sun.COM 	    (flags & DCMD_LOOPFIRST)) {
281710743SDavid.Hollister@Sun.COM 		if ((flags & DCMD_LOOP) && !(flags & DCMD_LOOPFIRST))
281810743SDavid.Hollister@Sun.COM 			mdb_printf("\n");
281910743SDavid.Hollister@Sun.COM 		mdb_printf("%16s %9s %4s B C  WorkFlags wserno DbgMsk %16s\n",
282010743SDavid.Hollister@Sun.COM 		    "Address", "State", "Inst", "DIP");
282110743SDavid.Hollister@Sun.COM 		mdb_printf("================================="
282210743SDavid.Hollister@Sun.COM 		    "============================================\n");
282310743SDavid.Hollister@Sun.COM 	}
282410743SDavid.Hollister@Sun.COM 
282510743SDavid.Hollister@Sun.COM 	switch (ss.state) {
282610743SDavid.Hollister@Sun.COM 	case STATE_NIL:
282710743SDavid.Hollister@Sun.COM 		state_str = "Invalid";
282810743SDavid.Hollister@Sun.COM 		break;
282910743SDavid.Hollister@Sun.COM 	case STATE_PROBING:
283010743SDavid.Hollister@Sun.COM 		state_str = "Probing";
283110743SDavid.Hollister@Sun.COM 		break;
283210743SDavid.Hollister@Sun.COM 	case STATE_RUNNING:
283310743SDavid.Hollister@Sun.COM 		state_str = "Running";
283410743SDavid.Hollister@Sun.COM 		break;
283510743SDavid.Hollister@Sun.COM 	case STATE_UNPROBING:
283610743SDavid.Hollister@Sun.COM 		state_str = "Unprobing";
283710743SDavid.Hollister@Sun.COM 		break;
283810743SDavid.Hollister@Sun.COM 	case STATE_DEAD:
283910743SDavid.Hollister@Sun.COM 		state_str = "Dead";
284010743SDavid.Hollister@Sun.COM 		break;
284111692SJesse.Butler@Sun.COM 	case STATE_IN_RESET:
284211692SJesse.Butler@Sun.COM 		state_str = "In Reset";
284311692SJesse.Butler@Sun.COM 		break;
284410743SDavid.Hollister@Sun.COM 	}
284510743SDavid.Hollister@Sun.COM 
284610743SDavid.Hollister@Sun.COM 	mdb_printf("%16p %9s %4d %1d %1d 0x%08x 0x%04x 0x%04x %16p\n", addr,
284710743SDavid.Hollister@Sun.COM 	    state_str, dip.devi_instance, ss.blocked, ss.configuring,
284810743SDavid.Hollister@Sun.COM 	    ss.work_flags, ss.wserno, ss.debug_mask, ss.dip);
284910743SDavid.Hollister@Sun.COM 	mdb_printf("\n");
285010743SDavid.Hollister@Sun.COM 
285110743SDavid.Hollister@Sun.COM 	mdb_inc_indent(4);
285210743SDavid.Hollister@Sun.COM 	display_matching_work(ss, index, snum, tag_type);
285310743SDavid.Hollister@Sun.COM 	mdb_dec_indent(4);
285410743SDavid.Hollister@Sun.COM 	mdb_printf("\n");
285510743SDavid.Hollister@Sun.COM 
285610743SDavid.Hollister@Sun.COM 	return (DCMD_OK);
285710743SDavid.Hollister@Sun.COM }
285810743SDavid.Hollister@Sun.COM 
285911694SDavid.Hollister@Sun.COM #ifndef _KMDB
286011694SDavid.Hollister@Sun.COM static int
pmcs_dump_fwlog(struct pmcs_hw * ss,int instance,const char * ofile)286111694SDavid.Hollister@Sun.COM pmcs_dump_fwlog(struct pmcs_hw *ss, int instance, const char *ofile)
286211694SDavid.Hollister@Sun.COM {
286311694SDavid.Hollister@Sun.COM 	uint8_t *fwlogp;
286411694SDavid.Hollister@Sun.COM 	int	ofilefd = -1;
286511694SDavid.Hollister@Sun.COM 	char	ofilename[MAXPATHLEN];
286611694SDavid.Hollister@Sun.COM 	int	rval = DCMD_OK;
286711694SDavid.Hollister@Sun.COM 
286811694SDavid.Hollister@Sun.COM 	if (ss->fwlogp == NULL) {
286911694SDavid.Hollister@Sun.COM 		mdb_warn("Firmware event log disabled for instance %d",
287011694SDavid.Hollister@Sun.COM 		    instance);
287111694SDavid.Hollister@Sun.COM 		return (DCMD_OK);
287211694SDavid.Hollister@Sun.COM 	}
287311694SDavid.Hollister@Sun.COM 
287411694SDavid.Hollister@Sun.COM 	if (snprintf(ofilename, MAXPATHLEN, "%s%d", ofile, instance) >
287511694SDavid.Hollister@Sun.COM 	    MAXPATHLEN) {
287611694SDavid.Hollister@Sun.COM 		mdb_warn("Output filename is too long for instance %d",
287711694SDavid.Hollister@Sun.COM 		    instance);
287811694SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
287911694SDavid.Hollister@Sun.COM 	}
288011694SDavid.Hollister@Sun.COM 
288111694SDavid.Hollister@Sun.COM 	fwlogp = mdb_alloc(PMCS_FWLOG_SIZE, UM_SLEEP);
288211694SDavid.Hollister@Sun.COM 
288311694SDavid.Hollister@Sun.COM 	if (MDB_RD(fwlogp, PMCS_FWLOG_SIZE, ss->fwlogp) == -1) {
288411694SDavid.Hollister@Sun.COM 		NOREAD(fwlogp, ss->fwlogp);
288511694SDavid.Hollister@Sun.COM 		rval = DCMD_ERR;
288611694SDavid.Hollister@Sun.COM 		goto cleanup;
288711694SDavid.Hollister@Sun.COM 	}
288811694SDavid.Hollister@Sun.COM 
288911694SDavid.Hollister@Sun.COM 	ofilefd = open(ofilename, O_WRONLY | O_CREAT,
289011694SDavid.Hollister@Sun.COM 	    S_IRUSR | S_IRGRP | S_IROTH);
289111694SDavid.Hollister@Sun.COM 	if (ofilefd < 0) {
289211694SDavid.Hollister@Sun.COM 		mdb_warn("Unable to open '%s' to dump instance %d event log",
289311694SDavid.Hollister@Sun.COM 		    ofilename, instance);
289411694SDavid.Hollister@Sun.COM 		rval = DCMD_ERR;
289511694SDavid.Hollister@Sun.COM 		goto cleanup;
289611694SDavid.Hollister@Sun.COM 	}
289711694SDavid.Hollister@Sun.COM 
289811694SDavid.Hollister@Sun.COM 	if (write(ofilefd, fwlogp, PMCS_FWLOG_SIZE) != PMCS_FWLOG_SIZE) {
289911694SDavid.Hollister@Sun.COM 		mdb_warn("Failed to write %d bytes to output file: instance %d",
290011694SDavid.Hollister@Sun.COM 		    PMCS_FWLOG_SIZE, instance);
290111694SDavid.Hollister@Sun.COM 		rval = DCMD_ERR;
290211694SDavid.Hollister@Sun.COM 		goto cleanup;
290311694SDavid.Hollister@Sun.COM 	}
290411694SDavid.Hollister@Sun.COM 
290511694SDavid.Hollister@Sun.COM 	mdb_printf("Event log for instance %d written to %s\n", instance,
290611694SDavid.Hollister@Sun.COM 	    ofilename);
290711694SDavid.Hollister@Sun.COM 
290811694SDavid.Hollister@Sun.COM cleanup:
290911694SDavid.Hollister@Sun.COM 	if (ofilefd >= 0) {
291011694SDavid.Hollister@Sun.COM 		close(ofilefd);
291111694SDavid.Hollister@Sun.COM 	}
291211694SDavid.Hollister@Sun.COM 	mdb_free(fwlogp, PMCS_FWLOG_SIZE);
291311694SDavid.Hollister@Sun.COM 	return (rval);
291411694SDavid.Hollister@Sun.COM }
291511694SDavid.Hollister@Sun.COM 
291611694SDavid.Hollister@Sun.COM static int
pmcs_fwlog(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)291711694SDavid.Hollister@Sun.COM pmcs_fwlog(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
291811694SDavid.Hollister@Sun.COM {
291911694SDavid.Hollister@Sun.COM 	void		*pmcs_state;
292011694SDavid.Hollister@Sun.COM 	const char	*ofile = NULL;
292111694SDavid.Hollister@Sun.COM 	struct pmcs_hw	ss;
292211694SDavid.Hollister@Sun.COM 	struct dev_info	dip;
292311694SDavid.Hollister@Sun.COM 
292411694SDavid.Hollister@Sun.COM 	if (mdb_getopts(argc, argv, 'o', MDB_OPT_STR, &ofile, NULL) != argc) {
292511694SDavid.Hollister@Sun.COM 		return (DCMD_USAGE);
292611694SDavid.Hollister@Sun.COM 	}
292711694SDavid.Hollister@Sun.COM 
292811694SDavid.Hollister@Sun.COM 	if (ofile == NULL) {
292911694SDavid.Hollister@Sun.COM 		mdb_printf("No output file specified\n");
293011694SDavid.Hollister@Sun.COM 		return (DCMD_USAGE);
293111694SDavid.Hollister@Sun.COM 	}
293211694SDavid.Hollister@Sun.COM 
293311694SDavid.Hollister@Sun.COM 	if (!(flags & DCMD_ADDRSPEC)) {
293411694SDavid.Hollister@Sun.COM 		pmcs_state = NULL;
293511694SDavid.Hollister@Sun.COM 		if (mdb_readvar(&pmcs_state, "pmcs_softc_state") == -1) {
293611694SDavid.Hollister@Sun.COM 			mdb_warn("can't read pmcs_softc_state");
293711694SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
293811694SDavid.Hollister@Sun.COM 		}
293911694SDavid.Hollister@Sun.COM 		if (mdb_pwalk_dcmd("genunix`softstate", "pmcs`pmcs_fwlog", argc,
294011694SDavid.Hollister@Sun.COM 		    argv, (uintptr_t)pmcs_state) == -1) {
294111694SDavid.Hollister@Sun.COM 			mdb_warn("mdb_pwalk_dcmd failed for pmcs_log");
294211694SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
294311694SDavid.Hollister@Sun.COM 		}
294411694SDavid.Hollister@Sun.COM 		return (DCMD_OK);
294511694SDavid.Hollister@Sun.COM 	}
294611694SDavid.Hollister@Sun.COM 
294711694SDavid.Hollister@Sun.COM 	if (MDB_RD(&ss, sizeof (ss), addr) == -1) {
294811694SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
294911694SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
295011694SDavid.Hollister@Sun.COM 	}
295111694SDavid.Hollister@Sun.COM 
295211694SDavid.Hollister@Sun.COM 	if (MDB_RD(&dip, sizeof (struct dev_info), ss.dip) == -1) {
295311694SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
295411694SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
295511694SDavid.Hollister@Sun.COM 	}
295611694SDavid.Hollister@Sun.COM 
295711694SDavid.Hollister@Sun.COM 	return (pmcs_dump_fwlog(&ss, dip.devi_instance, ofile));
295811694SDavid.Hollister@Sun.COM }
295911694SDavid.Hollister@Sun.COM #endif	/* _KMDB */
296011694SDavid.Hollister@Sun.COM 
296110696SDavid.Hollister@Sun.COM static int
pmcs_log(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)296211048SDavid.Hollister@Sun.COM pmcs_log(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
296311048SDavid.Hollister@Sun.COM {
296411048SDavid.Hollister@Sun.COM 	void		*pmcs_state;
296511048SDavid.Hollister@Sun.COM 	struct pmcs_hw	ss;
296611048SDavid.Hollister@Sun.COM 	struct dev_info	dip;
296711048SDavid.Hollister@Sun.COM 	const char	*match_phy_path = NULL;
296811347SRamana.Srikanth@Sun.COM 	uint64_t 	match_sas_address = 0, tail_lines = 0;
296912120SDavid.Hollister@Sun.COM 	uint_t		verbose = 0;
297011048SDavid.Hollister@Sun.COM 
297111048SDavid.Hollister@Sun.COM 	if (!(flags & DCMD_ADDRSPEC)) {
297211048SDavid.Hollister@Sun.COM 		pmcs_state = NULL;
297311048SDavid.Hollister@Sun.COM 		if (mdb_readvar(&pmcs_state, "pmcs_softc_state") == -1) {
297411048SDavid.Hollister@Sun.COM 			mdb_warn("can't read pmcs_softc_state");
297511048SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
297611048SDavid.Hollister@Sun.COM 		}
297711048SDavid.Hollister@Sun.COM 		if (mdb_pwalk_dcmd("genunix`softstate", "pmcs`pmcs_log", argc,
297811048SDavid.Hollister@Sun.COM 		    argv, (uintptr_t)pmcs_state) == -1) {
297911048SDavid.Hollister@Sun.COM 			mdb_warn("mdb_pwalk_dcmd failed for pmcs_log");
298011048SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
298111048SDavid.Hollister@Sun.COM 		}
298211048SDavid.Hollister@Sun.COM 		return (DCMD_OK);
298311048SDavid.Hollister@Sun.COM 	}
298411048SDavid.Hollister@Sun.COM 
298511048SDavid.Hollister@Sun.COM 	if (mdb_getopts(argc, argv,
298611347SRamana.Srikanth@Sun.COM 	    'l', MDB_OPT_UINT64, &tail_lines,
298711048SDavid.Hollister@Sun.COM 	    'p', MDB_OPT_STR, &match_phy_path,
298811048SDavid.Hollister@Sun.COM 	    's', MDB_OPT_UINT64, &match_sas_address,
298912120SDavid.Hollister@Sun.COM 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
299011048SDavid.Hollister@Sun.COM 	    NULL) != argc) {
299111048SDavid.Hollister@Sun.COM 		return (DCMD_USAGE);
299211048SDavid.Hollister@Sun.COM 	}
299311048SDavid.Hollister@Sun.COM 
299411048SDavid.Hollister@Sun.COM 	if (MDB_RD(&ss, sizeof (ss), addr) == -1) {
299511048SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
299611048SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
299711048SDavid.Hollister@Sun.COM 	}
299811048SDavid.Hollister@Sun.COM 
299911048SDavid.Hollister@Sun.COM 	if (MDB_RD(&dip, sizeof (struct dev_info), ss.dip) == -1) {
300011048SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
300111048SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
300211048SDavid.Hollister@Sun.COM 	}
300311048SDavid.Hollister@Sun.COM 
300411048SDavid.Hollister@Sun.COM 	if (!(flags & DCMD_LOOP)) {
300511048SDavid.Hollister@Sun.COM 		return (pmcs_dump_tracelog(B_TRUE, dip.devi_instance,
300612120SDavid.Hollister@Sun.COM 		    tail_lines, match_phy_path, match_sas_address, verbose));
300711048SDavid.Hollister@Sun.COM 	} else if (flags & DCMD_LOOPFIRST) {
300811347SRamana.Srikanth@Sun.COM 		return (pmcs_dump_tracelog(B_FALSE, 0, tail_lines,
300912120SDavid.Hollister@Sun.COM 		    match_phy_path, match_sas_address, verbose));
301011048SDavid.Hollister@Sun.COM 	} else {
301111048SDavid.Hollister@Sun.COM 		return (DCMD_OK);
301211048SDavid.Hollister@Sun.COM 	}
301311048SDavid.Hollister@Sun.COM }
301411048SDavid.Hollister@Sun.COM 
301511048SDavid.Hollister@Sun.COM static int
pmcs_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)301610696SDavid.Hollister@Sun.COM pmcs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
301710696SDavid.Hollister@Sun.COM {
301811048SDavid.Hollister@Sun.COM 	struct pmcs_hw		ss;
301910696SDavid.Hollister@Sun.COM 	uint_t			verbose = FALSE;
302010696SDavid.Hollister@Sun.COM 	uint_t			phy_info = FALSE;
302110696SDavid.Hollister@Sun.COM 	uint_t			hw_info = FALSE;
302210696SDavid.Hollister@Sun.COM 	uint_t			target_info = FALSE;
302310696SDavid.Hollister@Sun.COM 	uint_t			work_info = FALSE;
302410696SDavid.Hollister@Sun.COM 	uint_t			ic_info = FALSE;
302510696SDavid.Hollister@Sun.COM 	uint_t			iport_info = FALSE;
302610696SDavid.Hollister@Sun.COM 	uint_t			waitqs_info = FALSE;
302710696SDavid.Hollister@Sun.COM 	uint_t			ibq = FALSE;
302810696SDavid.Hollister@Sun.COM 	uint_t			obq = FALSE;
302910696SDavid.Hollister@Sun.COM 	uint_t			tgt_phy_count = FALSE;
303010743SDavid.Hollister@Sun.COM 	uint_t			compq = FALSE;
303111048SDavid.Hollister@Sun.COM 	uint_t			unconfigured = FALSE;
303211334SReed.Liu@Sun.COM 	uint_t			damap_info = FALSE;
303311334SReed.Liu@Sun.COM 	uint_t			dtc_info = FALSE;
303412060SDavid.Hollister@Sun.COM 	uint_t			wserno = FALSE;
303512120SDavid.Hollister@Sun.COM 	uint_t			fwlog = FALSE;
3036*12791Sdavid.hollister@oracle.com 	boolean_t		devid_filter = FALSE;
3037*12791Sdavid.hollister@oracle.com 	uintptr_t		pdevid;
3038*12791Sdavid.hollister@oracle.com 	uint32_t		devid;
303910696SDavid.Hollister@Sun.COM 	int			rv = DCMD_OK;
304010696SDavid.Hollister@Sun.COM 	void			*pmcs_state;
304110696SDavid.Hollister@Sun.COM 	char			*state_str;
304210696SDavid.Hollister@Sun.COM 	struct dev_info		dip;
304311334SReed.Liu@Sun.COM 	per_iport_setting_t	pis;
304410696SDavid.Hollister@Sun.COM 
304510696SDavid.Hollister@Sun.COM 	if (!(flags & DCMD_ADDRSPEC)) {
304610696SDavid.Hollister@Sun.COM 		pmcs_state = NULL;
304710696SDavid.Hollister@Sun.COM 		if (mdb_readvar(&pmcs_state, "pmcs_softc_state") == -1) {
304810696SDavid.Hollister@Sun.COM 			mdb_warn("can't read pmcs_softc_state");
304910696SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
305010696SDavid.Hollister@Sun.COM 		}
305110696SDavid.Hollister@Sun.COM 		if (mdb_pwalk_dcmd("genunix`softstate", "pmcs`pmcs", argc, argv,
305210696SDavid.Hollister@Sun.COM 		    (uintptr_t)pmcs_state) == -1) {
305310696SDavid.Hollister@Sun.COM 			mdb_warn("mdb_pwalk_dcmd failed");
305410696SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
305510696SDavid.Hollister@Sun.COM 		}
305610696SDavid.Hollister@Sun.COM 		return (DCMD_OK);
305710696SDavid.Hollister@Sun.COM 	}
305810696SDavid.Hollister@Sun.COM 
305910696SDavid.Hollister@Sun.COM 	if (mdb_getopts(argc, argv,
306010743SDavid.Hollister@Sun.COM 	    'c', MDB_OPT_SETBITS, TRUE, &compq,
306111334SReed.Liu@Sun.COM 	    'd', MDB_OPT_SETBITS, TRUE, &dtc_info,
3062*12791Sdavid.hollister@oracle.com 	    'D', MDB_OPT_UINTPTR_SET, &devid_filter, &pdevid,
306312120SDavid.Hollister@Sun.COM 	    'e', MDB_OPT_SETBITS, TRUE, &fwlog,
306410696SDavid.Hollister@Sun.COM 	    'h', MDB_OPT_SETBITS, TRUE, &hw_info,
306510696SDavid.Hollister@Sun.COM 	    'i', MDB_OPT_SETBITS, TRUE, &ic_info,
306610696SDavid.Hollister@Sun.COM 	    'I', MDB_OPT_SETBITS, TRUE, &iport_info,
306711334SReed.Liu@Sun.COM 	    'm', MDB_OPT_SETBITS, TRUE, &damap_info,
306810696SDavid.Hollister@Sun.COM 	    'p', MDB_OPT_SETBITS, TRUE, &phy_info,
306910696SDavid.Hollister@Sun.COM 	    'q', MDB_OPT_SETBITS, TRUE, &ibq,
307010696SDavid.Hollister@Sun.COM 	    'Q', MDB_OPT_SETBITS, TRUE, &obq,
307112060SDavid.Hollister@Sun.COM 	    's', MDB_OPT_SETBITS, TRUE, &wserno,
307210696SDavid.Hollister@Sun.COM 	    't', MDB_OPT_SETBITS, TRUE, &target_info,
307310696SDavid.Hollister@Sun.COM 	    'T', MDB_OPT_SETBITS, TRUE, &tgt_phy_count,
307411048SDavid.Hollister@Sun.COM 	    'u', MDB_OPT_SETBITS, TRUE, &unconfigured,
307510696SDavid.Hollister@Sun.COM 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
307610696SDavid.Hollister@Sun.COM 	    'w', MDB_OPT_SETBITS, TRUE, &work_info,
307710696SDavid.Hollister@Sun.COM 	    'W', MDB_OPT_SETBITS, TRUE, &waitqs_info,
307810696SDavid.Hollister@Sun.COM 	    NULL) != argc)
307910696SDavid.Hollister@Sun.COM 		return (DCMD_USAGE);
308010696SDavid.Hollister@Sun.COM 
308111334SReed.Liu@Sun.COM 	/*
308211334SReed.Liu@Sun.COM 	 * The 'd' and 'm' options implicitly enable the 'I' option
308311334SReed.Liu@Sun.COM 	 */
308411334SReed.Liu@Sun.COM 	pis.pis_damap_info = damap_info;
308511334SReed.Liu@Sun.COM 	pis.pis_dtc_info = dtc_info;
308611334SReed.Liu@Sun.COM 	if (damap_info || dtc_info) {
308711334SReed.Liu@Sun.COM 		iport_info = TRUE;
308811334SReed.Liu@Sun.COM 	}
308911334SReed.Liu@Sun.COM 
3090*12791Sdavid.hollister@oracle.com 	/*
3091*12791Sdavid.hollister@oracle.com 	 * The -D option is meaningless without -q and/or -Q, and implies
3092*12791Sdavid.hollister@oracle.com 	 * verbosity.
3093*12791Sdavid.hollister@oracle.com 	 */
3094*12791Sdavid.hollister@oracle.com 	if (devid_filter) {
3095*12791Sdavid.hollister@oracle.com 		devid = (uint64_t)pdevid & 0xffffffff;
3096*12791Sdavid.hollister@oracle.com 		if (!ibq && !obq) {
3097*12791Sdavid.hollister@oracle.com 			mdb_printf("-D requires either -q or -Q\n");
3098*12791Sdavid.hollister@oracle.com 			return (DCMD_USAGE);
3099*12791Sdavid.hollister@oracle.com 		}
3100*12791Sdavid.hollister@oracle.com 		if (devid > PMCS_DEVICE_ID_MASK) {
3101*12791Sdavid.hollister@oracle.com 			mdb_printf("Device ID invalid\n");
3102*12791Sdavid.hollister@oracle.com 			return (DCMD_USAGE);
3103*12791Sdavid.hollister@oracle.com 		}
3104*12791Sdavid.hollister@oracle.com 		verbose = TRUE;
3105*12791Sdavid.hollister@oracle.com 	}
3106*12791Sdavid.hollister@oracle.com 
310710696SDavid.Hollister@Sun.COM 	if (MDB_RD(&ss, sizeof (ss), addr) == -1) {
310810696SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
310910696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
311010696SDavid.Hollister@Sun.COM 	}
311110696SDavid.Hollister@Sun.COM 
311210696SDavid.Hollister@Sun.COM 	if (MDB_RD(&dip, sizeof (struct dev_info), ss.dip) == -1) {
311310696SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
311410696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
311510696SDavid.Hollister@Sun.COM 	}
311610696SDavid.Hollister@Sun.COM 
311710696SDavid.Hollister@Sun.COM 	/* processing completed */
311810696SDavid.Hollister@Sun.COM 
311910696SDavid.Hollister@Sun.COM 	if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) ||
312010696SDavid.Hollister@Sun.COM 	    (flags & DCMD_LOOPFIRST) || phy_info || target_info || hw_info ||
312111048SDavid.Hollister@Sun.COM 	    work_info || waitqs_info || ibq || obq || tgt_phy_count || compq ||
312212120SDavid.Hollister@Sun.COM 	    unconfigured || fwlog) {
312310696SDavid.Hollister@Sun.COM 		if ((flags & DCMD_LOOP) && !(flags & DCMD_LOOPFIRST))
312410696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
312510696SDavid.Hollister@Sun.COM 		mdb_printf("%16s %9s %4s B C  WorkFlags wserno DbgMsk %16s\n",
312610696SDavid.Hollister@Sun.COM 		    "Address", "State", "Inst", "DIP");
312710696SDavid.Hollister@Sun.COM 		mdb_printf("================================="
312810696SDavid.Hollister@Sun.COM 		    "============================================\n");
312910696SDavid.Hollister@Sun.COM 	}
313010696SDavid.Hollister@Sun.COM 
313110696SDavid.Hollister@Sun.COM 	switch (ss.state) {
313210696SDavid.Hollister@Sun.COM 	case STATE_NIL:
313310696SDavid.Hollister@Sun.COM 		state_str = "Invalid";
313410696SDavid.Hollister@Sun.COM 		break;
313510696SDavid.Hollister@Sun.COM 	case STATE_PROBING:
313610696SDavid.Hollister@Sun.COM 		state_str = "Probing";
313710696SDavid.Hollister@Sun.COM 		break;
313810696SDavid.Hollister@Sun.COM 	case STATE_RUNNING:
313910696SDavid.Hollister@Sun.COM 		state_str = "Running";
314010696SDavid.Hollister@Sun.COM 		break;
314110696SDavid.Hollister@Sun.COM 	case STATE_UNPROBING:
314210696SDavid.Hollister@Sun.COM 		state_str = "Unprobing";
314310696SDavid.Hollister@Sun.COM 		break;
314410696SDavid.Hollister@Sun.COM 	case STATE_DEAD:
314510696SDavid.Hollister@Sun.COM 		state_str = "Dead";
314610696SDavid.Hollister@Sun.COM 		break;
314711692SJesse.Butler@Sun.COM 	case STATE_IN_RESET:
314811692SJesse.Butler@Sun.COM 		state_str = "In Reset";
314911692SJesse.Butler@Sun.COM 		break;
315010696SDavid.Hollister@Sun.COM 	}
315110696SDavid.Hollister@Sun.COM 
315210696SDavid.Hollister@Sun.COM 	mdb_printf("%16p %9s %4d %1d %1d 0x%08x 0x%04x 0x%04x %16p\n", addr,
315310696SDavid.Hollister@Sun.COM 	    state_str, dip.devi_instance, ss.blocked, ss.configuring,
315410696SDavid.Hollister@Sun.COM 	    ss.work_flags, ss.wserno, ss.debug_mask, ss.dip);
315510696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
315610696SDavid.Hollister@Sun.COM 
315710696SDavid.Hollister@Sun.COM 	mdb_inc_indent(4);
315810696SDavid.Hollister@Sun.COM 
315910696SDavid.Hollister@Sun.COM 	if (waitqs_info)
316010696SDavid.Hollister@Sun.COM 		display_waitqs(ss, verbose);
316110696SDavid.Hollister@Sun.COM 
316210696SDavid.Hollister@Sun.COM 	if (hw_info)
316310696SDavid.Hollister@Sun.COM 		display_hwinfo(ss, verbose);
316410696SDavid.Hollister@Sun.COM 
316510696SDavid.Hollister@Sun.COM 	if (phy_info || tgt_phy_count)
316610696SDavid.Hollister@Sun.COM 		display_phys(ss, verbose, NULL, 0, tgt_phy_count);
316710696SDavid.Hollister@Sun.COM 
316810696SDavid.Hollister@Sun.COM 	if (target_info || tgt_phy_count)
316910696SDavid.Hollister@Sun.COM 		display_targets(ss, verbose, tgt_phy_count);
317010696SDavid.Hollister@Sun.COM 
317112060SDavid.Hollister@Sun.COM 	if (work_info || wserno)
317212060SDavid.Hollister@Sun.COM 		display_work(ss, verbose, wserno);
317310696SDavid.Hollister@Sun.COM 
317410696SDavid.Hollister@Sun.COM 	if (ic_info)
317510696SDavid.Hollister@Sun.COM 		display_ic(ss, verbose);
317610696SDavid.Hollister@Sun.COM 
317710696SDavid.Hollister@Sun.COM 	if (ibq)
3178*12791Sdavid.hollister@oracle.com 		display_inbound_queues(ss, devid, verbose);
317910696SDavid.Hollister@Sun.COM 
318010696SDavid.Hollister@Sun.COM 	if (obq)
3181*12791Sdavid.hollister@oracle.com 		display_outbound_queues(ss, devid, verbose);
318210696SDavid.Hollister@Sun.COM 
318310696SDavid.Hollister@Sun.COM 	if (iport_info)
318411334SReed.Liu@Sun.COM 		display_iport(ss, addr, verbose, &pis);
318510696SDavid.Hollister@Sun.COM 
318610743SDavid.Hollister@Sun.COM 	if (compq)
318710743SDavid.Hollister@Sun.COM 		display_completion_queue(ss);
318810743SDavid.Hollister@Sun.COM 
318911048SDavid.Hollister@Sun.COM 	if (unconfigured)
319011048SDavid.Hollister@Sun.COM 		display_unconfigured_targets(addr);
319111048SDavid.Hollister@Sun.COM 
319212120SDavid.Hollister@Sun.COM 	if (fwlog)
319312120SDavid.Hollister@Sun.COM 		display_event_log(ss);
319412120SDavid.Hollister@Sun.COM 
319510696SDavid.Hollister@Sun.COM 	mdb_dec_indent(4);
319610696SDavid.Hollister@Sun.COM 
319710696SDavid.Hollister@Sun.COM 	return (rv);
319810696SDavid.Hollister@Sun.COM }
319910696SDavid.Hollister@Sun.COM 
320010696SDavid.Hollister@Sun.COM void
pmcs_help()320110696SDavid.Hollister@Sun.COM pmcs_help()
320210696SDavid.Hollister@Sun.COM {
320310696SDavid.Hollister@Sun.COM 	mdb_printf("Prints summary information about each pmcs instance.\n"
320410743SDavid.Hollister@Sun.COM 	    "    -c: Dump the completion queue\n"
320511334SReed.Liu@Sun.COM 	    "    -d: Print per-iport information about device tree children\n"
3206*12791Sdavid.hollister@oracle.com 	    "    -D <device ID>: With -q/-Q, filter by device handle\n"
320712120SDavid.Hollister@Sun.COM 	    "    -e: Display the in-memory firmware event log\n"
320810696SDavid.Hollister@Sun.COM 	    "    -h: Print more detailed hardware information\n"
320910696SDavid.Hollister@Sun.COM 	    "    -i: Print interrupt coalescing information\n"
321010696SDavid.Hollister@Sun.COM 	    "    -I: Print information about each iport\n"
321111334SReed.Liu@Sun.COM 	    "    -m: Print per-iport information about DAM/damap state\n"
321210696SDavid.Hollister@Sun.COM 	    "    -p: Print information about each attached PHY\n"
321310696SDavid.Hollister@Sun.COM 	    "    -q: Dump inbound queues\n"
321410696SDavid.Hollister@Sun.COM 	    "    -Q: Dump outbound queues\n"
321512060SDavid.Hollister@Sun.COM 	    "    -s: Dump all work structures sorted by serial number\n"
321611048SDavid.Hollister@Sun.COM 	    "    -t: Print information about each configured target\n"
321710696SDavid.Hollister@Sun.COM 	    "    -T: Print target and PHY count summary\n"
321811048SDavid.Hollister@Sun.COM 	    "    -u: Show SAS address of all unconfigured targets\n"
321910696SDavid.Hollister@Sun.COM 	    "    -w: Dump work structures\n"
322010696SDavid.Hollister@Sun.COM 	    "    -W: List pmcs cmds waiting on various queues\n"
322110696SDavid.Hollister@Sun.COM 	    "    -v: Add verbosity to the above options\n");
322210696SDavid.Hollister@Sun.COM }
322310696SDavid.Hollister@Sun.COM 
322410743SDavid.Hollister@Sun.COM void
pmcs_log_help()322511048SDavid.Hollister@Sun.COM pmcs_log_help()
322611048SDavid.Hollister@Sun.COM {
322711048SDavid.Hollister@Sun.COM 	mdb_printf("Dump the pmcs log buffer, possibly with filtering.\n"
322811347SRamana.Srikanth@Sun.COM 	    "    -l TAIL_LINES:          Dump the last TAIL_LINES messages\n"
322911048SDavid.Hollister@Sun.COM 	    "    -p PHY_PATH:            Dump messages matching PHY_PATH\n"
323011048SDavid.Hollister@Sun.COM 	    "    -s SAS_ADDRESS:         Dump messages matching SAS_ADDRESS\n\n"
323111048SDavid.Hollister@Sun.COM 	    "Where: PHY_PATH can be found with ::pmcs -p (e.g. pp04.18.18.01)\n"
323211048SDavid.Hollister@Sun.COM 	    "       SAS_ADDRESS can be found with ::pmcs -t "
323311048SDavid.Hollister@Sun.COM 	    "(e.g. 5000c5000358c221)\n");
323411048SDavid.Hollister@Sun.COM }
323511048SDavid.Hollister@Sun.COM void
pmcs_tag_help()323610743SDavid.Hollister@Sun.COM pmcs_tag_help()
323710743SDavid.Hollister@Sun.COM {
323810743SDavid.Hollister@Sun.COM 	mdb_printf("Print all work structures by matching the tag.\n"
323910743SDavid.Hollister@Sun.COM 	    "    -i index:        Match tag index (0x000 - 0xfff)\n"
324010743SDavid.Hollister@Sun.COM 	    "    -s serialnumber: Match serial number (0x0000 - 0xffff)\n"
324110743SDavid.Hollister@Sun.COM 	    "    -t tagtype:      Match tag type [NONE(1), CBACK(2), "
324210743SDavid.Hollister@Sun.COM 	    "WAIT(3)]\n");
324310743SDavid.Hollister@Sun.COM }
324410743SDavid.Hollister@Sun.COM 
324510696SDavid.Hollister@Sun.COM static const mdb_dcmd_t dcmds[] = {
3246*12791Sdavid.hollister@oracle.com 	{ "pmcs", "?[-cdehiImpQqtTuwWv] [-D <device ID>]",
3247*12791Sdavid.hollister@oracle.com 	    "print pmcs information", pmcs_dcmd, pmcs_help
324810696SDavid.Hollister@Sun.COM 	},
324911048SDavid.Hollister@Sun.COM 	{ "pmcs_log",
325012120SDavid.Hollister@Sun.COM 	    "?[-v] [-p PHY_PATH | -s SAS_ADDRESS | -l TAIL_LINES]",
325111048SDavid.Hollister@Sun.COM 	    "dump pmcs log file", pmcs_log, pmcs_log_help
325211048SDavid.Hollister@Sun.COM 	},
325310743SDavid.Hollister@Sun.COM 	{ "pmcs_tag", "?[-t tagtype|-s serialnum|-i index]",
325410743SDavid.Hollister@Sun.COM 	    "Find work structures by tag type, serial number or index",
325510743SDavid.Hollister@Sun.COM 	    pmcs_tag, pmcs_tag_help
325610743SDavid.Hollister@Sun.COM 	},
325711694SDavid.Hollister@Sun.COM #ifndef _KMDB
325811694SDavid.Hollister@Sun.COM 	{ "pmcs_fwlog",
325911694SDavid.Hollister@Sun.COM 	    "?-o output_file",
326011694SDavid.Hollister@Sun.COM 	    "dump pmcs firmware event log to output_file", pmcs_fwlog, NULL
326111694SDavid.Hollister@Sun.COM 	},
326211694SDavid.Hollister@Sun.COM #endif	/* _KMDB */
326310696SDavid.Hollister@Sun.COM 	{ NULL }
326410696SDavid.Hollister@Sun.COM };
326510696SDavid.Hollister@Sun.COM 
326610696SDavid.Hollister@Sun.COM static const mdb_walker_t walkers[] = {
326710696SDavid.Hollister@Sun.COM 	{ "pmcs_targets", "walk target structures",
326810696SDavid.Hollister@Sun.COM 		targets_walk_i, targets_walk_s, targets_walk_f },
326910696SDavid.Hollister@Sun.COM 	{ "pmcs_phys", "walk PHY structures",
327010696SDavid.Hollister@Sun.COM 		phy_walk_i, phy_walk_s, phy_walk_f },
327110696SDavid.Hollister@Sun.COM 	{ NULL }
327210696SDavid.Hollister@Sun.COM };
327310696SDavid.Hollister@Sun.COM 
327410696SDavid.Hollister@Sun.COM static const mdb_modinfo_t modinfo = {
327510696SDavid.Hollister@Sun.COM 	MDB_API_VERSION, dcmds, walkers
327610696SDavid.Hollister@Sun.COM };
327710696SDavid.Hollister@Sun.COM 
327810696SDavid.Hollister@Sun.COM const mdb_modinfo_t *
_mdb_init(void)327910696SDavid.Hollister@Sun.COM _mdb_init(void)
328010696SDavid.Hollister@Sun.COM {
328110696SDavid.Hollister@Sun.COM 	return (&modinfo);
328210696SDavid.Hollister@Sun.COM }
3283