xref: /illumos-gate/usr/src/cmd/mdb/common/modules/sd/sd.c (revision 50c81445dc798873f49b7af4c98f8a1d3638de83)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
26*50c81445SGarrett D'Amore /*
27*50c81445SGarrett D'Amore  * Copyright 2022 RackTop Systems, Inc.
28*50c81445SGarrett D'Amore  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <sys/mdb_modapi.h>
317c478bd9Sstevel@tonic-gate #include <sys/scsi/scsi.h>
327c478bd9Sstevel@tonic-gate #include <sys/dkio.h>
337c478bd9Sstevel@tonic-gate #include <sys/taskq.h>
347c478bd9Sstevel@tonic-gate #include <sys/scsi/targets/sddef.h>
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate /* Represents global soft state data in walk_step, walk_init */
377c478bd9Sstevel@tonic-gate #define	SD_DATA(param)	((sd_str_p)wsp->walk_data)->param
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate /* Represents global soft state data in callback and related routines */
407c478bd9Sstevel@tonic-gate #define	SD_DATA_IN_CBACK(param)	((sd_str_p)walk_data)->param
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #define	SUCCESS			WALK_NEXT
437c478bd9Sstevel@tonic-gate #define	FAIL			WALK_ERR
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate /*
467c478bd9Sstevel@tonic-gate  * Primary attribute struct for buf extensions.
477c478bd9Sstevel@tonic-gate  */
487c478bd9Sstevel@tonic-gate struct __ddi_xbuf_attr {
497c478bd9Sstevel@tonic-gate 	kmutex_t	xa_mutex;
507c478bd9Sstevel@tonic-gate 	size_t		xa_allocsize;
517c478bd9Sstevel@tonic-gate 	uint32_t	xa_pending;	/* call to xbuf_iostart() is iminent */
527c478bd9Sstevel@tonic-gate 	uint32_t	xa_active_limit;
537c478bd9Sstevel@tonic-gate 	uint32_t	xa_active_count;
547c478bd9Sstevel@tonic-gate 	uint32_t	xa_active_lowater;
557c478bd9Sstevel@tonic-gate 	struct buf	*xa_headp;	/* FIFO buf queue head ptr */
567c478bd9Sstevel@tonic-gate 	struct buf	*xa_tailp;	/* FIFO buf queue tail ptr */
577c478bd9Sstevel@tonic-gate 	kmutex_t	xa_reserve_mutex;
587c478bd9Sstevel@tonic-gate 	uint32_t	xa_reserve_limit;
597c478bd9Sstevel@tonic-gate 	uint32_t	xa_reserve_count;
607c478bd9Sstevel@tonic-gate 	void		*xa_reserve_headp;
617c478bd9Sstevel@tonic-gate 	void		(*xa_strategy)(struct buf *, void *, void *);
627c478bd9Sstevel@tonic-gate 	void		*xa_attr_arg;
637c478bd9Sstevel@tonic-gate 	timeout_id_t	xa_timeid;
647c478bd9Sstevel@tonic-gate 	taskq_t		*xa_tq;
657c478bd9Sstevel@tonic-gate };
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate /*
687c478bd9Sstevel@tonic-gate  * Provides soft state information like the number of elements, pointer
697c478bd9Sstevel@tonic-gate  * to soft state elements etc
707c478bd9Sstevel@tonic-gate  */
717c478bd9Sstevel@tonic-gate typedef struct i_ddi_soft_state sd_state_str_t, *sd_state_str_ptr;
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate /* structure to store soft state statistics */
747c478bd9Sstevel@tonic-gate typedef struct sd_str {
757c478bd9Sstevel@tonic-gate 	void		*sd_state;
767c478bd9Sstevel@tonic-gate 	uintptr_t	current_root;
777c478bd9Sstevel@tonic-gate 	int		current_list_count;
787c478bd9Sstevel@tonic-gate 	int		valid_root_count;
797c478bd9Sstevel@tonic-gate 	int		silent;
807c478bd9Sstevel@tonic-gate 	sd_state_str_t	sd_state_data;
817c478bd9Sstevel@tonic-gate } sd_str_t, *sd_str_p;
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate  *    Function: buf_avforw_walk_init
867c478bd9Sstevel@tonic-gate  *
877c478bd9Sstevel@tonic-gate  * Description: MDB calls the init function to initiate the walk,
887c478bd9Sstevel@tonic-gate  *		in response to mdb_walk() function called by the
897c478bd9Sstevel@tonic-gate  *		dcmd 'buf_avforw' or when the user executes the
907c478bd9Sstevel@tonic-gate  *		walk dcmd 'address::walk buf_avforw'.
917c478bd9Sstevel@tonic-gate  *
927c478bd9Sstevel@tonic-gate  *   Arguments: new mdb_walk_state_t structure. A new structure is
937c478bd9Sstevel@tonic-gate  *		created for each walk, so that multiple instances of
947c478bd9Sstevel@tonic-gate  *		the walker can be active simultaneously.
957c478bd9Sstevel@tonic-gate  */
967c478bd9Sstevel@tonic-gate static int
buf_avforw_walk_init(mdb_walk_state_t * wsp)977c478bd9Sstevel@tonic-gate buf_avforw_walk_init(mdb_walk_state_t *wsp)
987c478bd9Sstevel@tonic-gate {
99892ad162SToomas Soome 	if (wsp->walk_addr == 0) {
1007c478bd9Sstevel@tonic-gate 		mdb_warn("buffer address required with the command\n");
1017c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
1027c478bd9Sstevel@tonic-gate 	}
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	wsp->walk_data = mdb_alloc(sizeof (buf_t), UM_SLEEP);
1057c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
1067c478bd9Sstevel@tonic-gate }
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate /*
1107c478bd9Sstevel@tonic-gate  *    Function: buf_avforw_walk_step
1117c478bd9Sstevel@tonic-gate  *
1127c478bd9Sstevel@tonic-gate  * Description: The step function is invoked by the walker during each
1137c478bd9Sstevel@tonic-gate  *		iteration. Its primary job is to determine the address
1147c478bd9Sstevel@tonic-gate  *		of the next 'buf_avforw' object, read in the local copy
1157c478bd9Sstevel@tonic-gate  *		of this object, call the callback 'buf_callback' function,
1167c478bd9Sstevel@tonic-gate  *		and return its status. The iteration is terminated when
1177c478bd9Sstevel@tonic-gate  *		the walker encounters a null queue pointer which signifies
1187c478bd9Sstevel@tonic-gate  *		end of queue.
1197c478bd9Sstevel@tonic-gate  *
1207c478bd9Sstevel@tonic-gate  *   Arguments: mdb_walk_state_t structure
1217c478bd9Sstevel@tonic-gate  */
1227c478bd9Sstevel@tonic-gate static int
buf_avforw_walk_step(mdb_walk_state_t * wsp)1237c478bd9Sstevel@tonic-gate buf_avforw_walk_step(mdb_walk_state_t *wsp)
1247c478bd9Sstevel@tonic-gate {
1257c478bd9Sstevel@tonic-gate 	int		status;
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	/*
1287c478bd9Sstevel@tonic-gate 	 * if walk_addr is null then it effectively means an end of all
1297c478bd9Sstevel@tonic-gate 	 * buf structures, hence end the iterations.
1307c478bd9Sstevel@tonic-gate 	 */
131892ad162SToomas Soome 	if (wsp->walk_addr == 0) {
1327c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
1337c478bd9Sstevel@tonic-gate 	}
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	/*
1367c478bd9Sstevel@tonic-gate 	 * Read the contents of the current object, invoke the callback
1377c478bd9Sstevel@tonic-gate 	 * and assign the next objects address to mdb_walk_state_t structure.
1387c478bd9Sstevel@tonic-gate 	 */
1397c478bd9Sstevel@tonic-gate 	if (mdb_vread(wsp->walk_data, sizeof (buf_t), wsp->walk_addr) == -1) {
1407c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read buf at %p", wsp->walk_addr);
1417c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
1427c478bd9Sstevel@tonic-gate 	}
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
1457c478bd9Sstevel@tonic-gate 	    wsp->walk_cbdata);
1467c478bd9Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)(((buf_t *)wsp->walk_data)->av_forw);
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	return (status);
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate /*
1527c478bd9Sstevel@tonic-gate  *    Function: buf_callback
1537c478bd9Sstevel@tonic-gate  *
1547c478bd9Sstevel@tonic-gate  * Description: This is the callback function called by the 'buf_avforw'
1557c478bd9Sstevel@tonic-gate  *		walker when 'buf_avforw' dcmd is invoked.
1567c478bd9Sstevel@tonic-gate  *		It is called during each walk step. It displays the contents
1577c478bd9Sstevel@tonic-gate  *		of the current object (addr) passed to it by the step
1587c478bd9Sstevel@tonic-gate  *		function. It also prints the header and footer during the
1597c478bd9Sstevel@tonic-gate  *		first and the last iteration of the walker.
1607c478bd9Sstevel@tonic-gate  *
1617c478bd9Sstevel@tonic-gate  *   Arguments: addr -> current buf_avforw objects address.
1627c478bd9Sstevel@tonic-gate  *		walk_data -> private storage for the walker.
1637c478bd9Sstevel@tonic-gate  *		buf_entries -> private data for the callback. It represents
1647c478bd9Sstevel@tonic-gate  *		the count of objects processed so far.
1657c478bd9Sstevel@tonic-gate  */
1667c478bd9Sstevel@tonic-gate static int
buf_callback(uintptr_t addr,const void * walk_data,void * buf_entries)1677c478bd9Sstevel@tonic-gate buf_callback(uintptr_t addr, const void *walk_data, void *buf_entries)
1687c478bd9Sstevel@tonic-gate {
1697c478bd9Sstevel@tonic-gate 	int	*count = (int *)buf_entries;
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 	/*
1727c478bd9Sstevel@tonic-gate 	 * If this is the first invocation of the command, print a
1737c478bd9Sstevel@tonic-gate 	 * header line for the output that will follow.
1747c478bd9Sstevel@tonic-gate 	 */
1757c478bd9Sstevel@tonic-gate 	if (*count == 0) {
1767c478bd9Sstevel@tonic-gate 		mdb_printf("============================\n");
1777c478bd9Sstevel@tonic-gate 		mdb_printf("Walking buf list via av_forw\n");
1787c478bd9Sstevel@tonic-gate 		mdb_printf("============================\n");
1797c478bd9Sstevel@tonic-gate 	}
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	/*
1827c478bd9Sstevel@tonic-gate 	 * read the object and print the contents.
1837c478bd9Sstevel@tonic-gate 	 */
1847c478bd9Sstevel@tonic-gate 	mdb_set_dot(addr);
1857c478bd9Sstevel@tonic-gate 	mdb_eval("$<buf");
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	mdb_printf("---\n");
1887c478bd9Sstevel@tonic-gate 	(*count)++;
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 	/* if this is the last entry and print the footer */
1917c478bd9Sstevel@tonic-gate 	if (((buf_t *)walk_data)->av_forw == NULL) {
1927c478bd9Sstevel@tonic-gate 		mdb_printf("---------------------------\n");
1937c478bd9Sstevel@tonic-gate 		mdb_printf("Processed %d Buf entries\n", *count);
1947c478bd9Sstevel@tonic-gate 		mdb_printf("---------------------------\n");
1957c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
1967c478bd9Sstevel@tonic-gate 	}
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
1997c478bd9Sstevel@tonic-gate }
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate /*
2027c478bd9Sstevel@tonic-gate  *    Function: buf_avforw_walk_fini
2037c478bd9Sstevel@tonic-gate  *
2047c478bd9Sstevel@tonic-gate  * Description: The buf_avforw_walk_fini is called when the walk is terminated
2057c478bd9Sstevel@tonic-gate  *		in response to WALK_DONE in buf_avforw_walk_step. It frees
2067c478bd9Sstevel@tonic-gate  *		the walk_data structure.
2077c478bd9Sstevel@tonic-gate  *
2087c478bd9Sstevel@tonic-gate  *   Arguments: mdb_walk_state_t structure
2097c478bd9Sstevel@tonic-gate  */
2107c478bd9Sstevel@tonic-gate static void
buf_avforw_walk_fini(mdb_walk_state_t * wsp)2117c478bd9Sstevel@tonic-gate buf_avforw_walk_fini(mdb_walk_state_t *wsp)
2127c478bd9Sstevel@tonic-gate {
2137c478bd9Sstevel@tonic-gate 	mdb_free(wsp->walk_data, sizeof (buf_t));
2147c478bd9Sstevel@tonic-gate }
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate /*
2177c478bd9Sstevel@tonic-gate  *    Function: dump_xbuf_attr
2187c478bd9Sstevel@tonic-gate  *
2197c478bd9Sstevel@tonic-gate  * Description: Prints the contents of Xbuf queue.
2207c478bd9Sstevel@tonic-gate  *
2217c478bd9Sstevel@tonic-gate  *   Arguments: object contents pointer and address.
2227c478bd9Sstevel@tonic-gate  */
2237c478bd9Sstevel@tonic-gate static void
dump_xbuf_attr(struct __ddi_xbuf_attr * xba_ptr,uintptr_t mem_addr)2247c478bd9Sstevel@tonic-gate dump_xbuf_attr(struct __ddi_xbuf_attr *xba_ptr, uintptr_t mem_addr)
2257c478bd9Sstevel@tonic-gate {
2267c478bd9Sstevel@tonic-gate 	mdb_printf("0x%8lx:\tmutex\t\tallocsize\tpending\n",
2277c478bd9Sstevel@tonic-gate 	    mem_addr + offsetof(struct __ddi_xbuf_attr, xa_mutex));
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 	mdb_printf("           \t%lx\t\t%d\t\t%d\n",
2307c478bd9Sstevel@tonic-gate 	    xba_ptr->xa_mutex._opaque[0], xba_ptr->xa_allocsize,
2317c478bd9Sstevel@tonic-gate 	    xba_ptr->xa_pending);
2327c478bd9Sstevel@tonic-gate 	mdb_printf("0x%8lx:\tactive_limit\tactive_count\tactive_lowater\n",
2337c478bd9Sstevel@tonic-gate 	    mem_addr + offsetof(struct __ddi_xbuf_attr, xa_active_limit));
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	mdb_printf("           \t%lx\t\t%lx\t\t%lx\n",
2367c478bd9Sstevel@tonic-gate 	    xba_ptr->xa_active_limit, xba_ptr->xa_active_count,
2377c478bd9Sstevel@tonic-gate 	    xba_ptr->xa_active_lowater);
2387c478bd9Sstevel@tonic-gate 	mdb_printf("0x%8lx:\theadp\t\ttailp\n",
2397c478bd9Sstevel@tonic-gate 	    mem_addr + offsetof(struct __ddi_xbuf_attr, xa_headp));
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	mdb_printf("           \t%lx%c\t%lx\n",
2427c478bd9Sstevel@tonic-gate 	    xba_ptr->xa_headp, (xba_ptr->xa_headp == 0?'\t':' '),
2437c478bd9Sstevel@tonic-gate 	    xba_ptr->xa_tailp);
2447c478bd9Sstevel@tonic-gate 	mdb_printf(
2457c478bd9Sstevel@tonic-gate 	"0x%8lx:\treserve_mutex\treserve_limit\treserve_count\treserve_headp\n",
2467c478bd9Sstevel@tonic-gate 	    mem_addr + offsetof(struct __ddi_xbuf_attr, xa_reserve_mutex));
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	mdb_printf("           \t%lx\t\t%lx\t\t%lx\t\t%lx\n",
2497c478bd9Sstevel@tonic-gate 	    xba_ptr->xa_reserve_mutex._opaque[0], xba_ptr->xa_reserve_limit,
2507c478bd9Sstevel@tonic-gate 	    xba_ptr->xa_reserve_count, xba_ptr->xa_reserve_headp);
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	mdb_printf("0x%8lx:\ttimeid\t\ttq\n",
2537c478bd9Sstevel@tonic-gate 	    mem_addr + offsetof(struct __ddi_xbuf_attr, xa_timeid));
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	mdb_printf("           \t%lx%c\t%lx\n",
2567c478bd9Sstevel@tonic-gate 	    xba_ptr->xa_timeid, (xba_ptr->xa_timeid == 0?'\t':' '),
2577c478bd9Sstevel@tonic-gate 	    xba_ptr->xa_tq);
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate /*
2617c478bd9Sstevel@tonic-gate  *    Function: init_softstate_members
2627c478bd9Sstevel@tonic-gate  *
2637c478bd9Sstevel@tonic-gate  * Description: Initialize mdb_walk_state_t structure with either 'sd' or
2647c478bd9Sstevel@tonic-gate  *		'ssd' related information.
2657c478bd9Sstevel@tonic-gate  *
2667c478bd9Sstevel@tonic-gate  *   Arguments: new mdb_walk_state_t structure
2677c478bd9Sstevel@tonic-gate  */
2687c478bd9Sstevel@tonic-gate static int
init_softstate_members(mdb_walk_state_t * wsp)2697c478bd9Sstevel@tonic-gate init_softstate_members(mdb_walk_state_t *wsp)
2707c478bd9Sstevel@tonic-gate {
2717c478bd9Sstevel@tonic-gate 	wsp->walk_data = mdb_alloc(sizeof (sd_str_t), UM_SLEEP);
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 	/*
2747c478bd9Sstevel@tonic-gate 	 * store the soft state statistics variables like non-zero
2757c478bd9Sstevel@tonic-gate 	 * soft state entries, base address, actual count of soft state
2767c478bd9Sstevel@tonic-gate 	 * processed etc.
2777c478bd9Sstevel@tonic-gate 	 */
2787c478bd9Sstevel@tonic-gate 	SD_DATA(sd_state) = (sd_state_str_ptr)wsp->walk_addr;
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	SD_DATA(current_list_count) = 0;
2817c478bd9Sstevel@tonic-gate 	SD_DATA(valid_root_count) = 0;
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	if (mdb_vread((void *)&SD_DATA(sd_state_data),
2847c478bd9Sstevel@tonic-gate 	    sizeof (sd_state_str_t), wsp->walk_addr) == -1) {
2857c478bd9Sstevel@tonic-gate 		mdb_warn("failed to sd_state at %p", wsp->walk_addr);
2867c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
2877c478bd9Sstevel@tonic-gate 	}
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)(SD_DATA(sd_state_data.array));
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	SD_DATA(current_root) = wsp->walk_addr;
2927c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate #if (!defined(__fibre))
2967c478bd9Sstevel@tonic-gate /*
2977c478bd9Sstevel@tonic-gate  *    Function: sd_state_walk_init
2987c478bd9Sstevel@tonic-gate  *
2997c478bd9Sstevel@tonic-gate  * Description: MDB calls the init function to initiate the walk,
3007c478bd9Sstevel@tonic-gate  *		in response to mdb_walk() function called by the
3017c478bd9Sstevel@tonic-gate  *		dcmd 'sd_state' or when the user executes the
3027c478bd9Sstevel@tonic-gate  *		walk dcmd '::walk sd_state'.
3037c478bd9Sstevel@tonic-gate  *		The init function initializes the walker to either
3047c478bd9Sstevel@tonic-gate  *		the user specified address or the default kernel
3057c478bd9Sstevel@tonic-gate  *		'sd_state' pointer.
3067c478bd9Sstevel@tonic-gate  *
3077c478bd9Sstevel@tonic-gate  *   Arguments: new mdb_walk_state_t structure
3087c478bd9Sstevel@tonic-gate  */
3097c478bd9Sstevel@tonic-gate static int
sd_state_walk_init(mdb_walk_state_t * wsp)3107c478bd9Sstevel@tonic-gate sd_state_walk_init(mdb_walk_state_t *wsp)
3117c478bd9Sstevel@tonic-gate {
312892ad162SToomas Soome 	if (wsp->walk_addr == 0 &&
3137c478bd9Sstevel@tonic-gate 	    mdb_readvar(&wsp->walk_addr, "sd_state") == -1) {
3147c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read 'sd_state'");
3157c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
3167c478bd9Sstevel@tonic-gate 	}
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	return (init_softstate_members(wsp));
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate #else
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate /*
3247c478bd9Sstevel@tonic-gate  *    Function: ssd_state_walk_init
3257c478bd9Sstevel@tonic-gate  *
3267c478bd9Sstevel@tonic-gate  * Description: MDB calls the init function to initiate the walk,
3277c478bd9Sstevel@tonic-gate  *		in response to mdb_walk() function called by the
3287c478bd9Sstevel@tonic-gate  *		dcmd 'ssd_state' or when the user executes the
3297c478bd9Sstevel@tonic-gate  *		walk dcmd '::walk ssd_state'.
3307c478bd9Sstevel@tonic-gate  *		The init function initializes the walker to either
3317c478bd9Sstevel@tonic-gate  *		the user specified address or the default kernel
3327c478bd9Sstevel@tonic-gate  *		'ssd_state' pointer.
3337c478bd9Sstevel@tonic-gate  *
3347c478bd9Sstevel@tonic-gate  *   Arguments: new mdb_walk_state_t structure
3357c478bd9Sstevel@tonic-gate  */
3367c478bd9Sstevel@tonic-gate static int
ssd_state_walk_init(mdb_walk_state_t * wsp)3377c478bd9Sstevel@tonic-gate ssd_state_walk_init(mdb_walk_state_t *wsp)
3387c478bd9Sstevel@tonic-gate {
33959b05390SToomas Soome 	if (wsp->walk_addr == (uintptr_t)NULL &&
3407c478bd9Sstevel@tonic-gate 	    mdb_readvar(&wsp->walk_addr, "ssd_state") == -1) {
3417c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read 'ssd_state'");
3427c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
3437c478bd9Sstevel@tonic-gate 	}
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	return (init_softstate_members(wsp));
3467c478bd9Sstevel@tonic-gate }
3477c478bd9Sstevel@tonic-gate #endif
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate /*
3517c478bd9Sstevel@tonic-gate  *    Function: sd_state_walk_step
3527c478bd9Sstevel@tonic-gate  *
3537c478bd9Sstevel@tonic-gate  * Description: The step function is invoked by the walker during each
3547c478bd9Sstevel@tonic-gate  *		iteration. Its primary job is to determine the address
3557c478bd9Sstevel@tonic-gate  *		of the next 'soft state' object, read in the local copy
3567c478bd9Sstevel@tonic-gate  *		of this object, call the callback 'sd_callback' function,
3577c478bd9Sstevel@tonic-gate  *		and return its status. The iteration is terminated when
3587c478bd9Sstevel@tonic-gate  *		the soft state counter equals the total soft state count
3597c478bd9Sstevel@tonic-gate  *		obtained initially.
3607c478bd9Sstevel@tonic-gate  *
3617c478bd9Sstevel@tonic-gate  *   Arguments: mdb_walk_state_t structure
3627c478bd9Sstevel@tonic-gate  */
3637c478bd9Sstevel@tonic-gate static int
sd_state_walk_step(mdb_walk_state_t * wsp)3647c478bd9Sstevel@tonic-gate sd_state_walk_step(mdb_walk_state_t *wsp)
3657c478bd9Sstevel@tonic-gate {
3667c478bd9Sstevel@tonic-gate 	int		status;
3677c478bd9Sstevel@tonic-gate 	void		*tp;
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	/*
3707c478bd9Sstevel@tonic-gate 	 * If all the soft state entries have been processed then stop
3717c478bd9Sstevel@tonic-gate 	 * future iterations.
3727c478bd9Sstevel@tonic-gate 	 */
3737c478bd9Sstevel@tonic-gate 	if (SD_DATA(current_list_count) >= SD_DATA(sd_state_data.n_items)) {
3747c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
3757c478bd9Sstevel@tonic-gate 	}
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	/*
3787c478bd9Sstevel@tonic-gate 	 * read the object contents, invoke the callback and set the
3797c478bd9Sstevel@tonic-gate 	 * mdb_walk_state_t structure to the next object.
3807c478bd9Sstevel@tonic-gate 	 */
3817c478bd9Sstevel@tonic-gate 	if (mdb_vread(&tp, sizeof (void *), wsp->walk_addr) == -1) {
3827c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read at %p", wsp->walk_addr);
3837c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
3847c478bd9Sstevel@tonic-gate 	}
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	status = wsp->walk_callback((uintptr_t)tp, wsp->walk_data,
3877c478bd9Sstevel@tonic-gate 	    wsp->walk_cbdata);
3887c478bd9Sstevel@tonic-gate 	if (tp != 0) {
3897c478bd9Sstevel@tonic-gate 		/* Count the number of non-zero un entries. */
3907c478bd9Sstevel@tonic-gate 		SD_DATA(valid_root_count++);
3917c478bd9Sstevel@tonic-gate 	}
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	wsp->walk_addr += sizeof (void *);
3947c478bd9Sstevel@tonic-gate 	SD_DATA(current_list_count++);
3957c478bd9Sstevel@tonic-gate 	return (status);
3967c478bd9Sstevel@tonic-gate }
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate /*
4007c478bd9Sstevel@tonic-gate  *    Function: sd_state_walk_fini
4017c478bd9Sstevel@tonic-gate  *
4027c478bd9Sstevel@tonic-gate  * Description: The sd_state_walk_fini is called when the walk is terminated
4037c478bd9Sstevel@tonic-gate  *		in response to WALK_DONE in sd_state_walk_step. It frees
4047c478bd9Sstevel@tonic-gate  *		the walk_data structure.
4057c478bd9Sstevel@tonic-gate  *
4067c478bd9Sstevel@tonic-gate  *   Arguments: mdb_walk_state_t structure
4077c478bd9Sstevel@tonic-gate  */
4087c478bd9Sstevel@tonic-gate static void
sd_state_walk_fini(mdb_walk_state_t * wsp)4097c478bd9Sstevel@tonic-gate sd_state_walk_fini(mdb_walk_state_t *wsp)
4107c478bd9Sstevel@tonic-gate {
4117c478bd9Sstevel@tonic-gate 	mdb_free(wsp->walk_data, sizeof (sd_str_t));
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate /*
4157c478bd9Sstevel@tonic-gate  *    Function: process_sdlun_waitq
4167c478bd9Sstevel@tonic-gate  *
4177c478bd9Sstevel@tonic-gate  * Description: Iterate over the wait Q members of the soft state.
4187c478bd9Sstevel@tonic-gate  *		Print the contents of each member. In case of silent mode
4197c478bd9Sstevel@tonic-gate  *		the contents are avoided and only the address is printed.
4207c478bd9Sstevel@tonic-gate  *
4217c478bd9Sstevel@tonic-gate  *   Arguments: starting queue address, print mode.
4227c478bd9Sstevel@tonic-gate  */
4237c478bd9Sstevel@tonic-gate static int
process_sdlun_waitq(uintptr_t walk_addr,int silent)4247c478bd9Sstevel@tonic-gate process_sdlun_waitq(uintptr_t walk_addr, int silent)
4257c478bd9Sstevel@tonic-gate {
4267c478bd9Sstevel@tonic-gate 	uintptr_t	rootBuf;
4277c478bd9Sstevel@tonic-gate 	buf_t		currentBuf;
4287c478bd9Sstevel@tonic-gate 	int		sdLunQ_count = 0;
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	rootBuf = walk_addr;
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	if (!silent) {
4337c478bd9Sstevel@tonic-gate 		mdb_printf("\nUN WAIT Q:\n");
4347c478bd9Sstevel@tonic-gate 		mdb_printf("----------\n");
4357c478bd9Sstevel@tonic-gate 	}
4367c478bd9Sstevel@tonic-gate 	mdb_printf("UN wait Q head: %lx\n", rootBuf);
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 	while (rootBuf) {
4397c478bd9Sstevel@tonic-gate 		/* Process the device's cmd. wait Q */
4407c478bd9Sstevel@tonic-gate 		if (!silent) {
4417c478bd9Sstevel@tonic-gate 			mdb_printf("UN WAIT Q list entry:\n");
4427c478bd9Sstevel@tonic-gate 			mdb_printf("------------------\n");
4437c478bd9Sstevel@tonic-gate 		}
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 		if (mdb_vread(&currentBuf, sizeof (buf_t),
4467c478bd9Sstevel@tonic-gate 		    (uintptr_t)rootBuf) == -1) {
4477c478bd9Sstevel@tonic-gate 			mdb_warn("failed to read buf at %p",
4487c478bd9Sstevel@tonic-gate 			    (uintptr_t)rootBuf);
4497c478bd9Sstevel@tonic-gate 			return (FAIL);
4507c478bd9Sstevel@tonic-gate 		}
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 		if (!silent) {
4537c478bd9Sstevel@tonic-gate 			mdb_set_dot(rootBuf);
4547c478bd9Sstevel@tonic-gate 			mdb_eval("$<buf");
4557c478bd9Sstevel@tonic-gate 			mdb_printf("---\n");
4567c478bd9Sstevel@tonic-gate 		}
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 		rootBuf = (uintptr_t)currentBuf.av_forw;
4597c478bd9Sstevel@tonic-gate 		++sdLunQ_count;
4607c478bd9Sstevel@tonic-gate 	}
4617c478bd9Sstevel@tonic-gate 
462892ad162SToomas Soome 	if (rootBuf == 0) {
4637c478bd9Sstevel@tonic-gate 		mdb_printf("------------------------------\n");
4647c478bd9Sstevel@tonic-gate 		mdb_printf("Processed %d UN WAIT Q entries\n", sdLunQ_count);
4657c478bd9Sstevel@tonic-gate 		mdb_printf("------------------------------\n");
4667c478bd9Sstevel@tonic-gate 	}
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	return (SUCCESS);
4697c478bd9Sstevel@tonic-gate }
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate /*
4727c478bd9Sstevel@tonic-gate  *    Function: process_xbuf
4737c478bd9Sstevel@tonic-gate  *
4747c478bd9Sstevel@tonic-gate  * Description: Iterate over the Xbuf Attr and Xbuf Attr wait Q of the soft
4757c478bd9Sstevel@tonic-gate  *		state.
4767c478bd9Sstevel@tonic-gate  *		Print the contents of each member. In case of silent mode
4777c478bd9Sstevel@tonic-gate  *		the contents are avoided and only the address is printed.
4787c478bd9Sstevel@tonic-gate  *
4797c478bd9Sstevel@tonic-gate  *   Arguments: starting xbuf address, print mode.
4807c478bd9Sstevel@tonic-gate  */
4817c478bd9Sstevel@tonic-gate static int
process_xbuf(uintptr_t xbuf_attr,int silent)4827c478bd9Sstevel@tonic-gate process_xbuf(uintptr_t xbuf_attr, int silent)
4837c478bd9Sstevel@tonic-gate {
4847c478bd9Sstevel@tonic-gate 	struct __ddi_xbuf_attr	xba;
4857c478bd9Sstevel@tonic-gate 	buf_t			xba_current;
4867c478bd9Sstevel@tonic-gate 	void			*xba_root;
4877c478bd9Sstevel@tonic-gate 	int			xbuf_q_count = 0;
4887c478bd9Sstevel@tonic-gate 
489892ad162SToomas Soome 	if (xbuf_attr == 0) {
4907c478bd9Sstevel@tonic-gate 		mdb_printf("---------------------------\n");
4917c478bd9Sstevel@tonic-gate 		mdb_printf("No XBUF ATTR entry\n");
4927c478bd9Sstevel@tonic-gate 		mdb_printf("---------------------------\n");
4937c478bd9Sstevel@tonic-gate 		return (SUCCESS);
4947c478bd9Sstevel@tonic-gate 	}
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 	/* Process the Xbuf Attr struct for a device. */
4977c478bd9Sstevel@tonic-gate 	if (mdb_vread((void *)&xba, sizeof (struct __ddi_xbuf_attr),
4987c478bd9Sstevel@tonic-gate 	    xbuf_attr) == -1) {
4997c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read xbuf_attr at %p", xbuf_attr);
5007c478bd9Sstevel@tonic-gate 		return (FAIL);
5017c478bd9Sstevel@tonic-gate 	}
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 	if (!silent) {
5047c478bd9Sstevel@tonic-gate 		mdb_printf("\nXBUF ATTR:\n");
5057c478bd9Sstevel@tonic-gate 		mdb_printf("----------\n");
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 		dump_xbuf_attr(&xba, xbuf_attr);
5087c478bd9Sstevel@tonic-gate 		mdb_printf("---\n");
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 		mdb_printf("\nXBUF Q:\n");
5117c478bd9Sstevel@tonic-gate 		mdb_printf("-------\n");
5127c478bd9Sstevel@tonic-gate 	}
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate 	mdb_printf("xbuf Q head: %lx\n", xba.xa_headp);
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 	xba_root = (void *) xba.xa_headp;
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	/* Process the Xbuf Attr wait Q, if there are any entries. */
5197c478bd9Sstevel@tonic-gate 	while ((uintptr_t)xba_root) {
5207c478bd9Sstevel@tonic-gate 		if (!silent) {
5217c478bd9Sstevel@tonic-gate 			mdb_printf("XBUF_Q list entry:\n");
5227c478bd9Sstevel@tonic-gate 			mdb_printf("------------------\n");
5237c478bd9Sstevel@tonic-gate 		}
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 		if (mdb_vread((void *)&xba_current, sizeof (buf_t),
5267c478bd9Sstevel@tonic-gate 		    (uintptr_t)xba_root) == -1) {
5277c478bd9Sstevel@tonic-gate 			mdb_warn("failed to read buf at %p",
5287c478bd9Sstevel@tonic-gate 			    (uintptr_t)xba_root);
5297c478bd9Sstevel@tonic-gate 			return (FAIL);
5307c478bd9Sstevel@tonic-gate 		}
5317c478bd9Sstevel@tonic-gate 		if (!silent) {
5327c478bd9Sstevel@tonic-gate 			mdb_set_dot((uintptr_t)xba_root);
5337c478bd9Sstevel@tonic-gate 			mdb_eval("$<buf");
5347c478bd9Sstevel@tonic-gate 			mdb_printf("---\n");
5357c478bd9Sstevel@tonic-gate 		}
5367c478bd9Sstevel@tonic-gate 		++xbuf_q_count;
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 		xba_root = (void *)xba_current.av_forw;
5397c478bd9Sstevel@tonic-gate 	}
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 	if (xba_root == NULL) {
5427c478bd9Sstevel@tonic-gate 		mdb_printf("---------------------------\n");
5437c478bd9Sstevel@tonic-gate 		mdb_printf("Processed %d XBUF Q entries\n", xbuf_q_count);
5447c478bd9Sstevel@tonic-gate 		mdb_printf("---------------------------\n");
5457c478bd9Sstevel@tonic-gate 	}
5467c478bd9Sstevel@tonic-gate 	return (SUCCESS);
5477c478bd9Sstevel@tonic-gate }
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate /*
5507c478bd9Sstevel@tonic-gate  *    Function: print_footer
5517c478bd9Sstevel@tonic-gate  *
5527c478bd9Sstevel@tonic-gate  * Description: Prints the footer if all the soft state entries are processed.
5537c478bd9Sstevel@tonic-gate  *
5547c478bd9Sstevel@tonic-gate  *   Arguments: private storage of the walker.
5557c478bd9Sstevel@tonic-gate  */
5567c478bd9Sstevel@tonic-gate static void
print_footer(const void * walk_data)5577c478bd9Sstevel@tonic-gate print_footer(const void *walk_data)
5587c478bd9Sstevel@tonic-gate {
5597c478bd9Sstevel@tonic-gate 	if (SD_DATA_IN_CBACK(current_list_count) >=
5607c478bd9Sstevel@tonic-gate 	    (SD_DATA_IN_CBACK(sd_state_data.n_items) - 1)) {
5617c478bd9Sstevel@tonic-gate 		mdb_printf("---------------------------\n");
5627c478bd9Sstevel@tonic-gate 		mdb_printf("Processed %d UN softstate entries\n",
5637c478bd9Sstevel@tonic-gate 		    SD_DATA_IN_CBACK(valid_root_count));
5647c478bd9Sstevel@tonic-gate 		mdb_printf("---------------------------\n");
5657c478bd9Sstevel@tonic-gate 	}
5667c478bd9Sstevel@tonic-gate }
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate /*
5697c478bd9Sstevel@tonic-gate  *    Function: sd_callback
5707c478bd9Sstevel@tonic-gate  *
5717c478bd9Sstevel@tonic-gate  * Description: This is the callback function called by the
5727c478bd9Sstevel@tonic-gate  *		'sd_state/ssd_state' walker when 'sd_state/ssd_state' dcmd
5737c478bd9Sstevel@tonic-gate  *		invokes the walker.
5747c478bd9Sstevel@tonic-gate  *		It is called during each walk step. It displays the contents
5757c478bd9Sstevel@tonic-gate  *		of the current soft state object (addr) passed to it by the
5767c478bd9Sstevel@tonic-gate  *		step function. It also prints the header and footer during the
5777c478bd9Sstevel@tonic-gate  *		first and the last step of the walker.
5787c478bd9Sstevel@tonic-gate  *		The contents of the soft state also includes various queues
5797c478bd9Sstevel@tonic-gate  *		it includes like Xbuf, semo_close, sdlun_waitq.
5807c478bd9Sstevel@tonic-gate  *
5817c478bd9Sstevel@tonic-gate  *   Arguments: addr -> current soft state objects address.
5827c478bd9Sstevel@tonic-gate  *		walk_data -> private storage for the walker.
5837c478bd9Sstevel@tonic-gate  *		flg_silent -> private data for the callback. It represents
5847c478bd9Sstevel@tonic-gate  *		the silent mode of operation.
5857c478bd9Sstevel@tonic-gate  */
5867c478bd9Sstevel@tonic-gate static int
sd_callback(uintptr_t addr,const void * walk_data,void * flg_silent)5877c478bd9Sstevel@tonic-gate sd_callback(uintptr_t addr, const void *walk_data, void *flg_silent)
5887c478bd9Sstevel@tonic-gate {
5897c478bd9Sstevel@tonic-gate 	struct sd_lun	sdLun;
5907c478bd9Sstevel@tonic-gate 	int		silent = *(int *)flg_silent;
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 	/*
5937c478bd9Sstevel@tonic-gate 	 * If this is the first invocation of the command, print a
5947c478bd9Sstevel@tonic-gate 	 * header line for the output that will follow.
5957c478bd9Sstevel@tonic-gate 	 */
5967c478bd9Sstevel@tonic-gate 	if (SD_DATA_IN_CBACK(current_list_count) == 0) {
5977c478bd9Sstevel@tonic-gate 		mdb_printf("walk_addr = %lx\n", SD_DATA_IN_CBACK(sd_state));
5987c478bd9Sstevel@tonic-gate 		mdb_printf("walking sd_state units via ptr: %lx\n",
5997c478bd9Sstevel@tonic-gate 		    SD_DATA_IN_CBACK(current_root));
6007c478bd9Sstevel@tonic-gate 		mdb_printf("%d entries in sd_state table\n",
6017c478bd9Sstevel@tonic-gate 		    SD_DATA_IN_CBACK(sd_state_data.n_items));
6027c478bd9Sstevel@tonic-gate 	}
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	mdb_printf("\nun %d: %lx\n", SD_DATA_IN_CBACK(current_list_count),
6057c478bd9Sstevel@tonic-gate 	    addr);
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate 	mdb_printf("--------------\n");
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 	/* if null soft state iterate over to next one */
6107c478bd9Sstevel@tonic-gate 	if (addr == 0) {
6117c478bd9Sstevel@tonic-gate 		print_footer(walk_data);
6127c478bd9Sstevel@tonic-gate 		return (SUCCESS);
6137c478bd9Sstevel@tonic-gate 	}
6147c478bd9Sstevel@tonic-gate 	/*
6157c478bd9Sstevel@tonic-gate 	 * For each buf, we need to read the sd_lun struct,
6167c478bd9Sstevel@tonic-gate 	 * and then print out its contents, and get the next.
6177c478bd9Sstevel@tonic-gate 	 */
6187c478bd9Sstevel@tonic-gate 	else if (mdb_vread(&sdLun, sizeof (struct sd_lun), (uintptr_t)addr) ==
6197c478bd9Sstevel@tonic-gate 	    sizeof (sdLun)) {
6207c478bd9Sstevel@tonic-gate 		if (!silent) {
6217c478bd9Sstevel@tonic-gate 			mdb_set_dot(addr);
6227c478bd9Sstevel@tonic-gate 			mdb_eval("$<sd_lun");
6237c478bd9Sstevel@tonic-gate 			mdb_printf("---\n");
6247c478bd9Sstevel@tonic-gate 		}
6257c478bd9Sstevel@tonic-gate 	} else {
6267c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read softstate at %p", addr);
6277c478bd9Sstevel@tonic-gate 		return (FAIL);
6287c478bd9Sstevel@tonic-gate 	}
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 	/* process device Xbuf Attr struct and wait Q */
6317c478bd9Sstevel@tonic-gate 	process_xbuf((uintptr_t)sdLun.un_xbuf_attr, silent);
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 	/* process device cmd wait Q */
6347c478bd9Sstevel@tonic-gate 	process_sdlun_waitq((uintptr_t)sdLun.un_waitq_headp, silent);
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 	/* print the actual number of soft state processed */
6377c478bd9Sstevel@tonic-gate 	print_footer(walk_data);
6387c478bd9Sstevel@tonic-gate 	return (SUCCESS);
6397c478bd9Sstevel@tonic-gate }
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate #if (!defined(__fibre))
6427c478bd9Sstevel@tonic-gate /*
6437c478bd9Sstevel@tonic-gate  *    Function: dcmd_sd_state
6447c478bd9Sstevel@tonic-gate  *
6457c478bd9Sstevel@tonic-gate  * Description: Scans through the sd soft state entries and prints their
6467c478bd9Sstevel@tonic-gate  *		contents including of various queues it contains. It uses
6477c478bd9Sstevel@tonic-gate  *		'sd_state' walker to perform a global walk. If a particular
6487c478bd9Sstevel@tonic-gate  *		soft state address is specified than it performs the above job
6497c478bd9Sstevel@tonic-gate  *		itself (local walk).
6507c478bd9Sstevel@tonic-gate  *
6517c478bd9Sstevel@tonic-gate  *   Arguments: addr -> user specified address or NULL if no address is
6527c478bd9Sstevel@tonic-gate  *			specified.
6537c478bd9Sstevel@tonic-gate  *		flags -> integer reflecting whether an address was specified,
6547c478bd9Sstevel@tonic-gate  *			 or if it was invoked by the walker in a loop etc.
6557c478bd9Sstevel@tonic-gate  *		argc -> the number of arguments supplied to the dcmd.
6567c478bd9Sstevel@tonic-gate  *		argv -> the actual arguments supplied by the user.
6577c478bd9Sstevel@tonic-gate  */
6587c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6597c478bd9Sstevel@tonic-gate static int
dcmd_sd_state(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)6607c478bd9Sstevel@tonic-gate dcmd_sd_state(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
6617c478bd9Sstevel@tonic-gate {
6627c478bd9Sstevel@tonic-gate 	struct sd_lun	sdLun;
6637c478bd9Sstevel@tonic-gate 	uint_t		silent = 0;
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate 	/* Enable the silent mode if '-s' option specified the user */
6667c478bd9Sstevel@tonic-gate 	if (mdb_getopts(argc, argv, 's', MDB_OPT_SETBITS, TRUE, &silent, NULL)
6677c478bd9Sstevel@tonic-gate 	    != argc) {
6687c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
6697c478bd9Sstevel@tonic-gate 	}
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 	/*
6727c478bd9Sstevel@tonic-gate 	 * If no address is specified on the command line, perform
6737c478bd9Sstevel@tonic-gate 	 * a global walk invoking 'sd_state' walker. If a particular address
6747c478bd9Sstevel@tonic-gate 	 * is specified then print the soft state and its queues.
6757c478bd9Sstevel@tonic-gate 	 */
6767c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
6777c478bd9Sstevel@tonic-gate 		mdb_walk("sd_state", sd_callback, (void *)&silent);
6787c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
6797c478bd9Sstevel@tonic-gate 	} else {
6807c478bd9Sstevel@tonic-gate 		mdb_printf("\nun: %lx\n", addr);
6817c478bd9Sstevel@tonic-gate 		mdb_printf("--------------\n");
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate 		/* read the sd_lun struct and print the contents */
6847c478bd9Sstevel@tonic-gate 		if (mdb_vread(&sdLun, sizeof (struct sd_lun),
6857c478bd9Sstevel@tonic-gate 		    (uintptr_t)addr) == sizeof (sdLun)) {
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate 			if (!silent) {
6887c478bd9Sstevel@tonic-gate 				mdb_set_dot(addr);
6897c478bd9Sstevel@tonic-gate 				mdb_eval("$<sd_lun");
6907c478bd9Sstevel@tonic-gate 				mdb_printf("---\n");
6917c478bd9Sstevel@tonic-gate 			}
6927c478bd9Sstevel@tonic-gate 		} else {
6937c478bd9Sstevel@tonic-gate 			mdb_warn("failed to read softstate at %p", addr);
6947c478bd9Sstevel@tonic-gate 			return (DCMD_OK);
6957c478bd9Sstevel@tonic-gate 		}
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate 		/* process Xbuf Attr struct and wait Q for the soft state */
6987c478bd9Sstevel@tonic-gate 		process_xbuf((uintptr_t)sdLun.un_xbuf_attr, silent);
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 		/* process device' cmd wait Q */
7017c478bd9Sstevel@tonic-gate 		process_sdlun_waitq((uintptr_t)sdLun.un_waitq_headp, silent);
7027c478bd9Sstevel@tonic-gate 	}
7037c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
7047c478bd9Sstevel@tonic-gate }
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate #else
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate /*
7097c478bd9Sstevel@tonic-gate  *    Function: dcmd_ssd_state
7107c478bd9Sstevel@tonic-gate  *
7117c478bd9Sstevel@tonic-gate  * Description: Scans through the ssd soft state entries and prints their
7127c478bd9Sstevel@tonic-gate  *		contents including of various queues it contains. It uses
7137c478bd9Sstevel@tonic-gate  *		'ssd_state' walker to perform a global walk. If a particular
7147c478bd9Sstevel@tonic-gate  *		soft state address is specified than it performs the above job
7157c478bd9Sstevel@tonic-gate  *		itself (local walk).
7167c478bd9Sstevel@tonic-gate  *
7177c478bd9Sstevel@tonic-gate  *   Arguments: addr -> user specified address or NULL if no address is
7187c478bd9Sstevel@tonic-gate  *			specified.
7197c478bd9Sstevel@tonic-gate  *		flags -> integer reflecting whether an address was specified,
7207c478bd9Sstevel@tonic-gate  *			 or if it was invoked by the walker in a loop etc.
7217c478bd9Sstevel@tonic-gate  *		argc -> the number of arguments supplied to the dcmd.
7227c478bd9Sstevel@tonic-gate  *		argv -> the actual arguments supplied by the user.
7237c478bd9Sstevel@tonic-gate  */
7247c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7257c478bd9Sstevel@tonic-gate static int
dcmd_ssd_state(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)7267c478bd9Sstevel@tonic-gate dcmd_ssd_state(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
7277c478bd9Sstevel@tonic-gate {
7287c478bd9Sstevel@tonic-gate 	struct sd_lun	sdLun;
7297c478bd9Sstevel@tonic-gate 	uint_t		silent = 0;
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 	/* Enable the silent mode if '-s' option specified the user */
7327c478bd9Sstevel@tonic-gate 	if (mdb_getopts(argc, argv, 's', MDB_OPT_SETBITS, TRUE, &silent, NULL)
7337c478bd9Sstevel@tonic-gate 	    != argc) {
7347c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
7357c478bd9Sstevel@tonic-gate 	}
7367c478bd9Sstevel@tonic-gate 
7377c478bd9Sstevel@tonic-gate 	/*
7387c478bd9Sstevel@tonic-gate 	 * If no address is specified on the command line, perform
7397c478bd9Sstevel@tonic-gate 	 * a global walk invoking 'sd_state' walker. If a particular address
7407c478bd9Sstevel@tonic-gate 	 * is specified then print the soft state and its queues.
7417c478bd9Sstevel@tonic-gate 	 */
7427c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
7437c478bd9Sstevel@tonic-gate 		mdb_walk("ssd_state", sd_callback, (void *)&silent);
7447c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
7457c478bd9Sstevel@tonic-gate 	} else {
7467c478bd9Sstevel@tonic-gate 		mdb_printf("\nun: %lx\n", addr);
7477c478bd9Sstevel@tonic-gate 		mdb_printf("--------------\n");
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 		/* read the sd_lun struct and print the contents */
7507c478bd9Sstevel@tonic-gate 		if (mdb_vread(&sdLun, sizeof (struct sd_lun),
7517c478bd9Sstevel@tonic-gate 		    (uintptr_t)addr) == sizeof (sdLun)) {
7527c478bd9Sstevel@tonic-gate 			if (!silent) {
7537c478bd9Sstevel@tonic-gate 				mdb_set_dot(addr);
7547c478bd9Sstevel@tonic-gate 				mdb_eval("$<sd_lun");
7557c478bd9Sstevel@tonic-gate 				mdb_printf("---\n");
7567c478bd9Sstevel@tonic-gate 			}
7577c478bd9Sstevel@tonic-gate 		} else {
7587c478bd9Sstevel@tonic-gate 			mdb_warn("failed to read softstate at %p", addr);
7597c478bd9Sstevel@tonic-gate 			return (DCMD_OK);
7607c478bd9Sstevel@tonic-gate 		}
7617c478bd9Sstevel@tonic-gate 
7627c478bd9Sstevel@tonic-gate 		/* process Xbuf Attr struct and wait Q for the soft state */
7637c478bd9Sstevel@tonic-gate 		process_xbuf((uintptr_t)sdLun.un_xbuf_attr, silent);
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate 		/* process device' cmd wait Q */
7667c478bd9Sstevel@tonic-gate 		process_sdlun_waitq((uintptr_t)sdLun.un_waitq_headp, silent);
7677c478bd9Sstevel@tonic-gate 	}
7687c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
7697c478bd9Sstevel@tonic-gate }
7707c478bd9Sstevel@tonic-gate #endif
7717c478bd9Sstevel@tonic-gate 
7727c478bd9Sstevel@tonic-gate /*
7737c478bd9Sstevel@tonic-gate  *    Function: dcmd_buf_avforw
7747c478bd9Sstevel@tonic-gate  *
7757c478bd9Sstevel@tonic-gate  * Description: Scans through the buf list via av_forw and prints
7767c478bd9Sstevel@tonic-gate  *		their contents.
7777c478bd9Sstevel@tonic-gate  *		It uses the 'buf_avforw' walker to perform the walk.
7787c478bd9Sstevel@tonic-gate  *
7797c478bd9Sstevel@tonic-gate  *   Arguments: addr -> user specified address.
7807c478bd9Sstevel@tonic-gate  *		flags -> integer reflecting whether an address was specified,
7817c478bd9Sstevel@tonic-gate  *			 or if it was invoked by the walker in a loop etc.
7827c478bd9Sstevel@tonic-gate  *		argc -> the number of arguments supplied to the dcmd.
7837c478bd9Sstevel@tonic-gate  *		argv -> the actual arguments supplied by the user.
7847c478bd9Sstevel@tonic-gate  */
7857c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7867c478bd9Sstevel@tonic-gate static int
dcmd_buf_avforw(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)7877c478bd9Sstevel@tonic-gate dcmd_buf_avforw(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
7887c478bd9Sstevel@tonic-gate {
7897c478bd9Sstevel@tonic-gate 	int	buf_entries = 0;
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate 	/* it does not take any arguments */
7927c478bd9Sstevel@tonic-gate 	if (argc != 0)
7937c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate 	/*
7967c478bd9Sstevel@tonic-gate 	 * If no address was specified on the command line, print the
7977c478bd9Sstevel@tonic-gate 	 * error msg, else scan and
7987c478bd9Sstevel@tonic-gate 	 * print out all the buffers available by invoking buf_avforw walker.
7997c478bd9Sstevel@tonic-gate 	 */
8007c478bd9Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC)) {
8017c478bd9Sstevel@tonic-gate 		mdb_pwalk("buf_avforw", buf_callback, (void *)&buf_entries,
8027c478bd9Sstevel@tonic-gate 		    addr);
8037c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
8047c478bd9Sstevel@tonic-gate 	} else {
8057c478bd9Sstevel@tonic-gate 		mdb_printf("buffer address required with the command\n");
8067c478bd9Sstevel@tonic-gate 	}
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate 	return (DCMD_USAGE);
8097c478bd9Sstevel@tonic-gate }
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate /*
8127c478bd9Sstevel@tonic-gate  * MDB module linkage information:
8137c478bd9Sstevel@tonic-gate  *
8147c478bd9Sstevel@tonic-gate  * List of structures describing our dcmds, a list of structures
8157c478bd9Sstevel@tonic-gate  * describing our walkers, and a function named _mdb_init to return a pointer
8167c478bd9Sstevel@tonic-gate  * to our module information.
8177c478bd9Sstevel@tonic-gate  */
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate static const mdb_dcmd_t dcmds[] = {
8207c478bd9Sstevel@tonic-gate 	{ "buf_avforw", ":", "buf_t list via av_forw", dcmd_buf_avforw},
8217c478bd9Sstevel@tonic-gate #if (!defined(__fibre))
8227c478bd9Sstevel@tonic-gate 	{ "sd_state", "[-s]", "sd soft state list", dcmd_sd_state},
8237c478bd9Sstevel@tonic-gate #else
8247c478bd9Sstevel@tonic-gate 	{ "ssd_state", "[-s]", "ssd soft state list", dcmd_ssd_state},
8257c478bd9Sstevel@tonic-gate #endif
8267c478bd9Sstevel@tonic-gate 	{ NULL }
8277c478bd9Sstevel@tonic-gate };
8287c478bd9Sstevel@tonic-gate 
8297c478bd9Sstevel@tonic-gate static const mdb_walker_t walkers[] = {
8307c478bd9Sstevel@tonic-gate 	{ "buf_avforw", "walk list of buf_t structures via av_forw",
8317c478bd9Sstevel@tonic-gate 	buf_avforw_walk_init, buf_avforw_walk_step, buf_avforw_walk_fini },
8327c478bd9Sstevel@tonic-gate #if (!defined(__fibre))
8337c478bd9Sstevel@tonic-gate 	{ "sd_state", "walk all sd soft state queues",
8347c478bd9Sstevel@tonic-gate 		sd_state_walk_init, sd_state_walk_step, sd_state_walk_fini },
8357c478bd9Sstevel@tonic-gate #else
8367c478bd9Sstevel@tonic-gate 	{ "ssd_state", "walk all ssd soft state queues",
8377c478bd9Sstevel@tonic-gate 		ssd_state_walk_init, sd_state_walk_step, sd_state_walk_fini },
8387c478bd9Sstevel@tonic-gate #endif
8397c478bd9Sstevel@tonic-gate 	{ NULL }
8407c478bd9Sstevel@tonic-gate };
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate static const mdb_modinfo_t modinfo = {
8437c478bd9Sstevel@tonic-gate 	MDB_API_VERSION, dcmds, walkers
8447c478bd9Sstevel@tonic-gate };
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate /*
8477c478bd9Sstevel@tonic-gate  *    Function: _mdb_init
8487c478bd9Sstevel@tonic-gate  *
8497c478bd9Sstevel@tonic-gate  * Description: Returns mdb_modinfo_t structure which provides linkage and
8507c478bd9Sstevel@tonic-gate  *		module identification information to the debugger.
8517c478bd9Sstevel@tonic-gate  *
8527c478bd9Sstevel@tonic-gate  *   Arguments: void
8537c478bd9Sstevel@tonic-gate  */
8547c478bd9Sstevel@tonic-gate const mdb_modinfo_t *
_mdb_init(void)8557c478bd9Sstevel@tonic-gate _mdb_init(void)
8567c478bd9Sstevel@tonic-gate {
8577c478bd9Sstevel@tonic-gate 	return (&modinfo);
8587c478bd9Sstevel@tonic-gate }
859