xref: /onnv-gate/usr/src/cmd/mdb/common/modules/fcp/fcp.c (revision 7836:4e95154b5b7a)
1*7836SJohn.Forte@Sun.COM /*
2*7836SJohn.Forte@Sun.COM  * CDDL HEADER START
3*7836SJohn.Forte@Sun.COM  *
4*7836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
5*7836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
6*7836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
7*7836SJohn.Forte@Sun.COM  *
8*7836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*7836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
11*7836SJohn.Forte@Sun.COM  * and limitations under the License.
12*7836SJohn.Forte@Sun.COM  *
13*7836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*7836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*7836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*7836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*7836SJohn.Forte@Sun.COM  *
19*7836SJohn.Forte@Sun.COM  * CDDL HEADER END
20*7836SJohn.Forte@Sun.COM  */
21*7836SJohn.Forte@Sun.COM /*
22*7836SJohn.Forte@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*7836SJohn.Forte@Sun.COM  * Use is subject to license terms.
24*7836SJohn.Forte@Sun.COM  *
25*7836SJohn.Forte@Sun.COM  * FCP mdb module
26*7836SJohn.Forte@Sun.COM  */
27*7836SJohn.Forte@Sun.COM 
28*7836SJohn.Forte@Sun.COM 
29*7836SJohn.Forte@Sun.COM #include <sys/mdb_modapi.h>
30*7836SJohn.Forte@Sun.COM #include <sys/mutex.h>
31*7836SJohn.Forte@Sun.COM #include <sys/modctl.h>
32*7836SJohn.Forte@Sun.COM #include <sys/scsi/scsi.h>
33*7836SJohn.Forte@Sun.COM #include <sys/sunndi.h>
34*7836SJohn.Forte@Sun.COM #include <sys/fibre-channel/fc.h>
35*7836SJohn.Forte@Sun.COM #include <sys/fibre-channel/ulp/fcpvar.h>
36*7836SJohn.Forte@Sun.COM 
37*7836SJohn.Forte@Sun.COM static struct fcp_port	port;
38*7836SJohn.Forte@Sun.COM static struct fcp_tgt	tgt;
39*7836SJohn.Forte@Sun.COM static struct fcp_lun	lun;
40*7836SJohn.Forte@Sun.COM static uint32_t	tgt_hash_index;
41*7836SJohn.Forte@Sun.COM 
42*7836SJohn.Forte@Sun.COM 
43*7836SJohn.Forte@Sun.COM /*
44*7836SJohn.Forte@Sun.COM  * Leadville fcp walker/dcmd code
45*7836SJohn.Forte@Sun.COM  */
46*7836SJohn.Forte@Sun.COM 
47*7836SJohn.Forte@Sun.COM static int
fcp_walk_i(mdb_walk_state_t * wsp)48*7836SJohn.Forte@Sun.COM fcp_walk_i(mdb_walk_state_t *wsp)
49*7836SJohn.Forte@Sun.COM {
50*7836SJohn.Forte@Sun.COM 	if (wsp->walk_addr == NULL &&
51*7836SJohn.Forte@Sun.COM 	    mdb_readvar(&wsp->walk_addr, "fcp_port_head") == -1) {
52*7836SJohn.Forte@Sun.COM 		mdb_warn("failed to read 'fcp_port_head'");
53*7836SJohn.Forte@Sun.COM 		return (WALK_ERR);
54*7836SJohn.Forte@Sun.COM 	}
55*7836SJohn.Forte@Sun.COM 
56*7836SJohn.Forte@Sun.COM 	wsp->walk_data = mdb_alloc(sizeof (struct fcp_port), UM_SLEEP);
57*7836SJohn.Forte@Sun.COM 	return (WALK_NEXT);
58*7836SJohn.Forte@Sun.COM }
59*7836SJohn.Forte@Sun.COM 
60*7836SJohn.Forte@Sun.COM static int
fcp_walk_s(mdb_walk_state_t * wsp)61*7836SJohn.Forte@Sun.COM fcp_walk_s(mdb_walk_state_t *wsp)
62*7836SJohn.Forte@Sun.COM {
63*7836SJohn.Forte@Sun.COM 	int status;
64*7836SJohn.Forte@Sun.COM 
65*7836SJohn.Forte@Sun.COM 	if (wsp->walk_addr == NULL)
66*7836SJohn.Forte@Sun.COM 		return (WALK_DONE);
67*7836SJohn.Forte@Sun.COM 
68*7836SJohn.Forte@Sun.COM 	if (mdb_vread(wsp->walk_data, sizeof (struct fcp_port),
69*7836SJohn.Forte@Sun.COM 	    wsp->walk_addr) == -1) {
70*7836SJohn.Forte@Sun.COM 		mdb_warn("failed to read fcp_port at %p", wsp->walk_addr);
71*7836SJohn.Forte@Sun.COM 		return (WALK_DONE);
72*7836SJohn.Forte@Sun.COM 	}
73*7836SJohn.Forte@Sun.COM 
74*7836SJohn.Forte@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
75*7836SJohn.Forte@Sun.COM 	    wsp->walk_cbdata);
76*7836SJohn.Forte@Sun.COM 
77*7836SJohn.Forte@Sun.COM 	wsp->walk_addr =
78*7836SJohn.Forte@Sun.COM 	    (uintptr_t)(((struct fcp_port *)wsp->walk_data)->port_next);
79*7836SJohn.Forte@Sun.COM 
80*7836SJohn.Forte@Sun.COM 	return (status);
81*7836SJohn.Forte@Sun.COM }
82*7836SJohn.Forte@Sun.COM 
83*7836SJohn.Forte@Sun.COM /*
84*7836SJohn.Forte@Sun.COM  * The walker's fini function is invoked at the end of each walk.
85*7836SJohn.Forte@Sun.COM  */
86*7836SJohn.Forte@Sun.COM static void
fcp_walk_f(mdb_walk_state_t * wsp)87*7836SJohn.Forte@Sun.COM fcp_walk_f(mdb_walk_state_t *wsp)
88*7836SJohn.Forte@Sun.COM {
89*7836SJohn.Forte@Sun.COM 	mdb_free(wsp->walk_data, sizeof (struct fcp_port));
90*7836SJohn.Forte@Sun.COM }
91*7836SJohn.Forte@Sun.COM 
92*7836SJohn.Forte@Sun.COM 
93*7836SJohn.Forte@Sun.COM static int
fcp(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)94*7836SJohn.Forte@Sun.COM fcp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
95*7836SJohn.Forte@Sun.COM {
96*7836SJohn.Forte@Sun.COM 	struct fcp_port		pinfo;
97*7836SJohn.Forte@Sun.COM 
98*7836SJohn.Forte@Sun.COM 	if (argc != 0) {
99*7836SJohn.Forte@Sun.COM 		return (DCMD_USAGE);
100*7836SJohn.Forte@Sun.COM 	}
101*7836SJohn.Forte@Sun.COM 
102*7836SJohn.Forte@Sun.COM 	if (!(flags & DCMD_ADDRSPEC)) {
103*7836SJohn.Forte@Sun.COM 		if (mdb_walk_dcmd("fcp", "fcp",
104*7836SJohn.Forte@Sun.COM 		    argc, argv) == -1) {
105*7836SJohn.Forte@Sun.COM 			mdb_warn("failed to walk 'fcp_port_head'");
106*7836SJohn.Forte@Sun.COM 			return (DCMD_ERR);
107*7836SJohn.Forte@Sun.COM 		}
108*7836SJohn.Forte@Sun.COM 		return (DCMD_OK);
109*7836SJohn.Forte@Sun.COM 	}
110*7836SJohn.Forte@Sun.COM 
111*7836SJohn.Forte@Sun.COM 	mdb_printf("FCP structure at %p\n", addr);
112*7836SJohn.Forte@Sun.COM 
113*7836SJohn.Forte@Sun.COM 	/*
114*7836SJohn.Forte@Sun.COM 	 * For each port, we just need to read the fc_fca_port_t struct, read
115*7836SJohn.Forte@Sun.COM 	 * the port_handle
116*7836SJohn.Forte@Sun.COM 	 */
117*7836SJohn.Forte@Sun.COM 	if (mdb_vread(&pinfo, sizeof (struct fcp_port), addr) !=
118*7836SJohn.Forte@Sun.COM 	    sizeof (struct fcp_port)) {
119*7836SJohn.Forte@Sun.COM 		mdb_warn("failed to read fcp_port at %p", addr);
120*7836SJohn.Forte@Sun.COM 		return (DCMD_OK);
121*7836SJohn.Forte@Sun.COM 	}
122*7836SJohn.Forte@Sun.COM 
123*7836SJohn.Forte@Sun.COM 	mdb_printf("  mutex             : 0x%-08x\n", pinfo.port_mutex);
124*7836SJohn.Forte@Sun.COM 	mdb_printf("  ipkt_list         : 0x%p\n", pinfo.port_ipkt_list);
125*7836SJohn.Forte@Sun.COM 	mdb_printf("  state             : 0x%-08x\n", pinfo.port_state);
126*7836SJohn.Forte@Sun.COM 	mdb_printf("  phys_state        : 0x%-08x\n", pinfo.port_phys_state);
127*7836SJohn.Forte@Sun.COM 	mdb_printf("  top               : %u\n", pinfo.port_topology);
128*7836SJohn.Forte@Sun.COM 	mdb_printf("  sid               : 0x%-06x\n", pinfo.port_id);
129*7836SJohn.Forte@Sun.COM 	mdb_printf("  reset_list        : 0x%p\n", pinfo.port_reset_list);
130*7836SJohn.Forte@Sun.COM 	mdb_printf("  link_cnt          : %u\n", pinfo.port_link_cnt);
131*7836SJohn.Forte@Sun.COM 	mdb_printf("  deadline          : %d\n", pinfo.port_deadline);
132*7836SJohn.Forte@Sun.COM 	mdb_printf("  port wwn          : "
133*7836SJohn.Forte@Sun.COM 	    "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
134*7836SJohn.Forte@Sun.COM 	    pinfo.port_pwwn.raw_wwn[0], pinfo.port_pwwn.raw_wwn[1],
135*7836SJohn.Forte@Sun.COM 	    pinfo.port_pwwn.raw_wwn[2], pinfo.port_pwwn.raw_wwn[3],
136*7836SJohn.Forte@Sun.COM 	    pinfo.port_pwwn.raw_wwn[4], pinfo.port_pwwn.raw_wwn[5],
137*7836SJohn.Forte@Sun.COM 	    pinfo.port_pwwn.raw_wwn[6], pinfo.port_pwwn.raw_wwn[7]);
138*7836SJohn.Forte@Sun.COM 	mdb_printf("  node wwn          : "
139*7836SJohn.Forte@Sun.COM 	    "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
140*7836SJohn.Forte@Sun.COM 	    pinfo.port_nwwn.raw_wwn[0], pinfo.port_nwwn.raw_wwn[1],
141*7836SJohn.Forte@Sun.COM 	    pinfo.port_nwwn.raw_wwn[2], pinfo.port_nwwn.raw_wwn[3],
142*7836SJohn.Forte@Sun.COM 	    pinfo.port_nwwn.raw_wwn[4], pinfo.port_nwwn.raw_wwn[5],
143*7836SJohn.Forte@Sun.COM 	    pinfo.port_nwwn.raw_wwn[6], pinfo.port_nwwn.raw_wwn[7]);
144*7836SJohn.Forte@Sun.COM 	mdb_printf("  handle            : 0x%p\n", pinfo.port_fp_handle);
145*7836SJohn.Forte@Sun.COM 	mdb_printf("  cmd_mutex         : 0x%-08x\n", pinfo.port_pkt_mutex);
146*7836SJohn.Forte@Sun.COM 	mdb_printf("  ncmds             : %u\n", pinfo.port_npkts);
147*7836SJohn.Forte@Sun.COM 	mdb_printf("  pkt_head          : 0x%p\n", pinfo.port_pkt_head);
148*7836SJohn.Forte@Sun.COM 	mdb_printf("  pkt_tail          : 0x%p\n", pinfo.port_pkt_tail);
149*7836SJohn.Forte@Sun.COM 	mdb_printf("  ipkt_cnt          : %d\n", pinfo.port_ipkt_cnt);
150*7836SJohn.Forte@Sun.COM 	mdb_printf("  instance          : %u\n", pinfo.port_instance);
151*7836SJohn.Forte@Sun.COM 	mdb_printf("  max_exch          : %u\n", pinfo.port_max_exch);
152*7836SJohn.Forte@Sun.COM 	mdb_printf("  cmds_aborted      : 0x%-08x\n",
153*7836SJohn.Forte@Sun.COM 	    pinfo.port_reset_action);
154*7836SJohn.Forte@Sun.COM 	mdb_printf("  cmds_dma_flags    : 0x%-08x\n",
155*7836SJohn.Forte@Sun.COM 	    pinfo.port_cmds_dma_flags);
156*7836SJohn.Forte@Sun.COM 	mdb_printf("  fcp_dma           : 0x%-08x\n", pinfo.port_fcp_dma);
157*7836SJohn.Forte@Sun.COM 	mdb_printf("  priv_pkt_len      : %u\n", pinfo.port_priv_pkt_len);
158*7836SJohn.Forte@Sun.COM 	mdb_printf("  data_dma_attr     : 0x%-08x\n",
159*7836SJohn.Forte@Sun.COM 	    pinfo.port_data_dma_attr);
160*7836SJohn.Forte@Sun.COM 	mdb_printf("  cmd_dma_attr      : 0x%-08x\n",
161*7836SJohn.Forte@Sun.COM 	    pinfo.port_cmd_dma_attr);
162*7836SJohn.Forte@Sun.COM 	mdb_printf("  resp_dma_attr     : 0x%-08x\n",
163*7836SJohn.Forte@Sun.COM 	    pinfo.port_resp_dma_attr);
164*7836SJohn.Forte@Sun.COM 	mdb_printf("  dma_acc_attr      : 0x%-08x\n",
165*7836SJohn.Forte@Sun.COM 	    pinfo.port_dma_acc_attr);
166*7836SJohn.Forte@Sun.COM 	mdb_printf("  tran              : 0x%p\n", pinfo.port_tran);
167*7836SJohn.Forte@Sun.COM 	mdb_printf("  dip               : 0x%p\n", pinfo.port_dip);
168*7836SJohn.Forte@Sun.COM 	mdb_printf("  reset_notify_listf: 0x%p\n",
169*7836SJohn.Forte@Sun.COM 	    pinfo.port_reset_notify_listf);
170*7836SJohn.Forte@Sun.COM 	mdb_printf("  event_defs        : 0x%p\n", pinfo.port_ndi_event_defs);
171*7836SJohn.Forte@Sun.COM 	mdb_printf("  event_hdl         : 0x%p\n", pinfo.port_ndi_event_hdl);
172*7836SJohn.Forte@Sun.COM 	mdb_printf("  events            : 0x%p\n", pinfo.port_ndi_events);
173*7836SJohn.Forte@Sun.COM 	mdb_printf("  tgt_hash_table    : 0x%p\n", pinfo.port_tgt_hash_table);
174*7836SJohn.Forte@Sun.COM 	mdb_printf("  mpxio             : %d\n", pinfo.port_mpxio);
175*7836SJohn.Forte@Sun.COM 
176*7836SJohn.Forte@Sun.COM 	mdb_printf("\n");
177*7836SJohn.Forte@Sun.COM 
178*7836SJohn.Forte@Sun.COM 	return (DCMD_OK);
179*7836SJohn.Forte@Sun.COM }
180*7836SJohn.Forte@Sun.COM 
181*7836SJohn.Forte@Sun.COM 
182*7836SJohn.Forte@Sun.COM /*
183*7836SJohn.Forte@Sun.COM  * Leadville cmds walker/dcmd code
184*7836SJohn.Forte@Sun.COM  */
185*7836SJohn.Forte@Sun.COM 
186*7836SJohn.Forte@Sun.COM static int
cmds_walk_i(mdb_walk_state_t * wsp)187*7836SJohn.Forte@Sun.COM cmds_walk_i(mdb_walk_state_t *wsp)
188*7836SJohn.Forte@Sun.COM {
189*7836SJohn.Forte@Sun.COM 	if (wsp->walk_addr == NULL) {
190*7836SJohn.Forte@Sun.COM 		mdb_warn("Can not perform global walk");
191*7836SJohn.Forte@Sun.COM 		return (WALK_ERR);
192*7836SJohn.Forte@Sun.COM 	}
193*7836SJohn.Forte@Sun.COM 
194*7836SJohn.Forte@Sun.COM 	/*
195*7836SJohn.Forte@Sun.COM 	 * Input should be a fcp_lun, so read it to get the fcp_pkt
196*7836SJohn.Forte@Sun.COM 	 * lists's head
197*7836SJohn.Forte@Sun.COM 	 */
198*7836SJohn.Forte@Sun.COM 
199*7836SJohn.Forte@Sun.COM 	if (mdb_vread(&lun, sizeof (struct fcp_lun), wsp->walk_addr) !=
200*7836SJohn.Forte@Sun.COM 	    sizeof (struct fcp_lun)) {
201*7836SJohn.Forte@Sun.COM 		mdb_warn("Unable to read in the fcp_lun structure address\n");
202*7836SJohn.Forte@Sun.COM 		return (WALK_ERR);
203*7836SJohn.Forte@Sun.COM 	}
204*7836SJohn.Forte@Sun.COM 
205*7836SJohn.Forte@Sun.COM 	wsp->walk_addr = (uintptr_t)(lun.lun_pkt_head);
206*7836SJohn.Forte@Sun.COM 	wsp->walk_data = mdb_alloc(sizeof (struct fcp_pkt), UM_SLEEP);
207*7836SJohn.Forte@Sun.COM 
208*7836SJohn.Forte@Sun.COM 	return (WALK_NEXT);
209*7836SJohn.Forte@Sun.COM }
210*7836SJohn.Forte@Sun.COM 
211*7836SJohn.Forte@Sun.COM static int
cmds_walk_s(mdb_walk_state_t * wsp)212*7836SJohn.Forte@Sun.COM cmds_walk_s(mdb_walk_state_t *wsp)
213*7836SJohn.Forte@Sun.COM {
214*7836SJohn.Forte@Sun.COM 	int status;
215*7836SJohn.Forte@Sun.COM 
216*7836SJohn.Forte@Sun.COM 	if (wsp->walk_addr == NULL)
217*7836SJohn.Forte@Sun.COM 		return (WALK_DONE);
218*7836SJohn.Forte@Sun.COM 
219*7836SJohn.Forte@Sun.COM 	if (mdb_vread(wsp->walk_data, sizeof (struct fcp_pkt),
220*7836SJohn.Forte@Sun.COM 	    wsp->walk_addr) == -1) {
221*7836SJohn.Forte@Sun.COM 		mdb_warn("failed to read fcp_pkt at %p", wsp->walk_addr);
222*7836SJohn.Forte@Sun.COM 		return (WALK_DONE);
223*7836SJohn.Forte@Sun.COM 	}
224*7836SJohn.Forte@Sun.COM 
225*7836SJohn.Forte@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
226*7836SJohn.Forte@Sun.COM 	    wsp->walk_cbdata);
227*7836SJohn.Forte@Sun.COM 
228*7836SJohn.Forte@Sun.COM 	wsp->walk_addr =
229*7836SJohn.Forte@Sun.COM 	    (uintptr_t)(((struct fcp_pkt *)wsp->walk_data)->cmd_forw);
230*7836SJohn.Forte@Sun.COM 
231*7836SJohn.Forte@Sun.COM 	return (status);
232*7836SJohn.Forte@Sun.COM }
233*7836SJohn.Forte@Sun.COM 
234*7836SJohn.Forte@Sun.COM /*
235*7836SJohn.Forte@Sun.COM  * The walker's fini function is invoked at the end of each walk.
236*7836SJohn.Forte@Sun.COM  */
237*7836SJohn.Forte@Sun.COM static void
cmds_walk_f(mdb_walk_state_t * wsp)238*7836SJohn.Forte@Sun.COM cmds_walk_f(mdb_walk_state_t *wsp)
239*7836SJohn.Forte@Sun.COM {
240*7836SJohn.Forte@Sun.COM 	mdb_free(wsp->walk_data, sizeof (struct fcp_pkt));
241*7836SJohn.Forte@Sun.COM }
242*7836SJohn.Forte@Sun.COM 
243*7836SJohn.Forte@Sun.COM 
244*7836SJohn.Forte@Sun.COM /*
245*7836SJohn.Forte@Sun.COM  * Leadville luns walker/dcmd code
246*7836SJohn.Forte@Sun.COM  */
247*7836SJohn.Forte@Sun.COM 
248*7836SJohn.Forte@Sun.COM static int
luns_walk_i(mdb_walk_state_t * wsp)249*7836SJohn.Forte@Sun.COM luns_walk_i(mdb_walk_state_t *wsp)
250*7836SJohn.Forte@Sun.COM {
251*7836SJohn.Forte@Sun.COM 	if (wsp->walk_addr == NULL) {
252*7836SJohn.Forte@Sun.COM 		mdb_warn("Can not perform global walk");
253*7836SJohn.Forte@Sun.COM 		return (WALK_ERR);
254*7836SJohn.Forte@Sun.COM 	}
255*7836SJohn.Forte@Sun.COM 
256*7836SJohn.Forte@Sun.COM 	/*
257*7836SJohn.Forte@Sun.COM 	 * Input should be a fcp_tgt, so read it to get the fcp_lun
258*7836SJohn.Forte@Sun.COM 	 * lists's head
259*7836SJohn.Forte@Sun.COM 	 */
260*7836SJohn.Forte@Sun.COM 
261*7836SJohn.Forte@Sun.COM 	if (mdb_vread(&tgt, sizeof (struct fcp_tgt), wsp->walk_addr) !=
262*7836SJohn.Forte@Sun.COM 	    sizeof (struct fcp_tgt)) {
263*7836SJohn.Forte@Sun.COM 		mdb_warn("Unable to read in the fcp_tgt structure address\n");
264*7836SJohn.Forte@Sun.COM 		return (WALK_ERR);
265*7836SJohn.Forte@Sun.COM 	}
266*7836SJohn.Forte@Sun.COM 
267*7836SJohn.Forte@Sun.COM 	wsp->walk_addr = (uintptr_t)(tgt.tgt_lun);
268*7836SJohn.Forte@Sun.COM 	wsp->walk_data = mdb_alloc(sizeof (struct fcp_lun), UM_SLEEP);
269*7836SJohn.Forte@Sun.COM 
270*7836SJohn.Forte@Sun.COM 	return (WALK_NEXT);
271*7836SJohn.Forte@Sun.COM }
272*7836SJohn.Forte@Sun.COM 
273*7836SJohn.Forte@Sun.COM static int
luns_walk_s(mdb_walk_state_t * wsp)274*7836SJohn.Forte@Sun.COM luns_walk_s(mdb_walk_state_t *wsp)
275*7836SJohn.Forte@Sun.COM {
276*7836SJohn.Forte@Sun.COM 	int status;
277*7836SJohn.Forte@Sun.COM 
278*7836SJohn.Forte@Sun.COM 	if (wsp->walk_addr == NULL)
279*7836SJohn.Forte@Sun.COM 		return (WALK_DONE);
280*7836SJohn.Forte@Sun.COM 
281*7836SJohn.Forte@Sun.COM 	if (mdb_vread(wsp->walk_data, sizeof (struct fcp_lun),
282*7836SJohn.Forte@Sun.COM 	    wsp->walk_addr) == -1) {
283*7836SJohn.Forte@Sun.COM 		mdb_warn("failed to read fcp_pkt at %p", wsp->walk_addr);
284*7836SJohn.Forte@Sun.COM 		return (WALK_DONE);
285*7836SJohn.Forte@Sun.COM 	}
286*7836SJohn.Forte@Sun.COM 
287*7836SJohn.Forte@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
288*7836SJohn.Forte@Sun.COM 	    wsp->walk_cbdata);
289*7836SJohn.Forte@Sun.COM 
290*7836SJohn.Forte@Sun.COM 	wsp->walk_addr =
291*7836SJohn.Forte@Sun.COM 	    (uintptr_t)(((struct fcp_lun *)wsp->walk_data)->lun_next);
292*7836SJohn.Forte@Sun.COM 
293*7836SJohn.Forte@Sun.COM 	return (status);
294*7836SJohn.Forte@Sun.COM }
295*7836SJohn.Forte@Sun.COM 
296*7836SJohn.Forte@Sun.COM /*
297*7836SJohn.Forte@Sun.COM  * The walker's fini function is invoked at the end of each walk.
298*7836SJohn.Forte@Sun.COM  */
299*7836SJohn.Forte@Sun.COM static void
luns_walk_f(mdb_walk_state_t * wsp)300*7836SJohn.Forte@Sun.COM luns_walk_f(mdb_walk_state_t *wsp)
301*7836SJohn.Forte@Sun.COM {
302*7836SJohn.Forte@Sun.COM 	mdb_free(wsp->walk_data, sizeof (struct fcp_lun));
303*7836SJohn.Forte@Sun.COM }
304*7836SJohn.Forte@Sun.COM 
305*7836SJohn.Forte@Sun.COM 
306*7836SJohn.Forte@Sun.COM /*
307*7836SJohn.Forte@Sun.COM  * Leadville targets walker/dcmd code
308*7836SJohn.Forte@Sun.COM  */
309*7836SJohn.Forte@Sun.COM 
310*7836SJohn.Forte@Sun.COM static int
targets_walk_i(mdb_walk_state_t * wsp)311*7836SJohn.Forte@Sun.COM targets_walk_i(mdb_walk_state_t *wsp)
312*7836SJohn.Forte@Sun.COM {
313*7836SJohn.Forte@Sun.COM 	if (wsp->walk_addr == NULL) {
314*7836SJohn.Forte@Sun.COM 		mdb_warn("Can not perform global walk\n");
315*7836SJohn.Forte@Sun.COM 		return (WALK_ERR);
316*7836SJohn.Forte@Sun.COM 	}
317*7836SJohn.Forte@Sun.COM 
318*7836SJohn.Forte@Sun.COM 	/*
319*7836SJohn.Forte@Sun.COM 	 * Input should be a fcp_port, so read it to get the port_tgt
320*7836SJohn.Forte@Sun.COM 	 * table's head
321*7836SJohn.Forte@Sun.COM 	 */
322*7836SJohn.Forte@Sun.COM 
323*7836SJohn.Forte@Sun.COM 	if (mdb_vread(&port, sizeof (struct fcp_port), wsp->walk_addr) !=
324*7836SJohn.Forte@Sun.COM 	    sizeof (struct fcp_port)) {
325*7836SJohn.Forte@Sun.COM 		mdb_warn("Unable to read in the port structure address\n");
326*7836SJohn.Forte@Sun.COM 		return (WALK_ERR);
327*7836SJohn.Forte@Sun.COM 	}
328*7836SJohn.Forte@Sun.COM 
329*7836SJohn.Forte@Sun.COM 	tgt_hash_index = 0;
330*7836SJohn.Forte@Sun.COM 
331*7836SJohn.Forte@Sun.COM 	while ((port.port_tgt_hash_table[tgt_hash_index] == NULL) &&
332*7836SJohn.Forte@Sun.COM 	    (tgt_hash_index < FCP_NUM_HASH)) {
333*7836SJohn.Forte@Sun.COM 		tgt_hash_index++;
334*7836SJohn.Forte@Sun.COM 	}
335*7836SJohn.Forte@Sun.COM 
336*7836SJohn.Forte@Sun.COM 	wsp->walk_addr = (uintptr_t)(port.port_tgt_hash_table[tgt_hash_index]);
337*7836SJohn.Forte@Sun.COM 
338*7836SJohn.Forte@Sun.COM 	wsp->walk_data = mdb_alloc(sizeof (struct fcp_tgt), UM_SLEEP);
339*7836SJohn.Forte@Sun.COM 
340*7836SJohn.Forte@Sun.COM 	return (WALK_NEXT);
341*7836SJohn.Forte@Sun.COM }
342*7836SJohn.Forte@Sun.COM 
343*7836SJohn.Forte@Sun.COM static int
targets_walk_s(mdb_walk_state_t * wsp)344*7836SJohn.Forte@Sun.COM targets_walk_s(mdb_walk_state_t *wsp)
345*7836SJohn.Forte@Sun.COM {
346*7836SJohn.Forte@Sun.COM 	int status;
347*7836SJohn.Forte@Sun.COM 
348*7836SJohn.Forte@Sun.COM 	if ((wsp->walk_addr == NULL) &&
349*7836SJohn.Forte@Sun.COM 	    (tgt_hash_index >= (FCP_NUM_HASH - 1))) {
350*7836SJohn.Forte@Sun.COM 		return (WALK_DONE);
351*7836SJohn.Forte@Sun.COM 	}
352*7836SJohn.Forte@Sun.COM 
353*7836SJohn.Forte@Sun.COM 	if (mdb_vread(wsp->walk_data, sizeof (struct fcp_tgt),
354*7836SJohn.Forte@Sun.COM 	    wsp->walk_addr) == -1) {
355*7836SJohn.Forte@Sun.COM 		mdb_warn("failed to read fcp_tgt at %p", wsp->walk_addr);
356*7836SJohn.Forte@Sun.COM 		return (WALK_DONE);
357*7836SJohn.Forte@Sun.COM 	}
358*7836SJohn.Forte@Sun.COM 
359*7836SJohn.Forte@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
360*7836SJohn.Forte@Sun.COM 	    wsp->walk_cbdata);
361*7836SJohn.Forte@Sun.COM 
362*7836SJohn.Forte@Sun.COM 	wsp->walk_addr =
363*7836SJohn.Forte@Sun.COM 	    (uintptr_t)(((struct fcp_tgt *)wsp->walk_data)->tgt_next);
364*7836SJohn.Forte@Sun.COM 
365*7836SJohn.Forte@Sun.COM 	if (wsp->walk_addr == NULL) {
366*7836SJohn.Forte@Sun.COM 		/*
367*7836SJohn.Forte@Sun.COM 		 * locate the next hash list
368*7836SJohn.Forte@Sun.COM 		 */
369*7836SJohn.Forte@Sun.COM 
370*7836SJohn.Forte@Sun.COM 		tgt_hash_index++;
371*7836SJohn.Forte@Sun.COM 
372*7836SJohn.Forte@Sun.COM 		while ((port.port_tgt_hash_table[tgt_hash_index] == NULL) &&
373*7836SJohn.Forte@Sun.COM 		    (tgt_hash_index < FCP_NUM_HASH)) {
374*7836SJohn.Forte@Sun.COM 			tgt_hash_index++;
375*7836SJohn.Forte@Sun.COM 		}
376*7836SJohn.Forte@Sun.COM 
377*7836SJohn.Forte@Sun.COM 		if (tgt_hash_index == FCP_NUM_HASH) {
378*7836SJohn.Forte@Sun.COM 			/* You're done */
379*7836SJohn.Forte@Sun.COM 			return (status);
380*7836SJohn.Forte@Sun.COM 		}
381*7836SJohn.Forte@Sun.COM 
382*7836SJohn.Forte@Sun.COM 		wsp->walk_addr =
383*7836SJohn.Forte@Sun.COM 		    (uintptr_t)(port.port_tgt_hash_table[tgt_hash_index]);
384*7836SJohn.Forte@Sun.COM 	}
385*7836SJohn.Forte@Sun.COM 
386*7836SJohn.Forte@Sun.COM 	return (status);
387*7836SJohn.Forte@Sun.COM }
388*7836SJohn.Forte@Sun.COM 
389*7836SJohn.Forte@Sun.COM /*
390*7836SJohn.Forte@Sun.COM  * The walker's fini function is invoked at the end of each walk.
391*7836SJohn.Forte@Sun.COM  */
392*7836SJohn.Forte@Sun.COM static void
targets_walk_f(mdb_walk_state_t * wsp)393*7836SJohn.Forte@Sun.COM targets_walk_f(mdb_walk_state_t *wsp)
394*7836SJohn.Forte@Sun.COM {
395*7836SJohn.Forte@Sun.COM 	mdb_free(wsp->walk_data, sizeof (struct fcp_tgt));
396*7836SJohn.Forte@Sun.COM }
397*7836SJohn.Forte@Sun.COM 
398*7836SJohn.Forte@Sun.COM 
399*7836SJohn.Forte@Sun.COM /*
400*7836SJohn.Forte@Sun.COM  * Leadville fcp_ipkt walker/dcmd code
401*7836SJohn.Forte@Sun.COM  */
402*7836SJohn.Forte@Sun.COM 
403*7836SJohn.Forte@Sun.COM static int
ipkt_walk_i(mdb_walk_state_t * wsp)404*7836SJohn.Forte@Sun.COM ipkt_walk_i(mdb_walk_state_t *wsp)
405*7836SJohn.Forte@Sun.COM {
406*7836SJohn.Forte@Sun.COM 	if (wsp->walk_addr == NULL) {
407*7836SJohn.Forte@Sun.COM 		mdb_warn("The address of a fcp_port"
408*7836SJohn.Forte@Sun.COM 		    " structure must be given\n");
409*7836SJohn.Forte@Sun.COM 		return (WALK_ERR);
410*7836SJohn.Forte@Sun.COM 	}
411*7836SJohn.Forte@Sun.COM 
412*7836SJohn.Forte@Sun.COM 	/*
413*7836SJohn.Forte@Sun.COM 	 * Input should be a fcp_port, so read it to get the ipkt
414*7836SJohn.Forte@Sun.COM 	 * list's head
415*7836SJohn.Forte@Sun.COM 	 */
416*7836SJohn.Forte@Sun.COM 
417*7836SJohn.Forte@Sun.COM 	if (mdb_vread(&port, sizeof (struct fcp_port), wsp->walk_addr) !=
418*7836SJohn.Forte@Sun.COM 	    sizeof (struct fcp_port)) {
419*7836SJohn.Forte@Sun.COM 		mdb_warn("Failed to read in the fcp_port"
420*7836SJohn.Forte@Sun.COM 		    " at 0x%p\n", wsp->walk_addr);
421*7836SJohn.Forte@Sun.COM 		return (WALK_ERR);
422*7836SJohn.Forte@Sun.COM 	}
423*7836SJohn.Forte@Sun.COM 
424*7836SJohn.Forte@Sun.COM 	wsp->walk_addr = (uintptr_t)(port.port_ipkt_list);
425*7836SJohn.Forte@Sun.COM 	wsp->walk_data = mdb_alloc(sizeof (struct fcp_ipkt), UM_SLEEP);
426*7836SJohn.Forte@Sun.COM 
427*7836SJohn.Forte@Sun.COM 	return (WALK_NEXT);
428*7836SJohn.Forte@Sun.COM }
429*7836SJohn.Forte@Sun.COM 
430*7836SJohn.Forte@Sun.COM static int
ipkt_walk_s(mdb_walk_state_t * wsp)431*7836SJohn.Forte@Sun.COM ipkt_walk_s(mdb_walk_state_t *wsp)
432*7836SJohn.Forte@Sun.COM {
433*7836SJohn.Forte@Sun.COM 	int status;
434*7836SJohn.Forte@Sun.COM 
435*7836SJohn.Forte@Sun.COM 	if (wsp->walk_addr == NULL)
436*7836SJohn.Forte@Sun.COM 		return (WALK_DONE);
437*7836SJohn.Forte@Sun.COM 
438*7836SJohn.Forte@Sun.COM 	if (mdb_vread(wsp->walk_data, sizeof (struct fcp_ipkt),
439*7836SJohn.Forte@Sun.COM 	    wsp->walk_addr) == -1) {
440*7836SJohn.Forte@Sun.COM 		mdb_warn("Failed to read in the fcp_ipkt"
441*7836SJohn.Forte@Sun.COM 		    " at 0x%p\n", wsp->walk_addr);
442*7836SJohn.Forte@Sun.COM 		return (WALK_DONE);
443*7836SJohn.Forte@Sun.COM 	}
444*7836SJohn.Forte@Sun.COM 
445*7836SJohn.Forte@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
446*7836SJohn.Forte@Sun.COM 	    wsp->walk_cbdata);
447*7836SJohn.Forte@Sun.COM 
448*7836SJohn.Forte@Sun.COM 	wsp->walk_addr =
449*7836SJohn.Forte@Sun.COM 	    (uintptr_t)(((struct fcp_ipkt *)wsp->walk_data)->ipkt_next);
450*7836SJohn.Forte@Sun.COM 
451*7836SJohn.Forte@Sun.COM 	return (status);
452*7836SJohn.Forte@Sun.COM }
453*7836SJohn.Forte@Sun.COM 
454*7836SJohn.Forte@Sun.COM /*
455*7836SJohn.Forte@Sun.COM  * The walker's fini function is invoked at the end of each walk.
456*7836SJohn.Forte@Sun.COM  */
457*7836SJohn.Forte@Sun.COM static void
ipkt_walk_f(mdb_walk_state_t * wsp)458*7836SJohn.Forte@Sun.COM ipkt_walk_f(mdb_walk_state_t *wsp)
459*7836SJohn.Forte@Sun.COM {
460*7836SJohn.Forte@Sun.COM 	mdb_free(wsp->walk_data, sizeof (struct fcp_ipkt));
461*7836SJohn.Forte@Sun.COM }
462*7836SJohn.Forte@Sun.COM 
463*7836SJohn.Forte@Sun.COM /*
464*7836SJohn.Forte@Sun.COM  * Leadville fcp_pkt walker/dcmd code
465*7836SJohn.Forte@Sun.COM  */
466*7836SJohn.Forte@Sun.COM 
467*7836SJohn.Forte@Sun.COM static int
pkt_walk_i(mdb_walk_state_t * wsp)468*7836SJohn.Forte@Sun.COM pkt_walk_i(mdb_walk_state_t *wsp)
469*7836SJohn.Forte@Sun.COM {
470*7836SJohn.Forte@Sun.COM 	if (wsp->walk_addr == NULL) {
471*7836SJohn.Forte@Sun.COM 		mdb_warn("The address of a fcp_port"
472*7836SJohn.Forte@Sun.COM 		    " structure must be given\n");
473*7836SJohn.Forte@Sun.COM 		return (WALK_ERR);
474*7836SJohn.Forte@Sun.COM 	}
475*7836SJohn.Forte@Sun.COM 
476*7836SJohn.Forte@Sun.COM 	/*
477*7836SJohn.Forte@Sun.COM 	 * Input should be an fcp_port, so read it to get the pkt
478*7836SJohn.Forte@Sun.COM 	 * list's head
479*7836SJohn.Forte@Sun.COM 	 */
480*7836SJohn.Forte@Sun.COM 
481*7836SJohn.Forte@Sun.COM 	if (mdb_vread(&port, sizeof (struct fcp_port), wsp->walk_addr) !=
482*7836SJohn.Forte@Sun.COM 	    sizeof (struct fcp_port)) {
483*7836SJohn.Forte@Sun.COM 		mdb_warn("Failed to read in the fcp_port"
484*7836SJohn.Forte@Sun.COM 		    " at 0x%p\n", wsp->walk_addr);
485*7836SJohn.Forte@Sun.COM 		return (WALK_ERR);
486*7836SJohn.Forte@Sun.COM 	}
487*7836SJohn.Forte@Sun.COM 
488*7836SJohn.Forte@Sun.COM 	wsp->walk_addr = (uintptr_t)(port.port_pkt_head);
489*7836SJohn.Forte@Sun.COM 	wsp->walk_data = mdb_alloc(sizeof (struct fcp_pkt), UM_SLEEP);
490*7836SJohn.Forte@Sun.COM 
491*7836SJohn.Forte@Sun.COM 	return (WALK_NEXT);
492*7836SJohn.Forte@Sun.COM }
493*7836SJohn.Forte@Sun.COM 
494*7836SJohn.Forte@Sun.COM static int
pkt_walk_s(mdb_walk_state_t * wsp)495*7836SJohn.Forte@Sun.COM pkt_walk_s(mdb_walk_state_t *wsp)
496*7836SJohn.Forte@Sun.COM {
497*7836SJohn.Forte@Sun.COM 	int status;
498*7836SJohn.Forte@Sun.COM 
499*7836SJohn.Forte@Sun.COM 	if (wsp->walk_addr == NULL)
500*7836SJohn.Forte@Sun.COM 		return (WALK_DONE);
501*7836SJohn.Forte@Sun.COM 
502*7836SJohn.Forte@Sun.COM 	if (mdb_vread(wsp->walk_data, sizeof (struct fcp_pkt),
503*7836SJohn.Forte@Sun.COM 	    wsp->walk_addr) == -1) {
504*7836SJohn.Forte@Sun.COM 		mdb_warn("Failed to read in the fcp_pkt"
505*7836SJohn.Forte@Sun.COM 		    " at 0x%p\n", wsp->walk_addr);
506*7836SJohn.Forte@Sun.COM 		return (WALK_DONE);
507*7836SJohn.Forte@Sun.COM 	}
508*7836SJohn.Forte@Sun.COM 
509*7836SJohn.Forte@Sun.COM 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
510*7836SJohn.Forte@Sun.COM 	    wsp->walk_cbdata);
511*7836SJohn.Forte@Sun.COM 
512*7836SJohn.Forte@Sun.COM 	wsp->walk_addr =
513*7836SJohn.Forte@Sun.COM 	    (uintptr_t)(((struct fcp_pkt *)wsp->walk_data)->cmd_next);
514*7836SJohn.Forte@Sun.COM 
515*7836SJohn.Forte@Sun.COM 	return (status);
516*7836SJohn.Forte@Sun.COM }
517*7836SJohn.Forte@Sun.COM 
518*7836SJohn.Forte@Sun.COM /*
519*7836SJohn.Forte@Sun.COM  * The walker's fini function is invoked at the end of each walk.
520*7836SJohn.Forte@Sun.COM  */
521*7836SJohn.Forte@Sun.COM static void
pkt_walk_f(mdb_walk_state_t * wsp)522*7836SJohn.Forte@Sun.COM pkt_walk_f(mdb_walk_state_t *wsp)
523*7836SJohn.Forte@Sun.COM {
524*7836SJohn.Forte@Sun.COM 	mdb_free(wsp->walk_data, sizeof (struct fcp_pkt));
525*7836SJohn.Forte@Sun.COM }
526*7836SJohn.Forte@Sun.COM 
527*7836SJohn.Forte@Sun.COM /*
528*7836SJohn.Forte@Sun.COM  * MDB module linkage information:
529*7836SJohn.Forte@Sun.COM  *
530*7836SJohn.Forte@Sun.COM  * We declare a list of structures describing our dcmds, a list of structures
531*7836SJohn.Forte@Sun.COM  * describing our walkers, and a function named _mdb_init to return a pointer
532*7836SJohn.Forte@Sun.COM  * to our module information.
533*7836SJohn.Forte@Sun.COM  */
534*7836SJohn.Forte@Sun.COM 
535*7836SJohn.Forte@Sun.COM static const mdb_dcmd_t dcmds[] = {
536*7836SJohn.Forte@Sun.COM 	{ "fcp", NULL, "Leadville fcp instances", fcp },
537*7836SJohn.Forte@Sun.COM 	{ NULL }
538*7836SJohn.Forte@Sun.COM };
539*7836SJohn.Forte@Sun.COM 
540*7836SJohn.Forte@Sun.COM static const mdb_walker_t walkers[] = {
541*7836SJohn.Forte@Sun.COM 	{ "fcp", "Walk list of Leadville fcp instances",
542*7836SJohn.Forte@Sun.COM 		fcp_walk_i, fcp_walk_s, fcp_walk_f },
543*7836SJohn.Forte@Sun.COM 	{ "cmds", "Walk list of SCSI commands in fcp's per-lun queue",
544*7836SJohn.Forte@Sun.COM 		cmds_walk_i, cmds_walk_s, cmds_walk_f },
545*7836SJohn.Forte@Sun.COM 	{ "luns", "Walk list of LUNs in an fcp target",
546*7836SJohn.Forte@Sun.COM 		luns_walk_i, luns_walk_s, luns_walk_f },
547*7836SJohn.Forte@Sun.COM 	{ "targets", "Walk list of fcp targets attached to the local port",
548*7836SJohn.Forte@Sun.COM 		targets_walk_i, targets_walk_s, targets_walk_f },
549*7836SJohn.Forte@Sun.COM 	{ "fcp_ipkt", "Walk list of internal packets queued on a local port",
550*7836SJohn.Forte@Sun.COM 		ipkt_walk_i, ipkt_walk_s, ipkt_walk_f},
551*7836SJohn.Forte@Sun.COM 	{ "fcp_pkt", "Walk list of packets queued on a local port",
552*7836SJohn.Forte@Sun.COM 		pkt_walk_i, pkt_walk_s, pkt_walk_f},
553*7836SJohn.Forte@Sun.COM 	{ NULL }
554*7836SJohn.Forte@Sun.COM };
555*7836SJohn.Forte@Sun.COM 
556*7836SJohn.Forte@Sun.COM static const mdb_modinfo_t modinfo = {
557*7836SJohn.Forte@Sun.COM 	MDB_API_VERSION, dcmds, walkers
558*7836SJohn.Forte@Sun.COM };
559*7836SJohn.Forte@Sun.COM 
560*7836SJohn.Forte@Sun.COM const mdb_modinfo_t *
_mdb_init(void)561*7836SJohn.Forte@Sun.COM _mdb_init(void)
562*7836SJohn.Forte@Sun.COM {
563*7836SJohn.Forte@Sun.COM 	return (&modinfo);
564*7836SJohn.Forte@Sun.COM }
565