1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#include <sys/types.h>
27#include <sys/mdb_modapi.h>
28
29#include <sys/nsctl/nsctl.h>
30#include <sys/unistat/spcs_s.h>
31#include <sys/unistat/spcs_s_k.h>
32
33#include <rpc/auth.h>
34#include <rpc/auth_unix.h>
35#include <rpc/auth_des.h>
36#include <rpc/svc.h>
37#include <rpc/xdr.h>
38#include <rpc/svc_soc.h>
39
40/* HACK HACK  so we can bring in rdc_io.h and friends */
41#define	nstset_t	char
42
43#include <sys/nsctl/rdc.h>
44#include <sys/nsctl/rdc_prot.h>
45#include <sys/nsctl/rdc_ioctl.h>
46#include <sys/nsctl/rdc_io.h>
47#include <sys/nsctl/rdc_bitmap.h>
48
49#include <sys/nsctl/nsvers.h>
50
51
52/*
53 * Walker for an array of rdc_k_info_t structures.
54 * A global walk is assumed to start at rdc_k_info.
55 */
56
57struct rdc_kinfo_winfo {
58	uintptr_t start;
59	uintptr_t end;
60};
61
62char bitstr[33] = { '0' };
63
64static int
65rdc_k_info_winit(mdb_walk_state_t *wsp)
66{
67	struct rdc_kinfo_winfo *winfo;
68	rdc_k_info_t *rdc_k_info;
69	int rdc_max_sets;
70
71	winfo = mdb_zalloc(sizeof (struct rdc_kinfo_winfo), UM_SLEEP);
72
73	if (mdb_readvar(&rdc_k_info, "rdc_k_info") == -1) {
74		mdb_warn("failed to read 'rdc_k_info'");
75		mdb_free(winfo,  sizeof (struct rdc_kinfo_winfo));
76		return (WALK_ERR);
77	}
78
79	if (mdb_readvar(&rdc_max_sets, "rdc_max_sets") == -1) {
80		mdb_warn("failed to read 'rdc_max_sets'");
81		mdb_free(winfo, sizeof (struct rdc_kinfo_winfo));
82		return (WALK_ERR);
83	}
84
85	winfo->start = (uintptr_t)rdc_k_info;
86	winfo->end = (uintptr_t)(rdc_k_info + rdc_max_sets);
87
88	if (wsp->walk_addr == NULL)
89		wsp->walk_addr = winfo->start;
90
91	wsp->walk_data = winfo;
92	return (WALK_NEXT);
93}
94
95
96static int
97rdc_k_info_wstep(mdb_walk_state_t *wsp)
98{
99	struct rdc_kinfo_winfo *winfo = wsp->walk_data;
100	int status;
101
102	if (wsp->walk_addr == NULL)
103		return (WALK_DONE);
104
105	if (wsp->walk_addr >= winfo->end)
106		return (WALK_DONE);
107
108	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
109	    wsp->walk_cbdata);
110
111	wsp->walk_addr += sizeof (rdc_k_info_t);
112	return (status);
113}
114
115
116static void
117rdc_k_info_wfini(mdb_walk_state_t *wsp)
118{
119	mdb_free(wsp->walk_data, sizeof (struct rdc_kinfo_winfo));
120}
121
122/*
123 * Walker for an array of rdc_u_info_t structures.
124 * A global walk is assumed to start at rdc_u_info.
125 */
126
127struct rdc_uinfo_winfo {
128	uintptr_t start;
129	uintptr_t end;
130};
131
132
133static int
134rdc_u_info_winit(mdb_walk_state_t *wsp)
135{
136	struct rdc_uinfo_winfo *winfo;
137	rdc_u_info_t *rdc_u_info;
138	int rdc_max_sets;
139
140	winfo = mdb_zalloc(sizeof (struct rdc_uinfo_winfo), UM_SLEEP);
141
142	if (mdb_readvar(&rdc_u_info, "rdc_u_info") == -1) {
143		mdb_warn("failed to read 'rdc_u_info'");
144		mdb_free(winfo,  sizeof (struct rdc_uinfo_winfo));
145		return (WALK_ERR);
146	}
147
148	if (mdb_readvar(&rdc_max_sets, "rdc_max_sets") == -1) {
149		mdb_warn("failed to read 'rdc_max_sets'");
150		mdb_free(winfo, sizeof (struct rdc_uinfo_winfo));
151		return (WALK_ERR);
152	}
153
154	winfo->start = (uintptr_t)rdc_u_info;
155	winfo->end = (uintptr_t)(rdc_u_info + rdc_max_sets);
156
157	if (wsp->walk_addr == NULL)
158		wsp->walk_addr = winfo->start;
159
160	wsp->walk_data = winfo;
161	return (WALK_NEXT);
162}
163
164
165static int
166rdc_u_info_wstep(mdb_walk_state_t *wsp)
167{
168	struct rdc_uinfo_winfo *winfo = wsp->walk_data;
169	int status;
170
171	if (wsp->walk_addr == NULL)
172		return (WALK_DONE);
173
174	if (wsp->walk_addr >= winfo->end)
175		return (WALK_DONE);
176
177	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
178	    wsp->walk_cbdata);
179
180	wsp->walk_addr += sizeof (rdc_u_info_t);
181	return (status);
182}
183
184
185static void
186rdc_u_info_wfini(mdb_walk_state_t *wsp)
187{
188	mdb_free(wsp->walk_data, sizeof (struct rdc_uinfo_winfo));
189}
190
191/*
192 * Walker for the rdc_if chain.
193 * A global walk is assumed to start at rdc_if_top.
194 */
195
196static int
197rdc_if_winit(mdb_walk_state_t *wsp)
198{
199	if (wsp->walk_addr == NULL &&
200	    mdb_readvar(&wsp->walk_addr, "rdc_if_top") == -1) {
201		mdb_warn("unable to read 'rdc_if_top'");
202		return (WALK_ERR);
203	}
204
205	wsp->walk_data = mdb_zalloc(sizeof (rdc_if_t), UM_SLEEP);
206
207	return (WALK_NEXT);
208}
209
210
211static int
212rdc_if_wstep(mdb_walk_state_t *wsp)
213{
214	int status;
215
216	if (wsp->walk_addr == NULL)
217		return (WALK_DONE);
218
219	if (mdb_vread(wsp->walk_data,
220	    sizeof (rdc_if_t), wsp->walk_addr) == -1) {
221		mdb_warn("failed to read rdc_if at %p", wsp->walk_addr);
222		return (WALK_DONE);
223	}
224
225	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
226	    wsp->walk_cbdata);
227
228	wsp->walk_addr = (uintptr_t)(((rdc_if_t *)wsp->walk_data)->next);
229	return (status);
230}
231
232
233static void
234rdc_if_wfini(mdb_walk_state_t *wsp)
235{
236	mdb_free(wsp->walk_data, sizeof (rdc_if_t));
237}
238
239/*
240 * Displays the asynchronous sleep q on the server.
241 */
242/*ARGSUSED*/
243static int
244rdc_sleepq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
245{
246	rdc_sleepq_t sq;
247
248	if (!(flags & DCMD_ADDRSPEC))
249		return (DCMD_USAGE);
250	while (addr) {
251		if (mdb_vread(&sq, sizeof (sq), addr) != sizeof (sq)) {
252			mdb_warn("failed to read rdc_sleepq at %p", addr);
253			return (DCMD_ERR);
254		}
255		mdb_printf("sequence number %u  qpos %d \n", sq.seq, sq.qpos);
256		addr = (uintptr_t)sq.next;
257	}
258	return (DCMD_OK);
259}
260
261/*
262 * display the header info for the pending diskq requests
263 */
264/*ARGSUSED*/
265static int
266rdc_iohdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
267{
268	io_hdr hdr;
269
270	if (!(flags & DCMD_ADDRSPEC))
271		return (DCMD_USAGE);
272
273	while (addr) {
274		if (mdb_vread(&hdr, sizeof (io_hdr), addr) != sizeof (io_hdr)) {
275			mdb_warn("failed to read io_hdr at %p", addr);
276			return (DCMD_ERR);
277		}
278		mdb_printf("iohdr: type %d pos %d qpos %d len %d flag 0x%x"
279		" iostatus %x setid %d next %p\n", hdr.dat.type, hdr.dat.pos,
280		hdr.dat.qpos, hdr.dat.len, hdr.dat.flag, hdr.dat.iostatus,
281		hdr.dat.setid, hdr.dat.next);
282
283		addr = (uintptr_t)hdr.dat.next;
284	}
285	return (DCMD_OK);
286}
287
288/*
289 * Display a krdc->group.
290 * Requires an address.
291 */
292/*ARGSUSED*/
293static int
294rdc_group(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
295{
296	struct rdc_group *group;
297	disk_queue	*dq;
298
299	if (!(flags & DCMD_ADDRSPEC))
300		return (DCMD_USAGE);
301
302
303	group = mdb_zalloc(sizeof (*group), UM_GC);
304
305	if (mdb_vread(group, sizeof (*group), addr) != sizeof (*group)) {
306		mdb_warn("failed to read rdc_group at %p", addr);
307		return (DCMD_ERR);
308	}
309#ifdef XXXJET
310	if (DCMD_HDRSPEC(flags)) {
311		mdb_printf("%-?s  %8T%-8s  %8T%s\n", "ADDR", "MAJOR", "INUSE");
312	}
313#endif
314	mdb_printf("count: %d  %8Twriter: %d  %8T flags: %d\n",
315	    group->count, group->rdc_writer, group->flags);
316	mdb_printf("thread num %d\n", group->rdc_thrnum);
317
318	dq = &group->diskq;
319	if (RDC_IS_MEMQ(group)) {
320		mdb_printf("queue type: Memory based\n");
321	} else if (RDC_IS_DISKQ(group)) {
322		mdb_printf("queue type: Disk based  %8Tqstate 0x%x\n",
323		    QSTATE(dq));
324	}
325	mdb_printf("ra_queue head: 0x%p  %8Ttail 0x%p\n",
326	    group->ra_queue.net_qhead, group->ra_queue.net_qtail);
327	mdb_printf("ra_queue blocks: %d  %8Titems %d\n",
328	    group->ra_queue.blocks, group->ra_queue.nitems);
329	mdb_printf("ra_queue blockhwm: %d itemhwm: %d\n",
330	    group->ra_queue.blocks_hwm, group->ra_queue.nitems_hwm);
331	mdb_printf("ra_queue hwmhit: %d qfillsleep: %d\n",
332	    group->ra_queue.hwmhit, group->ra_queue.qfill_sleeping);
333	mdb_printf("ra_queue throttle: %ld\n",
334	    group->ra_queue.throttle_delay);
335
336	if (RDC_IS_DISKQ(group)) {
337		mdb_printf("head: %d %8Tnxtio: %d  %8Ttail %d %8Tlastail: %d\n",
338		    QHEAD(dq), QNXTIO(dq), QTAIL(dq), LASTQTAIL(dq));
339		mdb_printf("coalbounds: %d %8Tqwrap: %d\n", QCOALBOUNDS(dq),
340		    QWRAP(dq));
341		mdb_printf("blocks: %d  %8Titems %d qfflags 0x%x \n",
342		    QBLOCKS(dq), QNITEMS(dq), group->ra_queue.qfflags);
343		mdb_printf("diskq throttle: %ld %8Tflags: %x\n",
344		    dq->throttle_delay, group->flags);
345		mdb_printf("disk queue nitems_hwm: %d %8Tblocks_hwm: %d\n",
346		    dq->nitems_hwm, dq->blocks_hwm);
347		mdb_printf("diskqfd:   0x%p %8Tdisqrsrv: %d lastio: 0x%p\n",
348		    group->diskqfd, group->diskqrsrv, dq->lastio);
349		mdb_printf("outstanding req %d iohdrs 0x%p iohdrs_last 0x%p\n",
350		    dq->hdrcnt, dq->iohdrs, dq->hdr_last);
351	}
352	mdb_printf("seq: %u\n", group->seq);
353	mdb_printf("seqack: %u\n", group->seqack);
354	mdb_printf("sleepq: 0x%p\n", group->sleepq);
355	mdb_printf("asyncstall %d\n", group->asyncstall);
356	mdb_printf("asyncdis %d\n", group->asyncdis);
357
358	mdb_inc_indent(4);
359	if (group->sleepq) {
360		rdc_sleepq((uintptr_t)group->sleepq, DCMD_ADDRSPEC,
361		    0, 0);
362	}
363	mdb_dec_indent(4);
364
365	return (DCMD_OK);
366}
367
368
369/*
370 * Display a krdc->lsrv.
371 * Requires an address.
372 */
373/*ARGSUSED*/
374static int
375rdc_srv(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
376{
377	rdc_srv_t *lsrv;
378	char name[MAX_RDC_HOST_SIZE];
379
380	if (!(flags & DCMD_ADDRSPEC))
381		return (DCMD_USAGE);
382
383
384	lsrv = mdb_zalloc(sizeof (*lsrv), UM_GC);
385
386	if (mdb_vread(lsrv, sizeof (*lsrv), addr) != sizeof (*lsrv)) {
387		mdb_warn("failed to read rdc_srv at %p", addr);
388		return (DCMD_ERR);
389	}
390
391	if (mdb_readstr(name, sizeof (name),
392		(uintptr_t)lsrv->ri_hostname) == -1) {
393		mdb_warn("failed to read ri_hostname name at %p", addr);
394		return (DCMD_ERR);
395	}
396
397	mdb_printf("host: %s  %16Tri_knconf 0x%p\n", name, lsrv->ri_knconf);
398
399	mdb_printf("ri_addr: 0x%p  %8Tsecdata 0x%p\n",
400	    addr + OFFSETOF(rdc_srv_t, ri_addr), lsrv->ri_secdata);
401
402	return (DCMD_OK);
403}
404
405/*
406 * Display a rdc_if_t.
407 * Requires an address.
408 */
409static int
410rdc_if(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
411{
412	rdc_if_t *ifp;
413
414	if (!(flags & DCMD_ADDRSPEC)) {
415		/*
416		 * paranoid mode on: qualify walker name with module name
417		 * using '`' syntax.
418		 */
419		if (mdb_walk_dcmd("rdc`rdc_if",
420			"rdc`rdc_if", argc, argv) == -1) {
421			mdb_warn("failed to walk 'rdc_if'");
422			return (DCMD_ERR);
423		}
424		return (DCMD_OK);
425	}
426
427	ifp = mdb_zalloc(sizeof (*ifp), UM_GC);
428
429	if (mdb_vread(ifp, sizeof (*ifp), addr) != sizeof (*ifp)) {
430		mdb_warn("failed to read rdc_srv at %p", addr);
431		return (DCMD_ERR);
432	}
433
434	mdb_printf("next: 0x%p  %8Tsrv 0x%p\n", ifp->next, ifp->srv);
435	mdb_printf("if_addr: 0x%p  %8Tr_ifaddr 0x%p\n",
436	    addr + OFFSETOF(rdc_if_t, ifaddr),
437	    addr + OFFSETOF(rdc_if_t, r_ifaddr));
438	mdb_printf("if_down: %d  %8Tprimary %d  %8Tsecondary  %d\n",
439		ifp->if_down, ifp->isprimary, ifp->issecondary);
440	mdb_printf("version %d  %8Tnoping  %d\n", ifp->rpc_version,
441		ifp->no_ping);
442	mdb_printf("\n");
443
444	return (DCMD_OK);
445}
446
447
448/*
449 * Display a rdc_buf_t
450 * Requires an address.
451 */
452/*ARGSUSED*/
453static int
454rdc_buf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
455{
456	rdc_buf_t *buf;
457
458	if (!(flags & DCMD_ADDRSPEC))
459		return (DCMD_USAGE);
460
461
462	buf = mdb_zalloc(sizeof (*buf), UM_GC);
463
464	if (mdb_vread(buf, sizeof (*buf), addr) != sizeof (*buf)) {
465		mdb_warn("failed to read rdc_buf at %p", addr);
466		return (DCMD_ERR);
467	}
468
469	mdb_printf("nsc_buf fd: 0x%p  %8Tvec 0x%p\n",
470	    buf->rdc_bufh.sb_fd, buf->rdc_bufh.sb_vec);
471
472	mdb_printf("nsc_buf pos: %d  %8Tlen %d\n",
473	    buf->rdc_bufh.sb_pos, buf->rdc_bufh.sb_len);
474
475	mdb_printf("nsc_buf flag: 0x%x  %8Terror %d\n",
476	    buf->rdc_bufh.sb_flag, buf->rdc_bufh.sb_error);
477
478	mdb_printf("anon_buf : 0x%p  %8Tfd 0x%p  %8Tbufp  0x%p\n",
479	    buf->rdc_anon, buf->rdc_fd, buf->rdc_bufp);
480
481	mdb_printf("vsize: %d  %8Tflags 0x%x\n",
482	    buf->rdc_vsize, buf->rdc_flags);
483
484	return (DCMD_OK);
485}
486
487/*ARGSUSED*/
488static int
489rdc_aio(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
490{
491	rdc_aio_t *aio;
492
493	if (!(flags & DCMD_ADDRSPEC))
494		return (DCMD_USAGE);
495
496	aio = mdb_zalloc(sizeof (*aio), UM_GC);
497
498	if (mdb_vread(aio, sizeof (*aio), addr) != sizeof (*aio)) {
499		mdb_warn("failed to read rdc_aio at %p", addr);
500		return (DCMD_ERR);
501	}
502	mdb_printf("rdc_aio next: %p %8T nsc_buf: %p %8T nsc_qbuf %p\n",
503	    aio->next, aio->handle, aio->qhandle);
504	mdb_printf("pos: %d len: %d qpos: %d flag: %x iostatus: %d index: %d"
505	    " seq: %d\n", aio->pos, aio->len, aio->qpos, aio->flag,
506	    aio->iostatus, aio->index, aio->seq);
507	return (DCMD_OK);
508}
509
510/*ARGSUSED*/
511static int
512rdc_dset(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
513{
514	rdc_net_dataset_t *dset;
515
516	if (!(flags & DCMD_ADDRSPEC))
517		return (DCMD_USAGE);
518
519	dset = mdb_zalloc(sizeof (*dset), UM_GC);
520
521	if (mdb_vread(dset, sizeof (*dset), addr) != sizeof (*dset)) {
522		mdb_warn("failed to read dset at %p", addr);
523		return (DCMD_ERR);
524	}
525	mdb_printf("dset id: %d %8T dset inuse: %d %8T dset delpend: %d\n",
526	    dset->id, dset->inuse, dset->delpend);
527	mdb_printf("dset items: %d %8T dset head %p %8T dset tail %p \n",
528	    dset->nitems, dset->head, dset->tail);
529	mdb_printf("dset pos %d %8T dset len %d\n", dset->pos, dset->fbalen);
530
531	return (DCMD_OK);
532}
533/*
534 * Display a single rdc_k_info structure.
535 * If called with no address, performs a global walk of all rdc_k_info.
536 * -a : all (i.e. display all devices, even if disabled
537 * -v : verbose
538 */
539
540const mdb_bitmask_t sv_flag_bits[] = {
541	{ "NSC_DEVICE", NSC_DEVICE, NSC_DEVICE },
542	{ "NSC_CACHE", NSC_CACHE, NSC_CACHE },
543	{ NULL, 0, 0 }
544};
545
546static int
547rdc_kinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
548{
549	rdc_k_info_t *krdc;
550	rdc_u_info_t *rdc_u_info, *urdc;
551	int a_opt, v_opt;
552	int dev_t_chars;
553
554	a_opt = v_opt = FALSE;
555	dev_t_chars = sizeof (dev_t) * 2;	/* # chars to display dev_t */
556
557	if (mdb_getopts(argc, argv,
558	    'a', MDB_OPT_SETBITS, TRUE, &a_opt,
559	    'v', MDB_OPT_SETBITS, TRUE, &v_opt) != argc)
560		return (DCMD_USAGE);
561
562	krdc = mdb_zalloc(sizeof (*krdc), UM_GC);
563	urdc = mdb_zalloc(sizeof (*urdc), UM_GC);
564
565	if (!(flags & DCMD_ADDRSPEC)) {
566		/*
567		 * paranoid mode on: qualify walker name with module name
568		 * using '`' syntax.
569		 */
570		if (mdb_walk_dcmd("rdc`rdc_kinfo",
571			"rdc`rdc_kinfo", argc, argv) == -1) {
572			mdb_warn("failed to walk 'rdc_kinfo'");
573			return (DCMD_ERR);
574		}
575		return (DCMD_OK);
576	}
577	if (DCMD_HDRSPEC(flags)) {
578		mdb_printf("%-?s  %8T%-*s  %8T%s\n", "ADDR",
579		    dev_t_chars, "TFLAG", "STATE");
580	}
581
582	if (mdb_vread(krdc, sizeof (*krdc), addr) != sizeof (*krdc)) {
583		mdb_warn("failed to read rdc_k_info at %p", addr);
584		return (DCMD_ERR);
585	}
586
587	if (mdb_readvar(&rdc_u_info, "rdc_u_info") == -1) {
588		mdb_warn("failed to read 'rdc_u_info'");
589		return (DCMD_ERR);
590	}
591
592	urdc = &rdc_u_info[krdc->index];
593
594	if (!a_opt && ((krdc->type_flag & RDC_CONFIGURED) == 0))
595		return (DCMD_OK);
596
597	mdb_printf("%?p  %8T%0*lx  %8T", addr, dev_t_chars, krdc->type_flag);
598
599
600	if (krdc->type_flag & RDC_DISABLEPEND)
601		mdb_printf(" disable pending");
602	if (krdc->type_flag &  RDC_ASYNCMODE)
603		mdb_printf(" async");
604	if (krdc->type_flag & RDC_RESUMEPEND)
605		mdb_printf(" resume pending");
606	if (krdc->type_flag & RDC_BUSYWAIT)
607		mdb_printf(" busywait");
608#ifdef RDC_SMALLIO
609	if (krdc->type_flag & RDC_SMALLIO)
610		mdb_printf(" smallio");
611#endif
612
613	mdb_printf("\n");
614
615	if (!v_opt)
616		return (DCMD_OK);
617
618	/*
619	 * verbose - print the rest of the structure as well.
620	 */
621
622	mdb_inc_indent(4);
623
624	mdb_printf("index: %d  %8Trindex: %d  %8Tbusyc: %d  %8Tmaxfbas:  %d\n",
625	    krdc->index, krdc->remote_index, krdc->busy_count, krdc->maxfbas);
626
627	mdb_printf("info_dev:  0x%p %8Tiodev: 0x%p  %8T %8T vers %d\n",
628	krdc->devices, krdc->iodev, krdc->rpc_version);
629
630	mdb_printf("iokstats:  0x%p\n", krdc->io_kstats);
631	mdb_printf("group:  0x%p %8Tgroup_next:  0x%p\n",
632		krdc->group, krdc->group_next);
633	mdb_printf("group lock: 0x%p aux_state: %d\n",
634	    &krdc->group->lock, krdc->aux_state);
635
636	mdb_inc_indent(4);
637	if (krdc->type_flag & RDC_ASYNCMODE) {
638		rdc_group((uintptr_t)krdc->group, DCMD_ADDRSPEC, 0, 0);
639	}
640	mdb_dec_indent(4);
641
642	mdb_printf("servinfo:  0x%p %8Tintf:  0x%p\nbitmap: 0x%p  %8T"
643	    "bitmap_ref:  0x%p\n",
644	    krdc->lsrv, krdc->intf, krdc->dcio_bitmap, krdc->bitmap_ref);
645
646	mdb_printf("bmap_size:  %d %8Tbmaprsrv: %d%8T bmap_write:  %d\n",
647	    krdc->bitmap_size, krdc->bmaprsrv, krdc->bitmap_write);
648
649	mdb_printf("bitmapfd:  0x%p %8Tremote_fd: 0x%p  %8T\n", krdc->bitmapfd,
650	    krdc->remote_fd);
651
652	mdb_printf("net_dataset:  0x%p %8Tdisk_status: %d  %8T\n",
653	    krdc->net_dataset, krdc->disk_status);
654
655	mdb_printf("many:  0x%p %8Tmulti: 0x%p  %8T\n", krdc->many_next,
656	    krdc->multi_next);
657
658	mdb_printf("rdc_uinfo: 0x%p\n\n", urdc);
659	mdb_dec_indent(4);
660	return (DCMD_OK);
661}
662
663
664static int
665rdc_uinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
666{
667	rdc_u_info_t *urdc;
668	rdc_k_info_t *rdc_k_info, *krdc, krdc1;
669	rdc_group_t grp;
670	disk_queue *dqp = NULL;
671	int a_opt, v_opt;
672	int dev_t_chars;
673	int rdcflags;
674
675	a_opt = v_opt = FALSE;
676	dev_t_chars = sizeof (dev_t) * 2;	/* # chars to display dev_t */
677
678	if (mdb_getopts(argc, argv,
679	    'a', MDB_OPT_SETBITS, TRUE, &a_opt,
680	    'v', MDB_OPT_SETBITS, TRUE, &v_opt) != argc)
681		return (DCMD_USAGE);
682
683	urdc = mdb_zalloc(sizeof (*urdc), UM_GC);
684	krdc = mdb_zalloc(sizeof (*krdc), UM_GC);
685
686	if (!(flags & DCMD_ADDRSPEC)) {
687		/*
688		 * paranoid mode on: qualify walker name with module name
689		 * using '`' syntax.
690		 */
691		if (mdb_walk_dcmd("rdc`rdc_uinfo",
692			"rdc`rdc_uinfo", argc, argv) == -1) {
693			mdb_warn("failed to walk 'rdc_uinfo'");
694			return (DCMD_ERR);
695		}
696		return (DCMD_OK);
697	}
698	if (DCMD_HDRSPEC(flags)) {
699		mdb_printf("%-?s  %8T%-*s  %8T%s\n", "ADDR",
700		    dev_t_chars, "FLAG", "STATE");
701	}
702
703	if (mdb_vread(urdc, sizeof (*urdc), addr) != sizeof (*urdc)) {
704		mdb_warn("failed to read rdc_u_info at %p", addr);
705		return (DCMD_ERR);
706	}
707
708	if (mdb_readvar(&rdc_k_info, "rdc_k_info") == -1) {
709		mdb_warn("failed to read 'rdc_k_info'");
710		return (DCMD_ERR);
711	}
712
713	krdc = &rdc_k_info[urdc->index];
714
715	if (!a_opt && ((urdc->flags & RDC_ENABLED) == 0))
716		return (DCMD_OK);
717
718
719	if (mdb_vread(&krdc1, sizeof (krdc1),
720	    (uintptr_t)krdc) != sizeof (krdc1)) {
721		mdb_warn("failed to read 'rdc_k_info1'");
722		return (DCMD_ERR);
723	}
724
725	if (krdc1.group) {
726		if (mdb_vread(&grp, sizeof (grp),
727		    (uintptr_t)krdc1.group) != sizeof (grp)) {
728			mdb_warn("failed to read group info ");
729			return (DCMD_ERR);
730		}
731		dqp = &grp.diskq;
732	}
733
734	rdcflags = (urdc->flags | urdc->sync_flags | urdc->bmap_flags);
735	mdb_printf("%?p  %8T%0*lx  %8T", addr, dev_t_chars, rdcflags);
736
737
738	if (rdcflags & RDC_PRIMARY)
739		mdb_printf(" primary");
740	if (rdcflags &  RDC_SLAVE)
741		mdb_printf(" slave");
742	if (rdcflags &  RDC_SYNCING)
743		mdb_printf(" syncing");
744	if (rdcflags &  RDC_SYNC_NEEDED)
745		mdb_printf(" sync_need");
746	if (rdcflags &  RDC_RSYNC_NEEDED)
747		mdb_printf(" rsync_need");
748	if (rdcflags & RDC_LOGGING)
749		mdb_printf(" logging");
750	if (rdcflags & RDC_QUEUING)
751		mdb_printf(" queuing");
752	if (rdcflags & RDC_DISKQ_FAILED)
753		mdb_printf(" diskq failed");
754	if (rdcflags & RDC_VOL_FAILED)
755		mdb_printf(" vol failed");
756	if (rdcflags & RDC_BMP_FAILED)
757		mdb_printf(" bmp failed");
758	if (rdcflags & RDC_ASYNC)
759		mdb_printf(" async");
760	if (rdcflags & RDC_CLR_AFTERSYNC)
761		mdb_printf(" clr_bitmap_aftersync");
762	if (dqp) {
763		if (IS_QSTATE(dqp, RDC_QNOBLOCK))
764			mdb_printf(" noblock");
765	}
766#ifdef RDC_SMALLIO
767	if (rdcflags & RDC_SMALLIO)
768		mdb_printf(" smallio");
769#endif
770
771	mdb_printf("\n");
772
773	if (!v_opt)
774		return (DCMD_OK);
775
776	/*
777	 * verbose - print the rest of the structure as well.
778	 */
779
780	mdb_inc_indent(4);
781	mdb_printf("\n");
782
783	mdb_printf("primary: %s  %8Tfile: %s  \nbitmap: %s  ",
784	    urdc->primary.intf, urdc->primary.file, urdc->primary.bitmap);
785	mdb_printf("netbuf: 0x%p\n", addr + OFFSETOF(rdc_set_t, primary));
786	mdb_printf("secondary: %s  %8Tfile: %s  \nbitmap: %s  ",
787	    urdc->secondary.intf, urdc->secondary.file, urdc->secondary.bitmap);
788	mdb_printf("netbuf: 0x%p\n", addr + OFFSETOF(rdc_set_t, secondary));
789
790	mdb_printf("sflags:  %d %8Tbflags: %d%8T mflags:  %d\n",
791		urdc->sync_flags, urdc->bmap_flags, urdc->mflags);
792	mdb_printf("index:  %d %8Tsync_pos: %d%8T vsize:  %d\n",
793		urdc->index, urdc->sync_pos, urdc->volume_size);
794	mdb_printf("setid:  %d %8Tbits set:  %d %8Tautosync: %d\n",
795		urdc->setid, urdc->bits_set, urdc->autosync);
796	mdb_printf("maxqfbas:  %d %8Tmaxqitems: %d\n",
797		urdc->maxqfbas, urdc->maxqitems);
798	mdb_printf("netconfig:  %p\n", urdc->netconfig);
799	mdb_printf("group:  %s %8TdirectIO: %s\n",
800		urdc->group_name, urdc->direct_file);
801	mdb_printf("diskqueue: %s ", urdc->disk_queue);
802	if (dqp) {
803		mdb_printf("diskqsize: %d\n", QSIZE(dqp));
804	} else {
805		mdb_printf("\n");
806	}
807	mdb_printf("rdc_k_info: 0x%p\n", krdc);
808	mdb_printf("\n");
809	mdb_dec_indent(4);
810
811	mdb_printf("\n");
812	return (DCMD_OK);
813}
814
815/*ARGSUSED*/
816static int
817rdc_infodev(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
818{
819	rdc_info_dev_t *infodev;
820	_rdc_info_dev_t *infp;
821
822	if (!(flags & DCMD_ADDRSPEC))
823		return (DCMD_USAGE);
824
825	infodev = mdb_zalloc(sizeof (*infodev), UM_GC);
826	infp = mdb_zalloc(sizeof (*infp), UM_GC);
827
828	if (mdb_vread(infodev, sizeof (*infodev), addr) != sizeof (*infodev)) {
829		mdb_warn("failed to read rdc_infodev at 0x%p\n", addr);
830		return (DCMD_ERR);
831	}
832
833	infp = &infodev->id_cache_dev;
834	mdb_inc_indent(4);
835
836	mdb_printf("id_next: 0x%p\n", infodev->id_next);
837	mdb_printf("id_cache_dev:\n");
838
839	mdb_inc_indent(4);
840	mdb_printf("bi_fd: 0x%p %8Tbi_iodev: 0x%p %8Tbi_krdc 0x%p\n",
841	    infp->bi_fd, infp->bi_iodev, infp->bi_krdc);
842	mdb_printf("bi_rsrv: %d %8Tbi_orsrv: %d %8Tbi_failed: %d %8T\n"
843	    "bi_ofailed: %d %8Tbi_flag: %d\n", infp->bi_rsrv, infp->bi_orsrv,
844	    infp->bi_failed, infp->bi_ofailed, infp->bi_flag);
845
846	infp = &infodev->id_raw_dev;
847
848	mdb_dec_indent(4);
849	mdb_printf("id_cache_dev:\n");
850	mdb_inc_indent(4);
851
852	mdb_printf("bi_fd: 0x%p %8Tbi_iodev: 0x%p %8Tbi_krdc 0x%p\n",
853	    infp->bi_fd, infp->bi_iodev, infp->bi_krdc);
854	mdb_printf("bi_rsrv: %d %8Tbi_orsrv: %d %8Tbi_failed: %d %8T\n"
855	    "bi_ofailed: %d %8Tbi_flag: %d\n", infp->bi_rsrv, infp->bi_orsrv,
856	    infp->bi_failed, infp->bi_ofailed, infp->bi_flag);
857
858	mdb_dec_indent(4);
859
860	mdb_printf("id_sets: %d %8Tid_release: %d %8Tid_flag %d",
861	    infodev->id_sets, infodev->id_release, infodev->id_flag);
862
863	if (infodev->id_flag & RDC_ID_CLOSING) {
864		mdb_printf("closing");
865	}
866	mdb_printf("\n");
867
868	mdb_dec_indent(4);
869	return (DCMD_OK);
870}
871
872/*
873 * Display general sv module information.
874 */
875
876#define	rdc_get_print(kvar, str, fmt, val)		\
877	if (mdb_readvar(&(val), #kvar) == -1) {		\
878		mdb_dec_indent(4);			\
879		mdb_warn("unable to read '" #kvar "'");	\
880		return (DCMD_ERR);			\
881	}						\
882	mdb_printf("%-20s" fmt "\n", str ":", val)
883
884/*ARGSUSED*/
885static int
886rdc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
887{
888	int maj, min, mic, baseline, i;
889
890	if (argc != 0)
891		return (DCMD_USAGE);
892
893	if (mdb_readvar(&maj, "sndr_major_rev") == -1) {
894		mdb_warn("unable to read 'sndr_major_rev'");
895		return (DCMD_ERR);
896	}
897
898	if (mdb_readvar(&min, "sndr_minor_rev") == -1) {
899		mdb_warn("unable to read 'sndr_minor_rev'");
900		return (DCMD_ERR);
901	}
902
903	if (mdb_readvar(&mic, "sndr_micro_rev") == -1) {
904		mdb_warn("unable to read 'sndr_micro_rev'");
905		return (DCMD_ERR);
906	}
907
908	if (mdb_readvar(&baseline, "sndr_baseline_rev") == -1) {
909		mdb_warn("unable to read 'sndr_baseline_rev'");
910		return (DCMD_ERR);
911	}
912
913	mdb_printf("Remote Mirror module version: kernel %d.%d.%d.%d; "
914		    "mdb %d.%d.%d.%d\n", maj, min, mic, baseline,
915	    ISS_VERSION_MAJ, ISS_VERSION_MIN, ISS_VERSION_MIC, ISS_VERSION_NUM);
916	mdb_inc_indent(4);
917
918	rdc_get_print(rdc_debug, "debug", "%d", i);
919	rdc_get_print(rdc_bitmap_mode, "bitmap mode", "%d", i);
920	rdc_get_print(rdc_max_sets, "max sndr devices", "%d", i);
921	rdc_get_print(rdc_rpc_tmout, "client RPC timeout", "%d", i);
922	rdc_get_print(rdc_health_thres, "health threshold", "%d", i);
923	rdc_get_print(MAX_RDC_FBAS, "max trans fba", "%d", i);
924
925	mdb_dec_indent(4);
926	return (DCMD_OK);
927}
928
929static int
930rdc_k2u(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
931{
932	rdc_k_info_t *krdc;
933	rdc_u_info_t *rdc_u_info, *urdc;
934	int rc;
935
936	if (!(flags & DCMD_ADDRSPEC))
937		return (DCMD_USAGE);
938
939	krdc = mdb_zalloc(sizeof (*krdc), UM_GC);
940	urdc = mdb_zalloc(sizeof (*urdc), UM_GC);
941
942	if (mdb_vread(krdc, sizeof (*krdc), addr) != sizeof (*krdc)) {
943		mdb_warn("failed to read krdc at %p", addr);
944		return (DCMD_ERR);
945	}
946
947	if (mdb_readvar(&rdc_u_info, "rdc_u_info") == -1) {
948		mdb_warn("failed to read 'rdc_u_info'");
949		return (DCMD_ERR);
950	}
951
952	urdc = &rdc_u_info[krdc->index];
953
954	rc = rdc_uinfo((uintptr_t)urdc, DCMD_ADDRSPEC, argc, argv);
955	return (rc);
956}
957
958static int
959rdc_u2k(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
960{
961	rdc_u_info_t *urdc;
962	rdc_k_info_t *rdc_k_info, *krdc;
963	int rc;
964
965	if (!(flags & DCMD_ADDRSPEC))
966		return (DCMD_USAGE);
967
968	urdc = mdb_zalloc(sizeof (*urdc), UM_GC);
969	krdc = mdb_zalloc(sizeof (*krdc), UM_GC);
970
971	if (mdb_vread(urdc, sizeof (*urdc), addr) != sizeof (*urdc)) {
972		mdb_warn("failed to read urdc at %p\n", addr);
973		return (DCMD_ERR);
974	}
975
976	if (mdb_readvar(&rdc_k_info, "rdc_k_info") == -1) {
977		mdb_warn("failed to read 'rdc_k_info'");
978		return (DCMD_ERR);
979	}
980
981	krdc = &rdc_k_info[urdc->index];
982
983	rc = rdc_kinfo((uintptr_t)krdc, DCMD_ADDRSPEC, argc, argv);
984	return (rc);
985}
986
987#ifdef DEBUG
988/*
989 * This routine is used to set the seq field in the rdc_kinfo->group
990 * structure. Used to test that the queue code handles the integer
991 * overflow correctly.
992 * Takes two arguments index and value.
993 * The index is the index into the kinfo structure array and
994 * the value is the new value to set into the seq field.
995 */
996/*ARGSUSED*/
997static int
998rdc_setseq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
999{
1000	rdc_k_info_t *rdc_k_info;
1001	rdc_group_t *group;
1002	int index;
1003	uint_t val;
1004	uintptr_t pokeaddr;
1005
1006	if (argc != 2) {
1007		mdb_warn("must have two arguments, index and value\n");
1008		return (DCMD_ERR);
1009	}
1010
1011	index = (int)mdb_strtoull(argv[0].a_un.a_str);
1012	val = (uint_t)mdb_strtoull(argv[1].a_un.a_str);
1013
1014	/*
1015	 * Find out where in memory the seq field.
1016	 * The structure offset first.
1017	 */
1018
1019	if (mdb_readvar(&rdc_k_info, "rdc_k_info") == -1) {
1020		mdb_warn("failed to read 'rdc_k_info'");
1021		return (DCMD_ERR);
1022	}
1023	pokeaddr = (uintptr_t)&rdc_k_info[index].group;
1024	if (mdb_vread(&group, sizeof (rdc_group_t *), pokeaddr) !=
1025	    sizeof (rdc_group_t *)) {
1026		mdb_warn("failed to fetch the group structure for set %d\n",
1027		    index);
1028		return (DCMD_ERR);
1029	}
1030	pokeaddr = (uintptr_t)(&group->seq);
1031	if (mdb_vwrite(&val, sizeof (val), pokeaddr) != sizeof (val)) {
1032		mdb_warn("failed to write seq at %p\n", pokeaddr);
1033		return (DCMD_ERR);
1034	}
1035
1036	return (DCMD_OK);
1037}
1038
1039
1040/*
1041 * This routine is used to set the seqack field in the rdc_kinfo->group
1042 * structure. Used to test that the queue code handles the integer
1043 * overflow correctly.
1044 * Takes two arguments index and value.
1045 * The index is the index into the kinfo structure array and
1046 * the value is the new value to set into the seqack field.
1047 */
1048/*ARGSUSED*/
1049static int
1050rdc_setseqack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1051{
1052	rdc_k_info_t *rdc_k_info;
1053	rdc_group_t *group;
1054	int index;
1055	uint_t val;
1056	uintptr_t pokeaddr;
1057
1058	if (argc != 2) {
1059		mdb_warn("must have two arguments, index and value\n");
1060		return (DCMD_ERR);
1061	}
1062
1063	index = (int)mdb_strtoull(argv[0].a_un.a_str);
1064	val = (uint_t)mdb_strtoull(argv[1].a_un.a_str);
1065
1066	/*
1067	 * Find out where in memory the seqack field.
1068	 * The structure offset first.
1069	 */
1070
1071	if (mdb_readvar(&rdc_k_info, "rdc_k_info") == -1) {
1072		mdb_warn("failed to read 'rdc_k_info'");
1073		return (DCMD_ERR);
1074	}
1075	pokeaddr = (uintptr_t)&rdc_k_info[index].group;
1076	if (mdb_vread(&group, sizeof (rdc_group_t *), pokeaddr) !=
1077	    sizeof (rdc_group_t *)) {
1078		mdb_warn("failed to fetch the group structure for set %d\n",
1079		    index);
1080		return (DCMD_ERR);
1081	}
1082	pokeaddr = (uintptr_t)(&group->seqack);
1083	if (mdb_vwrite(&val, sizeof (val), pokeaddr) != sizeof (val)) {
1084		mdb_warn("failed to write seqack at %p\n", pokeaddr);
1085		return (DCMD_ERR);
1086	}
1087
1088	return (DCMD_OK);
1089}
1090
1091/*
1092 * random define printing stuff, just does the define, and print the result
1093 */
1094/*ARGSUSED*/
1095static int
1096fba_to_log_num(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1097{
1098	int num;
1099	if (argc < 1) {
1100		mdb_warn("must have an argument\n");
1101		return (DCMD_ERR);
1102	}
1103	num = (int)mdb_strtoull(argv[0].a_un.a_str);
1104	num = FBA_TO_LOG_NUM(num);
1105	mdb_printf("LOG NUM: %d (0x%x)", num, num);
1106
1107	return (DCMD_OK);
1108}
1109
1110/*ARGSUSED*/
1111static int
1112log_to_fba_num(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1113{
1114	int num;
1115	if (argc < 1) {
1116		mdb_warn("must have an argument\n");
1117		return (DCMD_ERR);
1118	}
1119	num = (int)mdb_strtoull(argv[0].a_un.a_str);
1120	num = LOG_TO_FBA_NUM(num);
1121	mdb_printf("LOG NUM: %d (0x%x)", num, num);
1122
1123	return (DCMD_OK);
1124}
1125
1126static int
1127bmap_bit_isset(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1128{
1129	int st;
1130	int i, num;
1131	rdc_k_info_t *krdc;
1132	unsigned char *bmap;
1133	unsigned char *bmaddr;
1134	int bmsize;
1135
1136	if (!(flags & DCMD_ADDRSPEC))
1137		return (DCMD_USAGE);
1138
1139	if (argc < 1) {
1140		mdb_warn("must have an argument\n");
1141		return (DCMD_ERR);
1142	}
1143	krdc = mdb_zalloc(sizeof (*krdc), UM_GC);
1144
1145	if (mdb_vread(krdc, sizeof (*krdc), addr) != sizeof (*krdc)) {
1146		mdb_warn("failed to read rdc_k_info at %p", addr);
1147		return (DCMD_ERR);
1148	}
1149
1150	bmaddr = krdc->dcio_bitmap;
1151	bmsize = krdc->bitmap_size;
1152	bmap = mdb_zalloc(bmsize, UM_GC);
1153	if (mdb_vread(bmap, bmsize, (uintptr_t)bmaddr) != bmsize) {
1154		mdb_warn("failed to read bitmap");
1155		return (DCMD_ERR);
1156	}
1157
1158	num = (int)mdb_strtoull(argv[0].a_un.a_str);
1159	st = FBA_TO_LOG_NUM(num);
1160	i = BMAP_BIT_ISSET(bmap, st);
1161	mdb_printf(" BIT (%d) for %x %s set (%02x)", st, num, i?"IS":"IS NOT",
1162	    bmap[IND_BYTE(st)] & 0xff);
1163
1164	return (DCMD_OK);
1165}
1166
1167static int
1168bmap_bitref_isset(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1169{
1170	int num, st, i;
1171	rdc_k_info_t *krdc;
1172	unsigned char *brefbyte;
1173	unsigned int *brefint;
1174	void *bradder;
1175	int brsize;
1176	size_t refcntsize = sizeof (unsigned char);
1177	struct bm_ref_ops *refops;
1178
1179	if (!(flags & DCMD_ADDRSPEC))
1180		return (DCMD_USAGE);
1181
1182	if (argc < 1) {
1183		mdb_warn("must have an argument\n");
1184		return (DCMD_ERR);
1185	}
1186
1187	krdc = mdb_zalloc(sizeof (*krdc), UM_GC);
1188
1189	if (mdb_vread(krdc, sizeof (*krdc), addr) != sizeof (*krdc)) {
1190		mdb_warn("failed to read rdc_k_info at %p", addr);
1191		return (DCMD_ERR);
1192	}
1193
1194	bradder = krdc->bitmap_ref;
1195	refops = mdb_zalloc(sizeof (*refops), UM_GC);
1196	if (mdb_vread(refops, sizeof (*refops), (uintptr_t)krdc->bm_refs) !=
1197	    sizeof (*refops)) {
1198		mdb_warn("failed to read bm_refops at %p", krdc->bm_refs);
1199		return (DCMD_ERR);
1200	}
1201	refcntsize = refops->bmap_ref_size;
1202	brsize = krdc->bitmap_size * BITS_IN_BYTE * refcntsize;
1203	if (refcntsize == sizeof (unsigned char)) {
1204		brefbyte = mdb_zalloc(brsize, UM_GC);
1205		if (mdb_vread(brefbyte, brsize, (uintptr_t)bradder) != brsize) {
1206			mdb_warn("failed to read bitmap");
1207			return (DCMD_ERR);
1208		}
1209	} else {
1210		brefint = mdb_zalloc(brsize, UM_GC);
1211		if (mdb_vread(brefint, brsize, (uintptr_t)bradder) != brsize) {
1212			mdb_warn("failed to read bitmap");
1213			return (DCMD_ERR);
1214		}
1215	}
1216
1217	num = (int)mdb_strtoull(argv[0].a_un.a_str);
1218	st = FBA_TO_LOG_NUM(num);
1219	if (refcntsize == sizeof (unsigned char))
1220		i = brefbyte[st];
1221	else
1222		i = brefint[st];
1223
1224	mdb_printf("BITREF (%d) for %x %s set (%02x)", st, num, i?"IS":"IS NOT",
1225	    i);
1226
1227	return (DCMD_OK);
1228}
1229
1230/*ARGSUSED*/
1231static int
1232ind_byte(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1233{
1234	int num;
1235
1236	if (argc < 1) {
1237		mdb_warn("must have an argument\n");
1238		return (DCMD_ERR);
1239	}
1240	num = FBA_TO_LOG_NUM((int)mdb_strtoull(argv[0].a_un.a_str));
1241	mdb_printf("IND_BYTE: %d", IND_BYTE(num));
1242
1243	return (DCMD_OK);
1244}
1245
1246/*ARGSUSED*/
1247static int
1248ind_bit(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1249{
1250	int num;
1251
1252	if (argc < 1) {
1253		mdb_warn("must have an argument\n");
1254		return (DCMD_ERR);
1255	}
1256	num = FBA_TO_LOG_NUM((int)mdb_strtoull(argv[0].a_un.a_str));
1257	mdb_printf("IND_BIT: %d 0x%x", IND_BIT(num), IND_BIT(num));
1258
1259	return (DCMD_OK);
1260}
1261
1262static char *
1263print_bit(uint_t bitmask)
1264{
1265	int bitval = 1;
1266	int i;
1267
1268	bitstr[32] = '\0';
1269
1270	for (i = 31; i >= 0; i--) {
1271		if (bitmask & bitval) {
1272			bitstr[i] = '1';
1273		} else {
1274			bitstr[i] = '0';
1275		}
1276		bitval *= 2;
1277	}
1278	return (bitstr);
1279}
1280
1281/*ARGSUSED*/
1282static int
1283rdc_bitmask(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1284{
1285	uint_t bitmask = 0;
1286	int first, st, en, pos, len;
1287
1288	if (argc < 2) {
1289		mdb_warn("must have 2 args (pos, len)\n");
1290		return (DCMD_ERR);
1291	}
1292	pos = (int)mdb_strtoull(argv[0].a_un.a_str);
1293	len = (int)mdb_strtoull(argv[1].a_un.a_str);
1294
1295	if (len <= 0) {
1296		mdb_printf("non positive len specified");
1297		return (DCMD_ERR);
1298	}
1299
1300	if ((len - pos) > 2048) {
1301		mdb_printf("len out of range, 32 bit bitmask");
1302		return (DCMD_ERR);
1303	}
1304
1305	first = st = FBA_TO_LOG_NUM(pos);
1306	en = FBA_TO_LOG_NUM(pos + len - 1);
1307	while (st <= en) {
1308		BMAP_BIT_SET((uchar_t *)&bitmask, st - first);
1309		st++;
1310	}
1311
1312	mdb_printf("bitmask for POS: %d LEN: %d : 0x%08x (%s)", pos, len,
1313	    bitmask & 0xffffffff, print_bit(bitmask));
1314	return (DCMD_OK);
1315
1316}
1317
1318/*
1319 * Dump the bitmap of the krdc structure indicated by the index
1320 * argument. Used by the ZatoIchi tests.
1321 */
1322/*ARGSUSED*/
1323static int
1324rdc_bmapdump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1325{
1326	rdc_k_info_t *rdc_k_info;
1327	int index;
1328	uintptr_t bmapaddr;
1329	uintptr_t bmapdata;
1330	unsigned char *data;
1331	int bmapsize;
1332	int i;
1333	int st = 0;
1334	int en = 0;
1335
1336	if (argc < 1) {
1337		mdb_warn("must have index argument\n");
1338		return (DCMD_ERR);
1339	}
1340
1341	i = argc;
1342	if (i == 3) {
1343		en = (int)mdb_strtoull(argv[2].a_un.a_str);
1344		en = FBA_TO_LOG_NUM(en);
1345		i--;
1346	}
1347	if (i == 2) {
1348		st = (int)mdb_strtoull(argv[1].a_un.a_str);
1349		st = FBA_TO_LOG_NUM(st);
1350	}
1351
1352	index = (int)mdb_strtoull(argv[0].a_un.a_str);
1353	/*
1354	 * Find out where in memory the rdc_k_kinfo array starts
1355	 */
1356	if (mdb_readvar(&rdc_k_info, "rdc_k_info") == -1) {
1357		mdb_warn("failed to read 'rdc_k_info'");
1358		return (DCMD_ERR);
1359	}
1360	bmapaddr = (uintptr_t)(&rdc_k_info[index].bitmap_size);
1361	if (mdb_vread(&bmapsize, sizeof (bmapsize), bmapaddr)
1362	    != sizeof (bmapsize)) {
1363		mdb_warn("failed to read dcio_bitmap at %p\n", bmapaddr);
1364		return (DCMD_ERR);
1365	}
1366
1367	bmapaddr = (uintptr_t)(&rdc_k_info[index].dcio_bitmap);
1368	if (mdb_vread(&bmapdata, sizeof (bmapdata), bmapaddr)
1369	    != sizeof (bmapdata)) {
1370		mdb_warn("failed to read dcio_bitmap at %p\n", bmapaddr);
1371		return (DCMD_ERR);
1372	}
1373	data = mdb_zalloc(bmapsize, UM_SLEEP);
1374
1375	if (mdb_vread(data, bmapsize, bmapdata) != bmapsize) {
1376		mdb_warn("failed to read the bitmap data\n");
1377		mdb_free(data, bmapsize);
1378		return (DCMD_ERR);
1379	}
1380	mdb_printf("bitmap data address 0x%p bitmap size %d\n"
1381	    "kinfo 0x%p\n", bmapdata, bmapsize, &rdc_k_info[index]);
1382
1383	if ((st < 0) || ((st/8) > bmapsize) || (en < 0)) {
1384		mdb_warn("offset is out of range st %d bms %d en %d",
1385		    st, bmapsize, en);
1386		return (DCMD_ERR);
1387	}
1388	if (((en/8) > bmapsize) || (en == 0))
1389		en = bmapsize * 8;
1390
1391	mdb_printf("bit start pos: %d bit end pos: %d\n\n", st, en);
1392	st /= 8;
1393	en /= 8;
1394	for (i = st; i < en; i++) {
1395		mdb_printf("%02x ", data[i] & 0xff);
1396		if ((i % 16) == 15) {
1397			int s = LOG_TO_FBA_NUM((i-15)*8);
1398			int e = LOG_TO_FBA_NUM(((i+1)*8)) - 1;
1399			mdb_printf(" fbas: %x - %x\n", s, e);
1400		}
1401	}
1402	mdb_printf("\n");
1403	mdb_free(data, bmapsize);
1404	return (DCMD_OK);
1405}
1406
1407/*
1408 * dump the bitmap reference count
1409 */
1410/*ARGSUSED*/
1411static int
1412rdc_brefdump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1413{
1414	rdc_k_info_t *rdc_k_info;
1415	int index;
1416	uintptr_t bmapaddr;
1417	uintptr_t bmapdata;
1418	unsigned char *data;
1419	int bmapsize;
1420	int i;
1421	int st = 0;
1422	int en = 0;
1423
1424	if (argc < 1) {
1425		mdb_warn("must have index argument\n");
1426		return (DCMD_ERR);
1427	}
1428	index = (int)mdb_strtoull(argv[0].a_un.a_str);
1429
1430	i = argc;
1431	if (i == 3) {
1432		en = (int)mdb_strtoull(argv[2].a_un.a_str);
1433		en = FBA_TO_LOG_NUM(en);
1434		i--;
1435
1436	}
1437	if (i == 2) {
1438		st = (int)mdb_strtoull(argv[1].a_un.a_str);
1439		st = FBA_TO_LOG_NUM(st);
1440	}
1441
1442	/*
1443	 * Find out where in memory the rdc_k_kinfo array starts
1444	 */
1445	if (mdb_readvar(&rdc_k_info, "rdc_k_info") == -1) {
1446		mdb_warn("failed to read 'rdc_k_info'");
1447		return (DCMD_ERR);
1448	}
1449	bmapaddr = (uintptr_t)(&rdc_k_info[index].bitmap_size);
1450
1451	if (mdb_vread(&bmapsize, sizeof (bmapsize), bmapaddr)
1452	    != sizeof (bmapsize)) {
1453		mdb_warn("failed to read dcio_bitmap at %p\n", bmapaddr);
1454		return (DCMD_ERR);
1455	}
1456
1457	bmapsize *= 8;
1458	bmapaddr = (uintptr_t)(&rdc_k_info[index].bitmap_ref);
1459
1460	if (mdb_vread(&bmapdata, sizeof (bmapdata), bmapaddr)
1461	    != sizeof (bmapdata)) {
1462		mdb_warn("failed to read dcio_bitmap at %p\n", bmapaddr);
1463		return (DCMD_ERR);
1464	}
1465	data = mdb_zalloc(bmapsize, UM_SLEEP);
1466
1467	if (mdb_vread(data, bmapsize, bmapdata) != bmapsize) {
1468		mdb_warn("failed to read the bitmap data\n");
1469		mdb_free(data, bmapsize);
1470		return (DCMD_ERR);
1471	}
1472	mdb_printf("bitmap data address 0x%p bitmap size %d\n"
1473	    "kinfo 0x%p\n", bmapdata, bmapsize, &rdc_k_info[index]);
1474
1475	if ((st < 0) || (st > bmapsize) || (en < 0)) {
1476		mdb_warn("offset is out of range");
1477	}
1478	if ((en > bmapsize) || (en == 0))
1479		en = bmapsize;
1480
1481	mdb_printf("bit start pos: %d bit end pos: %d\n\n", st, en);
1482
1483	for (i = st; i < en; i++) {
1484		mdb_printf("%02x ", data[i] & 0xff);
1485		if ((i % 16) == 15) {
1486			int s = LOG_TO_FBA_NUM(i-15);
1487			int e = LOG_TO_FBA_NUM(i+1) - 1;
1488			mdb_printf(" fbas: 0x%x - 0x%x \n", s, e);
1489		}
1490	}
1491	mdb_printf("\n");
1492	mdb_free(data, bmapsize);
1493	return (DCMD_OK);
1494}
1495
1496static int
1497rdc_bmapnref(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1498{
1499	mdb_printf("\nRDC bitmap info\n");
1500	rdc_bmapdump(addr, flags, argc, argv);
1501	mdb_printf("RDC bitmap reference count info\n");
1502	rdc_brefdump(addr, flags, argc, argv);
1503	return (DCMD_OK);
1504}
1505
1506#endif
1507/*
1508 * MDB module linkage information:
1509 */
1510
1511static const mdb_dcmd_t dcmds[] = {
1512	{ "rdc", NULL, "display sndr module info", rdc },
1513	{ "rdc_buf", "?[-v]", "rdc_buf structure", rdc_buf },
1514	{ "rdc_kinfo", "?[-av]", "rdc_k_info structure", rdc_kinfo },
1515	{ "rdc_uinfo", "?[-av]", "rdc_u_info structure", rdc_uinfo },
1516	{ "rdc_group", "?", "rdc group structure", rdc_group },
1517	{ "rdc_srv", "?", "rdc_srv structure", rdc_srv },
1518	{ "rdc_if", "?", "rdc_if structure", rdc_if },
1519	{ "rdc_infodev", "?", "rdc_info_dev structure", rdc_infodev },
1520	{ "rdc_k2u", "?", "rdc_kinfo to rdc_uinfo", rdc_k2u },
1521	{ "rdc_u2k", "?", "rdc_uinfo to rdc_kinfo", rdc_u2k },
1522	{ "rdc_aio", "?", "rdc_aio structure", rdc_aio},
1523	{ "rdc_iohdr", "?", "rdc_iohdr structure", rdc_iohdr},
1524#ifdef DEBUG
1525	{ "rdc_setseq", "?", "Write seq field in group", rdc_setseq },
1526	{ "rdc_setseqack", "?", "Write seqack field in group", rdc_setseqack },
1527	{ "rdc_dset", "?", "Dump dset info", rdc_dset },
1528	{ "rdc_bmapdump", "?", "Dump bitmap", rdc_bmapdump },
1529	{ "rdc_brefdump", "?", "Dump bitmap reference count", rdc_brefdump },
1530	{ "rdc_bmapnref", "?", "Dump bitmap and ref count", rdc_bmapnref },
1531	{ "rdc_fba2log", "?", "fba to log num", fba_to_log_num },
1532	{ "rdc_log2fba", "?", "log to fba num", log_to_fba_num },
1533	{ "rdc_bitisset", "?", "check bit set", bmap_bit_isset },
1534	{ "rdc_brefisset", "?", "check bit ref set", bmap_bitref_isset },
1535	{ "rdc_indbyte", "?", "print indbyte", ind_byte },
1536	{ "rdc_indbit", "?", "print indbit", ind_bit },
1537	{ "rdc_bitmask", "?", "print bitmask for pos->len", rdc_bitmask },
1538#endif
1539	{ NULL }
1540};
1541
1542
1543static const mdb_walker_t walkers[] = {
1544	{ "rdc_kinfo", "walk the rdc_k_info array",
1545	    rdc_k_info_winit, rdc_k_info_wstep, rdc_k_info_wfini },
1546	{ "rdc_uinfo", "walk the rdc_u_info array",
1547	    rdc_u_info_winit, rdc_u_info_wstep, rdc_u_info_wfini },
1548	{ "rdc_if", "walk rdc_if chain",
1549	    rdc_if_winit, rdc_if_wstep, rdc_if_wfini },
1550	{ NULL }
1551};
1552
1553
1554static const mdb_modinfo_t modinfo = {
1555	MDB_API_VERSION, dcmds, walkers
1556};
1557
1558
1559const mdb_modinfo_t *
1560_mdb_init(void)
1561{
1562	return (&modinfo);
1563}
1564