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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
29 #include <sys/mdb_modapi.h>
30 #include <sys/mutex.h>
31 #include <sys/modctl.h>
32 #include <sys/scsi/scsi.h>
33 #include <sys/sunndi.h>
34 #include <sys/fibre-channel/fc.h>
35 #include <sys/fibre-channel/ulp/fcpvar.h>
37 static struct fcp_port port
;
38 static struct fcp_tgt tgt
;
39 static struct fcp_lun lun
;
40 static uint32_t tgt_hash_index
;
44 * Leadville fcp walker/dcmd code
48 fcp_walk_i(mdb_walk_state_t
*wsp
)
50 if (wsp
->walk_addr
== (uintptr_t)NULL
&&
51 mdb_readvar(&wsp
->walk_addr
, "fcp_port_head") == -1) {
52 mdb_warn("failed to read 'fcp_port_head'");
56 wsp
->walk_data
= mdb_alloc(sizeof (struct fcp_port
), UM_SLEEP
);
61 fcp_walk_s(mdb_walk_state_t
*wsp
)
65 if (wsp
->walk_addr
== (uintptr_t)NULL
)
68 if (mdb_vread(wsp
->walk_data
, sizeof (struct fcp_port
),
69 wsp
->walk_addr
) == -1) {
70 mdb_warn("failed to read fcp_port at %p", wsp
->walk_addr
);
74 status
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
78 (uintptr_t)(((struct fcp_port
*)wsp
->walk_data
)->port_next
);
84 * The walker's fini function is invoked at the end of each walk.
87 fcp_walk_f(mdb_walk_state_t
*wsp
)
89 mdb_free(wsp
->walk_data
, sizeof (struct fcp_port
));
94 fcp(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
96 struct fcp_port pinfo
;
102 if (!(flags
& DCMD_ADDRSPEC
)) {
103 if (mdb_walk_dcmd("fcp", "fcp",
105 mdb_warn("failed to walk 'fcp_port_head'");
111 mdb_printf("FCP structure at %p\n", addr
);
114 * For each port, we just need to read the fc_fca_port_t struct, read
117 if (mdb_vread(&pinfo
, sizeof (struct fcp_port
), addr
) !=
118 sizeof (struct fcp_port
)) {
119 mdb_warn("failed to read fcp_port at %p", addr
);
123 mdb_printf(" mutex : 0x%-08x\n", pinfo
.port_mutex
);
124 mdb_printf(" ipkt_list : 0x%p\n", pinfo
.port_ipkt_list
);
125 mdb_printf(" state : 0x%-08x\n", pinfo
.port_state
);
126 mdb_printf(" phys_state : 0x%-08x\n", pinfo
.port_phys_state
);
127 mdb_printf(" top : %u\n", pinfo
.port_topology
);
128 mdb_printf(" sid : 0x%-06x\n", pinfo
.port_id
);
129 mdb_printf(" reset_list : 0x%p\n", pinfo
.port_reset_list
);
130 mdb_printf(" link_cnt : %u\n", pinfo
.port_link_cnt
);
131 mdb_printf(" deadline : %d\n", pinfo
.port_deadline
);
132 mdb_printf(" port wwn : "
133 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
134 pinfo
.port_pwwn
.raw_wwn
[0], pinfo
.port_pwwn
.raw_wwn
[1],
135 pinfo
.port_pwwn
.raw_wwn
[2], pinfo
.port_pwwn
.raw_wwn
[3],
136 pinfo
.port_pwwn
.raw_wwn
[4], pinfo
.port_pwwn
.raw_wwn
[5],
137 pinfo
.port_pwwn
.raw_wwn
[6], pinfo
.port_pwwn
.raw_wwn
[7]);
138 mdb_printf(" node wwn : "
139 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
140 pinfo
.port_nwwn
.raw_wwn
[0], pinfo
.port_nwwn
.raw_wwn
[1],
141 pinfo
.port_nwwn
.raw_wwn
[2], pinfo
.port_nwwn
.raw_wwn
[3],
142 pinfo
.port_nwwn
.raw_wwn
[4], pinfo
.port_nwwn
.raw_wwn
[5],
143 pinfo
.port_nwwn
.raw_wwn
[6], pinfo
.port_nwwn
.raw_wwn
[7]);
144 mdb_printf(" handle : 0x%p\n", pinfo
.port_fp_handle
);
145 mdb_printf(" cmd_mutex : 0x%-08x\n", pinfo
.port_pkt_mutex
);
146 mdb_printf(" ncmds : %u\n", pinfo
.port_npkts
);
147 mdb_printf(" pkt_head : 0x%p\n", pinfo
.port_pkt_head
);
148 mdb_printf(" pkt_tail : 0x%p\n", pinfo
.port_pkt_tail
);
149 mdb_printf(" ipkt_cnt : %d\n", pinfo
.port_ipkt_cnt
);
150 mdb_printf(" instance : %u\n", pinfo
.port_instance
);
151 mdb_printf(" max_exch : %u\n", pinfo
.port_max_exch
);
152 mdb_printf(" cmds_aborted : 0x%-08x\n",
153 pinfo
.port_reset_action
);
154 mdb_printf(" cmds_dma_flags : 0x%-08x\n",
155 pinfo
.port_cmds_dma_flags
);
156 mdb_printf(" fcp_dma : 0x%-08x\n", pinfo
.port_fcp_dma
);
157 mdb_printf(" priv_pkt_len : %u\n", pinfo
.port_priv_pkt_len
);
158 mdb_printf(" data_dma_attr : 0x%-08x\n",
159 pinfo
.port_data_dma_attr
);
160 mdb_printf(" cmd_dma_attr : 0x%-08x\n",
161 pinfo
.port_cmd_dma_attr
);
162 mdb_printf(" resp_dma_attr : 0x%-08x\n",
163 pinfo
.port_resp_dma_attr
);
164 mdb_printf(" dma_acc_attr : 0x%-08x\n",
165 pinfo
.port_dma_acc_attr
);
166 mdb_printf(" tran : 0x%p\n", pinfo
.port_tran
);
167 mdb_printf(" dip : 0x%p\n", pinfo
.port_dip
);
168 mdb_printf(" reset_notify_listf: 0x%p\n",
169 pinfo
.port_reset_notify_listf
);
170 mdb_printf(" event_defs : 0x%p\n", pinfo
.port_ndi_event_defs
);
171 mdb_printf(" event_hdl : 0x%p\n", pinfo
.port_ndi_event_hdl
);
172 mdb_printf(" events : 0x%p\n", pinfo
.port_ndi_events
);
173 mdb_printf(" tgt_hash_table : 0x%p\n", pinfo
.port_tgt_hash_table
);
174 mdb_printf(" mpxio : %d\n", pinfo
.port_mpxio
);
183 * Leadville cmds walker/dcmd code
187 cmds_walk_i(mdb_walk_state_t
*wsp
)
189 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
190 mdb_warn("Can not perform global walk");
195 * Input should be a fcp_lun, so read it to get the fcp_pkt
199 if (mdb_vread(&lun
, sizeof (struct fcp_lun
), wsp
->walk_addr
) !=
200 sizeof (struct fcp_lun
)) {
201 mdb_warn("Unable to read in the fcp_lun structure address\n");
205 wsp
->walk_addr
= (uintptr_t)(lun
.lun_pkt_head
);
206 wsp
->walk_data
= mdb_alloc(sizeof (struct fcp_pkt
), UM_SLEEP
);
212 cmds_walk_s(mdb_walk_state_t
*wsp
)
216 if (wsp
->walk_addr
== (uintptr_t)NULL
)
219 if (mdb_vread(wsp
->walk_data
, sizeof (struct fcp_pkt
),
220 wsp
->walk_addr
) == -1) {
221 mdb_warn("failed to read fcp_pkt at %p", wsp
->walk_addr
);
225 status
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
229 (uintptr_t)(((struct fcp_pkt
*)wsp
->walk_data
)->cmd_forw
);
235 * The walker's fini function is invoked at the end of each walk.
238 cmds_walk_f(mdb_walk_state_t
*wsp
)
240 mdb_free(wsp
->walk_data
, sizeof (struct fcp_pkt
));
245 * Leadville luns walker/dcmd code
249 luns_walk_i(mdb_walk_state_t
*wsp
)
251 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
252 mdb_warn("Can not perform global walk");
257 * Input should be a fcp_tgt, so read it to get the fcp_lun
261 if (mdb_vread(&tgt
, sizeof (struct fcp_tgt
), wsp
->walk_addr
) !=
262 sizeof (struct fcp_tgt
)) {
263 mdb_warn("Unable to read in the fcp_tgt structure address\n");
267 wsp
->walk_addr
= (uintptr_t)(tgt
.tgt_lun
);
268 wsp
->walk_data
= mdb_alloc(sizeof (struct fcp_lun
), UM_SLEEP
);
274 luns_walk_s(mdb_walk_state_t
*wsp
)
278 if (wsp
->walk_addr
== (uintptr_t)NULL
)
281 if (mdb_vread(wsp
->walk_data
, sizeof (struct fcp_lun
),
282 wsp
->walk_addr
) == -1) {
283 mdb_warn("failed to read fcp_pkt at %p", wsp
->walk_addr
);
287 status
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
291 (uintptr_t)(((struct fcp_lun
*)wsp
->walk_data
)->lun_next
);
297 * The walker's fini function is invoked at the end of each walk.
300 luns_walk_f(mdb_walk_state_t
*wsp
)
302 mdb_free(wsp
->walk_data
, sizeof (struct fcp_lun
));
307 * Leadville targets walker/dcmd code
311 targets_walk_i(mdb_walk_state_t
*wsp
)
313 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
314 mdb_warn("Can not perform global walk\n");
319 * Input should be a fcp_port, so read it to get the port_tgt
323 if (mdb_vread(&port
, sizeof (struct fcp_port
), wsp
->walk_addr
) !=
324 sizeof (struct fcp_port
)) {
325 mdb_warn("Unable to read in the port structure address\n");
331 while ((port
.port_tgt_hash_table
[tgt_hash_index
] == NULL
) &&
332 (tgt_hash_index
< FCP_NUM_HASH
)) {
336 wsp
->walk_addr
= (uintptr_t)(port
.port_tgt_hash_table
[tgt_hash_index
]);
338 wsp
->walk_data
= mdb_alloc(sizeof (struct fcp_tgt
), UM_SLEEP
);
344 targets_walk_s(mdb_walk_state_t
*wsp
)
348 if ((wsp
->walk_addr
== (uintptr_t)NULL
) &&
349 (tgt_hash_index
>= (FCP_NUM_HASH
- 1))) {
353 if (mdb_vread(wsp
->walk_data
, sizeof (struct fcp_tgt
),
354 wsp
->walk_addr
) == -1) {
355 mdb_warn("failed to read fcp_tgt at %p", wsp
->walk_addr
);
359 status
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
363 (uintptr_t)(((struct fcp_tgt
*)wsp
->walk_data
)->tgt_next
);
365 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
367 * locate the next hash list
372 while ((port
.port_tgt_hash_table
[tgt_hash_index
] == NULL
) &&
373 (tgt_hash_index
< FCP_NUM_HASH
)) {
377 if (tgt_hash_index
== FCP_NUM_HASH
) {
383 (uintptr_t)(port
.port_tgt_hash_table
[tgt_hash_index
]);
390 * The walker's fini function is invoked at the end of each walk.
393 targets_walk_f(mdb_walk_state_t
*wsp
)
395 mdb_free(wsp
->walk_data
, sizeof (struct fcp_tgt
));
400 * Leadville fcp_ipkt walker/dcmd code
404 ipkt_walk_i(mdb_walk_state_t
*wsp
)
406 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
407 mdb_warn("The address of a fcp_port"
408 " structure must be given\n");
413 * Input should be a fcp_port, so read it to get the ipkt
417 if (mdb_vread(&port
, sizeof (struct fcp_port
), wsp
->walk_addr
) !=
418 sizeof (struct fcp_port
)) {
419 mdb_warn("Failed to read in the fcp_port"
420 " at 0x%p\n", wsp
->walk_addr
);
424 wsp
->walk_addr
= (uintptr_t)(port
.port_ipkt_list
);
425 wsp
->walk_data
= mdb_alloc(sizeof (struct fcp_ipkt
), UM_SLEEP
);
431 ipkt_walk_s(mdb_walk_state_t
*wsp
)
435 if (wsp
->walk_addr
== (uintptr_t)NULL
)
438 if (mdb_vread(wsp
->walk_data
, sizeof (struct fcp_ipkt
),
439 wsp
->walk_addr
) == -1) {
440 mdb_warn("Failed to read in the fcp_ipkt"
441 " at 0x%p\n", wsp
->walk_addr
);
445 status
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
449 (uintptr_t)(((struct fcp_ipkt
*)wsp
->walk_data
)->ipkt_next
);
455 * The walker's fini function is invoked at the end of each walk.
458 ipkt_walk_f(mdb_walk_state_t
*wsp
)
460 mdb_free(wsp
->walk_data
, sizeof (struct fcp_ipkt
));
464 * Leadville fcp_pkt walker/dcmd code
468 pkt_walk_i(mdb_walk_state_t
*wsp
)
470 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
471 mdb_warn("The address of a fcp_port"
472 " structure must be given\n");
477 * Input should be an fcp_port, so read it to get the pkt
481 if (mdb_vread(&port
, sizeof (struct fcp_port
), wsp
->walk_addr
) !=
482 sizeof (struct fcp_port
)) {
483 mdb_warn("Failed to read in the fcp_port"
484 " at 0x%p\n", wsp
->walk_addr
);
488 wsp
->walk_addr
= (uintptr_t)(port
.port_pkt_head
);
489 wsp
->walk_data
= mdb_alloc(sizeof (struct fcp_pkt
), UM_SLEEP
);
495 pkt_walk_s(mdb_walk_state_t
*wsp
)
499 if (wsp
->walk_addr
== (uintptr_t)NULL
)
502 if (mdb_vread(wsp
->walk_data
, sizeof (struct fcp_pkt
),
503 wsp
->walk_addr
) == -1) {
504 mdb_warn("Failed to read in the fcp_pkt"
505 " at 0x%p\n", wsp
->walk_addr
);
509 status
= wsp
->walk_callback(wsp
->walk_addr
, wsp
->walk_data
,
513 (uintptr_t)(((struct fcp_pkt
*)wsp
->walk_data
)->cmd_next
);
519 * The walker's fini function is invoked at the end of each walk.
522 pkt_walk_f(mdb_walk_state_t
*wsp
)
524 mdb_free(wsp
->walk_data
, sizeof (struct fcp_pkt
));
528 * MDB module linkage information:
530 * We declare a list of structures describing our dcmds, a list of structures
531 * describing our walkers, and a function named _mdb_init to return a pointer
532 * to our module information.
535 static const mdb_dcmd_t dcmds
[] = {
536 { "fcp", NULL
, "Leadville fcp instances", fcp
},
540 static const mdb_walker_t walkers
[] = {
541 { "fcp", "Walk list of Leadville fcp instances",
542 fcp_walk_i
, fcp_walk_s
, fcp_walk_f
},
543 { "cmds", "Walk list of SCSI commands in fcp's per-lun queue",
544 cmds_walk_i
, cmds_walk_s
, cmds_walk_f
},
545 { "luns", "Walk list of LUNs in an fcp target",
546 luns_walk_i
, luns_walk_s
, luns_walk_f
},
547 { "targets", "Walk list of fcp targets attached to the local port",
548 targets_walk_i
, targets_walk_s
, targets_walk_f
},
549 { "fcp_ipkt", "Walk list of internal packets queued on a local port",
550 ipkt_walk_i
, ipkt_walk_s
, ipkt_walk_f
},
551 { "fcp_pkt", "Walk list of packets queued on a local port",
552 pkt_walk_i
, pkt_walk_s
, pkt_walk_f
},
556 static const mdb_modinfo_t modinfo
= {
557 MDB_API_VERSION
, dcmds
, walkers
560 const mdb_modinfo_t
*