1*2577Sramat /*
2*2577Sramat * CDDL HEADER START
3*2577Sramat *
4*2577Sramat * The contents of this file are subject to the terms of the
5*2577Sramat * Common Development and Distribution License (the "License").
6*2577Sramat * You may not use this file except in compliance with the License.
7*2577Sramat *
8*2577Sramat * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*2577Sramat * or http://www.opensolaris.org/os/licensing.
10*2577Sramat * See the License for the specific language governing permissions
11*2577Sramat * and limitations under the License.
12*2577Sramat *
13*2577Sramat * When distributing Covered Code, include this CDDL HEADER in each
14*2577Sramat * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*2577Sramat * If applicable, add the following below this CDDL HEADER, with the
16*2577Sramat * fields enclosed by brackets "[]" replaced with your own identifying
17*2577Sramat * information: Portions Copyright [yyyy] [name of copyright owner]
18*2577Sramat *
19*2577Sramat * CDDL HEADER END
20*2577Sramat */
21*2577Sramat /*
22*2577Sramat * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23*2577Sramat * Use is subject to license terms.
24*2577Sramat */
25*2577Sramat
26*2577Sramat #pragma ident "%Z%%M% %I% %E% SMI"
27*2577Sramat
28*2577Sramat #include <sys/kmem.h>
29*2577Sramat #include <sys/proc.h>
30*2577Sramat #include <sys/time.h>
31*2577Sramat #include <sys/conf.h>
32*2577Sramat #include <sys/file.h>
33*2577Sramat #include <sys/ddi.h>
34*2577Sramat #include <sys/ddi_impldefs.h>
35*2577Sramat #include <sys/modctl.h>
36*2577Sramat #include <sys/sunddi.h>
37*2577Sramat #include <sys/scsi/scsi.h>
38*2577Sramat #include <sys/scsi/impl/scsi_reset_notify.h>
39*2577Sramat #include <sys/sunmdi.h>
40*2577Sramat #include <sys/mdi_impldefs.h>
41*2577Sramat #include <sys/scsi/adapters/scsi_vhci.h>
42*2577Sramat #include <sys/scsi/scsi_types.h>
43*2577Sramat #include <sys/disp.h>
44*2577Sramat #include <sys/types.h>
45*2577Sramat #include <sys/mdb_modapi.h>
46*2577Sramat
47*2577Sramat #define FT(var, typ) (*((typ *)(&(var))))
48*2577Sramat
49*2577Sramat static int dump_states(uintptr_t array_vaddr, int verbose,
50*2577Sramat struct i_ddi_soft_state *sp);
51*2577Sramat static int i_vhci_states(uintptr_t addr, uint_t flags, int argc,
52*2577Sramat const mdb_arg_t *argv, struct i_ddi_soft_state *sp);
53*2577Sramat static int vhci_states(uintptr_t addr, uint_t flags, int argc,
54*2577Sramat const mdb_arg_t *argv);
55*2577Sramat
56*2577Sramat static int mdiclient(uintptr_t addr, uint_t flags, int argc,
57*2577Sramat const mdb_arg_t *argv);
58*2577Sramat static int vhciguid(uintptr_t addr, uint_t flags, int argc,
59*2577Sramat const mdb_arg_t *argv);
60*2577Sramat static int vhcilun(uintptr_t addr, uint_t flags, int argc,
61*2577Sramat const mdb_arg_t *argv);
62*2577Sramat static int i_vhcilun(uintptr_t addr, uint_t display_single_guid, char *guid);
63*2577Sramat
64*2577Sramat /* Utils */
65*2577Sramat static int get_mdbstr(uintptr_t addr, char *name);
66*2577Sramat static void dump_mutex(kmutex_t m, char *name);
67*2577Sramat static void dump_condvar(kcondvar_t c, char *name);
68*2577Sramat static void dump_string(uintptr_t addr, char *name);
69*2577Sramat static void dump_flags(unsigned long long flags, char **strings);
70*2577Sramat static void dump_state_str(char *name, uintptr_t addr, char **strings);
71*2577Sramat
72*2577Sramat static int mpxio_walk_cb(uintptr_t addr, const void *data, void *cbdata);
73*2577Sramat
74*2577Sramat static const mdb_dcmd_t dcmds[] = {
75*2577Sramat { "vhci_states", "[ -v ]", "dump all the vhci state pointers",
76*2577Sramat vhci_states },
77*2577Sramat { "vhciguid", NULL, "list all clients or given a guid, list one client",
78*2577Sramat vhciguid },
79*2577Sramat { NULL }
80*2577Sramat };
81*2577Sramat
82*2577Sramat static const mdb_modinfo_t modinfo = {
83*2577Sramat MDB_API_VERSION, dcmds, NULL
84*2577Sramat };
85*2577Sramat
86*2577Sramat static char *client_lb_str[] =
87*2577Sramat {
88*2577Sramat "NONE",
89*2577Sramat "RR",
90*2577Sramat "LBA",
91*2577Sramat NULL
92*2577Sramat };
93*2577Sramat
94*2577Sramat static char *mdi_client_states[] =
95*2577Sramat {
96*2577Sramat NULL,
97*2577Sramat "OPTIMAL",
98*2577Sramat "DEGRADED",
99*2577Sramat "FAILED",
100*2577Sramat NULL
101*2577Sramat };
102*2577Sramat
103*2577Sramat static char *client_flags[] =
104*2577Sramat {
105*2577Sramat "MDI_CLIENT_FLAGS_OFFLINE",
106*2577Sramat "MDI_CLIENT_FLAGS_SUSPEND",
107*2577Sramat "MDI_CLIENT_FLAGS_POWER_DOWN",
108*2577Sramat "MDI_CLIENT_FLAGS_DETACH",
109*2577Sramat "MDI_CLIENT_FLAGS_FAILOVER",
110*2577Sramat "MDI_CLIENT_FLAGS_REPORT_DEV",
111*2577Sramat "MDI_CLIENT_FLAGS_PATH_FREE_IN_PROGRESS",
112*2577Sramat "MDI_CLIENT_FLAGS_ASYNC_FREE",
113*2577Sramat "MDI_CLIENT_FLAGS_DEV_NOT_SUPPORTED",
114*2577Sramat NULL
115*2577Sramat };
116*2577Sramat
117*2577Sramat static char *vhci_conf_flags[] =
118*2577Sramat {
119*2577Sramat "VHCI_CONF_FLAGS_AUTO_FAILBACK",
120*2577Sramat NULL
121*2577Sramat };
122*2577Sramat
123*2577Sramat static char *svlun_flags[] =
124*2577Sramat {
125*2577Sramat "VLUN_TASK_D_ALIVE_FLG",
126*2577Sramat "VLUN_RESERVE_ACTIVE_FLG",
127*2577Sramat "VLUN_QUIESCED_FLG",
128*2577Sramat NULL
129*2577Sramat };
130*2577Sramat
131*2577Sramat static char mdipathinfo_cb_str[] = "::print struct mdi_pathinfo";
132*2577Sramat
133*2577Sramat const mdb_modinfo_t *
_mdb_init(void)134*2577Sramat _mdb_init(void)
135*2577Sramat {
136*2577Sramat return (&modinfo);
137*2577Sramat }
138*2577Sramat
139*2577Sramat /*
140*2577Sramat * mdiclient()
141*2577Sramat *
142*2577Sramat * Dump mdi_client_t info and list all paths.
143*2577Sramat */
144*2577Sramat /* ARGSUSED */
145*2577Sramat static int
mdiclient(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)146*2577Sramat mdiclient(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
147*2577Sramat {
148*2577Sramat struct mdi_client value;
149*2577Sramat
150*2577Sramat if (!(flags & DCMD_ADDRSPEC)) {
151*2577Sramat mdb_warn("mdiclient: requires an address");
152*2577Sramat return (DCMD_ERR);
153*2577Sramat }
154*2577Sramat
155*2577Sramat if (mdb_vread(&value, sizeof (struct mdi_client), addr)
156*2577Sramat != sizeof (struct mdi_client)) {
157*2577Sramat mdb_warn("mdiclient: Failed read on %l#r\n", addr);
158*2577Sramat return (DCMD_ERR);
159*2577Sramat }
160*2577Sramat mdb_printf("----------------- mdi_client @ %#lr ----------\n", addr);
161*2577Sramat dump_string((uintptr_t)value.ct_guid, "GUID (ct_guid)");
162*2577Sramat dump_string((uintptr_t)value.ct_drvname, "Driver Name (ct_drvname)");
163*2577Sramat dump_state_str("Load Balance (ct_lb)", value.ct_lb, client_lb_str);
164*2577Sramat mdb_printf("\n");
165*2577Sramat mdb_printf("ct_hnext: %26l#r::print struct mdi_client\n",
166*2577Sramat value.ct_hnext);
167*2577Sramat mdb_printf("ct_hprev: %26l#r::print struct mdi_client\n",
168*2577Sramat value.ct_hprev);
169*2577Sramat mdb_printf("ct_dip: %28l#r::print struct dev_info\n", value.ct_dip);
170*2577Sramat mdb_printf("ct_vhci: %27l#r::print struct mdi_vhci\n", value.ct_vhci);
171*2577Sramat mdb_printf("ct_cprivate: %23l#r\n", value.ct_cprivate);
172*2577Sramat mdb_printf("\nct_path_head: %22l#r::print struct mdi_pathinfo\n",
173*2577Sramat value.ct_path_head);
174*2577Sramat mdb_printf("ct_path_tail: %22l#r::print struct mdi_pathinfo\n",
175*2577Sramat value.ct_path_tail);
176*2577Sramat mdb_printf("ct_path_last: %22l#r::print struct mdi_pathfinfo\n",
177*2577Sramat value.ct_path_last);
178*2577Sramat mdb_printf("ct_path_count: %21d\n", value.ct_path_count);
179*2577Sramat mdb_printf("List of paths:\n");
180*2577Sramat mdb_pwalk("mdipi_client_list", (mdb_walk_cb_t)mpxio_walk_cb,
181*2577Sramat mdipathinfo_cb_str, (uintptr_t)value.ct_path_head);
182*2577Sramat
183*2577Sramat mdb_printf("\n");
184*2577Sramat dump_state_str("Client State (ct_state)", value.ct_state,
185*2577Sramat mdi_client_states);
186*2577Sramat dump_mutex(value.ct_mutex, "per-client mutex (ct_mutex):");
187*2577Sramat mdb_printf("ct_flags: %26d\n", value.ct_flags);
188*2577Sramat if (value.ct_flags) {
189*2577Sramat dump_flags((unsigned long long)value.ct_flags, client_flags);
190*2577Sramat }
191*2577Sramat mdb_printf("ct_unstable: %23d\n", value.ct_unstable);
192*2577Sramat dump_condvar(value.ct_unstable_cv, "ct_unstable_cv");
193*2577Sramat dump_condvar(value.ct_failover_cv, "ct_failover_cv");
194*2577Sramat
195*2577Sramat mdb_printf("\n");
196*2577Sramat mdb_printf("ct_failover_flags TEMP_VAR: %8d\n", value.ct_failover_flags)
197*2577Sramat ;
198*2577Sramat mdb_printf("ct_failover_status UNUSED: %9d\n", value.ct_failover_status)
199*2577Sramat ;
200*2577Sramat
201*2577Sramat return (DCMD_OK);
202*2577Sramat }
203*2577Sramat
204*2577Sramat /*
205*2577Sramat * vhcilun()
206*2577Sramat *
207*2577Sramat * Get client info given a guid.
208*2577Sramat */
209*2577Sramat /* ARGSUSED */
210*2577Sramat static int
vhcilun(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)211*2577Sramat vhcilun(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
212*2577Sramat {
213*2577Sramat if (!(flags & DCMD_ADDRSPEC)) {
214*2577Sramat mdb_warn("sv_lun: requires an address");
215*2577Sramat return (DCMD_ERR);
216*2577Sramat }
217*2577Sramat
218*2577Sramat return (i_vhcilun(addr, 0 /* display_single_guid */, 0));
219*2577Sramat }
220*2577Sramat
221*2577Sramat /*
222*2577Sramat * vhciguid()
223*2577Sramat *
224*2577Sramat * List all the clients.
225*2577Sramat */
226*2577Sramat /* ARGSUSED */
227*2577Sramat static int
vhciguid(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)228*2577Sramat vhciguid(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
229*2577Sramat {
230*2577Sramat
231*2577Sramat struct i_ddi_soft_state ss;
232*2577Sramat int i;
233*2577Sramat
234*2577Sramat mdi_vhci_t *mdi_vhci_value;
235*2577Sramat mdi_client_t *mdi_client_value;
236*2577Sramat struct client_hash *ct_hash_val;
237*2577Sramat struct client_hash *ct_hash_table_val;
238*2577Sramat
239*2577Sramat int len = strlen(MDI_HCI_CLASS_SCSI);
240*2577Sramat int mdi_vhci_len = sizeof (*mdi_vhci_value);
241*2577Sramat int mdi_client_len = sizeof (*mdi_client_value);
242*2577Sramat int ct_hash_len = sizeof (*ct_hash_val);
243*2577Sramat
244*2577Sramat int ct_hash_count = 0;
245*2577Sramat char *class;
246*2577Sramat int found = 0;
247*2577Sramat uintptr_t buf;
248*2577Sramat uintptr_t temp;
249*2577Sramat
250*2577Sramat
251*2577Sramat
252*2577Sramat if (flags & DCMD_ADDRSPEC)
253*2577Sramat mdb_warn("This command doesn't use an address\n");
254*2577Sramat
255*2577Sramat if (i_vhci_states(0, 0, 0, 0, &ss) != DCMD_OK)
256*2577Sramat return (DCMD_ERR);
257*2577Sramat
258*2577Sramat if (mdb_readvar(&buf, "mdi_vhci_head") == -1) {
259*2577Sramat mdb_warn("mdi driver variable mdi_vhci_head not found.\n");
260*2577Sramat mdb_warn("Is the driver loaded ?\n");
261*2577Sramat return (DCMD_ERR);
262*2577Sramat }
263*2577Sramat mdb_printf("----------------- mdi_vhci_head @ %#lr ----------\n", buf);
264*2577Sramat mdi_vhci_value = (mdi_vhci_t *)mdb_alloc(mdi_vhci_len, UM_SLEEP|UM_GC);
265*2577Sramat if (mdb_vread(mdi_vhci_value, mdi_vhci_len, buf) != mdi_vhci_len) {
266*2577Sramat mdb_warn("vhciguid: Failed read on %l#r\n", mdi_vhci_value);
267*2577Sramat mdb_free(mdi_vhci_value, mdi_vhci_len);
268*2577Sramat return (DCMD_ERR);
269*2577Sramat }
270*2577Sramat temp = (uintptr_t)mdi_vhci_value->vh_class;
271*2577Sramat class = (char *)mdb_alloc(len, UM_SLEEP|UM_GC);
272*2577Sramat if (mdb_vread(class, strlen(MDI_HCI_CLASS_SCSI), temp)
273*2577Sramat != strlen(MDI_HCI_CLASS_SCSI)) {
274*2577Sramat mdb_warn("vhciguid: Failed read of class %l#r\n",
275*2577Sramat mdi_vhci_value);
276*2577Sramat mdb_free(mdi_vhci_value, mdi_vhci_len);
277*2577Sramat mdb_free(class, len);
278*2577Sramat return (DCMD_ERR);
279*2577Sramat }
280*2577Sramat class[len] = 0;
281*2577Sramat mdb_printf("----------------- class @ %s----------\n", class);
282*2577Sramat while (class) {
283*2577Sramat if (strcmp(class, MDI_HCI_CLASS_SCSI) == 0) {
284*2577Sramat found = 1;
285*2577Sramat break;
286*2577Sramat }
287*2577Sramat if (mdi_vhci_value->vh_next == NULL) {
288*2577Sramat break;
289*2577Sramat }
290*2577Sramat temp = (uintptr_t)mdi_vhci_value->vh_next;
291*2577Sramat if (mdb_vread(mdi_vhci_value, mdi_vhci_len, temp)
292*2577Sramat != mdi_vhci_len) {
293*2577Sramat mdb_warn("vhciguid: Failed read on vh->next %l#r\n",
294*2577Sramat mdi_vhci_value);
295*2577Sramat break;
296*2577Sramat }
297*2577Sramat temp = (uintptr_t)mdi_vhci_value->vh_class;
298*2577Sramat if (mdb_vread(class, strlen(MDI_HCI_CLASS_SCSI), temp) !=
299*2577Sramat strlen(MDI_HCI_CLASS_SCSI)) {
300*2577Sramat mdb_warn("vhciguid: Failed read on vh->next %l#r\n",
301*2577Sramat mdi_vhci_value);
302*2577Sramat break;
303*2577Sramat }
304*2577Sramat class[len] = 0;
305*2577Sramat }
306*2577Sramat
307*2577Sramat if (found == 0) {
308*2577Sramat mdb_warn("vhciguid: No scsi_vhci class found");
309*2577Sramat mdb_free(mdi_vhci_value, mdi_vhci_len);
310*2577Sramat mdb_free(class, len);
311*2577Sramat return (DCMD_ERR);
312*2577Sramat }
313*2577Sramat mdb_printf("----- Number of devices found %d ----------\n",
314*2577Sramat mdi_vhci_value->vh_client_count);
315*2577Sramat for (i = 0; i < CLIENT_HASH_TABLE_SIZE; i++) {
316*2577Sramat ct_hash_table_val = &mdi_vhci_value->vh_client_table[i];
317*2577Sramat if (ct_hash_table_val == NULL)
318*2577Sramat continue;
319*2577Sramat
320*2577Sramat /* Read client_hash structure */
321*2577Sramat ct_hash_val = (struct client_hash *)mdb_alloc(ct_hash_len,
322*2577Sramat UM_SLEEP|UM_GC);
323*2577Sramat temp = (uintptr_t)ct_hash_table_val;
324*2577Sramat if (mdb_vread(ct_hash_val, ct_hash_len, temp) != ct_hash_len) {
325*2577Sramat mdb_warn("Failed read on hash %l#r\n",
326*2577Sramat ct_hash_val);
327*2577Sramat break;
328*2577Sramat }
329*2577Sramat mdb_printf("----hash[%d] %l#r: devices mapped = %d --\n",
330*2577Sramat i, ct_hash_table_val, ct_hash_val->ct_hash_count);
331*2577Sramat if (ct_hash_val->ct_hash_count == 0) {
332*2577Sramat continue;
333*2577Sramat }
334*2577Sramat
335*2577Sramat ct_hash_count = ct_hash_val->ct_hash_count;
336*2577Sramat
337*2577Sramat /* Read mdi_client structures */
338*2577Sramat mdi_client_value = (mdi_client_t *)mdb_alloc(mdi_client_len,
339*2577Sramat UM_SLEEP|UM_GC);
340*2577Sramat temp = (uintptr_t)ct_hash_val->ct_hash_head;
341*2577Sramat if (mdb_vread(mdi_client_value, mdi_client_len, temp)
342*2577Sramat != mdi_client_len) {
343*2577Sramat mdb_warn("Failed read on client %l#r\n",
344*2577Sramat mdi_client_value);
345*2577Sramat break;
346*2577Sramat }
347*2577Sramat mdb_printf("mdi_client %l#r %l#r ------\n",
348*2577Sramat mdi_client_value, mdi_client_value->ct_vprivate);
349*2577Sramat vhcilun((uintptr_t)mdi_client_value->ct_vprivate,
350*2577Sramat DCMD_ADDRSPEC, 0, 0);
351*2577Sramat
352*2577Sramat while (--ct_hash_count) {
353*2577Sramat temp = (uintptr_t)mdi_client_value->ct_hnext;
354*2577Sramat if (mdb_vread(mdi_client_value, mdi_client_len,
355*2577Sramat temp) != mdi_client_len) {
356*2577Sramat mdb_warn("Failed read on client %l#r\n",
357*2577Sramat mdi_client_value);
358*2577Sramat break;
359*2577Sramat }
360*2577Sramat vhcilun((uintptr_t)mdi_client_value->ct_vprivate,
361*2577Sramat DCMD_ADDRSPEC, 0, 0);
362*2577Sramat }
363*2577Sramat }
364*2577Sramat mdb_printf("----------done----------\n");
365*2577Sramat
366*2577Sramat return (DCMD_OK);
367*2577Sramat }
368*2577Sramat
369*2577Sramat /*
370*2577Sramat * Print the flag name by comparing flags to the mask variable.
371*2577Sramat */
372*2577Sramat static void
dump_flags(unsigned long long flags,char ** strings)373*2577Sramat dump_flags(unsigned long long flags, char **strings)
374*2577Sramat {
375*2577Sramat int i, linel = 8, first = 1;
376*2577Sramat unsigned long long mask = 1;
377*2577Sramat
378*2577Sramat for (i = 0; i < 64; i++) {
379*2577Sramat if (strings[i] == NULL)
380*2577Sramat break;
381*2577Sramat if (flags & mask) {
382*2577Sramat if (!first) {
383*2577Sramat mdb_printf(" | ");
384*2577Sramat } else {
385*2577Sramat first = 0;
386*2577Sramat }
387*2577Sramat /* make output pretty */
388*2577Sramat linel += strlen(strings[i]) + 3;
389*2577Sramat if (linel > 80) {
390*2577Sramat mdb_printf("\n\t");
391*2577Sramat linel = strlen(strings[i]) + 1 + 8;
392*2577Sramat }
393*2577Sramat mdb_printf("%s", strings[i]);
394*2577Sramat }
395*2577Sramat mask <<= 1;
396*2577Sramat }
397*2577Sramat mdb_printf("\n");
398*2577Sramat }
399*2577Sramat
400*2577Sramat /* ARGSUSED */
401*2577Sramat static int
vhci_states(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)402*2577Sramat vhci_states(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
403*2577Sramat {
404*2577Sramat return (i_vhci_states(addr, flags, argc, argv, NULL));
405*2577Sramat }
406*2577Sramat
407*2577Sramat /*
408*2577Sramat * dump_states()
409*2577Sramat *
410*2577Sramat * Print the state information for vhci_states().
411*2577Sramat */
412*2577Sramat static int
dump_states(uintptr_t array_vaddr,int verbose,struct i_ddi_soft_state * sp)413*2577Sramat dump_states(uintptr_t array_vaddr, int verbose, struct i_ddi_soft_state *sp)
414*2577Sramat {
415*2577Sramat int i;
416*2577Sramat int array_size;
417*2577Sramat struct i_ddi_soft_state *ss;
418*2577Sramat struct scsi_vhci vhci;
419*2577Sramat
420*2577Sramat if (sp == NULL) {
421*2577Sramat ss = (struct i_ddi_soft_state *)mdb_alloc(sizeof (*ss),
422*2577Sramat UM_SLEEP|UM_GC);
423*2577Sramat } else {
424*2577Sramat ss = sp;
425*2577Sramat }
426*2577Sramat if (mdb_vread(ss, sizeof (*ss), array_vaddr) != sizeof (*ss)) {
427*2577Sramat mdb_warn("Cannot read softstate struct (Invalid pointer?).\n");
428*2577Sramat return (DCMD_ERR);
429*2577Sramat }
430*2577Sramat array_size = ss->n_items * (sizeof (void *));
431*2577Sramat array_vaddr = (uintptr_t)ss->array;
432*2577Sramat ss->array = mdb_alloc(array_size, UM_SLEEP|UM_GC);
433*2577Sramat if (mdb_vread(ss->array, array_size, array_vaddr) != array_size) {
434*2577Sramat mdb_warn("Corrupted softstate struct.\n");
435*2577Sramat return (DCMD_ERR);
436*2577Sramat }
437*2577Sramat if (sp != NULL)
438*2577Sramat return (DCMD_OK);
439*2577Sramat if (verbose) {
440*2577Sramat /*
441*2577Sramat * ss->size is of type size_t which is 4 bytes and 8 bytes
442*2577Sramat * on 32-bit and 64-bit systems respectively.
443*2577Sramat */
444*2577Sramat #ifdef _LP64
445*2577Sramat mdb_printf("Softstate size is %lld(0x%llx) bytes.\n\n",
446*2577Sramat ss->size, ss->size);
447*2577Sramat #else
448*2577Sramat mdb_printf("Softstate size is %ld(0x%lx) bytes.\n\n",
449*2577Sramat ss->size, ss->size);
450*2577Sramat #endif
451*2577Sramat mdb_printf("state pointer\t\t\t\t\tinstance\n");
452*2577Sramat mdb_printf("=============\t\t\t\t\t========\n");
453*2577Sramat }
454*2577Sramat for (i = 0; i < ss->n_items; i++) {
455*2577Sramat if (ss->array[i] == 0)
456*2577Sramat continue;
457*2577Sramat
458*2577Sramat if (mdb_vread(&vhci, sizeof (vhci), (uintptr_t)ss->array[i])
459*2577Sramat != sizeof (vhci)) {
460*2577Sramat mdb_warn("Corrupted softstate struct.\n");
461*2577Sramat return (DCMD_ERR);
462*2577Sramat }
463*2577Sramat if (verbose) {
464*2577Sramat mdb_printf("%l#r::print struct scsi_vhci\t\t %d\n",
465*2577Sramat ss->array[i], i);
466*2577Sramat mdb_printf("\nvhci_conf_flags: %d\n",
467*2577Sramat vhci.vhci_conf_flags);
468*2577Sramat if (vhci.vhci_conf_flags) {
469*2577Sramat mdb_printf("\t");
470*2577Sramat dump_flags((unsigned long long)
471*2577Sramat vhci.vhci_conf_flags, vhci_conf_flags);
472*2577Sramat }
473*2577Sramat } else {
474*2577Sramat mdb_printf("%l#r\n", ss->array[i]);
475*2577Sramat }
476*2577Sramat }
477*2577Sramat return (DCMD_OK);
478*2577Sramat }
479*2577Sramat
480*2577Sramat static int
get_mdbstr(uintptr_t addr,char * string_val)481*2577Sramat get_mdbstr(uintptr_t addr, char *string_val)
482*2577Sramat {
483*2577Sramat if (mdb_readstr(string_val, MAXNAMELEN, addr) == -1) {
484*2577Sramat mdb_warn("Error Reading String from %l#r\n", addr);
485*2577Sramat return (1);
486*2577Sramat }
487*2577Sramat
488*2577Sramat return (0);
489*2577Sramat }
490*2577Sramat
491*2577Sramat static void
dump_state_str(char * name,uintptr_t addr,char ** strings)492*2577Sramat dump_state_str(char *name, uintptr_t addr, char **strings)
493*2577Sramat {
494*2577Sramat mdb_printf("%s: %s (%l#r)\n", name, strings[(unsigned long)addr], addr);
495*2577Sramat }
496*2577Sramat
497*2577Sramat /* VHCI UTILS */
498*2577Sramat
499*2577Sramat /*
500*2577Sramat * i_vhci_states()
501*2577Sramat *
502*2577Sramat * Internal routine for vhci_states() to check for -v arg and then
503*2577Sramat * print state info.
504*2577Sramat */
505*2577Sramat /* ARGSUSED */
506*2577Sramat static int
i_vhci_states(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv,struct i_ddi_soft_state * sp)507*2577Sramat i_vhci_states(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv,
508*2577Sramat struct i_ddi_soft_state *sp)
509*2577Sramat {
510*2577Sramat uintptr_t adr;
511*2577Sramat int verbose = 0;
512*2577Sramat
513*2577Sramat if (mdb_readvar(&adr, "vhci_softstate") == -1) {
514*2577Sramat mdb_warn("vhci driver variable vhci_softstate not found.\n");
515*2577Sramat mdb_warn("Is the driver loaded ?\n");
516*2577Sramat return (DCMD_ERR);
517*2577Sramat }
518*2577Sramat if (sp == NULL) {
519*2577Sramat if (mdb_getopts(argc, argv,
520*2577Sramat 'v', MDB_OPT_SETBITS, TRUE, &verbose) != argc) {
521*2577Sramat return (DCMD_USAGE);
522*2577Sramat }
523*2577Sramat }
524*2577Sramat
525*2577Sramat return (dump_states(adr, verbose, sp));
526*2577Sramat }
527*2577Sramat
528*2577Sramat /*
529*2577Sramat * i_vhcilun()
530*2577Sramat *
531*2577Sramat * Internal routine for vhciguid() to print client info.
532*2577Sramat */
533*2577Sramat static int
i_vhcilun(uintptr_t addr,uint_t display_single_guid,char * guid)534*2577Sramat i_vhcilun(uintptr_t addr, uint_t display_single_guid, char *guid)
535*2577Sramat {
536*2577Sramat
537*2577Sramat scsi_vhci_lun_t value;
538*2577Sramat struct dev_info dev_info_value;
539*2577Sramat char string_val[MAXNAMELEN];
540*2577Sramat int found = 0;
541*2577Sramat struct mdi_client ct_value;
542*2577Sramat uintptr_t temp_addr;
543*2577Sramat
544*2577Sramat do {
545*2577Sramat if (mdb_vread(&value, sizeof (scsi_vhci_lun_t), addr) !=
546*2577Sramat sizeof (scsi_vhci_lun_t)) {
547*2577Sramat mdb_warn("sv_lun: Failed read on %l#r", addr);
548*2577Sramat return (DCMD_ERR);
549*2577Sramat }
550*2577Sramat
551*2577Sramat temp_addr = addr;
552*2577Sramat addr = (uintptr_t)value.svl_hash_next;
553*2577Sramat
554*2577Sramat if (!get_mdbstr((uintptr_t)value.svl_lun_wwn, string_val)) {
555*2577Sramat if (display_single_guid) {
556*2577Sramat if (strcmp(string_val, guid) == 0) {
557*2577Sramat found = 1;
558*2577Sramat } else continue;
559*2577Sramat }
560*2577Sramat }
561*2577Sramat
562*2577Sramat mdb_printf("%t%l#r::print struct scsi_vhci_lun", temp_addr);
563*2577Sramat
564*2577Sramat if (mdb_vread(&dev_info_value, sizeof (struct dev_info),
565*2577Sramat (uintptr_t)value.svl_dip) != sizeof (struct dev_info)) {
566*2577Sramat mdb_warn("svl_dip: Failed read on %l#r",
567*2577Sramat value.svl_dip);
568*2577Sramat return (DCMD_ERR);
569*2577Sramat }
570*2577Sramat
571*2577Sramat mdb_printf("\n%tGUID: %s\n", string_val);
572*2577Sramat if (value.svl_active_pclass != NULL) {
573*2577Sramat if (!get_mdbstr((uintptr_t)value.svl_active_pclass,
574*2577Sramat string_val)) {
575*2577Sramat mdb_printf("%tActv_cl: %s", string_val);
576*2577Sramat }
577*2577Sramat } else {
578*2577Sramat mdb_printf(" No active pclass");
579*2577Sramat }
580*2577Sramat if (display_single_guid) {
581*2577Sramat mdb_printf(" (%l#r)", value.svl_active_pclass);
582*2577Sramat }
583*2577Sramat
584*2577Sramat mdb_printf("\n%t%l#r::print struct mdi_client",
585*2577Sramat dev_info_value.devi_mdi_client);
586*2577Sramat
587*2577Sramat if (value.svl_flags) {
588*2577Sramat mdb_printf("\t");
589*2577Sramat dump_flags((unsigned long long)value.svl_flags,
590*2577Sramat svlun_flags);
591*2577Sramat } else {
592*2577Sramat mdb_printf("\n");
593*2577Sramat }
594*2577Sramat
595*2577Sramat if (found) {
596*2577Sramat mdiclient((uintptr_t)dev_info_value.devi_mdi_client,
597*2577Sramat DCMD_ADDRSPEC, 0, 0);
598*2577Sramat } else {
599*2577Sramat if (mdb_vread(&ct_value, sizeof (struct mdi_client),
600*2577Sramat (uintptr_t)dev_info_value.devi_mdi_client) !=
601*2577Sramat sizeof (struct mdi_client)) {
602*2577Sramat mdb_warn("mdiclient: Failed read on %l#r",
603*2577Sramat dev_info_value.devi_mdi_client);
604*2577Sramat return (DCMD_ERR);
605*2577Sramat }
606*2577Sramat if (ct_value.ct_flags) {
607*2577Sramat mdb_printf("\t");
608*2577Sramat dump_flags((unsigned long long)
609*2577Sramat ct_value.ct_flags, client_flags);
610*2577Sramat }
611*2577Sramat mdb_printf("%t");
612*2577Sramat dump_state_str("LB", ct_value.ct_lb, client_lb_str);
613*2577Sramat mdb_printf("\n");
614*2577Sramat }
615*2577Sramat } while (addr && !found);
616*2577Sramat return (DCMD_OK);
617*2577Sramat }
618*2577Sramat
619*2577Sramat static void
dump_mutex(kmutex_t m,char * name)620*2577Sramat dump_mutex(kmutex_t m, char *name)
621*2577Sramat {
622*2577Sramat mdb_printf("%s is%s held\n", name, FT(m, uint64_t) == 0 ? " not" : "");
623*2577Sramat }
624*2577Sramat
625*2577Sramat static void
dump_condvar(kcondvar_t c,char * name)626*2577Sramat dump_condvar(kcondvar_t c, char *name)
627*2577Sramat {
628*2577Sramat mdb_printf("Threads sleeping on %s = %d\n", name, (int)FT(c, ushort_t));
629*2577Sramat }
630*2577Sramat
631*2577Sramat static void
dump_string(uintptr_t addr,char * name)632*2577Sramat dump_string(uintptr_t addr, char *name)
633*2577Sramat {
634*2577Sramat char string_val[MAXNAMELEN];
635*2577Sramat
636*2577Sramat if (get_mdbstr(addr, string_val)) {
637*2577Sramat return;
638*2577Sramat }
639*2577Sramat mdb_printf("%s: %s (%l#r)\n", name, string_val, addr);
640*2577Sramat }
641*2577Sramat
642*2577Sramat /* ARGSUSED */
643*2577Sramat static int
mpxio_walk_cb(uintptr_t addr,const void * data,void * cbdata)644*2577Sramat mpxio_walk_cb(uintptr_t addr, const void *data, void *cbdata)
645*2577Sramat {
646*2577Sramat mdb_printf("%t%l#r%s\n", addr, (char *)cbdata);
647*2577Sramat return (0);
648*2577Sramat }
649