xref: /onnv-gate/usr/src/cmd/mdb/common/modules/pmcs/pmcs.c (revision 10696:cd0f390dd9e2)
1*10696SDavid.Hollister@Sun.COM /*
2*10696SDavid.Hollister@Sun.COM  * CDDL HEADER START
3*10696SDavid.Hollister@Sun.COM  *
4*10696SDavid.Hollister@Sun.COM  * The contents of this file are subject to the terms of the
5*10696SDavid.Hollister@Sun.COM  * Common Development and Distribution License (the "License").
6*10696SDavid.Hollister@Sun.COM  * You may not use this file except in compliance with the License.
7*10696SDavid.Hollister@Sun.COM  *
8*10696SDavid.Hollister@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*10696SDavid.Hollister@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*10696SDavid.Hollister@Sun.COM  * See the License for the specific language governing permissions
11*10696SDavid.Hollister@Sun.COM  * and limitations under the License.
12*10696SDavid.Hollister@Sun.COM  *
13*10696SDavid.Hollister@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*10696SDavid.Hollister@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*10696SDavid.Hollister@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*10696SDavid.Hollister@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*10696SDavid.Hollister@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*10696SDavid.Hollister@Sun.COM  *
19*10696SDavid.Hollister@Sun.COM  * CDDL HEADER END
20*10696SDavid.Hollister@Sun.COM  */
21*10696SDavid.Hollister@Sun.COM /*
22*10696SDavid.Hollister@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*10696SDavid.Hollister@Sun.COM  * Use is subject to license terms.
24*10696SDavid.Hollister@Sun.COM  */
25*10696SDavid.Hollister@Sun.COM 
26*10696SDavid.Hollister@Sun.COM #include <limits.h>
27*10696SDavid.Hollister@Sun.COM #include <sys/mdb_modapi.h>
28*10696SDavid.Hollister@Sun.COM #include <sys/sysinfo.h>
29*10696SDavid.Hollister@Sun.COM #include <sys/scsi/scsi.h>
30*10696SDavid.Hollister@Sun.COM #include <sys/scsi/adapters/pmcs/pmcs.h>
31*10696SDavid.Hollister@Sun.COM 
32*10696SDavid.Hollister@Sun.COM #define	MDB_RD(a, b, c)	mdb_vread(a, b, (uintptr_t)c)
33*10696SDavid.Hollister@Sun.COM #define	NOREAD(a, b)	mdb_warn("could not read " #a " at 0x%p", b)
34*10696SDavid.Hollister@Sun.COM 
35*10696SDavid.Hollister@Sun.COM static pmcs_hw_t ss;
36*10696SDavid.Hollister@Sun.COM static pmcs_xscsi_t **targets = NULL;
37*10696SDavid.Hollister@Sun.COM static int target_idx;
38*10696SDavid.Hollister@Sun.COM 
39*10696SDavid.Hollister@Sun.COM static uint32_t	sas_phys, sata_phys, exp_phys, num_expanders, empty_phys;
40*10696SDavid.Hollister@Sun.COM 
41*10696SDavid.Hollister@Sun.COM static pmcs_phy_t *pmcs_next_sibling(pmcs_phy_t *phyp);
42*10696SDavid.Hollister@Sun.COM 
43*10696SDavid.Hollister@Sun.COM static void
44*10696SDavid.Hollister@Sun.COM print_sas_address(pmcs_phy_t *phy)
45*10696SDavid.Hollister@Sun.COM {
46*10696SDavid.Hollister@Sun.COM 	int idx;
47*10696SDavid.Hollister@Sun.COM 
48*10696SDavid.Hollister@Sun.COM 	for (idx = 0; idx < 8; idx++) {
49*10696SDavid.Hollister@Sun.COM 		mdb_printf("%02x", phy->sas_address[idx]);
50*10696SDavid.Hollister@Sun.COM 	}
51*10696SDavid.Hollister@Sun.COM }
52*10696SDavid.Hollister@Sun.COM 
53*10696SDavid.Hollister@Sun.COM /*ARGSUSED*/
54*10696SDavid.Hollister@Sun.COM static void
55*10696SDavid.Hollister@Sun.COM display_ic(struct pmcs_hw m, int verbose)
56*10696SDavid.Hollister@Sun.COM {
57*10696SDavid.Hollister@Sun.COM 	int msec_per_tick;
58*10696SDavid.Hollister@Sun.COM 
59*10696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&msec_per_tick, "msec_per_tick") == -1) {
60*10696SDavid.Hollister@Sun.COM 		mdb_warn("can't read msec_per_tick");
61*10696SDavid.Hollister@Sun.COM 		msec_per_tick = 0;
62*10696SDavid.Hollister@Sun.COM 	}
63*10696SDavid.Hollister@Sun.COM 
64*10696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
65*10696SDavid.Hollister@Sun.COM 	mdb_printf("Interrupt coalescing timer info\n");
66*10696SDavid.Hollister@Sun.COM 	mdb_printf("-------------------------------\n");
67*10696SDavid.Hollister@Sun.COM 	if (msec_per_tick == 0) {
68*10696SDavid.Hollister@Sun.COM 		mdb_printf("Quantum                       : ?? ms\n");
69*10696SDavid.Hollister@Sun.COM 	} else {
70*10696SDavid.Hollister@Sun.COM 		mdb_printf("Quantum                       : %d ms\n",
71*10696SDavid.Hollister@Sun.COM 		    m.io_intr_coal.quantum * msec_per_tick);
72*10696SDavid.Hollister@Sun.COM 	}
73*10696SDavid.Hollister@Sun.COM 	mdb_printf("Timer enabled                 : ");
74*10696SDavid.Hollister@Sun.COM 	if (m.io_intr_coal.timer_on) {
75*10696SDavid.Hollister@Sun.COM 		mdb_printf("Yes\n");
76*10696SDavid.Hollister@Sun.COM 		mdb_printf("Coalescing timer value        : %d us\n",
77*10696SDavid.Hollister@Sun.COM 		    m.io_intr_coal.intr_coal_timer);
78*10696SDavid.Hollister@Sun.COM 	} else {
79*10696SDavid.Hollister@Sun.COM 		mdb_printf("No\n");
80*10696SDavid.Hollister@Sun.COM 	}
81*10696SDavid.Hollister@Sun.COM 	mdb_printf("Total nsecs between interrupts: %ld\n",
82*10696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.nsecs_between_intrs);
83*10696SDavid.Hollister@Sun.COM 	mdb_printf("Time of last I/O interrupt    : %ld\n",
84*10696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.last_io_comp);
85*10696SDavid.Hollister@Sun.COM 	mdb_printf("Number of I/O interrupts      : %d\n",
86*10696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.num_intrs);
87*10696SDavid.Hollister@Sun.COM 	mdb_printf("Number of I/O completions     : %d\n",
88*10696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.num_io_completions);
89*10696SDavid.Hollister@Sun.COM 	mdb_printf("Max I/O completion interrupts : %d\n",
90*10696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.max_io_completions);
91*10696SDavid.Hollister@Sun.COM 	mdb_printf("Measured ECHO int latency     : %d ns\n",
92*10696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.intr_latency);
93*10696SDavid.Hollister@Sun.COM 	mdb_printf("Interrupt threshold           : %d\n",
94*10696SDavid.Hollister@Sun.COM 	    m.io_intr_coal.intr_threshold);
95*10696SDavid.Hollister@Sun.COM }
96*10696SDavid.Hollister@Sun.COM 
97*10696SDavid.Hollister@Sun.COM /*ARGSUSED*/
98*10696SDavid.Hollister@Sun.COM static int
99*10696SDavid.Hollister@Sun.COM pmcs_iport_phy_walk_cb(uintptr_t addr, const void *wdata, void *priv)
100*10696SDavid.Hollister@Sun.COM {
101*10696SDavid.Hollister@Sun.COM 	struct pmcs_phy		phy;
102*10696SDavid.Hollister@Sun.COM 
103*10696SDavid.Hollister@Sun.COM 	if (mdb_vread(&phy, sizeof (struct pmcs_phy), addr) !=
104*10696SDavid.Hollister@Sun.COM 	    sizeof (struct pmcs_phy)) {
105*10696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
106*10696SDavid.Hollister@Sun.COM 	}
107*10696SDavid.Hollister@Sun.COM 
108*10696SDavid.Hollister@Sun.COM 	mdb_printf("%16p %2d\n", addr, phy.phynum);
109*10696SDavid.Hollister@Sun.COM 
110*10696SDavid.Hollister@Sun.COM 	return (0);
111*10696SDavid.Hollister@Sun.COM }
112*10696SDavid.Hollister@Sun.COM 
113*10696SDavid.Hollister@Sun.COM /*ARGSUSED*/
114*10696SDavid.Hollister@Sun.COM static int
115*10696SDavid.Hollister@Sun.COM pmcs_iport_walk_cb(uintptr_t addr, const void *wdata, void *priv)
116*10696SDavid.Hollister@Sun.COM {
117*10696SDavid.Hollister@Sun.COM 	struct pmcs_iport	iport;
118*10696SDavid.Hollister@Sun.COM 	uintptr_t		list_addr;
119*10696SDavid.Hollister@Sun.COM 	char			*ua_state;
120*10696SDavid.Hollister@Sun.COM 	char			portid[4];
121*10696SDavid.Hollister@Sun.COM 	char			unit_address[34];
122*10696SDavid.Hollister@Sun.COM 
123*10696SDavid.Hollister@Sun.COM 	if (mdb_vread(&iport, sizeof (struct pmcs_iport), addr) !=
124*10696SDavid.Hollister@Sun.COM 	    sizeof (struct pmcs_iport)) {
125*10696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
126*10696SDavid.Hollister@Sun.COM 	}
127*10696SDavid.Hollister@Sun.COM 
128*10696SDavid.Hollister@Sun.COM 	if (mdb_readstr(unit_address, sizeof (unit_address),
129*10696SDavid.Hollister@Sun.COM 	    (uintptr_t)(iport.ua)) == -1) {
130*10696SDavid.Hollister@Sun.COM 		strncpy(unit_address, "Unset", sizeof (unit_address));
131*10696SDavid.Hollister@Sun.COM 	}
132*10696SDavid.Hollister@Sun.COM 
133*10696SDavid.Hollister@Sun.COM 	if (iport.portid == 0xffff) {
134*10696SDavid.Hollister@Sun.COM 		mdb_snprintf(portid, sizeof (portid), "%s", "-");
135*10696SDavid.Hollister@Sun.COM 	} else {
136*10696SDavid.Hollister@Sun.COM 		mdb_snprintf(portid, sizeof (portid), "%d", iport.portid);
137*10696SDavid.Hollister@Sun.COM 	}
138*10696SDavid.Hollister@Sun.COM 
139*10696SDavid.Hollister@Sun.COM 	switch (iport.ua_state) {
140*10696SDavid.Hollister@Sun.COM 	case UA_INACTIVE:
141*10696SDavid.Hollister@Sun.COM 		ua_state = "Inactive";
142*10696SDavid.Hollister@Sun.COM 		break;
143*10696SDavid.Hollister@Sun.COM 	case UA_PEND_ACTIVATE:
144*10696SDavid.Hollister@Sun.COM 		ua_state = "PendActivate";
145*10696SDavid.Hollister@Sun.COM 		break;
146*10696SDavid.Hollister@Sun.COM 	case UA_ACTIVE:
147*10696SDavid.Hollister@Sun.COM 		ua_state = "Active";
148*10696SDavid.Hollister@Sun.COM 		break;
149*10696SDavid.Hollister@Sun.COM 	case UA_PEND_DEACTIVATE:
150*10696SDavid.Hollister@Sun.COM 		ua_state = "PendDeactivate";
151*10696SDavid.Hollister@Sun.COM 		break;
152*10696SDavid.Hollister@Sun.COM 	default:
153*10696SDavid.Hollister@Sun.COM 		ua_state = "Unknown";
154*10696SDavid.Hollister@Sun.COM 	}
155*10696SDavid.Hollister@Sun.COM 
156*10696SDavid.Hollister@Sun.COM 	if (strlen(unit_address) < 3) {
157*10696SDavid.Hollister@Sun.COM 		/* Standard iport unit address */
158*10696SDavid.Hollister@Sun.COM 		mdb_printf("UA %-16s %16s %8s %8s %16s", "Iport", "UA State",
159*10696SDavid.Hollister@Sun.COM 		    "PortID", "NumPhys", "DIP\n");
160*10696SDavid.Hollister@Sun.COM 		mdb_printf("%2s %16p %16s %8s %8d %16p\n", unit_address, addr,
161*10696SDavid.Hollister@Sun.COM 		    ua_state, portid, iport.nphy, iport.dip);
162*10696SDavid.Hollister@Sun.COM 	} else {
163*10696SDavid.Hollister@Sun.COM 		/* Temporary iport unit address */
164*10696SDavid.Hollister@Sun.COM 		mdb_printf("%-32s %16s %20s %8s %8s %16s", "UA", "Iport",
165*10696SDavid.Hollister@Sun.COM 		    "UA State", "PortID", "NumPhys", "DIP\n");
166*10696SDavid.Hollister@Sun.COM 		mdb_printf("%32s %16p %20s %8s %8d %16p\n", unit_address, addr,
167*10696SDavid.Hollister@Sun.COM 		    ua_state, portid, iport.nphy, iport.dip);
168*10696SDavid.Hollister@Sun.COM 	}
169*10696SDavid.Hollister@Sun.COM 
170*10696SDavid.Hollister@Sun.COM 	if (iport.nphy > 0) {
171*10696SDavid.Hollister@Sun.COM 		mdb_inc_indent(4);
172*10696SDavid.Hollister@Sun.COM 		mdb_printf("%-18s %8s", "Phy", "PhyNum\n");
173*10696SDavid.Hollister@Sun.COM 		mdb_inc_indent(2);
174*10696SDavid.Hollister@Sun.COM 		list_addr =
175*10696SDavid.Hollister@Sun.COM 		    (uintptr_t)(addr + offsetof(struct pmcs_iport, phys));
176*10696SDavid.Hollister@Sun.COM 		if (mdb_pwalk("list", pmcs_iport_phy_walk_cb, NULL,
177*10696SDavid.Hollister@Sun.COM 		    list_addr) == -1) {
178*10696SDavid.Hollister@Sun.COM 			mdb_warn("pmcs iport walk failed");
179*10696SDavid.Hollister@Sun.COM 		}
180*10696SDavid.Hollister@Sun.COM 		mdb_dec_indent(6);
181*10696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
182*10696SDavid.Hollister@Sun.COM 	}
183*10696SDavid.Hollister@Sun.COM 
184*10696SDavid.Hollister@Sun.COM 	return (0);
185*10696SDavid.Hollister@Sun.COM }
186*10696SDavid.Hollister@Sun.COM 
187*10696SDavid.Hollister@Sun.COM /*ARGSUSED*/
188*10696SDavid.Hollister@Sun.COM static void
189*10696SDavid.Hollister@Sun.COM display_iport(struct pmcs_hw m, uintptr_t addr, int verbose)
190*10696SDavid.Hollister@Sun.COM {
191*10696SDavid.Hollister@Sun.COM 	uintptr_t	list_addr;
192*10696SDavid.Hollister@Sun.COM 
193*10696SDavid.Hollister@Sun.COM 	if (m.iports_attached) {
194*10696SDavid.Hollister@Sun.COM 		mdb_printf("Iport information:\n");
195*10696SDavid.Hollister@Sun.COM 		mdb_printf("-----------------\n");
196*10696SDavid.Hollister@Sun.COM 	} else {
197*10696SDavid.Hollister@Sun.COM 		mdb_printf("No Iports found.\n\n");
198*10696SDavid.Hollister@Sun.COM 		return;
199*10696SDavid.Hollister@Sun.COM 	}
200*10696SDavid.Hollister@Sun.COM 
201*10696SDavid.Hollister@Sun.COM 	list_addr = (uintptr_t)(addr + offsetof(struct pmcs_hw, iports));
202*10696SDavid.Hollister@Sun.COM 
203*10696SDavid.Hollister@Sun.COM 	if (mdb_pwalk("list", pmcs_iport_walk_cb, NULL, list_addr) == -1) {
204*10696SDavid.Hollister@Sun.COM 		mdb_warn("pmcs iport walk failed");
205*10696SDavid.Hollister@Sun.COM 	}
206*10696SDavid.Hollister@Sun.COM 
207*10696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
208*10696SDavid.Hollister@Sun.COM }
209*10696SDavid.Hollister@Sun.COM 
210*10696SDavid.Hollister@Sun.COM /*ARGSUSED*/
211*10696SDavid.Hollister@Sun.COM static void
212*10696SDavid.Hollister@Sun.COM display_hwinfo(struct pmcs_hw m, int verbose)
213*10696SDavid.Hollister@Sun.COM {
214*10696SDavid.Hollister@Sun.COM 	struct pmcs_hw	*mp = &m;
215*10696SDavid.Hollister@Sun.COM 	char		*fwsupport;
216*10696SDavid.Hollister@Sun.COM 
217*10696SDavid.Hollister@Sun.COM 	switch (PMCS_FW_TYPE(mp)) {
218*10696SDavid.Hollister@Sun.COM 	case PMCS_FW_TYPE_RELEASED:
219*10696SDavid.Hollister@Sun.COM 		fwsupport = "Released";
220*10696SDavid.Hollister@Sun.COM 		break;
221*10696SDavid.Hollister@Sun.COM 	case PMCS_FW_TYPE_DEVELOPMENT:
222*10696SDavid.Hollister@Sun.COM 		fwsupport = "Development";
223*10696SDavid.Hollister@Sun.COM 		break;
224*10696SDavid.Hollister@Sun.COM 	case PMCS_FW_TYPE_ALPHA:
225*10696SDavid.Hollister@Sun.COM 		fwsupport = "Alpha";
226*10696SDavid.Hollister@Sun.COM 		break;
227*10696SDavid.Hollister@Sun.COM 	case PMCS_FW_TYPE_BETA:
228*10696SDavid.Hollister@Sun.COM 		fwsupport = "Beta";
229*10696SDavid.Hollister@Sun.COM 		break;
230*10696SDavid.Hollister@Sun.COM 	default:
231*10696SDavid.Hollister@Sun.COM 		fwsupport = "Special";
232*10696SDavid.Hollister@Sun.COM 		break;
233*10696SDavid.Hollister@Sun.COM 	}
234*10696SDavid.Hollister@Sun.COM 
235*10696SDavid.Hollister@Sun.COM 	mdb_printf("\nHardware information:\n");
236*10696SDavid.Hollister@Sun.COM 	mdb_printf("---------------------\n");
237*10696SDavid.Hollister@Sun.COM 
238*10696SDavid.Hollister@Sun.COM 	mdb_printf("Chip revision:    %c\n", 'A' + m.chiprev);
239*10696SDavid.Hollister@Sun.COM 	mdb_printf("SAS WWID:         %"PRIx64"\n", m.sas_wwns[0]);
240*10696SDavid.Hollister@Sun.COM 	mdb_printf("Firmware version: %x.%x.%x (%s)\n",
241*10696SDavid.Hollister@Sun.COM 	    PMCS_FW_MAJOR(mp), PMCS_FW_MINOR(mp), PMCS_FW_MICRO(mp),
242*10696SDavid.Hollister@Sun.COM 	    fwsupport);
243*10696SDavid.Hollister@Sun.COM 
244*10696SDavid.Hollister@Sun.COM 	mdb_printf("Number of PHYs:   %d\n", m.nphy);
245*10696SDavid.Hollister@Sun.COM 	mdb_printf("Maximum commands: %d\n", m.max_cmd);
246*10696SDavid.Hollister@Sun.COM 	mdb_printf("Maximum devices:  %d\n", m.max_dev);
247*10696SDavid.Hollister@Sun.COM 	mdb_printf("I/O queue depth:  %d\n", m.ioq_depth);
248*10696SDavid.Hollister@Sun.COM 	if (m.fwlog == 0) {
249*10696SDavid.Hollister@Sun.COM 		mdb_printf("Firmware logging: Disabled\n");
250*10696SDavid.Hollister@Sun.COM 	} else {
251*10696SDavid.Hollister@Sun.COM 		mdb_printf("Firmware logging: Enabled (%d)\n", m.fwlog);
252*10696SDavid.Hollister@Sun.COM 	}
253*10696SDavid.Hollister@Sun.COM }
254*10696SDavid.Hollister@Sun.COM 
255*10696SDavid.Hollister@Sun.COM static void
256*10696SDavid.Hollister@Sun.COM display_targets(struct pmcs_hw m, int verbose, int totals_only)
257*10696SDavid.Hollister@Sun.COM {
258*10696SDavid.Hollister@Sun.COM 	char		*dtype;
259*10696SDavid.Hollister@Sun.COM 	pmcs_xscsi_t	xs;
260*10696SDavid.Hollister@Sun.COM 	pmcs_phy_t	phy;
261*10696SDavid.Hollister@Sun.COM 	uint16_t	max_dev, idx;
262*10696SDavid.Hollister@Sun.COM 	uint32_t	sas_targets = 0, smp_targets = 0, sata_targets = 0;
263*10696SDavid.Hollister@Sun.COM 
264*10696SDavid.Hollister@Sun.COM 	max_dev = m.max_dev;
265*10696SDavid.Hollister@Sun.COM 
266*10696SDavid.Hollister@Sun.COM 	if (targets == NULL) {
267*10696SDavid.Hollister@Sun.COM 		targets = mdb_alloc(sizeof (targets) * max_dev, UM_SLEEP);
268*10696SDavid.Hollister@Sun.COM 	}
269*10696SDavid.Hollister@Sun.COM 
270*10696SDavid.Hollister@Sun.COM 	if (MDB_RD(targets, sizeof (targets) * max_dev, m.targets) == -1) {
271*10696SDavid.Hollister@Sun.COM 		NOREAD(targets, m.targets);
272*10696SDavid.Hollister@Sun.COM 		return;
273*10696SDavid.Hollister@Sun.COM 	}
274*10696SDavid.Hollister@Sun.COM 
275*10696SDavid.Hollister@Sun.COM 	if (!totals_only) {
276*10696SDavid.Hollister@Sun.COM 		mdb_printf("\nTarget information:\n");
277*10696SDavid.Hollister@Sun.COM 		mdb_printf("---------------------------------------\n");
278*10696SDavid.Hollister@Sun.COM 		mdb_printf("VTGT %-16s %-16s %-5s %8s %s", "SAS Address",
279*10696SDavid.Hollister@Sun.COM 		    "PHY Address", "DType", "Active", "DS");
280*10696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
281*10696SDavid.Hollister@Sun.COM 	}
282*10696SDavid.Hollister@Sun.COM 
283*10696SDavid.Hollister@Sun.COM 	for (idx = 0; idx < max_dev; idx++) {
284*10696SDavid.Hollister@Sun.COM 		if (targets[idx] == NULL) {
285*10696SDavid.Hollister@Sun.COM 			continue;
286*10696SDavid.Hollister@Sun.COM 		}
287*10696SDavid.Hollister@Sun.COM 
288*10696SDavid.Hollister@Sun.COM 		if (MDB_RD(&xs, sizeof (xs), targets[idx]) == -1) {
289*10696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_xscsi_t, targets[idx]);
290*10696SDavid.Hollister@Sun.COM 			continue;
291*10696SDavid.Hollister@Sun.COM 		}
292*10696SDavid.Hollister@Sun.COM 
293*10696SDavid.Hollister@Sun.COM 		/*
294*10696SDavid.Hollister@Sun.COM 		 * It has to be one of new, assigned or dying to be of interest.
295*10696SDavid.Hollister@Sun.COM 		 */
296*10696SDavid.Hollister@Sun.COM 		if (xs.new == 0 && xs.assigned == 0 && xs.dying == 0) {
297*10696SDavid.Hollister@Sun.COM 			continue;
298*10696SDavid.Hollister@Sun.COM 		}
299*10696SDavid.Hollister@Sun.COM 
300*10696SDavid.Hollister@Sun.COM 		switch (xs.dtype) {
301*10696SDavid.Hollister@Sun.COM 		case NOTHING:
302*10696SDavid.Hollister@Sun.COM 			dtype = "None";
303*10696SDavid.Hollister@Sun.COM 			break;
304*10696SDavid.Hollister@Sun.COM 		case SATA:
305*10696SDavid.Hollister@Sun.COM 			dtype = "SATA";
306*10696SDavid.Hollister@Sun.COM 			sata_targets++;
307*10696SDavid.Hollister@Sun.COM 			break;
308*10696SDavid.Hollister@Sun.COM 		case SAS:
309*10696SDavid.Hollister@Sun.COM 			dtype = "SAS";
310*10696SDavid.Hollister@Sun.COM 			sas_targets++;
311*10696SDavid.Hollister@Sun.COM 			break;
312*10696SDavid.Hollister@Sun.COM 		case EXPANDER:
313*10696SDavid.Hollister@Sun.COM 			dtype = "SMP";
314*10696SDavid.Hollister@Sun.COM 			smp_targets++;
315*10696SDavid.Hollister@Sun.COM 			break;
316*10696SDavid.Hollister@Sun.COM 		}
317*10696SDavid.Hollister@Sun.COM 
318*10696SDavid.Hollister@Sun.COM 		if (totals_only) {
319*10696SDavid.Hollister@Sun.COM 			continue;
320*10696SDavid.Hollister@Sun.COM 		}
321*10696SDavid.Hollister@Sun.COM 
322*10696SDavid.Hollister@Sun.COM 		if (xs.phy) {
323*10696SDavid.Hollister@Sun.COM 			if (MDB_RD(&phy, sizeof (phy), xs.phy) == -1) {
324*10696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_phy_t, xs.phy);
325*10696SDavid.Hollister@Sun.COM 				continue;
326*10696SDavid.Hollister@Sun.COM 			}
327*10696SDavid.Hollister@Sun.COM 			mdb_printf("%4d ", idx);
328*10696SDavid.Hollister@Sun.COM 			print_sas_address(&phy);
329*10696SDavid.Hollister@Sun.COM 			mdb_printf(" %16p", xs.phy);
330*10696SDavid.Hollister@Sun.COM 		} else {
331*10696SDavid.Hollister@Sun.COM 			mdb_printf("%4d %16s", idx, "<no phy avail>");
332*10696SDavid.Hollister@Sun.COM 		}
333*10696SDavid.Hollister@Sun.COM 		mdb_printf(" %5s", dtype);
334*10696SDavid.Hollister@Sun.COM 		mdb_printf(" %8d", xs.actv_cnt);
335*10696SDavid.Hollister@Sun.COM 		mdb_printf(" %2d", xs.dev_state);
336*10696SDavid.Hollister@Sun.COM 
337*10696SDavid.Hollister@Sun.COM 		if (verbose) {
338*10696SDavid.Hollister@Sun.COM 			if (xs.new) {
339*10696SDavid.Hollister@Sun.COM 				mdb_printf(" new");
340*10696SDavid.Hollister@Sun.COM 			} else if (xs.dying) {
341*10696SDavid.Hollister@Sun.COM 				mdb_printf(" dying");
342*10696SDavid.Hollister@Sun.COM 			} else if (xs.assigned) {
343*10696SDavid.Hollister@Sun.COM 				mdb_printf(" assigned");
344*10696SDavid.Hollister@Sun.COM 			}
345*10696SDavid.Hollister@Sun.COM 			if (xs.draining) {
346*10696SDavid.Hollister@Sun.COM 				mdb_printf(" draining");
347*10696SDavid.Hollister@Sun.COM 			}
348*10696SDavid.Hollister@Sun.COM 			if (xs.reset_wait) {
349*10696SDavid.Hollister@Sun.COM 				mdb_printf(" reset_wait");
350*10696SDavid.Hollister@Sun.COM 			}
351*10696SDavid.Hollister@Sun.COM 			if (xs.resetting) {
352*10696SDavid.Hollister@Sun.COM 				mdb_printf(" resetting");
353*10696SDavid.Hollister@Sun.COM 			}
354*10696SDavid.Hollister@Sun.COM 			if (xs.recover_wait) {
355*10696SDavid.Hollister@Sun.COM 				mdb_printf(" recover_wait");
356*10696SDavid.Hollister@Sun.COM 			}
357*10696SDavid.Hollister@Sun.COM 			if (xs.recovering) {
358*10696SDavid.Hollister@Sun.COM 				mdb_printf(" recovering");
359*10696SDavid.Hollister@Sun.COM 			}
360*10696SDavid.Hollister@Sun.COM 			if (xs.event_recovery) {
361*10696SDavid.Hollister@Sun.COM 				mdb_printf(" event recovery");
362*10696SDavid.Hollister@Sun.COM 			}
363*10696SDavid.Hollister@Sun.COM 			if (xs.special_running) {
364*10696SDavid.Hollister@Sun.COM 				mdb_printf(" special_active");
365*10696SDavid.Hollister@Sun.COM 			}
366*10696SDavid.Hollister@Sun.COM 			if (xs.ncq) {
367*10696SDavid.Hollister@Sun.COM 				mdb_printf(" ncq_tagmap=0x%x qdepth=%d",
368*10696SDavid.Hollister@Sun.COM 				    xs.tagmap, xs.qdepth);
369*10696SDavid.Hollister@Sun.COM 			} else if (xs.pio) {
370*10696SDavid.Hollister@Sun.COM 				mdb_printf(" pio");
371*10696SDavid.Hollister@Sun.COM 			}
372*10696SDavid.Hollister@Sun.COM 		}
373*10696SDavid.Hollister@Sun.COM 
374*10696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
375*10696SDavid.Hollister@Sun.COM 	}
376*10696SDavid.Hollister@Sun.COM 
377*10696SDavid.Hollister@Sun.COM 	if (!totals_only) {
378*10696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
379*10696SDavid.Hollister@Sun.COM 	}
380*10696SDavid.Hollister@Sun.COM 
381*10696SDavid.Hollister@Sun.COM 	mdb_printf("%19s %d (%d SAS + %d SATA + %d SMP)\n",
382*10696SDavid.Hollister@Sun.COM 	    "Configured targets:", (sas_targets + sata_targets + smp_targets),
383*10696SDavid.Hollister@Sun.COM 	    sas_targets, sata_targets, smp_targets);
384*10696SDavid.Hollister@Sun.COM }
385*10696SDavid.Hollister@Sun.COM 
386*10696SDavid.Hollister@Sun.COM /*ARGSUSED1*/
387*10696SDavid.Hollister@Sun.COM static void
388*10696SDavid.Hollister@Sun.COM display_work(struct pmcs_hw m, int verbose)
389*10696SDavid.Hollister@Sun.COM {
390*10696SDavid.Hollister@Sun.COM 	int		idx;
391*10696SDavid.Hollister@Sun.COM 	int		tgt;
392*10696SDavid.Hollister@Sun.COM 	int		hdrp =  0;
393*10696SDavid.Hollister@Sun.COM 	pmcs_xscsi_t	xs;
394*10696SDavid.Hollister@Sun.COM 	pmcs_phy_t	phy;
395*10696SDavid.Hollister@Sun.COM 	char		buf[16];
396*10696SDavid.Hollister@Sun.COM 	pmcwork_t	work, *wp = &work;
397*10696SDavid.Hollister@Sun.COM 	uintptr_t	_wp;
398*10696SDavid.Hollister@Sun.COM 	char		*state;
399*10696SDavid.Hollister@Sun.COM 	char		*path;
400*10696SDavid.Hollister@Sun.COM 
401*10696SDavid.Hollister@Sun.COM 	mdb_printf("\nActive Work structure information:\n");
402*10696SDavid.Hollister@Sun.COM 	mdb_printf("----------------------------------\n");
403*10696SDavid.Hollister@Sun.COM 
404*10696SDavid.Hollister@Sun.COM 	_wp = (uintptr_t)m.work;
405*10696SDavid.Hollister@Sun.COM 
406*10696SDavid.Hollister@Sun.COM 	for (idx = 0; idx < m.max_cmd; idx++, _wp += sizeof (pmcwork_t)) {
407*10696SDavid.Hollister@Sun.COM 		if (MDB_RD(&work, sizeof (pmcwork_t), _wp) == -1) {
408*10696SDavid.Hollister@Sun.COM 			NOREAD(pmcwork_t, _wp);
409*10696SDavid.Hollister@Sun.COM 			continue;
410*10696SDavid.Hollister@Sun.COM 		}
411*10696SDavid.Hollister@Sun.COM 		if (wp->htag == PMCS_TAG_TYPE_FREE) {
412*10696SDavid.Hollister@Sun.COM 			continue;
413*10696SDavid.Hollister@Sun.COM 		}
414*10696SDavid.Hollister@Sun.COM 		if (hdrp++ == 0) {
415*10696SDavid.Hollister@Sun.COM 			mdb_printf("%8s %10s %20s %8s %8s O D\n",
416*10696SDavid.Hollister@Sun.COM 			    "HTag", "State", "Phy Path", "Target", "Timer");
417*10696SDavid.Hollister@Sun.COM 		}
418*10696SDavid.Hollister@Sun.COM 		switch (wp->state) {
419*10696SDavid.Hollister@Sun.COM 		case PMCS_WORK_STATE_NIL:
420*10696SDavid.Hollister@Sun.COM 			state = "N/A";
421*10696SDavid.Hollister@Sun.COM 			break;
422*10696SDavid.Hollister@Sun.COM 		case PMCS_WORK_STATE_READY:
423*10696SDavid.Hollister@Sun.COM 			state = "Ready";
424*10696SDavid.Hollister@Sun.COM 			break;
425*10696SDavid.Hollister@Sun.COM 		case PMCS_WORK_STATE_ONCHIP:
426*10696SDavid.Hollister@Sun.COM 			state = "On Chip";
427*10696SDavid.Hollister@Sun.COM 			break;
428*10696SDavid.Hollister@Sun.COM 		case PMCS_WORK_STATE_INTR:
429*10696SDavid.Hollister@Sun.COM 			state = "In Intr";
430*10696SDavid.Hollister@Sun.COM 			break;
431*10696SDavid.Hollister@Sun.COM 		case PMCS_WORK_STATE_IOCOMPQ:
432*10696SDavid.Hollister@Sun.COM 			state = "I/O Comp";
433*10696SDavid.Hollister@Sun.COM 			break;
434*10696SDavid.Hollister@Sun.COM 		case PMCS_WORK_STATE_ABORTED:
435*10696SDavid.Hollister@Sun.COM 			state = "I/O Aborted";
436*10696SDavid.Hollister@Sun.COM 			break;
437*10696SDavid.Hollister@Sun.COM 		case PMCS_WORK_STATE_TIMED_OUT:
438*10696SDavid.Hollister@Sun.COM 			state = "I/O Timed Out";
439*10696SDavid.Hollister@Sun.COM 			break;
440*10696SDavid.Hollister@Sun.COM 		default:
441*10696SDavid.Hollister@Sun.COM 			mdb_snprintf(buf, sizeof (buf), "STATE=%d", wp->state);
442*10696SDavid.Hollister@Sun.COM 			state = buf;
443*10696SDavid.Hollister@Sun.COM 			break;
444*10696SDavid.Hollister@Sun.COM 		}
445*10696SDavid.Hollister@Sun.COM 		if (wp->ssp_event && wp->ssp_event != 0xffffffff) {
446*10696SDavid.Hollister@Sun.COM 			mdb_printf("SSP event 0x%x", wp->ssp_event);
447*10696SDavid.Hollister@Sun.COM 		}
448*10696SDavid.Hollister@Sun.COM 		tgt = -1;
449*10696SDavid.Hollister@Sun.COM 		if (wp->xp) {
450*10696SDavid.Hollister@Sun.COM 			if (MDB_RD(&xs, sizeof (xs), wp->xp) == -1) {
451*10696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_xscsi_t, wp->xp);
452*10696SDavid.Hollister@Sun.COM 			} else {
453*10696SDavid.Hollister@Sun.COM 				tgt = xs.target_num;
454*10696SDavid.Hollister@Sun.COM 			}
455*10696SDavid.Hollister@Sun.COM 		}
456*10696SDavid.Hollister@Sun.COM 		if (wp->phy) {
457*10696SDavid.Hollister@Sun.COM 			if (MDB_RD(&phy, sizeof (phy), wp->phy) == -1) {
458*10696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_phy_t, wp->phy);
459*10696SDavid.Hollister@Sun.COM 				continue;
460*10696SDavid.Hollister@Sun.COM 			}
461*10696SDavid.Hollister@Sun.COM 			path = phy.path;
462*10696SDavid.Hollister@Sun.COM 		} else {
463*10696SDavid.Hollister@Sun.COM 			path = "????";
464*10696SDavid.Hollister@Sun.COM 		}
465*10696SDavid.Hollister@Sun.COM 		mdb_printf("%08x %10s %20s %8d %8u %1d %1d\n",
466*10696SDavid.Hollister@Sun.COM 		    wp->htag, state, path, tgt, wp->timer,
467*10696SDavid.Hollister@Sun.COM 		    wp->onwire, wp->dead);
468*10696SDavid.Hollister@Sun.COM 	}
469*10696SDavid.Hollister@Sun.COM }
470*10696SDavid.Hollister@Sun.COM 
471*10696SDavid.Hollister@Sun.COM static void
472*10696SDavid.Hollister@Sun.COM print_spcmd(pmcs_cmd_t *sp, void *kaddr, int printhdr, int indent)
473*10696SDavid.Hollister@Sun.COM {
474*10696SDavid.Hollister@Sun.COM 	if (indent)
475*10696SDavid.Hollister@Sun.COM 		mdb_inc_indent(4);
476*10696SDavid.Hollister@Sun.COM 	if (printhdr) {
477*10696SDavid.Hollister@Sun.COM 		mdb_printf("%16s %16s %16s %8s %s\n",
478*10696SDavid.Hollister@Sun.COM 		    "Command", "SCSA pkt", "DMA Chunks", "HTAG", "SATL Tag");
479*10696SDavid.Hollister@Sun.COM 	}
480*10696SDavid.Hollister@Sun.COM 	mdb_printf("%16p %16p %16p %08x %08x\n",
481*10696SDavid.Hollister@Sun.COM 	    kaddr, sp->cmd_pkt, sp->cmd_clist, sp->cmd_tag, sp->cmd_satltag);
482*10696SDavid.Hollister@Sun.COM 	if (indent)
483*10696SDavid.Hollister@Sun.COM 		mdb_dec_indent(4);
484*10696SDavid.Hollister@Sun.COM }
485*10696SDavid.Hollister@Sun.COM 
486*10696SDavid.Hollister@Sun.COM /*ARGSUSED1*/
487*10696SDavid.Hollister@Sun.COM static void
488*10696SDavid.Hollister@Sun.COM display_waitqs(struct pmcs_hw m, int verbose)
489*10696SDavid.Hollister@Sun.COM {
490*10696SDavid.Hollister@Sun.COM 	pmcs_cmd_t	*sp, s;
491*10696SDavid.Hollister@Sun.COM 	pmcs_xscsi_t	xs;
492*10696SDavid.Hollister@Sun.COM 	int		first, i;
493*10696SDavid.Hollister@Sun.COM 	int		max_dev = m.max_dev;
494*10696SDavid.Hollister@Sun.COM 
495*10696SDavid.Hollister@Sun.COM 	sp = m.dq.stqh_first;
496*10696SDavid.Hollister@Sun.COM 	first = 1;
497*10696SDavid.Hollister@Sun.COM 	while (sp) {
498*10696SDavid.Hollister@Sun.COM 		if (first) {
499*10696SDavid.Hollister@Sun.COM 			mdb_printf("\nDead Command Queue:\n");
500*10696SDavid.Hollister@Sun.COM 			mdb_printf("---------------------------\n");
501*10696SDavid.Hollister@Sun.COM 		}
502*10696SDavid.Hollister@Sun.COM 		if (MDB_RD(&s, sizeof (s), sp) == -1) {
503*10696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_cmd_t, sp);
504*10696SDavid.Hollister@Sun.COM 			break;
505*10696SDavid.Hollister@Sun.COM 		}
506*10696SDavid.Hollister@Sun.COM 		print_spcmd(&s, sp, first, 0);
507*10696SDavid.Hollister@Sun.COM 		sp = s.cmd_next.stqe_next;
508*10696SDavid.Hollister@Sun.COM 		first = 0;
509*10696SDavid.Hollister@Sun.COM 	}
510*10696SDavid.Hollister@Sun.COM 
511*10696SDavid.Hollister@Sun.COM 	sp = m.cq.stqh_first;
512*10696SDavid.Hollister@Sun.COM 	first = 1;
513*10696SDavid.Hollister@Sun.COM 	while (sp) {
514*10696SDavid.Hollister@Sun.COM 		if (first) {
515*10696SDavid.Hollister@Sun.COM 			mdb_printf("\nCompletion Command Queue:\n");
516*10696SDavid.Hollister@Sun.COM 			mdb_printf("---------------------------\n");
517*10696SDavid.Hollister@Sun.COM 		}
518*10696SDavid.Hollister@Sun.COM 		if (MDB_RD(&s, sizeof (s), sp) == -1) {
519*10696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_cmd_t, sp);
520*10696SDavid.Hollister@Sun.COM 			break;
521*10696SDavid.Hollister@Sun.COM 		}
522*10696SDavid.Hollister@Sun.COM 		print_spcmd(&s, sp, first, 0);
523*10696SDavid.Hollister@Sun.COM 		sp = s.cmd_next.stqe_next;
524*10696SDavid.Hollister@Sun.COM 		first = 0;
525*10696SDavid.Hollister@Sun.COM 	}
526*10696SDavid.Hollister@Sun.COM 
527*10696SDavid.Hollister@Sun.COM 
528*10696SDavid.Hollister@Sun.COM 	if (targets == NULL) {
529*10696SDavid.Hollister@Sun.COM 		targets = mdb_alloc(sizeof (targets) * max_dev, UM_SLEEP);
530*10696SDavid.Hollister@Sun.COM 	}
531*10696SDavid.Hollister@Sun.COM 
532*10696SDavid.Hollister@Sun.COM 	if (MDB_RD(targets, sizeof (targets) * max_dev, m.targets) == -1) {
533*10696SDavid.Hollister@Sun.COM 		NOREAD(targets, m.targets);
534*10696SDavid.Hollister@Sun.COM 		return;
535*10696SDavid.Hollister@Sun.COM 	}
536*10696SDavid.Hollister@Sun.COM 
537*10696SDavid.Hollister@Sun.COM 	for (i = 0; i < max_dev; i++) {
538*10696SDavid.Hollister@Sun.COM 		if (targets[i] == NULL) {
539*10696SDavid.Hollister@Sun.COM 			continue;
540*10696SDavid.Hollister@Sun.COM 		}
541*10696SDavid.Hollister@Sun.COM 		if (MDB_RD(&xs, sizeof (xs), targets[i]) == -1) {
542*10696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_xscsi_t, targets[i]);
543*10696SDavid.Hollister@Sun.COM 			continue;
544*10696SDavid.Hollister@Sun.COM 		}
545*10696SDavid.Hollister@Sun.COM 		sp = xs.wq.stqh_first;
546*10696SDavid.Hollister@Sun.COM 		first = 1;
547*10696SDavid.Hollister@Sun.COM 		while (sp) {
548*10696SDavid.Hollister@Sun.COM 			if (first) {
549*10696SDavid.Hollister@Sun.COM 				mdb_printf("\nTarget %u Wait Queue:\n",
550*10696SDavid.Hollister@Sun.COM 				    xs.target_num);
551*10696SDavid.Hollister@Sun.COM 				mdb_printf("---------------------------\n");
552*10696SDavid.Hollister@Sun.COM 			}
553*10696SDavid.Hollister@Sun.COM 			if (MDB_RD(&s, sizeof (s), sp) == -1) {
554*10696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_cmd_t, sp);
555*10696SDavid.Hollister@Sun.COM 				break;
556*10696SDavid.Hollister@Sun.COM 			}
557*10696SDavid.Hollister@Sun.COM 			print_spcmd(&s, sp, first, 0);
558*10696SDavid.Hollister@Sun.COM 			sp = s.cmd_next.stqe_next;
559*10696SDavid.Hollister@Sun.COM 			first = 0;
560*10696SDavid.Hollister@Sun.COM 		}
561*10696SDavid.Hollister@Sun.COM 		sp = xs.aq.stqh_first;
562*10696SDavid.Hollister@Sun.COM 		first = 1;
563*10696SDavid.Hollister@Sun.COM 		while (sp) {
564*10696SDavid.Hollister@Sun.COM 			if (first) {
565*10696SDavid.Hollister@Sun.COM 				mdb_printf("\nTarget %u Active Queue:\n",
566*10696SDavid.Hollister@Sun.COM 				    xs.target_num);
567*10696SDavid.Hollister@Sun.COM 				mdb_printf("---------------------------\n");
568*10696SDavid.Hollister@Sun.COM 			}
569*10696SDavid.Hollister@Sun.COM 			if (MDB_RD(&s, sizeof (s), sp) == -1) {
570*10696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_cmd_t, sp);
571*10696SDavid.Hollister@Sun.COM 				break;
572*10696SDavid.Hollister@Sun.COM 			}
573*10696SDavid.Hollister@Sun.COM 			print_spcmd(&s, sp, first, 0);
574*10696SDavid.Hollister@Sun.COM 			sp = s.cmd_next.stqe_next;
575*10696SDavid.Hollister@Sun.COM 			first = 0;
576*10696SDavid.Hollister@Sun.COM 		}
577*10696SDavid.Hollister@Sun.COM 		sp = xs.sq.stqh_first;
578*10696SDavid.Hollister@Sun.COM 		first = 1;
579*10696SDavid.Hollister@Sun.COM 		while (sp) {
580*10696SDavid.Hollister@Sun.COM 			if (first) {
581*10696SDavid.Hollister@Sun.COM 				mdb_printf("\nTarget %u Special Queue:\n",
582*10696SDavid.Hollister@Sun.COM 				    xs.target_num);
583*10696SDavid.Hollister@Sun.COM 				mdb_printf("---------------------------\n");
584*10696SDavid.Hollister@Sun.COM 			}
585*10696SDavid.Hollister@Sun.COM 			if (MDB_RD(&s, sizeof (s), sp) == -1) {
586*10696SDavid.Hollister@Sun.COM 				NOREAD(pmcs_cmd_t, sp);
587*10696SDavid.Hollister@Sun.COM 				break;
588*10696SDavid.Hollister@Sun.COM 			}
589*10696SDavid.Hollister@Sun.COM 			print_spcmd(&s, sp, first, 0);
590*10696SDavid.Hollister@Sun.COM 			sp = s.cmd_next.stqe_next;
591*10696SDavid.Hollister@Sun.COM 			first = 0;
592*10696SDavid.Hollister@Sun.COM 		}
593*10696SDavid.Hollister@Sun.COM 	}
594*10696SDavid.Hollister@Sun.COM }
595*10696SDavid.Hollister@Sun.COM 
596*10696SDavid.Hollister@Sun.COM static char *
597*10696SDavid.Hollister@Sun.COM ibq_type(int qnum)
598*10696SDavid.Hollister@Sun.COM {
599*10696SDavid.Hollister@Sun.COM 	if (qnum < 0 || qnum >= PMCS_NIQ) {
600*10696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
601*10696SDavid.Hollister@Sun.COM 	}
602*10696SDavid.Hollister@Sun.COM 
603*10696SDavid.Hollister@Sun.COM 	if (qnum < PMCS_IQ_OTHER) {
604*10696SDavid.Hollister@Sun.COM 		return ("I/O");
605*10696SDavid.Hollister@Sun.COM 	}
606*10696SDavid.Hollister@Sun.COM 
607*10696SDavid.Hollister@Sun.COM 	return ("Other");
608*10696SDavid.Hollister@Sun.COM }
609*10696SDavid.Hollister@Sun.COM 
610*10696SDavid.Hollister@Sun.COM static char *
611*10696SDavid.Hollister@Sun.COM obq_type(int qnum)
612*10696SDavid.Hollister@Sun.COM {
613*10696SDavid.Hollister@Sun.COM 	switch (qnum) {
614*10696SDavid.Hollister@Sun.COM 	case PMCS_OQ_IODONE:
615*10696SDavid.Hollister@Sun.COM 		return ("I/O");
616*10696SDavid.Hollister@Sun.COM 		break;
617*10696SDavid.Hollister@Sun.COM 	case PMCS_OQ_GENERAL:
618*10696SDavid.Hollister@Sun.COM 		return ("General");
619*10696SDavid.Hollister@Sun.COM 		break;
620*10696SDavid.Hollister@Sun.COM 	case PMCS_OQ_EVENTS:
621*10696SDavid.Hollister@Sun.COM 		return ("Events");
622*10696SDavid.Hollister@Sun.COM 		break;
623*10696SDavid.Hollister@Sun.COM 	default:
624*10696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
625*10696SDavid.Hollister@Sun.COM 	}
626*10696SDavid.Hollister@Sun.COM }
627*10696SDavid.Hollister@Sun.COM 
628*10696SDavid.Hollister@Sun.COM static char *
629*10696SDavid.Hollister@Sun.COM iomb_cat(uint32_t cat)
630*10696SDavid.Hollister@Sun.COM {
631*10696SDavid.Hollister@Sun.COM 	switch (cat) {
632*10696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_NET:
633*10696SDavid.Hollister@Sun.COM 		return ("NET");
634*10696SDavid.Hollister@Sun.COM 		break;
635*10696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_FC:
636*10696SDavid.Hollister@Sun.COM 		return ("FC");
637*10696SDavid.Hollister@Sun.COM 		break;
638*10696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_SAS:
639*10696SDavid.Hollister@Sun.COM 		return ("SAS");
640*10696SDavid.Hollister@Sun.COM 		break;
641*10696SDavid.Hollister@Sun.COM 	case PMCS_IOMB_CAT_SCSI:
642*10696SDavid.Hollister@Sun.COM 		return ("SCSI");
643*10696SDavid.Hollister@Sun.COM 		break;
644*10696SDavid.Hollister@Sun.COM 	default:
645*10696SDavid.Hollister@Sun.COM 		return ("???");
646*10696SDavid.Hollister@Sun.COM 	}
647*10696SDavid.Hollister@Sun.COM }
648*10696SDavid.Hollister@Sun.COM 
649*10696SDavid.Hollister@Sun.COM static char *
650*10696SDavid.Hollister@Sun.COM inbound_iomb_opcode(uint32_t opcode)
651*10696SDavid.Hollister@Sun.COM {
652*10696SDavid.Hollister@Sun.COM 	switch (opcode) {
653*10696SDavid.Hollister@Sun.COM 	case PMCIN_ECHO:
654*10696SDavid.Hollister@Sun.COM 		return ("ECHO");
655*10696SDavid.Hollister@Sun.COM 		break;
656*10696SDavid.Hollister@Sun.COM 	case PMCIN_GET_INFO:
657*10696SDavid.Hollister@Sun.COM 		return ("GET_INFO");
658*10696SDavid.Hollister@Sun.COM 		break;
659*10696SDavid.Hollister@Sun.COM 	case PMCIN_GET_VPD:
660*10696SDavid.Hollister@Sun.COM 		return ("GET_VPD");
661*10696SDavid.Hollister@Sun.COM 		break;
662*10696SDavid.Hollister@Sun.COM 	case PMCIN_PHY_START:
663*10696SDavid.Hollister@Sun.COM 		return ("PHY_START");
664*10696SDavid.Hollister@Sun.COM 		break;
665*10696SDavid.Hollister@Sun.COM 	case PMCIN_PHY_STOP:
666*10696SDavid.Hollister@Sun.COM 		return ("PHY_STOP");
667*10696SDavid.Hollister@Sun.COM 		break;
668*10696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_IO_START:
669*10696SDavid.Hollister@Sun.COM 		return ("INI_IO_START");
670*10696SDavid.Hollister@Sun.COM 		break;
671*10696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_TM_START:
672*10696SDavid.Hollister@Sun.COM 		return ("INI_TM_START");
673*10696SDavid.Hollister@Sun.COM 		break;
674*10696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_EXT_IO_START:
675*10696SDavid.Hollister@Sun.COM 		return ("INI_EXT_IO_START");
676*10696SDavid.Hollister@Sun.COM 		break;
677*10696SDavid.Hollister@Sun.COM 	case PMCIN_DEVICE_HANDLE_ACCEPT:
678*10696SDavid.Hollister@Sun.COM 		return ("DEVICE_HANDLE_ACCEPT");
679*10696SDavid.Hollister@Sun.COM 		break;
680*10696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_TGT_IO_START:
681*10696SDavid.Hollister@Sun.COM 		return ("TGT_IO_START");
682*10696SDavid.Hollister@Sun.COM 		break;
683*10696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_TGT_RESPONSE_START:
684*10696SDavid.Hollister@Sun.COM 		return ("TGT_RESPONSE_START");
685*10696SDavid.Hollister@Sun.COM 		break;
686*10696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_EDC_EXT_IO_START:
687*10696SDavid.Hollister@Sun.COM 		return ("INI_EDC_EXT_IO_START");
688*10696SDavid.Hollister@Sun.COM 		break;
689*10696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_INI_EDC_EXT_IO_START1:
690*10696SDavid.Hollister@Sun.COM 		return ("INI_EDC_EXT_IO_START1");
691*10696SDavid.Hollister@Sun.COM 		break;
692*10696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_TGT_EDC_IO_START:
693*10696SDavid.Hollister@Sun.COM 		return ("TGT_EDC_IO_START");
694*10696SDavid.Hollister@Sun.COM 		break;
695*10696SDavid.Hollister@Sun.COM 	case PMCIN_SSP_ABORT:
696*10696SDavid.Hollister@Sun.COM 		return ("SSP_ABORT");
697*10696SDavid.Hollister@Sun.COM 		break;
698*10696SDavid.Hollister@Sun.COM 	case PMCIN_DEREGISTER_DEVICE_HANDLE:
699*10696SDavid.Hollister@Sun.COM 		return ("DEREGISTER_DEVICE_HANDLE");
700*10696SDavid.Hollister@Sun.COM 		break;
701*10696SDavid.Hollister@Sun.COM 	case PMCIN_GET_DEVICE_HANDLE:
702*10696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_HANDLE");
703*10696SDavid.Hollister@Sun.COM 		break;
704*10696SDavid.Hollister@Sun.COM 	case PMCIN_SMP_REQUEST:
705*10696SDavid.Hollister@Sun.COM 		return ("SMP_REQUEST");
706*10696SDavid.Hollister@Sun.COM 		break;
707*10696SDavid.Hollister@Sun.COM 	case PMCIN_SMP_RESPONSE:
708*10696SDavid.Hollister@Sun.COM 		return ("SMP_RESPONSE");
709*10696SDavid.Hollister@Sun.COM 		break;
710*10696SDavid.Hollister@Sun.COM 	case PMCIN_SMP_ABORT:
711*10696SDavid.Hollister@Sun.COM 		return ("SMP_ABORT");
712*10696SDavid.Hollister@Sun.COM 		break;
713*10696SDavid.Hollister@Sun.COM 	case PMCIN_ASSISTED_DISCOVERY:
714*10696SDavid.Hollister@Sun.COM 		return ("ASSISTED_DISCOVERY");
715*10696SDavid.Hollister@Sun.COM 		break;
716*10696SDavid.Hollister@Sun.COM 	case PMCIN_REGISTER_DEVICE:
717*10696SDavid.Hollister@Sun.COM 		return ("REGISTER_DEVICE");
718*10696SDavid.Hollister@Sun.COM 		break;
719*10696SDavid.Hollister@Sun.COM 	case PMCIN_SATA_HOST_IO_START:
720*10696SDavid.Hollister@Sun.COM 		return ("SATA_HOST_IO_START");
721*10696SDavid.Hollister@Sun.COM 		break;
722*10696SDavid.Hollister@Sun.COM 	case PMCIN_SATA_ABORT:
723*10696SDavid.Hollister@Sun.COM 		return ("SATA_ABORT");
724*10696SDavid.Hollister@Sun.COM 		break;
725*10696SDavid.Hollister@Sun.COM 	case PMCIN_LOCAL_PHY_CONTROL:
726*10696SDavid.Hollister@Sun.COM 		return ("LOCAL_PHY_CONTROL");
727*10696SDavid.Hollister@Sun.COM 		break;
728*10696SDavid.Hollister@Sun.COM 	case PMCIN_GET_DEVICE_INFO:
729*10696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_INFO");
730*10696SDavid.Hollister@Sun.COM 		break;
731*10696SDavid.Hollister@Sun.COM 	case PMCIN_TWI:
732*10696SDavid.Hollister@Sun.COM 		return ("TWI");
733*10696SDavid.Hollister@Sun.COM 		break;
734*10696SDavid.Hollister@Sun.COM 	case PMCIN_FW_FLASH_UPDATE:
735*10696SDavid.Hollister@Sun.COM 		return ("FW_FLASH_UPDATE");
736*10696SDavid.Hollister@Sun.COM 		break;
737*10696SDavid.Hollister@Sun.COM 	case PMCIN_SET_VPD:
738*10696SDavid.Hollister@Sun.COM 		return ("SET_VPD");
739*10696SDavid.Hollister@Sun.COM 		break;
740*10696SDavid.Hollister@Sun.COM 	case PMCIN_GPIO:
741*10696SDavid.Hollister@Sun.COM 		return ("GPIO");
742*10696SDavid.Hollister@Sun.COM 		break;
743*10696SDavid.Hollister@Sun.COM 	case PMCIN_SAS_DIAG_MODE_START_END:
744*10696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_MODE_START_END");
745*10696SDavid.Hollister@Sun.COM 		break;
746*10696SDavid.Hollister@Sun.COM 	case PMCIN_SAS_DIAG_EXECUTE:
747*10696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_EXECUTE");
748*10696SDavid.Hollister@Sun.COM 		break;
749*10696SDavid.Hollister@Sun.COM 	case PMCIN_SAW_HW_EVENT_ACK:
750*10696SDavid.Hollister@Sun.COM 		return ("SAS_HW_EVENT_ACK");
751*10696SDavid.Hollister@Sun.COM 		break;
752*10696SDavid.Hollister@Sun.COM 	case PMCIN_GET_TIME_STAMP:
753*10696SDavid.Hollister@Sun.COM 		return ("GET_TIME_STAMP");
754*10696SDavid.Hollister@Sun.COM 		break;
755*10696SDavid.Hollister@Sun.COM 	case PMCIN_PORT_CONTROL:
756*10696SDavid.Hollister@Sun.COM 		return ("PORT_CONTROL");
757*10696SDavid.Hollister@Sun.COM 		break;
758*10696SDavid.Hollister@Sun.COM 	case PMCIN_GET_NVMD_DATA:
759*10696SDavid.Hollister@Sun.COM 		return ("GET_NVMD_DATA");
760*10696SDavid.Hollister@Sun.COM 		break;
761*10696SDavid.Hollister@Sun.COM 	case PMCIN_SET_NVMD_DATA:
762*10696SDavid.Hollister@Sun.COM 		return ("SET_NVMD_DATA");
763*10696SDavid.Hollister@Sun.COM 		break;
764*10696SDavid.Hollister@Sun.COM 	case PMCIN_SET_DEVICE_STATE:
765*10696SDavid.Hollister@Sun.COM 		return ("SET_DEVICE_STATE");
766*10696SDavid.Hollister@Sun.COM 		break;
767*10696SDavid.Hollister@Sun.COM 	case PMCIN_GET_DEVICE_STATE:
768*10696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_STATE");
769*10696SDavid.Hollister@Sun.COM 		break;
770*10696SDavid.Hollister@Sun.COM 	default:
771*10696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
772*10696SDavid.Hollister@Sun.COM 		break;
773*10696SDavid.Hollister@Sun.COM 	}
774*10696SDavid.Hollister@Sun.COM }
775*10696SDavid.Hollister@Sun.COM 
776*10696SDavid.Hollister@Sun.COM static char *
777*10696SDavid.Hollister@Sun.COM outbound_iomb_opcode(uint32_t opcode)
778*10696SDavid.Hollister@Sun.COM {
779*10696SDavid.Hollister@Sun.COM 	switch (opcode) {
780*10696SDavid.Hollister@Sun.COM 	case PMCOUT_ECHO:
781*10696SDavid.Hollister@Sun.COM 		return ("ECHO");
782*10696SDavid.Hollister@Sun.COM 		break;
783*10696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_INFO:
784*10696SDavid.Hollister@Sun.COM 		return ("GET_INFO");
785*10696SDavid.Hollister@Sun.COM 		break;
786*10696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_VPD:
787*10696SDavid.Hollister@Sun.COM 		return ("GET_VPD");
788*10696SDavid.Hollister@Sun.COM 		break;
789*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_HW_EVENT:
790*10696SDavid.Hollister@Sun.COM 		return ("SAS_HW_EVENT");
791*10696SDavid.Hollister@Sun.COM 		break;
792*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_COMPLETION:
793*10696SDavid.Hollister@Sun.COM 		return ("SSP_COMPLETION");
794*10696SDavid.Hollister@Sun.COM 		break;
795*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SMP_COMPLETION:
796*10696SDavid.Hollister@Sun.COM 		return ("SMP_COMPLETION");
797*10696SDavid.Hollister@Sun.COM 		break;
798*10696SDavid.Hollister@Sun.COM 	case PMCOUT_LOCAL_PHY_CONTROL:
799*10696SDavid.Hollister@Sun.COM 		return ("LOCAL_PHY_CONTROL");
800*10696SDavid.Hollister@Sun.COM 		break;
801*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_ASSISTED_DISCOVERY_EVENT:
802*10696SDavid.Hollister@Sun.COM 		return ("SAS_ASSISTED_DISCOVERY_SENT");
803*10696SDavid.Hollister@Sun.COM 		break;
804*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_ASSISTED_DISCOVERY_EVENT:
805*10696SDavid.Hollister@Sun.COM 		return ("SATA_ASSISTED_DISCOVERY_SENT");
806*10696SDavid.Hollister@Sun.COM 		break;
807*10696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_REGISTRATION:
808*10696SDavid.Hollister@Sun.COM 		return ("DEVICE_REGISTRATION");
809*10696SDavid.Hollister@Sun.COM 		break;
810*10696SDavid.Hollister@Sun.COM 	case PMCOUT_DEREGISTER_DEVICE_HANDLE:
811*10696SDavid.Hollister@Sun.COM 		return ("DEREGISTER_DEVICE_HANDLE");
812*10696SDavid.Hollister@Sun.COM 		break;
813*10696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_DEVICE_HANDLE:
814*10696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_HANDLE");
815*10696SDavid.Hollister@Sun.COM 		break;
816*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_COMPLETION:
817*10696SDavid.Hollister@Sun.COM 		return ("SATA_COMPLETION");
818*10696SDavid.Hollister@Sun.COM 		break;
819*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_EVENT:
820*10696SDavid.Hollister@Sun.COM 		return ("SATA_EVENT");
821*10696SDavid.Hollister@Sun.COM 		break;
822*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_EVENT:
823*10696SDavid.Hollister@Sun.COM 		return ("SSP_EVENT");
824*10696SDavid.Hollister@Sun.COM 		break;
825*10696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_HANDLE_ARRIVED:
826*10696SDavid.Hollister@Sun.COM 		return ("DEVICE_HANDLE_ARRIVED");
827*10696SDavid.Hollister@Sun.COM 		break;
828*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SMP_REQUEST_RECEIVED:
829*10696SDavid.Hollister@Sun.COM 		return ("SMP_REQUEST_RECEIVED");
830*10696SDavid.Hollister@Sun.COM 		break;
831*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_REQUEST_RECEIVED:
832*10696SDavid.Hollister@Sun.COM 		return ("SSP_REQUEST_RECEIVED");
833*10696SDavid.Hollister@Sun.COM 		break;
834*10696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_INFO:
835*10696SDavid.Hollister@Sun.COM 		return ("DEVICE_INFO");
836*10696SDavid.Hollister@Sun.COM 		break;
837*10696SDavid.Hollister@Sun.COM 	case PMCOUT_FW_FLASH_UPDATE:
838*10696SDavid.Hollister@Sun.COM 		return ("FW_FLASH_UPDATE");
839*10696SDavid.Hollister@Sun.COM 		break;
840*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_VPD:
841*10696SDavid.Hollister@Sun.COM 		return ("SET_VPD");
842*10696SDavid.Hollister@Sun.COM 		break;
843*10696SDavid.Hollister@Sun.COM 	case PMCOUT_GPIO:
844*10696SDavid.Hollister@Sun.COM 		return ("GPIO");
845*10696SDavid.Hollister@Sun.COM 		break;
846*10696SDavid.Hollister@Sun.COM 	case PMCOUT_GPIO_EVENT:
847*10696SDavid.Hollister@Sun.COM 		return ("GPIO_EVENT");
848*10696SDavid.Hollister@Sun.COM 		break;
849*10696SDavid.Hollister@Sun.COM 	case PMCOUT_GENERAL_EVENT:
850*10696SDavid.Hollister@Sun.COM 		return ("GENERAL_EVENT");
851*10696SDavid.Hollister@Sun.COM 		break;
852*10696SDavid.Hollister@Sun.COM 	case PMCOUT_TWI:
853*10696SDavid.Hollister@Sun.COM 		return ("TWI");
854*10696SDavid.Hollister@Sun.COM 		break;
855*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SSP_ABORT:
856*10696SDavid.Hollister@Sun.COM 		return ("SSP_ABORT");
857*10696SDavid.Hollister@Sun.COM 		break;
858*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SATA_ABORT:
859*10696SDavid.Hollister@Sun.COM 		return ("SATA_ABORT");
860*10696SDavid.Hollister@Sun.COM 		break;
861*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_DIAG_MODE_START_END:
862*10696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_MODE_START_END");
863*10696SDavid.Hollister@Sun.COM 		break;
864*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_DIAG_EXECUTE:
865*10696SDavid.Hollister@Sun.COM 		return ("SAS_DIAG_EXECUTE");
866*10696SDavid.Hollister@Sun.COM 		break;
867*10696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_TIME_STAMP:
868*10696SDavid.Hollister@Sun.COM 		return ("GET_TIME_STAMP");
869*10696SDavid.Hollister@Sun.COM 		break;
870*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SAS_HW_EVENT_ACK_ACK:
871*10696SDavid.Hollister@Sun.COM 		return ("SAS_HW_EVENT_ACK_ACK");
872*10696SDavid.Hollister@Sun.COM 		break;
873*10696SDavid.Hollister@Sun.COM 	case PMCOUT_PORT_CONTROL:
874*10696SDavid.Hollister@Sun.COM 		return ("PORT_CONTROL");
875*10696SDavid.Hollister@Sun.COM 		break;
876*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SKIP_ENTRIES:
877*10696SDavid.Hollister@Sun.COM 		return ("SKIP_ENTRIES");
878*10696SDavid.Hollister@Sun.COM 		break;
879*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SMP_ABORT:
880*10696SDavid.Hollister@Sun.COM 		return ("SMP_ABORT");
881*10696SDavid.Hollister@Sun.COM 		break;
882*10696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_NVMD_DATA:
883*10696SDavid.Hollister@Sun.COM 		return ("GET_NVMD_DATA");
884*10696SDavid.Hollister@Sun.COM 		break;
885*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_NVMD_DATA:
886*10696SDavid.Hollister@Sun.COM 		return ("SET_NVMD_DATA");
887*10696SDavid.Hollister@Sun.COM 		break;
888*10696SDavid.Hollister@Sun.COM 	case PMCOUT_DEVICE_HANDLE_REMOVED:
889*10696SDavid.Hollister@Sun.COM 		return ("DEVICE_HANDLE_REMOVED");
890*10696SDavid.Hollister@Sun.COM 		break;
891*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_DEVICE_STATE:
892*10696SDavid.Hollister@Sun.COM 		return ("SET_DEVICE_STATE");
893*10696SDavid.Hollister@Sun.COM 		break;
894*10696SDavid.Hollister@Sun.COM 	case PMCOUT_GET_DEVICE_STATE:
895*10696SDavid.Hollister@Sun.COM 		return ("GET_DEVICE_STATE");
896*10696SDavid.Hollister@Sun.COM 		break;
897*10696SDavid.Hollister@Sun.COM 	case PMCOUT_SET_DEVICE_INFO:
898*10696SDavid.Hollister@Sun.COM 		return ("SET_DEVICE_INFO");
899*10696SDavid.Hollister@Sun.COM 		break;
900*10696SDavid.Hollister@Sun.COM 	default:
901*10696SDavid.Hollister@Sun.COM 		return ("UNKNOWN");
902*10696SDavid.Hollister@Sun.COM 		break;
903*10696SDavid.Hollister@Sun.COM 	}
904*10696SDavid.Hollister@Sun.COM }
905*10696SDavid.Hollister@Sun.COM 
906*10696SDavid.Hollister@Sun.COM static void
907*10696SDavid.Hollister@Sun.COM dump_one_qentry_outbound(uint32_t *qentryp, int idx)
908*10696SDavid.Hollister@Sun.COM {
909*10696SDavid.Hollister@Sun.COM 	int qeidx;
910*10696SDavid.Hollister@Sun.COM 	uint32_t word0 = LE_32(*qentryp);
911*10696SDavid.Hollister@Sun.COM 
912*10696SDavid.Hollister@Sun.COM 	mdb_printf("Entry #%02d\n", idx);
913*10696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
914*10696SDavid.Hollister@Sun.COM 
915*10696SDavid.Hollister@Sun.COM 	mdb_printf("Header: 0x%08x (", word0);
916*10696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_VALID) {
917*10696SDavid.Hollister@Sun.COM 		mdb_printf("VALID, ");
918*10696SDavid.Hollister@Sun.COM 	}
919*10696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_HIPRI) {
920*10696SDavid.Hollister@Sun.COM 		mdb_printf("HIPRI, ");
921*10696SDavid.Hollister@Sun.COM 	}
922*10696SDavid.Hollister@Sun.COM 	mdb_printf("OBID=%d, ",
923*10696SDavid.Hollister@Sun.COM 	    (word0 & PMCS_IOMB_OBID_MASK) >> PMCS_IOMB_OBID_SHIFT);
924*10696SDavid.Hollister@Sun.COM 	mdb_printf("CAT=%s, ",
925*10696SDavid.Hollister@Sun.COM 	    iomb_cat((word0 & PMCS_IOMB_CAT_MASK) >> PMCS_IOMB_CAT_SHIFT));
926*10696SDavid.Hollister@Sun.COM 	mdb_printf("OPCODE=%s",
927*10696SDavid.Hollister@Sun.COM 	    outbound_iomb_opcode(word0 & PMCS_IOMB_OPCODE_MASK));
928*10696SDavid.Hollister@Sun.COM 	mdb_printf(")\n");
929*10696SDavid.Hollister@Sun.COM 
930*10696SDavid.Hollister@Sun.COM 	mdb_printf("Remaining Payload:\n");
931*10696SDavid.Hollister@Sun.COM 
932*10696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
933*10696SDavid.Hollister@Sun.COM 	for (qeidx = 1; qeidx < (PMCS_QENTRY_SIZE / 4); qeidx++) {
934*10696SDavid.Hollister@Sun.COM 		mdb_printf("%08x ", LE_32(*(qentryp + qeidx)));
935*10696SDavid.Hollister@Sun.COM 	}
936*10696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
937*10696SDavid.Hollister@Sun.COM 	mdb_dec_indent(4);
938*10696SDavid.Hollister@Sun.COM }
939*10696SDavid.Hollister@Sun.COM 
940*10696SDavid.Hollister@Sun.COM static void
941*10696SDavid.Hollister@Sun.COM display_outbound_queues(struct pmcs_hw ss, uint_t verbose)
942*10696SDavid.Hollister@Sun.COM {
943*10696SDavid.Hollister@Sun.COM 	int		idx, qidx;
944*10696SDavid.Hollister@Sun.COM 	uintptr_t	obqp;
945*10696SDavid.Hollister@Sun.COM 	uint32_t	*cip;
946*10696SDavid.Hollister@Sun.COM 	uint32_t	*qentryp = mdb_alloc(PMCS_QENTRY_SIZE, UM_SLEEP);
947*10696SDavid.Hollister@Sun.COM 	uint32_t	last_consumed, oqpi;
948*10696SDavid.Hollister@Sun.COM 
949*10696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
950*10696SDavid.Hollister@Sun.COM 	mdb_printf("Outbound Queues\n");
951*10696SDavid.Hollister@Sun.COM 	mdb_printf("---------------\n");
952*10696SDavid.Hollister@Sun.COM 
953*10696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
954*10696SDavid.Hollister@Sun.COM 
955*10696SDavid.Hollister@Sun.COM 	for (qidx = 0; qidx < PMCS_NOQ; qidx++) {
956*10696SDavid.Hollister@Sun.COM 		obqp = (uintptr_t)ss.oqp[qidx];
957*10696SDavid.Hollister@Sun.COM 
958*10696SDavid.Hollister@Sun.COM 		if (obqp == NULL) {
959*10696SDavid.Hollister@Sun.COM 			mdb_printf("No outbound queue ptr for queue #%d\n",
960*10696SDavid.Hollister@Sun.COM 			    qidx);
961*10696SDavid.Hollister@Sun.COM 			continue;
962*10696SDavid.Hollister@Sun.COM 		}
963*10696SDavid.Hollister@Sun.COM 
964*10696SDavid.Hollister@Sun.COM 		mdb_printf("Outbound Queue #%d (Queue Type = %s)\n", qidx,
965*10696SDavid.Hollister@Sun.COM 		    obq_type(qidx));
966*10696SDavid.Hollister@Sun.COM 		/*
967*10696SDavid.Hollister@Sun.COM 		 * Chip is the producer, so read the actual producer index
968*10696SDavid.Hollister@Sun.COM 		 * and not the driver's version
969*10696SDavid.Hollister@Sun.COM 		 */
970*10696SDavid.Hollister@Sun.COM 		cip = (uint32_t *)((void *)ss.cip);
971*10696SDavid.Hollister@Sun.COM 		if (MDB_RD(&oqpi, 4, cip + OQPI_BASE_OFFSET +
972*10696SDavid.Hollister@Sun.COM 		    (qidx * 4)) == -1) {
973*10696SDavid.Hollister@Sun.COM 			mdb_warn("Couldn't read oqpi\n");
974*10696SDavid.Hollister@Sun.COM 			break;
975*10696SDavid.Hollister@Sun.COM 		}
976*10696SDavid.Hollister@Sun.COM 
977*10696SDavid.Hollister@Sun.COM 		mdb_printf("Producer index: %d  Consumer index: %d\n\n",
978*10696SDavid.Hollister@Sun.COM 		    LE_32(oqpi), ss.oqci[qidx]);
979*10696SDavid.Hollister@Sun.COM 		mdb_inc_indent(2);
980*10696SDavid.Hollister@Sun.COM 
981*10696SDavid.Hollister@Sun.COM 		if (ss.oqci[qidx] == 0) {
982*10696SDavid.Hollister@Sun.COM 			last_consumed = ss.ioq_depth - 1;
983*10696SDavid.Hollister@Sun.COM 		} else {
984*10696SDavid.Hollister@Sun.COM 			last_consumed = ss.oqci[qidx] - 1;
985*10696SDavid.Hollister@Sun.COM 		}
986*10696SDavid.Hollister@Sun.COM 
987*10696SDavid.Hollister@Sun.COM 
988*10696SDavid.Hollister@Sun.COM 		if (!verbose) {
989*10696SDavid.Hollister@Sun.COM 			mdb_printf("Last processed entry:\n");
990*10696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
991*10696SDavid.Hollister@Sun.COM 			    (obqp + (PMCS_QENTRY_SIZE * last_consumed)))
992*10696SDavid.Hollister@Sun.COM 			    == -1) {
993*10696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
994*10696SDavid.Hollister@Sun.COM 				    (obqp + (PMCS_QENTRY_SIZE *
995*10696SDavid.Hollister@Sun.COM 				    last_consumed)));
996*10696SDavid.Hollister@Sun.COM 				break;
997*10696SDavid.Hollister@Sun.COM 			}
998*10696SDavid.Hollister@Sun.COM 			dump_one_qentry_outbound(qentryp, last_consumed);
999*10696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
1000*10696SDavid.Hollister@Sun.COM 			mdb_dec_indent(2);
1001*10696SDavid.Hollister@Sun.COM 			continue;
1002*10696SDavid.Hollister@Sun.COM 		}
1003*10696SDavid.Hollister@Sun.COM 
1004*10696SDavid.Hollister@Sun.COM 		for (idx = 0; idx < ss.ioq_depth; idx++) {
1005*10696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
1006*10696SDavid.Hollister@Sun.COM 			    (obqp + (PMCS_QENTRY_SIZE * idx))) == -1) {
1007*10696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
1008*10696SDavid.Hollister@Sun.COM 				    (obqp + (PMCS_QENTRY_SIZE * idx)));
1009*10696SDavid.Hollister@Sun.COM 				break;
1010*10696SDavid.Hollister@Sun.COM 			}
1011*10696SDavid.Hollister@Sun.COM 			dump_one_qentry_outbound(qentryp, idx);
1012*10696SDavid.Hollister@Sun.COM 		}
1013*10696SDavid.Hollister@Sun.COM 
1014*10696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
1015*10696SDavid.Hollister@Sun.COM 		mdb_dec_indent(2);
1016*10696SDavid.Hollister@Sun.COM 	}
1017*10696SDavid.Hollister@Sun.COM 
1018*10696SDavid.Hollister@Sun.COM 	mdb_dec_indent(2);
1019*10696SDavid.Hollister@Sun.COM 	mdb_free(qentryp, PMCS_QENTRY_SIZE);
1020*10696SDavid.Hollister@Sun.COM }
1021*10696SDavid.Hollister@Sun.COM 
1022*10696SDavid.Hollister@Sun.COM static void
1023*10696SDavid.Hollister@Sun.COM dump_one_qentry_inbound(uint32_t *qentryp, int idx)
1024*10696SDavid.Hollister@Sun.COM {
1025*10696SDavid.Hollister@Sun.COM 	int qeidx;
1026*10696SDavid.Hollister@Sun.COM 	uint32_t word0 = LE_32(*qentryp);
1027*10696SDavid.Hollister@Sun.COM 
1028*10696SDavid.Hollister@Sun.COM 	mdb_printf("Entry #%02d\n", idx);
1029*10696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
1030*10696SDavid.Hollister@Sun.COM 
1031*10696SDavid.Hollister@Sun.COM 	mdb_printf("Header: 0x%08x (", word0);
1032*10696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_VALID) {
1033*10696SDavid.Hollister@Sun.COM 		mdb_printf("VALID, ");
1034*10696SDavid.Hollister@Sun.COM 	}
1035*10696SDavid.Hollister@Sun.COM 	if (word0 & PMCS_IOMB_HIPRI) {
1036*10696SDavid.Hollister@Sun.COM 		mdb_printf("HIPRI, ");
1037*10696SDavid.Hollister@Sun.COM 	}
1038*10696SDavid.Hollister@Sun.COM 	mdb_printf("OBID=%d, ",
1039*10696SDavid.Hollister@Sun.COM 	    (word0 & PMCS_IOMB_OBID_MASK) >> PMCS_IOMB_OBID_SHIFT);
1040*10696SDavid.Hollister@Sun.COM 	mdb_printf("CAT=%s, ",
1041*10696SDavid.Hollister@Sun.COM 	    iomb_cat((word0 & PMCS_IOMB_CAT_MASK) >> PMCS_IOMB_CAT_SHIFT));
1042*10696SDavid.Hollister@Sun.COM 	mdb_printf("OPCODE=%s",
1043*10696SDavid.Hollister@Sun.COM 	    inbound_iomb_opcode(word0 & PMCS_IOMB_OPCODE_MASK));
1044*10696SDavid.Hollister@Sun.COM 	mdb_printf(")\n");
1045*10696SDavid.Hollister@Sun.COM 
1046*10696SDavid.Hollister@Sun.COM 	mdb_printf("HTAG: 0x%08x\n", LE_32(*(qentryp + 1)));
1047*10696SDavid.Hollister@Sun.COM 	mdb_printf("Remaining Payload:\n");
1048*10696SDavid.Hollister@Sun.COM 
1049*10696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
1050*10696SDavid.Hollister@Sun.COM 	for (qeidx = 2; qeidx < (PMCS_QENTRY_SIZE / 4); qeidx++) {
1051*10696SDavid.Hollister@Sun.COM 		mdb_printf("%08x ", LE_32(*(qentryp + qeidx)));
1052*10696SDavid.Hollister@Sun.COM 	}
1053*10696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
1054*10696SDavid.Hollister@Sun.COM 	mdb_dec_indent(4);
1055*10696SDavid.Hollister@Sun.COM }
1056*10696SDavid.Hollister@Sun.COM 
1057*10696SDavid.Hollister@Sun.COM static void
1058*10696SDavid.Hollister@Sun.COM display_inbound_queues(struct pmcs_hw ss, uint_t verbose)
1059*10696SDavid.Hollister@Sun.COM {
1060*10696SDavid.Hollister@Sun.COM 	int		idx, qidx, iqci, last_consumed;
1061*10696SDavid.Hollister@Sun.COM 	uintptr_t	ibqp;
1062*10696SDavid.Hollister@Sun.COM 	uint32_t	*qentryp = mdb_alloc(PMCS_QENTRY_SIZE, UM_SLEEP);
1063*10696SDavid.Hollister@Sun.COM 	uint32_t	*cip;
1064*10696SDavid.Hollister@Sun.COM 
1065*10696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
1066*10696SDavid.Hollister@Sun.COM 	mdb_printf("Inbound Queues\n");
1067*10696SDavid.Hollister@Sun.COM 	mdb_printf("--------------\n");
1068*10696SDavid.Hollister@Sun.COM 
1069*10696SDavid.Hollister@Sun.COM 	mdb_inc_indent(2);
1070*10696SDavid.Hollister@Sun.COM 
1071*10696SDavid.Hollister@Sun.COM 	for (qidx = 0; qidx < PMCS_NIQ; qidx++) {
1072*10696SDavid.Hollister@Sun.COM 		ibqp = (uintptr_t)ss.iqp[qidx];
1073*10696SDavid.Hollister@Sun.COM 
1074*10696SDavid.Hollister@Sun.COM 		if (ibqp == NULL) {
1075*10696SDavid.Hollister@Sun.COM 			mdb_printf("No inbound queue ptr for queue #%d\n",
1076*10696SDavid.Hollister@Sun.COM 			    qidx);
1077*10696SDavid.Hollister@Sun.COM 			continue;
1078*10696SDavid.Hollister@Sun.COM 		}
1079*10696SDavid.Hollister@Sun.COM 
1080*10696SDavid.Hollister@Sun.COM 		mdb_printf("Inbound Queue #%d (Queue Type = %s)\n", qidx,
1081*10696SDavid.Hollister@Sun.COM 		    ibq_type(qidx));
1082*10696SDavid.Hollister@Sun.COM 
1083*10696SDavid.Hollister@Sun.COM 		cip = (uint32_t *)((void *)ss.cip);
1084*10696SDavid.Hollister@Sun.COM 		if (MDB_RD(&iqci, 4, cip + (qidx * 4)) == -1) {
1085*10696SDavid.Hollister@Sun.COM 			mdb_warn("Couldn't read iqci\n");
1086*10696SDavid.Hollister@Sun.COM 			break;
1087*10696SDavid.Hollister@Sun.COM 		}
1088*10696SDavid.Hollister@Sun.COM 		iqci = LE_32(iqci);
1089*10696SDavid.Hollister@Sun.COM 
1090*10696SDavid.Hollister@Sun.COM 		mdb_printf("Producer index: %d  Consumer index: %d\n\n",
1091*10696SDavid.Hollister@Sun.COM 		    ss.shadow_iqpi[qidx], iqci);
1092*10696SDavid.Hollister@Sun.COM 		mdb_inc_indent(2);
1093*10696SDavid.Hollister@Sun.COM 
1094*10696SDavid.Hollister@Sun.COM 		if (iqci == 0) {
1095*10696SDavid.Hollister@Sun.COM 			last_consumed = ss.ioq_depth - 1;
1096*10696SDavid.Hollister@Sun.COM 		} else {
1097*10696SDavid.Hollister@Sun.COM 			last_consumed = iqci - 1;
1098*10696SDavid.Hollister@Sun.COM 		}
1099*10696SDavid.Hollister@Sun.COM 
1100*10696SDavid.Hollister@Sun.COM 		if (!verbose) {
1101*10696SDavid.Hollister@Sun.COM 			mdb_printf("Last processed entry:\n");
1102*10696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
1103*10696SDavid.Hollister@Sun.COM 			    (ibqp + (PMCS_QENTRY_SIZE * last_consumed)))
1104*10696SDavid.Hollister@Sun.COM 			    == -1) {
1105*10696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
1106*10696SDavid.Hollister@Sun.COM 				    (ibqp + (PMCS_QENTRY_SIZE *
1107*10696SDavid.Hollister@Sun.COM 				    last_consumed)));
1108*10696SDavid.Hollister@Sun.COM 				break;
1109*10696SDavid.Hollister@Sun.COM 			}
1110*10696SDavid.Hollister@Sun.COM 			dump_one_qentry_inbound(qentryp, last_consumed);
1111*10696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
1112*10696SDavid.Hollister@Sun.COM 			mdb_dec_indent(2);
1113*10696SDavid.Hollister@Sun.COM 			continue;
1114*10696SDavid.Hollister@Sun.COM 		}
1115*10696SDavid.Hollister@Sun.COM 
1116*10696SDavid.Hollister@Sun.COM 		for (idx = 0; idx < ss.ioq_depth; idx++) {
1117*10696SDavid.Hollister@Sun.COM 			if (MDB_RD(qentryp, PMCS_QENTRY_SIZE,
1118*10696SDavid.Hollister@Sun.COM 			    (ibqp + (PMCS_QENTRY_SIZE * idx))) == -1) {
1119*10696SDavid.Hollister@Sun.COM 				mdb_warn("Couldn't read queue entry at 0x%p\n",
1120*10696SDavid.Hollister@Sun.COM 				    (ibqp + (PMCS_QENTRY_SIZE * idx)));
1121*10696SDavid.Hollister@Sun.COM 				break;
1122*10696SDavid.Hollister@Sun.COM 			}
1123*10696SDavid.Hollister@Sun.COM 			dump_one_qentry_inbound(qentryp, idx);
1124*10696SDavid.Hollister@Sun.COM 		}
1125*10696SDavid.Hollister@Sun.COM 
1126*10696SDavid.Hollister@Sun.COM 		mdb_printf("\n");
1127*10696SDavid.Hollister@Sun.COM 		mdb_dec_indent(2);
1128*10696SDavid.Hollister@Sun.COM 	}
1129*10696SDavid.Hollister@Sun.COM 
1130*10696SDavid.Hollister@Sun.COM 	mdb_dec_indent(2);
1131*10696SDavid.Hollister@Sun.COM 	mdb_free(qentryp, PMCS_QENTRY_SIZE);
1132*10696SDavid.Hollister@Sun.COM }
1133*10696SDavid.Hollister@Sun.COM 
1134*10696SDavid.Hollister@Sun.COM static void
1135*10696SDavid.Hollister@Sun.COM display_phy(struct pmcs_phy phy, int verbose, int totals_only)
1136*10696SDavid.Hollister@Sun.COM {
1137*10696SDavid.Hollister@Sun.COM 	char		*dtype, *speed;
1138*10696SDavid.Hollister@Sun.COM 	char		*yes = "Yes";
1139*10696SDavid.Hollister@Sun.COM 	char		*no = "No";
1140*10696SDavid.Hollister@Sun.COM 	char		*cfgd = no;
1141*10696SDavid.Hollister@Sun.COM 	char		*apend = no;
1142*10696SDavid.Hollister@Sun.COM 	char		*asent = no;
1143*10696SDavid.Hollister@Sun.COM 	char		*dead = no;
1144*10696SDavid.Hollister@Sun.COM 	char		*changed = no;
1145*10696SDavid.Hollister@Sun.COM 
1146*10696SDavid.Hollister@Sun.COM 	switch (phy.dtype) {
1147*10696SDavid.Hollister@Sun.COM 	case NOTHING:
1148*10696SDavid.Hollister@Sun.COM 		dtype = "None";
1149*10696SDavid.Hollister@Sun.COM 		break;
1150*10696SDavid.Hollister@Sun.COM 	case SATA:
1151*10696SDavid.Hollister@Sun.COM 		dtype = "SATA";
1152*10696SDavid.Hollister@Sun.COM 		if (phy.configured) {
1153*10696SDavid.Hollister@Sun.COM 			++sata_phys;
1154*10696SDavid.Hollister@Sun.COM 		}
1155*10696SDavid.Hollister@Sun.COM 		break;
1156*10696SDavid.Hollister@Sun.COM 	case SAS:
1157*10696SDavid.Hollister@Sun.COM 		dtype = "SAS";
1158*10696SDavid.Hollister@Sun.COM 		if (phy.configured) {
1159*10696SDavid.Hollister@Sun.COM 			++sas_phys;
1160*10696SDavid.Hollister@Sun.COM 		}
1161*10696SDavid.Hollister@Sun.COM 		break;
1162*10696SDavid.Hollister@Sun.COM 	case EXPANDER:
1163*10696SDavid.Hollister@Sun.COM 		dtype = "EXP";
1164*10696SDavid.Hollister@Sun.COM 		if (phy.configured) {
1165*10696SDavid.Hollister@Sun.COM 			++exp_phys;
1166*10696SDavid.Hollister@Sun.COM 		}
1167*10696SDavid.Hollister@Sun.COM 		break;
1168*10696SDavid.Hollister@Sun.COM 	}
1169*10696SDavid.Hollister@Sun.COM 
1170*10696SDavid.Hollister@Sun.COM 	if (phy.dtype == NOTHING) {
1171*10696SDavid.Hollister@Sun.COM 		empty_phys++;
1172*10696SDavid.Hollister@Sun.COM 	} else if ((phy.dtype == EXPANDER) && phy.configured) {
1173*10696SDavid.Hollister@Sun.COM 		num_expanders++;
1174*10696SDavid.Hollister@Sun.COM 	}
1175*10696SDavid.Hollister@Sun.COM 
1176*10696SDavid.Hollister@Sun.COM 	if (totals_only) {
1177*10696SDavid.Hollister@Sun.COM 		return;
1178*10696SDavid.Hollister@Sun.COM 	}
1179*10696SDavid.Hollister@Sun.COM 
1180*10696SDavid.Hollister@Sun.COM 	switch (phy.link_rate) {
1181*10696SDavid.Hollister@Sun.COM 	case SAS_LINK_RATE_1_5GBIT:
1182*10696SDavid.Hollister@Sun.COM 		speed = "1.5Gb/s";
1183*10696SDavid.Hollister@Sun.COM 		break;
1184*10696SDavid.Hollister@Sun.COM 	case SAS_LINK_RATE_3GBIT:
1185*10696SDavid.Hollister@Sun.COM 		speed = "3 Gb/s";
1186*10696SDavid.Hollister@Sun.COM 		break;
1187*10696SDavid.Hollister@Sun.COM 	case SAS_LINK_RATE_6GBIT:
1188*10696SDavid.Hollister@Sun.COM 		speed = "6 Gb/s";
1189*10696SDavid.Hollister@Sun.COM 		break;
1190*10696SDavid.Hollister@Sun.COM 	default:
1191*10696SDavid.Hollister@Sun.COM 		speed = "N/A";
1192*10696SDavid.Hollister@Sun.COM 		break;
1193*10696SDavid.Hollister@Sun.COM 	}
1194*10696SDavid.Hollister@Sun.COM 
1195*10696SDavid.Hollister@Sun.COM 	if ((phy.dtype != NOTHING) || verbose) {
1196*10696SDavid.Hollister@Sun.COM 		print_sas_address(&phy);
1197*10696SDavid.Hollister@Sun.COM 
1198*10696SDavid.Hollister@Sun.COM 		if (phy.device_id != PMCS_INVALID_DEVICE_ID) {
1199*10696SDavid.Hollister@Sun.COM 			mdb_printf(" %3d %4d %6s %4s ",
1200*10696SDavid.Hollister@Sun.COM 			    phy.device_id, phy.phynum, speed, dtype);
1201*10696SDavid.Hollister@Sun.COM 		} else {
1202*10696SDavid.Hollister@Sun.COM 			mdb_printf(" N/A %4d %6s %4s ",
1203*10696SDavid.Hollister@Sun.COM 			    phy.phynum, speed, dtype);
1204*10696SDavid.Hollister@Sun.COM 		}
1205*10696SDavid.Hollister@Sun.COM 
1206*10696SDavid.Hollister@Sun.COM 		if (verbose) {
1207*10696SDavid.Hollister@Sun.COM 			if (phy.abort_sent) {
1208*10696SDavid.Hollister@Sun.COM 				asent = yes;
1209*10696SDavid.Hollister@Sun.COM 			}
1210*10696SDavid.Hollister@Sun.COM 			if (phy.abort_pending) {
1211*10696SDavid.Hollister@Sun.COM 				apend = yes;
1212*10696SDavid.Hollister@Sun.COM 			}
1213*10696SDavid.Hollister@Sun.COM 			if (phy.configured) {
1214*10696SDavid.Hollister@Sun.COM 				cfgd = yes;
1215*10696SDavid.Hollister@Sun.COM 			}
1216*10696SDavid.Hollister@Sun.COM 			if (phy.dead) {
1217*10696SDavid.Hollister@Sun.COM 				dead = yes;
1218*10696SDavid.Hollister@Sun.COM 			}
1219*10696SDavid.Hollister@Sun.COM 			if (phy.changed) {
1220*10696SDavid.Hollister@Sun.COM 				changed = yes;
1221*10696SDavid.Hollister@Sun.COM 			}
1222*10696SDavid.Hollister@Sun.COM 
1223*10696SDavid.Hollister@Sun.COM 			mdb_printf("%-4s %-4s %-4s %-4s %-4s %3d "
1224*10696SDavid.Hollister@Sun.COM 			    "0x%p ", cfgd, apend, asent,
1225*10696SDavid.Hollister@Sun.COM 			    changed, dead, phy.ref_count, phy.phy_lock);
1226*10696SDavid.Hollister@Sun.COM 		}
1227*10696SDavid.Hollister@Sun.COM 
1228*10696SDavid.Hollister@Sun.COM 		mdb_printf("Path: %s\n", phy.path);
1229*10696SDavid.Hollister@Sun.COM 	}
1230*10696SDavid.Hollister@Sun.COM }
1231*10696SDavid.Hollister@Sun.COM 
1232*10696SDavid.Hollister@Sun.COM static void
1233*10696SDavid.Hollister@Sun.COM display_phys(struct pmcs_hw ss, int verbose, struct pmcs_phy *parent, int level,
1234*10696SDavid.Hollister@Sun.COM     int totals_only)
1235*10696SDavid.Hollister@Sun.COM {
1236*10696SDavid.Hollister@Sun.COM 	pmcs_phy_t	phy;
1237*10696SDavid.Hollister@Sun.COM 	pmcs_phy_t	*pphy = parent;
1238*10696SDavid.Hollister@Sun.COM 
1239*10696SDavid.Hollister@Sun.COM 	mdb_inc_indent(3);
1240*10696SDavid.Hollister@Sun.COM 
1241*10696SDavid.Hollister@Sun.COM 	if (parent == NULL) {
1242*10696SDavid.Hollister@Sun.COM 		pphy = (pmcs_phy_t *)ss.root_phys;
1243*10696SDavid.Hollister@Sun.COM 	} else {
1244*10696SDavid.Hollister@Sun.COM 		pphy = (pmcs_phy_t *)parent;
1245*10696SDavid.Hollister@Sun.COM 	}
1246*10696SDavid.Hollister@Sun.COM 
1247*10696SDavid.Hollister@Sun.COM 	if (level == 0) {
1248*10696SDavid.Hollister@Sun.COM 		sas_phys = 0;
1249*10696SDavid.Hollister@Sun.COM 		sata_phys = 0;
1250*10696SDavid.Hollister@Sun.COM 		exp_phys = 0;
1251*10696SDavid.Hollister@Sun.COM 		num_expanders = 0;
1252*10696SDavid.Hollister@Sun.COM 		empty_phys = 0;
1253*10696SDavid.Hollister@Sun.COM 	}
1254*10696SDavid.Hollister@Sun.COM 
1255*10696SDavid.Hollister@Sun.COM 	if (!totals_only) {
1256*10696SDavid.Hollister@Sun.COM 		if (level == 0) {
1257*10696SDavid.Hollister@Sun.COM 			mdb_printf("PHY information\n");
1258*10696SDavid.Hollister@Sun.COM 		}
1259*10696SDavid.Hollister@Sun.COM 		mdb_printf("--------\n");
1260*10696SDavid.Hollister@Sun.COM 		mdb_printf("Level %2d\n", level);
1261*10696SDavid.Hollister@Sun.COM 		mdb_printf("--------\n");
1262*10696SDavid.Hollister@Sun.COM 		mdb_printf("SAS Address      Hdl Phy#  Speed Type ");
1263*10696SDavid.Hollister@Sun.COM 
1264*10696SDavid.Hollister@Sun.COM 		if (verbose) {
1265*10696SDavid.Hollister@Sun.COM 			mdb_printf("Cfgd AbtP AbtS Chgd Dead Ref Lock\n");
1266*10696SDavid.Hollister@Sun.COM 		} else {
1267*10696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
1268*10696SDavid.Hollister@Sun.COM 		}
1269*10696SDavid.Hollister@Sun.COM 	}
1270*10696SDavid.Hollister@Sun.COM 
1271*10696SDavid.Hollister@Sun.COM 	while (pphy) {
1272*10696SDavid.Hollister@Sun.COM 		if (MDB_RD(&phy, sizeof (phy), (uintptr_t)pphy) == -1) {
1273*10696SDavid.Hollister@Sun.COM 			NOREAD(pmcs_phy_t, phy);
1274*10696SDavid.Hollister@Sun.COM 			break;
1275*10696SDavid.Hollister@Sun.COM 		}
1276*10696SDavid.Hollister@Sun.COM 
1277*10696SDavid.Hollister@Sun.COM 		display_phy(phy, verbose, totals_only);
1278*10696SDavid.Hollister@Sun.COM 
1279*10696SDavid.Hollister@Sun.COM 		if (phy.children) {
1280*10696SDavid.Hollister@Sun.COM 			display_phys(ss, verbose, phy.children, level + 1,
1281*10696SDavid.Hollister@Sun.COM 			    totals_only);
1282*10696SDavid.Hollister@Sun.COM 			if (!totals_only) {
1283*10696SDavid.Hollister@Sun.COM 				mdb_printf("\n");
1284*10696SDavid.Hollister@Sun.COM 			}
1285*10696SDavid.Hollister@Sun.COM 		}
1286*10696SDavid.Hollister@Sun.COM 
1287*10696SDavid.Hollister@Sun.COM 		pphy = phy.sibling;
1288*10696SDavid.Hollister@Sun.COM 	}
1289*10696SDavid.Hollister@Sun.COM 
1290*10696SDavid.Hollister@Sun.COM 	mdb_dec_indent(3);
1291*10696SDavid.Hollister@Sun.COM 
1292*10696SDavid.Hollister@Sun.COM 	if (level == 0) {
1293*10696SDavid.Hollister@Sun.COM 		if (verbose) {
1294*10696SDavid.Hollister@Sun.COM 			mdb_printf("%19s %d (%d SAS + %d SATA + %d SMP) "
1295*10696SDavid.Hollister@Sun.COM 			    "(+%d subsidiary + %d empty)\n", "Occupied PHYs:",
1296*10696SDavid.Hollister@Sun.COM 			    (sas_phys + sata_phys + num_expanders),
1297*10696SDavid.Hollister@Sun.COM 			    sas_phys, sata_phys, num_expanders,
1298*10696SDavid.Hollister@Sun.COM 			    (exp_phys - num_expanders), empty_phys);
1299*10696SDavid.Hollister@Sun.COM 		} else {
1300*10696SDavid.Hollister@Sun.COM 			mdb_printf("%19s %d (%d SAS + %d SATA + %d SMP)\n",
1301*10696SDavid.Hollister@Sun.COM 			    "Occupied PHYs:",
1302*10696SDavid.Hollister@Sun.COM 			    (sas_phys + sata_phys + num_expanders),
1303*10696SDavid.Hollister@Sun.COM 			    sas_phys, sata_phys, num_expanders);
1304*10696SDavid.Hollister@Sun.COM 		}
1305*10696SDavid.Hollister@Sun.COM 	}
1306*10696SDavid.Hollister@Sun.COM }
1307*10696SDavid.Hollister@Sun.COM 
1308*10696SDavid.Hollister@Sun.COM /*
1309*10696SDavid.Hollister@Sun.COM  * MAX_INST_STRLEN is the largest string size from which we will attempt
1310*10696SDavid.Hollister@Sun.COM  * to convert to an instance number.  The string will be formed up as
1311*10696SDavid.Hollister@Sun.COM  * "0t<inst>\0" so that mdb_strtoull can parse it properly.
1312*10696SDavid.Hollister@Sun.COM  */
1313*10696SDavid.Hollister@Sun.COM #define	MAX_INST_STRLEN	8
1314*10696SDavid.Hollister@Sun.COM 
1315*10696SDavid.Hollister@Sun.COM static int
1316*10696SDavid.Hollister@Sun.COM pmcs_dump_tracelog(boolean_t filter, int instance)
1317*10696SDavid.Hollister@Sun.COM {
1318*10696SDavid.Hollister@Sun.COM 	pmcs_tbuf_t *tbuf_addr;
1319*10696SDavid.Hollister@Sun.COM 	uint_t tbuf_idx;
1320*10696SDavid.Hollister@Sun.COM 	pmcs_tbuf_t tbuf;
1321*10696SDavid.Hollister@Sun.COM 	boolean_t wrap, elem_filtered;
1322*10696SDavid.Hollister@Sun.COM 	uint_t start_idx, elems_to_print, idx, tbuf_num_elems;
1323*10696SDavid.Hollister@Sun.COM 	char *bufp;
1324*10696SDavid.Hollister@Sun.COM 	char elem_inst[MAX_INST_STRLEN], ei_idx;
1325*10696SDavid.Hollister@Sun.COM 
1326*10696SDavid.Hollister@Sun.COM 	/* Get the address of the first element */
1327*10696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&tbuf_addr, "pmcs_tbuf") == -1) {
1328*10696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf");
1329*10696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
1330*10696SDavid.Hollister@Sun.COM 	}
1331*10696SDavid.Hollister@Sun.COM 
1332*10696SDavid.Hollister@Sun.COM 	/* Get the total number */
1333*10696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&tbuf_num_elems, "pmcs_tbuf_num_elems") == -1) {
1334*10696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf_num_elems");
1335*10696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
1336*10696SDavid.Hollister@Sun.COM 	}
1337*10696SDavid.Hollister@Sun.COM 
1338*10696SDavid.Hollister@Sun.COM 	/* Get the current index */
1339*10696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&tbuf_idx, "pmcs_tbuf_idx") == -1) {
1340*10696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf_idx");
1341*10696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
1342*10696SDavid.Hollister@Sun.COM 	}
1343*10696SDavid.Hollister@Sun.COM 
1344*10696SDavid.Hollister@Sun.COM 	/* Indicator as to whether the buffer has wrapped */
1345*10696SDavid.Hollister@Sun.COM 	if (mdb_readvar(&wrap, "pmcs_tbuf_wrap") == -1) {
1346*10696SDavid.Hollister@Sun.COM 		mdb_warn("can't read pmcs_tbuf_wrap");
1347*10696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
1348*10696SDavid.Hollister@Sun.COM 	}
1349*10696SDavid.Hollister@Sun.COM 
1350*10696SDavid.Hollister@Sun.COM 	/* Figure out where we start and stop */
1351*10696SDavid.Hollister@Sun.COM 	if (wrap) {
1352*10696SDavid.Hollister@Sun.COM 		start_idx = tbuf_idx;
1353*10696SDavid.Hollister@Sun.COM 		elems_to_print = tbuf_num_elems;
1354*10696SDavid.Hollister@Sun.COM 	} else {
1355*10696SDavid.Hollister@Sun.COM 		start_idx = 0;
1356*10696SDavid.Hollister@Sun.COM 		elems_to_print = tbuf_idx;
1357*10696SDavid.Hollister@Sun.COM 	}
1358*10696SDavid.Hollister@Sun.COM 
1359*10696SDavid.Hollister@Sun.COM 	idx = start_idx;
1360*10696SDavid.Hollister@Sun.COM 
1361*10696SDavid.Hollister@Sun.COM 	/* Dump the buffer contents */
1362*10696SDavid.Hollister@Sun.COM 	while (elems_to_print != 0) {
1363*10696SDavid.Hollister@Sun.COM 		if (MDB_RD(&tbuf, sizeof (pmcs_tbuf_t), (tbuf_addr + idx))
1364*10696SDavid.Hollister@Sun.COM 		    == -1) {
1365*10696SDavid.Hollister@Sun.COM 			NOREAD(tbuf, (tbuf_addr + idx));
1366*10696SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
1367*10696SDavid.Hollister@Sun.COM 		}
1368*10696SDavid.Hollister@Sun.COM 
1369*10696SDavid.Hollister@Sun.COM 		elem_filtered = B_FALSE;
1370*10696SDavid.Hollister@Sun.COM 
1371*10696SDavid.Hollister@Sun.COM 		if (filter) {
1372*10696SDavid.Hollister@Sun.COM 			bufp = tbuf.buf;
1373*10696SDavid.Hollister@Sun.COM 			/* Skip the driver name */
1374*10696SDavid.Hollister@Sun.COM 			while (*bufp < '0' || *bufp > '9') {
1375*10696SDavid.Hollister@Sun.COM 				bufp++;
1376*10696SDavid.Hollister@Sun.COM 			}
1377*10696SDavid.Hollister@Sun.COM 
1378*10696SDavid.Hollister@Sun.COM 			ei_idx = 0;
1379*10696SDavid.Hollister@Sun.COM 			elem_inst[ei_idx++] = '0';
1380*10696SDavid.Hollister@Sun.COM 			elem_inst[ei_idx++] = 't';
1381*10696SDavid.Hollister@Sun.COM 			while (*bufp != ':' && ei_idx < (MAX_INST_STRLEN - 1)) {
1382*10696SDavid.Hollister@Sun.COM 				elem_inst[ei_idx++] = *bufp;
1383*10696SDavid.Hollister@Sun.COM 				bufp++;
1384*10696SDavid.Hollister@Sun.COM 			}
1385*10696SDavid.Hollister@Sun.COM 			elem_inst[ei_idx] = 0;
1386*10696SDavid.Hollister@Sun.COM 
1387*10696SDavid.Hollister@Sun.COM 			/* Get the instance */
1388*10696SDavid.Hollister@Sun.COM 			if ((int)mdb_strtoull(elem_inst) != instance) {
1389*10696SDavid.Hollister@Sun.COM 				elem_filtered = B_TRUE;
1390*10696SDavid.Hollister@Sun.COM 			}
1391*10696SDavid.Hollister@Sun.COM 		}
1392*10696SDavid.Hollister@Sun.COM 
1393*10696SDavid.Hollister@Sun.COM 		if (!elem_filtered) {
1394*10696SDavid.Hollister@Sun.COM 			mdb_printf("%Y.%09ld %s\n", tbuf.timestamp, tbuf.buf);
1395*10696SDavid.Hollister@Sun.COM 		}
1396*10696SDavid.Hollister@Sun.COM 
1397*10696SDavid.Hollister@Sun.COM 		--elems_to_print;
1398*10696SDavid.Hollister@Sun.COM 		if (++idx == tbuf_num_elems) {
1399*10696SDavid.Hollister@Sun.COM 			idx = 0;
1400*10696SDavid.Hollister@Sun.COM 		}
1401*10696SDavid.Hollister@Sun.COM 	}
1402*10696SDavid.Hollister@Sun.COM 
1403*10696SDavid.Hollister@Sun.COM 	return (DCMD_OK);
1404*10696SDavid.Hollister@Sun.COM }
1405*10696SDavid.Hollister@Sun.COM 
1406*10696SDavid.Hollister@Sun.COM /*
1407*10696SDavid.Hollister@Sun.COM  * Walkers
1408*10696SDavid.Hollister@Sun.COM  */
1409*10696SDavid.Hollister@Sun.COM static int
1410*10696SDavid.Hollister@Sun.COM targets_walk_i(mdb_walk_state_t *wsp)
1411*10696SDavid.Hollister@Sun.COM {
1412*10696SDavid.Hollister@Sun.COM 	if (wsp->walk_addr == NULL) {
1413*10696SDavid.Hollister@Sun.COM 		mdb_warn("Can not perform global walk\n");
1414*10696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
1415*10696SDavid.Hollister@Sun.COM 	}
1416*10696SDavid.Hollister@Sun.COM 
1417*10696SDavid.Hollister@Sun.COM 	/*
1418*10696SDavid.Hollister@Sun.COM 	 * Address provided belongs to HBA softstate.  Get the targets pointer
1419*10696SDavid.Hollister@Sun.COM 	 * to begin the walk.
1420*10696SDavid.Hollister@Sun.COM 	 */
1421*10696SDavid.Hollister@Sun.COM 	if (mdb_vread(&ss, sizeof (pmcs_hw_t), wsp->walk_addr) !=
1422*10696SDavid.Hollister@Sun.COM 	    sizeof (pmcs_hw_t)) {
1423*10696SDavid.Hollister@Sun.COM 		mdb_warn("Unable to read HBA softstate\n");
1424*10696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
1425*10696SDavid.Hollister@Sun.COM 	}
1426*10696SDavid.Hollister@Sun.COM 
1427*10696SDavid.Hollister@Sun.COM 	if (targets == NULL) {
1428*10696SDavid.Hollister@Sun.COM 		targets = mdb_alloc(sizeof (targets) * ss.max_dev, UM_SLEEP);
1429*10696SDavid.Hollister@Sun.COM 	}
1430*10696SDavid.Hollister@Sun.COM 
1431*10696SDavid.Hollister@Sun.COM 	if (MDB_RD(targets, sizeof (targets) * ss.max_dev, ss.targets) == -1) {
1432*10696SDavid.Hollister@Sun.COM 		NOREAD(targets, ss.targets);
1433*10696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
1434*10696SDavid.Hollister@Sun.COM 	}
1435*10696SDavid.Hollister@Sun.COM 
1436*10696SDavid.Hollister@Sun.COM 	target_idx = 0;
1437*10696SDavid.Hollister@Sun.COM 	wsp->walk_addr = (uintptr_t)(targets[0]);
1438*10696SDavid.Hollister@Sun.COM 	wsp->walk_data = mdb_alloc(sizeof (pmcs_xscsi_t), UM_SLEEP);
1439*10696SDavid.Hollister@Sun.COM 
1440*10696SDavid.Hollister@Sun.COM 	return (WALK_NEXT);
1441*10696SDavid.Hollister@Sun.COM }
1442*10696SDavid.Hollister@Sun.COM 
1443*10696SDavid.Hollister@Sun.COM static int
1444*10696SDavid.Hollister@Sun.COM targets_walk_s(mdb_walk_state_t *wsp)
1445*10696SDavid.Hollister@Sun.COM {
1446*10696SDavid.Hollister@Sun.COM 	int status;
1447*10696SDavid.Hollister@Sun.COM 
1448*10696SDavid.Hollister@Sun.COM 	if (target_idx == ss.max_dev) {
1449*10696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
1450*10696SDavid.Hollister@Sun.COM 	}
1451*10696SDavid.Hollister@Sun.COM 
1452*10696SDavid.Hollister@Sun.COM 	if (mdb_vread(wsp->walk_data, sizeof (pmcs_xscsi_t),
1453*10696SDavid.Hollister@Sun.COM 	    wsp->walk_addr) == -1) {
1454*10696SDavid.Hollister@Sun.COM 		mdb_warn("Failed to read target at %p", (void *)wsp->walk_addr);
1455*10696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
1456*10696SDavid.Hollister@Sun.COM 	}
1457*10696SDavid.Hollister@Sun.COM 
1458*10696SDavid.Hollister@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
1459*10696SDavid.Hollister@Sun.COM 	    wsp->walk_cbdata);
1460*10696SDavid.Hollister@Sun.COM 
1461*10696SDavid.Hollister@Sun.COM 	do {
1462*10696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)(targets[++target_idx]);
1463*10696SDavid.Hollister@Sun.COM 	} while ((wsp->walk_addr == NULL) && (target_idx < ss.max_dev));
1464*10696SDavid.Hollister@Sun.COM 
1465*10696SDavid.Hollister@Sun.COM 	if (target_idx == ss.max_dev) {
1466*10696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
1467*10696SDavid.Hollister@Sun.COM 	}
1468*10696SDavid.Hollister@Sun.COM 
1469*10696SDavid.Hollister@Sun.COM 	return (status);
1470*10696SDavid.Hollister@Sun.COM }
1471*10696SDavid.Hollister@Sun.COM 
1472*10696SDavid.Hollister@Sun.COM static void
1473*10696SDavid.Hollister@Sun.COM targets_walk_f(mdb_walk_state_t *wsp)
1474*10696SDavid.Hollister@Sun.COM {
1475*10696SDavid.Hollister@Sun.COM 	mdb_free(wsp->walk_data, sizeof (pmcs_xscsi_t));
1476*10696SDavid.Hollister@Sun.COM }
1477*10696SDavid.Hollister@Sun.COM 
1478*10696SDavid.Hollister@Sun.COM 
1479*10696SDavid.Hollister@Sun.COM static pmcs_phy_t *
1480*10696SDavid.Hollister@Sun.COM pmcs_next_sibling(pmcs_phy_t *phyp)
1481*10696SDavid.Hollister@Sun.COM {
1482*10696SDavid.Hollister@Sun.COM 	pmcs_phy_t parent;
1483*10696SDavid.Hollister@Sun.COM 
1484*10696SDavid.Hollister@Sun.COM 	/*
1485*10696SDavid.Hollister@Sun.COM 	 * First, if this is a root PHY, there are no more siblings
1486*10696SDavid.Hollister@Sun.COM 	 */
1487*10696SDavid.Hollister@Sun.COM 	if (phyp->level == 0) {
1488*10696SDavid.Hollister@Sun.COM 		return (NULL);
1489*10696SDavid.Hollister@Sun.COM 	}
1490*10696SDavid.Hollister@Sun.COM 
1491*10696SDavid.Hollister@Sun.COM 	/*
1492*10696SDavid.Hollister@Sun.COM 	 * Otherwise, next sibling is the parent's sibling
1493*10696SDavid.Hollister@Sun.COM 	 */
1494*10696SDavid.Hollister@Sun.COM 	while (phyp->level > 0) {
1495*10696SDavid.Hollister@Sun.COM 		if (mdb_vread(&parent, sizeof (pmcs_phy_t),
1496*10696SDavid.Hollister@Sun.COM 		    (uintptr_t)phyp->parent) == -1) {
1497*10696SDavid.Hollister@Sun.COM 			mdb_warn("pmcs_next_sibling: Failed to read PHY at %p",
1498*10696SDavid.Hollister@Sun.COM 			    (void *)phyp->parent);
1499*10696SDavid.Hollister@Sun.COM 			return (NULL);
1500*10696SDavid.Hollister@Sun.COM 		}
1501*10696SDavid.Hollister@Sun.COM 
1502*10696SDavid.Hollister@Sun.COM 		if (parent.sibling != NULL) {
1503*10696SDavid.Hollister@Sun.COM 			break;
1504*10696SDavid.Hollister@Sun.COM 		}
1505*10696SDavid.Hollister@Sun.COM 
1506*10696SDavid.Hollister@Sun.COM 		phyp = phyp->parent;
1507*10696SDavid.Hollister@Sun.COM 	}
1508*10696SDavid.Hollister@Sun.COM 
1509*10696SDavid.Hollister@Sun.COM 	return (parent.sibling);
1510*10696SDavid.Hollister@Sun.COM }
1511*10696SDavid.Hollister@Sun.COM 
1512*10696SDavid.Hollister@Sun.COM static int
1513*10696SDavid.Hollister@Sun.COM phy_walk_i(mdb_walk_state_t *wsp)
1514*10696SDavid.Hollister@Sun.COM {
1515*10696SDavid.Hollister@Sun.COM 	if (wsp->walk_addr == NULL) {
1516*10696SDavid.Hollister@Sun.COM 		mdb_warn("Can not perform global walk\n");
1517*10696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
1518*10696SDavid.Hollister@Sun.COM 	}
1519*10696SDavid.Hollister@Sun.COM 
1520*10696SDavid.Hollister@Sun.COM 	/*
1521*10696SDavid.Hollister@Sun.COM 	 * Address provided belongs to HBA softstate.  Get the targets pointer
1522*10696SDavid.Hollister@Sun.COM 	 * to begin the walk.
1523*10696SDavid.Hollister@Sun.COM 	 */
1524*10696SDavid.Hollister@Sun.COM 	if (mdb_vread(&ss, sizeof (pmcs_hw_t), wsp->walk_addr) !=
1525*10696SDavid.Hollister@Sun.COM 	    sizeof (pmcs_hw_t)) {
1526*10696SDavid.Hollister@Sun.COM 		mdb_warn("Unable to read HBA softstate\n");
1527*10696SDavid.Hollister@Sun.COM 		return (WALK_ERR);
1528*10696SDavid.Hollister@Sun.COM 	}
1529*10696SDavid.Hollister@Sun.COM 
1530*10696SDavid.Hollister@Sun.COM 	wsp->walk_addr = (uintptr_t)(ss.root_phys);
1531*10696SDavid.Hollister@Sun.COM 	wsp->walk_data = mdb_alloc(sizeof (pmcs_phy_t), UM_SLEEP);
1532*10696SDavid.Hollister@Sun.COM 
1533*10696SDavid.Hollister@Sun.COM 	return (WALK_NEXT);
1534*10696SDavid.Hollister@Sun.COM }
1535*10696SDavid.Hollister@Sun.COM 
1536*10696SDavid.Hollister@Sun.COM static int
1537*10696SDavid.Hollister@Sun.COM phy_walk_s(mdb_walk_state_t *wsp)
1538*10696SDavid.Hollister@Sun.COM {
1539*10696SDavid.Hollister@Sun.COM 	pmcs_phy_t *phyp, *nphyp;
1540*10696SDavid.Hollister@Sun.COM 	int status;
1541*10696SDavid.Hollister@Sun.COM 
1542*10696SDavid.Hollister@Sun.COM 	if (mdb_vread(wsp->walk_data, sizeof (pmcs_phy_t),
1543*10696SDavid.Hollister@Sun.COM 	    wsp->walk_addr) == -1) {
1544*10696SDavid.Hollister@Sun.COM 		mdb_warn("phy_walk_s: Failed to read PHY at %p",
1545*10696SDavid.Hollister@Sun.COM 		    (void *)wsp->walk_addr);
1546*10696SDavid.Hollister@Sun.COM 		return (WALK_DONE);
1547*10696SDavid.Hollister@Sun.COM 	}
1548*10696SDavid.Hollister@Sun.COM 
1549*10696SDavid.Hollister@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
1550*10696SDavid.Hollister@Sun.COM 	    wsp->walk_cbdata);
1551*10696SDavid.Hollister@Sun.COM 
1552*10696SDavid.Hollister@Sun.COM 	phyp = (pmcs_phy_t *)wsp->walk_data;
1553*10696SDavid.Hollister@Sun.COM 	if (phyp->children) {
1554*10696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)(phyp->children);
1555*10696SDavid.Hollister@Sun.COM 	} else {
1556*10696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)(phyp->sibling);
1557*10696SDavid.Hollister@Sun.COM 	}
1558*10696SDavid.Hollister@Sun.COM 
1559*10696SDavid.Hollister@Sun.COM 	if (wsp->walk_addr == NULL) {
1560*10696SDavid.Hollister@Sun.COM 		/*
1561*10696SDavid.Hollister@Sun.COM 		 * We reached the end of this sibling list.  Trudge back up
1562*10696SDavid.Hollister@Sun.COM 		 * to the parent and find the next sibling after the expander
1563*10696SDavid.Hollister@Sun.COM 		 * we just finished traversing, if there is one.
1564*10696SDavid.Hollister@Sun.COM 		 */
1565*10696SDavid.Hollister@Sun.COM 		nphyp = pmcs_next_sibling(phyp);
1566*10696SDavid.Hollister@Sun.COM 
1567*10696SDavid.Hollister@Sun.COM 		if (nphyp == NULL) {
1568*10696SDavid.Hollister@Sun.COM 			return (WALK_DONE);
1569*10696SDavid.Hollister@Sun.COM 		}
1570*10696SDavid.Hollister@Sun.COM 
1571*10696SDavid.Hollister@Sun.COM 		wsp->walk_addr = (uintptr_t)nphyp;
1572*10696SDavid.Hollister@Sun.COM 	}
1573*10696SDavid.Hollister@Sun.COM 
1574*10696SDavid.Hollister@Sun.COM 	return (status);
1575*10696SDavid.Hollister@Sun.COM }
1576*10696SDavid.Hollister@Sun.COM 
1577*10696SDavid.Hollister@Sun.COM static void
1578*10696SDavid.Hollister@Sun.COM phy_walk_f(mdb_walk_state_t *wsp)
1579*10696SDavid.Hollister@Sun.COM {
1580*10696SDavid.Hollister@Sun.COM 	mdb_free(wsp->walk_data, sizeof (pmcs_phy_t));
1581*10696SDavid.Hollister@Sun.COM }
1582*10696SDavid.Hollister@Sun.COM 
1583*10696SDavid.Hollister@Sun.COM static int
1584*10696SDavid.Hollister@Sun.COM pmcs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1585*10696SDavid.Hollister@Sun.COM {
1586*10696SDavid.Hollister@Sun.COM 	struct	pmcs_hw		ss;
1587*10696SDavid.Hollister@Sun.COM 	uint_t			verbose = FALSE;
1588*10696SDavid.Hollister@Sun.COM 	uint_t			phy_info = FALSE;
1589*10696SDavid.Hollister@Sun.COM 	uint_t			hw_info = FALSE;
1590*10696SDavid.Hollister@Sun.COM 	uint_t			target_info = FALSE;
1591*10696SDavid.Hollister@Sun.COM 	uint_t			work_info = FALSE;
1592*10696SDavid.Hollister@Sun.COM 	uint_t			ic_info = FALSE;
1593*10696SDavid.Hollister@Sun.COM 	uint_t			iport_info = FALSE;
1594*10696SDavid.Hollister@Sun.COM 	uint_t			waitqs_info = FALSE;
1595*10696SDavid.Hollister@Sun.COM 	uint_t			tracelog = FALSE;
1596*10696SDavid.Hollister@Sun.COM 	uint_t			ibq = FALSE;
1597*10696SDavid.Hollister@Sun.COM 	uint_t			obq = FALSE;
1598*10696SDavid.Hollister@Sun.COM 	uint_t			tgt_phy_count = FALSE;
1599*10696SDavid.Hollister@Sun.COM 	int			rv = DCMD_OK;
1600*10696SDavid.Hollister@Sun.COM 	void			*pmcs_state;
1601*10696SDavid.Hollister@Sun.COM 	char			*state_str;
1602*10696SDavid.Hollister@Sun.COM 	struct dev_info		dip;
1603*10696SDavid.Hollister@Sun.COM 
1604*10696SDavid.Hollister@Sun.COM 	if (!(flags & DCMD_ADDRSPEC)) {
1605*10696SDavid.Hollister@Sun.COM 		pmcs_state = NULL;
1606*10696SDavid.Hollister@Sun.COM 		if (mdb_readvar(&pmcs_state, "pmcs_softc_state") == -1) {
1607*10696SDavid.Hollister@Sun.COM 			mdb_warn("can't read pmcs_softc_state");
1608*10696SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
1609*10696SDavid.Hollister@Sun.COM 		}
1610*10696SDavid.Hollister@Sun.COM 		if (mdb_pwalk_dcmd("genunix`softstate", "pmcs`pmcs", argc, argv,
1611*10696SDavid.Hollister@Sun.COM 		    (uintptr_t)pmcs_state) == -1) {
1612*10696SDavid.Hollister@Sun.COM 			mdb_warn("mdb_pwalk_dcmd failed");
1613*10696SDavid.Hollister@Sun.COM 			return (DCMD_ERR);
1614*10696SDavid.Hollister@Sun.COM 		}
1615*10696SDavid.Hollister@Sun.COM 		return (DCMD_OK);
1616*10696SDavid.Hollister@Sun.COM 	}
1617*10696SDavid.Hollister@Sun.COM 
1618*10696SDavid.Hollister@Sun.COM 	if (mdb_getopts(argc, argv,
1619*10696SDavid.Hollister@Sun.COM 	    'h', MDB_OPT_SETBITS, TRUE, &hw_info,
1620*10696SDavid.Hollister@Sun.COM 	    'i', MDB_OPT_SETBITS, TRUE, &ic_info,
1621*10696SDavid.Hollister@Sun.COM 	    'I', MDB_OPT_SETBITS, TRUE, &iport_info,
1622*10696SDavid.Hollister@Sun.COM 	    'l', MDB_OPT_SETBITS, TRUE, &tracelog,
1623*10696SDavid.Hollister@Sun.COM 	    'p', MDB_OPT_SETBITS, TRUE, &phy_info,
1624*10696SDavid.Hollister@Sun.COM 	    'q', MDB_OPT_SETBITS, TRUE, &ibq,
1625*10696SDavid.Hollister@Sun.COM 	    'Q', MDB_OPT_SETBITS, TRUE, &obq,
1626*10696SDavid.Hollister@Sun.COM 	    't', MDB_OPT_SETBITS, TRUE, &target_info,
1627*10696SDavid.Hollister@Sun.COM 	    'T', MDB_OPT_SETBITS, TRUE, &tgt_phy_count,
1628*10696SDavid.Hollister@Sun.COM 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
1629*10696SDavid.Hollister@Sun.COM 	    'w', MDB_OPT_SETBITS, TRUE, &work_info,
1630*10696SDavid.Hollister@Sun.COM 	    'W', MDB_OPT_SETBITS, TRUE, &waitqs_info,
1631*10696SDavid.Hollister@Sun.COM 	    NULL) != argc)
1632*10696SDavid.Hollister@Sun.COM 		return (DCMD_USAGE);
1633*10696SDavid.Hollister@Sun.COM 
1634*10696SDavid.Hollister@Sun.COM 	if (MDB_RD(&ss, sizeof (ss), addr) == -1) {
1635*10696SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
1636*10696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
1637*10696SDavid.Hollister@Sun.COM 	}
1638*10696SDavid.Hollister@Sun.COM 
1639*10696SDavid.Hollister@Sun.COM 	if (MDB_RD(&dip, sizeof (struct dev_info), ss.dip) == -1) {
1640*10696SDavid.Hollister@Sun.COM 		NOREAD(pmcs_hw_t, addr);
1641*10696SDavid.Hollister@Sun.COM 		return (DCMD_ERR);
1642*10696SDavid.Hollister@Sun.COM 	}
1643*10696SDavid.Hollister@Sun.COM 
1644*10696SDavid.Hollister@Sun.COM 	/*
1645*10696SDavid.Hollister@Sun.COM 	 * Dumping the trace log is special.  It's global, not per-HBA.
1646*10696SDavid.Hollister@Sun.COM 	 * Thus, a provided address is ignored.  In addition, other options
1647*10696SDavid.Hollister@Sun.COM 	 * cannot be specified at the same time.
1648*10696SDavid.Hollister@Sun.COM 	 */
1649*10696SDavid.Hollister@Sun.COM 
1650*10696SDavid.Hollister@Sun.COM 	if (tracelog) {
1651*10696SDavid.Hollister@Sun.COM 		if (hw_info || ic_info || iport_info || phy_info || work_info ||
1652*10696SDavid.Hollister@Sun.COM 		    target_info || waitqs_info || ibq || obq || tgt_phy_count) {
1653*10696SDavid.Hollister@Sun.COM 			return (DCMD_USAGE);
1654*10696SDavid.Hollister@Sun.COM 		}
1655*10696SDavid.Hollister@Sun.COM 
1656*10696SDavid.Hollister@Sun.COM 		if ((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) {
1657*10696SDavid.Hollister@Sun.COM 			return (pmcs_dump_tracelog(B_TRUE, dip.devi_instance));
1658*10696SDavid.Hollister@Sun.COM 		} else if (flags & DCMD_LOOPFIRST) {
1659*10696SDavid.Hollister@Sun.COM 			return (pmcs_dump_tracelog(B_FALSE, 0));
1660*10696SDavid.Hollister@Sun.COM 		} else {
1661*10696SDavid.Hollister@Sun.COM 			return (DCMD_OK);
1662*10696SDavid.Hollister@Sun.COM 		}
1663*10696SDavid.Hollister@Sun.COM 	}
1664*10696SDavid.Hollister@Sun.COM 
1665*10696SDavid.Hollister@Sun.COM 	/* processing completed */
1666*10696SDavid.Hollister@Sun.COM 
1667*10696SDavid.Hollister@Sun.COM 	if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) ||
1668*10696SDavid.Hollister@Sun.COM 	    (flags & DCMD_LOOPFIRST) || phy_info || target_info || hw_info ||
1669*10696SDavid.Hollister@Sun.COM 	    work_info || waitqs_info || ibq || obq || tgt_phy_count) {
1670*10696SDavid.Hollister@Sun.COM 		if ((flags & DCMD_LOOP) && !(flags & DCMD_LOOPFIRST))
1671*10696SDavid.Hollister@Sun.COM 			mdb_printf("\n");
1672*10696SDavid.Hollister@Sun.COM 		mdb_printf("%16s %9s %4s B C  WorkFlags wserno DbgMsk %16s\n",
1673*10696SDavid.Hollister@Sun.COM 		    "Address", "State", "Inst", "DIP");
1674*10696SDavid.Hollister@Sun.COM 		mdb_printf("================================="
1675*10696SDavid.Hollister@Sun.COM 		    "============================================\n");
1676*10696SDavid.Hollister@Sun.COM 	}
1677*10696SDavid.Hollister@Sun.COM 
1678*10696SDavid.Hollister@Sun.COM 	switch (ss.state) {
1679*10696SDavid.Hollister@Sun.COM 	case STATE_NIL:
1680*10696SDavid.Hollister@Sun.COM 		state_str = "Invalid";
1681*10696SDavid.Hollister@Sun.COM 		break;
1682*10696SDavid.Hollister@Sun.COM 	case STATE_PROBING:
1683*10696SDavid.Hollister@Sun.COM 		state_str = "Probing";
1684*10696SDavid.Hollister@Sun.COM 		break;
1685*10696SDavid.Hollister@Sun.COM 	case STATE_RUNNING:
1686*10696SDavid.Hollister@Sun.COM 		state_str = "Running";
1687*10696SDavid.Hollister@Sun.COM 		break;
1688*10696SDavid.Hollister@Sun.COM 	case STATE_UNPROBING:
1689*10696SDavid.Hollister@Sun.COM 		state_str = "Unprobing";
1690*10696SDavid.Hollister@Sun.COM 		break;
1691*10696SDavid.Hollister@Sun.COM 	case STATE_DEAD:
1692*10696SDavid.Hollister@Sun.COM 		state_str = "Dead";
1693*10696SDavid.Hollister@Sun.COM 		break;
1694*10696SDavid.Hollister@Sun.COM 	}
1695*10696SDavid.Hollister@Sun.COM 
1696*10696SDavid.Hollister@Sun.COM 	mdb_printf("%16p %9s %4d %1d %1d 0x%08x 0x%04x 0x%04x %16p\n", addr,
1697*10696SDavid.Hollister@Sun.COM 	    state_str, dip.devi_instance, ss.blocked, ss.configuring,
1698*10696SDavid.Hollister@Sun.COM 	    ss.work_flags, ss.wserno, ss.debug_mask, ss.dip);
1699*10696SDavid.Hollister@Sun.COM 	mdb_printf("\n");
1700*10696SDavid.Hollister@Sun.COM 
1701*10696SDavid.Hollister@Sun.COM 	mdb_inc_indent(4);
1702*10696SDavid.Hollister@Sun.COM 
1703*10696SDavid.Hollister@Sun.COM 	if (waitqs_info)
1704*10696SDavid.Hollister@Sun.COM 		display_waitqs(ss, verbose);
1705*10696SDavid.Hollister@Sun.COM 
1706*10696SDavid.Hollister@Sun.COM 	if (hw_info)
1707*10696SDavid.Hollister@Sun.COM 		display_hwinfo(ss, verbose);
1708*10696SDavid.Hollister@Sun.COM 
1709*10696SDavid.Hollister@Sun.COM 	if (phy_info || tgt_phy_count)
1710*10696SDavid.Hollister@Sun.COM 		display_phys(ss, verbose, NULL, 0, tgt_phy_count);
1711*10696SDavid.Hollister@Sun.COM 
1712*10696SDavid.Hollister@Sun.COM 	if (target_info || tgt_phy_count)
1713*10696SDavid.Hollister@Sun.COM 		display_targets(ss, verbose, tgt_phy_count);
1714*10696SDavid.Hollister@Sun.COM 
1715*10696SDavid.Hollister@Sun.COM 	if (work_info)
1716*10696SDavid.Hollister@Sun.COM 		display_work(ss, verbose);
1717*10696SDavid.Hollister@Sun.COM 
1718*10696SDavid.Hollister@Sun.COM 	if (ic_info)
1719*10696SDavid.Hollister@Sun.COM 		display_ic(ss, verbose);
1720*10696SDavid.Hollister@Sun.COM 
1721*10696SDavid.Hollister@Sun.COM 	if (ibq)
1722*10696SDavid.Hollister@Sun.COM 		display_inbound_queues(ss, verbose);
1723*10696SDavid.Hollister@Sun.COM 
1724*10696SDavid.Hollister@Sun.COM 	if (obq)
1725*10696SDavid.Hollister@Sun.COM 		display_outbound_queues(ss, verbose);
1726*10696SDavid.Hollister@Sun.COM 
1727*10696SDavid.Hollister@Sun.COM 	if (iport_info)
1728*10696SDavid.Hollister@Sun.COM 		display_iport(ss, addr, verbose);
1729*10696SDavid.Hollister@Sun.COM 
1730*10696SDavid.Hollister@Sun.COM 	mdb_dec_indent(4);
1731*10696SDavid.Hollister@Sun.COM 
1732*10696SDavid.Hollister@Sun.COM 	return (rv);
1733*10696SDavid.Hollister@Sun.COM }
1734*10696SDavid.Hollister@Sun.COM 
1735*10696SDavid.Hollister@Sun.COM void
1736*10696SDavid.Hollister@Sun.COM pmcs_help()
1737*10696SDavid.Hollister@Sun.COM {
1738*10696SDavid.Hollister@Sun.COM 	mdb_printf("Prints summary information about each pmcs instance.\n"
1739*10696SDavid.Hollister@Sun.COM 	    "    -h: Print more detailed hardware information\n"
1740*10696SDavid.Hollister@Sun.COM 	    "    -i: Print interrupt coalescing information\n"
1741*10696SDavid.Hollister@Sun.COM 	    "    -I: Print information about each iport\n"
1742*10696SDavid.Hollister@Sun.COM 	    "    -l: Dump the trace log (cannot be used with other options)\n"
1743*10696SDavid.Hollister@Sun.COM 	    "    -p: Print information about each attached PHY\n"
1744*10696SDavid.Hollister@Sun.COM 	    "    -q: Dump inbound queues\n"
1745*10696SDavid.Hollister@Sun.COM 	    "    -Q: Dump outbound queues\n"
1746*10696SDavid.Hollister@Sun.COM 	    "    -t: Print information about each known target\n"
1747*10696SDavid.Hollister@Sun.COM 	    "    -T: Print target and PHY count summary\n"
1748*10696SDavid.Hollister@Sun.COM 	    "    -w: Dump work structures\n"
1749*10696SDavid.Hollister@Sun.COM 	    "    -W: List pmcs cmds waiting on various queues\n"
1750*10696SDavid.Hollister@Sun.COM 	    "    -v: Add verbosity to the above options\n");
1751*10696SDavid.Hollister@Sun.COM }
1752*10696SDavid.Hollister@Sun.COM 
1753*10696SDavid.Hollister@Sun.COM static const mdb_dcmd_t dcmds[] = {
1754*10696SDavid.Hollister@Sun.COM 	{ "pmcs", "?[-hiIpQqtTwWv] | -l", "print pmcs information",
1755*10696SDavid.Hollister@Sun.COM 	    pmcs_dcmd, pmcs_help
1756*10696SDavid.Hollister@Sun.COM 	},
1757*10696SDavid.Hollister@Sun.COM 	{ NULL }
1758*10696SDavid.Hollister@Sun.COM };
1759*10696SDavid.Hollister@Sun.COM 
1760*10696SDavid.Hollister@Sun.COM static const mdb_walker_t walkers[] = {
1761*10696SDavid.Hollister@Sun.COM 	{ "pmcs_targets", "walk target structures",
1762*10696SDavid.Hollister@Sun.COM 		targets_walk_i, targets_walk_s, targets_walk_f },
1763*10696SDavid.Hollister@Sun.COM 	{ "pmcs_phys", "walk PHY structures",
1764*10696SDavid.Hollister@Sun.COM 		phy_walk_i, phy_walk_s, phy_walk_f },
1765*10696SDavid.Hollister@Sun.COM 	{ NULL }
1766*10696SDavid.Hollister@Sun.COM };
1767*10696SDavid.Hollister@Sun.COM 
1768*10696SDavid.Hollister@Sun.COM static const mdb_modinfo_t modinfo = {
1769*10696SDavid.Hollister@Sun.COM 	MDB_API_VERSION, dcmds, walkers
1770*10696SDavid.Hollister@Sun.COM };
1771*10696SDavid.Hollister@Sun.COM 
1772*10696SDavid.Hollister@Sun.COM const mdb_modinfo_t *
1773*10696SDavid.Hollister@Sun.COM _mdb_init(void)
1774*10696SDavid.Hollister@Sun.COM {
1775*10696SDavid.Hollister@Sun.COM 	return (&modinfo);
1776*10696SDavid.Hollister@Sun.COM }
1777