1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <sys/dditypes.h>
28 #include <sys/mdb_modapi.h>
29 #include <sys/modctl.h>
30 #include <sys/sunddi.h>
31 #include <sys/lpif.h>
32 #include <sys/stmf.h>
33 #include <sys/portif.h>
34 #include <sys/list.h>
35 #include <stmf_impl.h>
36 #include <lun_map.h>
37 #include <stmf_state.h>
38
39 #include <sys/fct.h>
40 #include <fct_impl.h>
41
42 #include "cmd_options.h"
43
44 static int
45 stmf_ilport_walk_i(mdb_walk_state_t *wsp)
46 {
47 if (wsp->walk_addr == NULL) {
48 struct stmf_state state;
49
50 if (mdb_readsym(&state, sizeof (struct stmf_state),
51 "stmf_state") == -1) {
52 mdb_warn("failed to read stmf_state");
53 return (WALK_ERR);
54 }
55 wsp->walk_addr = (uintptr_t)state.stmf_ilportlist;
56 }
57
58 wsp->walk_data = mdb_alloc(sizeof (stmf_i_local_port_t), UM_SLEEP);
59 return (WALK_NEXT);
60 }
61
62 static int
63 stmf_ilport_walk_s(mdb_walk_state_t *wsp)
64 {
65 int status = WALK_NEXT;
66
67 if (wsp->walk_addr == NULL)
68 return (WALK_DONE);
69
70 if (mdb_vread(wsp->walk_data, sizeof (struct stmf_i_local_port),
71 wsp->walk_addr) == -1) {
72 mdb_warn("failed to read stmf_i_local_port_t at %p",
73 wsp->walk_addr);
74 return (WALK_ERR);
75 }
76
77 if (wsp->walk_callback)
78 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
79 wsp->walk_cbdata);
80
81 wsp->walk_addr = (uintptr_t)
82 (((struct stmf_i_local_port *)wsp->walk_data)->ilport_next);
83
84 return (status);
85 }
86
87 static void
88 stmf_ilport_walk_f(mdb_walk_state_t *wsp)
89 {
90 mdb_free(wsp->walk_data, sizeof (struct stmf_i_local_port));
91 }
92
93 static int
94 dump_ilport(struct stmf_i_local_port *ilportp, int verbose)
95 {
96 if (ilportp == NULL)
97 return (DCMD_OK);
98
99 mdb_printf("%p\n", ilportp);
100
101 if (verbose) {
102 /* here assume the alias is maximumly 1024 bytes */
103 char alias[255];
104 struct stmf_local_port lport;
105 struct stmf_i_local_port ilport;
106
107 if (mdb_vread(&ilport, sizeof (ilport), (uintptr_t)ilportp)
108 == -1) {
109 mdb_warn("failed to read stmf_i_local_port at %p",
110 ilportp);
111 return (DCMD_ERR);
112 }
113
114 memset(alias, 0, sizeof (alias));
115 if (mdb_vread(&lport, sizeof (lport),
116 (uintptr_t)ilport.ilport_lport) == -1) {
117 mdb_warn("failed to read stmf_local_port at %p",
118 ilport.ilport_lport);
119 return (DCMD_ERR);
120 }
121 if (lport.lport_alias && mdb_vread(alias, sizeof (alias),
122 (uintptr_t)lport.lport_alias) == -1) {
123 mdb_warn("failed to read memory at %p",
124 lport.lport_alias);
125 return (DCMD_ERR);
126 }
127
128 mdb_printf(" lport: %p\n", ilport.ilport_lport);
129 if (lport.lport_alias)
130 mdb_printf(" port alias: %s\n", alias);
131 mdb_printf(" port provider: %p\n", lport.lport_pp);
132 }
133
134 return (DCMD_OK);
135 }
136
137 /*ARGSUSED*/
138 static int
139 stmf_ilports(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
140 {
141 int i;
142 int verbose = 0;
143 mdb_walk_state_t ws = {NULL, };
144
145 for (i = 0; i < argc; i++) {
146 char *ptr = (char *)argv[i].a_un.a_str;
147
148 if (ptr[0] == '-')
149 ptr++;
150 while (*ptr) {
151 if (*ptr == 'v')
152 verbose = 1;
153 ptr++;
154 }
155 }
156
157 if (stmf_ilport_walk_i(&ws) == WALK_ERR)
158 return (DCMD_ERR);
159
160 dump_ilport((stmf_i_local_port_t *)ws.walk_addr, verbose);
161
162 while (stmf_ilport_walk_s(&ws) == WALK_NEXT)
163 dump_ilport((stmf_i_local_port_t *)ws.walk_addr, verbose);
164
165 stmf_ilport_walk_f(&ws);
166 return (DCMD_OK);
167 }
168
169 struct stmf_i_local_port *
170 next_stmf_port(mdb_walk_state_t *wsp)
171 {
172 if (wsp->walk_addr == NULL) {
173 if (stmf_ilport_walk_i(wsp) == WALK_ERR) {
174 stmf_ilport_walk_f(wsp);
175 return (NULL);
176 }
177 if (wsp->walk_addr == NULL)
178 stmf_ilport_walk_f(wsp);
179 return ((struct stmf_i_local_port *)wsp->walk_addr);
180 }
181
182 if (stmf_ilport_walk_s(wsp) == WALK_ERR) {
183 stmf_ilport_walk_f(wsp);
184 return (NULL);
185 }
186 if (wsp->walk_addr == NULL)
187 stmf_ilport_walk_f(wsp);
188 return ((struct stmf_i_local_port *)wsp->walk_addr);
189 }
190
191
192 /*ARGSUSED*/
193 static int
194 stmf_iss(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
195 {
196 struct stmf_i_local_port iport;
197 struct stmf_i_scsi_session *issp;
198 struct stmf_i_scsi_session iss;
199 int i;
200 int verbose = 0;
201
202 for (i = 0; i < argc; i++) {
203 char *ptr = (char *)argv[i].a_un.a_str;
204
205 if (ptr[0] == '-')
206 ptr++;
207 while (*ptr) {
208 if (*ptr == 'v')
209 verbose = 1;
210 ptr++;
211 }
212 }
213
214 if (addr == NULL) {
215 mdb_warn("address of stmf_i_local_port should be specified\n");
216 return (DCMD_ERR);
217 }
218
219 /*
220 * Input should be stmf_i_local_port_t.
221 */
222 if (mdb_vread(&iport, sizeof (struct stmf_i_local_port), addr)
223 != sizeof (struct stmf_i_local_port)) {
224 mdb_warn("Unable to read in stmf_i_local_port at %p\n", addr);
225 return (DCMD_ERR);
226 }
227
228 issp = iport.ilport_ss_list;
229
230 while (issp) {
231 if (mdb_vread(&iss, sizeof (iss), (uintptr_t)issp) == -1) {
232 mdb_warn("failed to read stmf_i_scsi_session_t at %p",
233 issp);
234 return (DCMD_ERR);
235 }
236
237 mdb_printf("%p\n", issp);
238 if (verbose) {
239 mdb_printf(" scsi session: %p\n", iss.iss_ss);
240 }
241
242 issp = iss.iss_next;
243 }
244
245 return (DCMD_OK);
246 }
247
248 /*ARGSUSED*/
249 static int
250 stmf_ilus(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
251 {
252 struct stmf_state state;
253 struct stmf_i_lu ilu;
254 struct stmf_i_lu *ilup;
255 int i;
256 int verbose = 0;
257
258 for (i = 0; i < argc; i++) {
259 char *ptr = (char *)argv[i].a_un.a_str;
260
261 if (ptr[0] == '-')
262 ptr++;
263 while (*ptr) {
264 if (*ptr == 'v')
265 verbose = 1;
266 ptr++;
267 }
268 }
269
270 if (mdb_readsym(&state, sizeof (struct stmf_state), "stmf_state")
271 == -1) {
272 mdb_warn("failed to read stmf_state");
273 return (DCMD_ERR);
274 }
275
276 ilup = state.stmf_ilulist;
277 while (ilup) {
278 if (mdb_vread(&ilu, sizeof (struct stmf_i_lu), (uintptr_t)ilup)
279 == -1) {
280 mdb_warn("failed to read stmf_i_lu_t at %p", ilup);
281 return (DCMD_ERR);
282 }
283
284 mdb_printf("%p\n", ilup);
285 if (verbose) {
286 mdb_printf(" lu: %p\n", ilu.ilu_lu);
287
288 /* XXX lu_alias? what is its size? */
289 }
290
291 ilup = ilu.ilu_next;
292 }
293
294 return (DCMD_OK);
295 }
296
297 /*ARGSUSED*/
298 static int
299 stmf_i_lu_providers(uintptr_t addr, uint_t flags, int argc,
300 const mdb_arg_t *argv)
301 {
302 struct stmf_state state;
303 struct stmf_i_lu_provider ilp;
304 struct stmf_i_lu_provider *ilpp;
305 int i;
306 int verbose = 0;
307
308 for (i = 0; i < argc; i++) {
309 char *ptr = (char *)argv[i].a_un.a_str;
310
311 if (ptr[0] == '-')
312 ptr++;
313 while (*ptr) {
314 if (*ptr == 'v')
315 verbose = 1;
316 ptr++;
317 }
318 }
319
320 if (mdb_readsym(&state, sizeof (struct stmf_state), "stmf_state")
321 == -1) {
322 mdb_warn("failed to read stmf_state");
323 return (DCMD_ERR);
324 }
325
326 ilpp = state.stmf_ilplist;
327 while (ilpp) {
328 if (mdb_vread(&ilp, sizeof (stmf_i_lu_provider_t),
329 (uintptr_t)ilpp) == -1) {
330 mdb_warn("failed to read stmf_i_lu_provider_t at %p",
331 ilpp);
332 return (DCMD_ERR);
333 }
334
335 mdb_printf("%p\n", ilpp);
336 if (verbose) {
337 mdb_printf(" lu provider: %p\n", ilp.ilp_lp);
338 }
339
340 ilpp = ilp.ilp_next;
341 }
342
343 return (DCMD_OK);
344 }
345
346 /*ARGSUSED*/
347 static int
348 stmf_i_port_providers(uintptr_t addr, uint_t flags, int argc,
349 const mdb_arg_t *argv)
350 {
351 struct stmf_state state;
352 struct stmf_i_port_provider ipp;
353 struct stmf_i_port_provider *ippp;
354 int i;
355 int verbose = 0;
356
357 for (i = 0; i < argc; i++) {
358 char *ptr = (char *)argv[i].a_un.a_str;
359
360 if (ptr[0] == '-')
361 ptr++;
362 while (*ptr) {
363 if (*ptr == 'v')
364 verbose = 1;
365 ptr++;
366 }
367 }
368
369 if (mdb_readsym(&state, sizeof (struct stmf_state), "stmf_state")
370 == -1) {
371 mdb_warn("failed to read stmf_state");
372 return (DCMD_ERR);
373 }
374
375 ippp = state.stmf_ipplist;
376 while (ippp) {
377 if (mdb_vread(&ipp, sizeof (stmf_i_port_provider_t),
378 (uintptr_t)ippp) == -1) {
379 mdb_warn("failed to read stmf_i_port_provider_t at %p",
380 ippp);
381 return (DCMD_ERR);
382 }
383
384 mdb_printf("%p\n", ippp);
385 if (verbose) {
386 mdb_printf(" port provider: %p\n", ipp.ipp_pp);
387 }
388
389 ippp = ipp.ipp_next;
390 }
391
392 return (DCMD_OK);
393 }
394
395 int string2wwn(const char *s, uint8_t wwn[8]);
396
397 static uint16_t port_max_logins;
398 static int rp_index;
399
400 /*
401 * Cervert stmf_i_local_port to fct_i_local_port
402 */
403 /*ARGSUSED*/
404 static struct fct_i_local_port *
405 __ilport2iport(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
406 {
407 struct stmf_i_local_port iport;
408 struct stmf_local_port lport;
409 struct fct_local_port fport;
410
411 if (!(flags & DCMD_ADDRSPEC)) {
412 mdb_warn("stmf_i_local_port address should be specified");
413 return (NULL);
414 }
415
416 /*
417 * Input should be stmf_i_local_port_t.
418 */
419 if (mdb_vread(&iport, sizeof (struct stmf_i_local_port), addr)
420 != sizeof (struct stmf_i_local_port)) {
421 mdb_warn("Unable to read in stmf_i_local_port\n");
422 return (NULL);
423 }
424
425 if (mdb_vread(&lport, sizeof (stmf_local_port_t),
426 (uintptr_t)iport.ilport_lport) != sizeof (stmf_local_port_t)) {
427 mdb_warn("Unable to read in stmf_local_port\n");
428 return (NULL);
429 }
430
431 if (mdb_vread(&fport, sizeof (fct_local_port_t),
432 (uintptr_t)lport.lport_port_private)
433 != sizeof (fct_local_port_t)) {
434 mdb_warn("Unable to read in fct_local_port\n");
435 return (NULL);
436 }
437
438 return (fport.port_fct_private);
439 }
440
441 static int
442 ilport2iport(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
443 {
444 struct fct_i_local_port *iportp;
445 int i;
446 int verbose = 0;
447
448 for (i = 0; i < argc; i++) {
449 char *ptr = (char *)argv[i].a_un.a_str;
450
451 if (ptr[0] == '-')
452 ptr++;
453 while (*ptr) {
454 if (*ptr == 'v')
455 verbose = 1;
456 ptr++;
457 }
458 }
459
460
461 iportp = __ilport2iport(addr, flags, argc, argv);
462 if (iportp) {
463 mdb_printf("%p\n", iportp);
464 if (verbose) {
465 struct fct_i_local_port iport;
466 /* is the alias always 16 bytes in size ? */
467 char alias[16];
468
469 memset(alias, 0, sizeof (alias));
470 if (mdb_vread(&iport, sizeof (fct_i_local_port_t),
471 (uintptr_t)iportp)
472 != sizeof (fct_i_local_port_t)) {
473 mdb_warn("Unable to read in fct_i_local_port"
474 "at %p\n", iportp);
475 return (DCMD_ERR);
476 }
477 if (iport.iport_alias &&
478 mdb_vread(alias, sizeof (alias),
479 (uintptr_t)iport.iport_alias)
480 != sizeof (alias)) {
481 mdb_warn("Unable to read in memory at %p",
482 iport.iport_alias);
483 return (DCMD_ERR);
484 }
485 mdb_printf(" port: %p\n", iport.iport_port);
486 if (iport.iport_alias)
487 mdb_printf(" alias: %s\n", alias);
488 }
489 }
490 return (DCMD_OK);
491 }
492
493 /*
494 * by wwn, we can only find one local port
495 */
496 static struct stmf_i_local_port *
497 find_lport_by_wwn(uint8_t wwn[8])
498 {
499 struct stmf_i_local_port *siport;
500 struct fct_i_local_port *fiport;
501 struct fct_i_local_port iport;
502 struct fct_local_port fport;
503 mdb_walk_state_t ws = {NULL, };
504
505 while ((siport = next_stmf_port(&ws)) != NULL) {
506 fiport = __ilport2iport((uintptr_t)siport, DCMD_ADDRSPEC,
507 0, NULL);
508 if (fiport == NULL)
509 return (NULL);
510
511 if (mdb_vread(&iport, sizeof (fct_i_local_port_t),
512 (uintptr_t)fiport)
513 != sizeof (fct_i_local_port_t)) {
514 mdb_warn("Unable to read in fct_i_local_port\n");
515 return (NULL);
516 }
517 if (mdb_vread(&fport, sizeof (fct_local_port_t),
518 (uintptr_t)iport.iport_port)
519 != sizeof (fct_local_port_t)) {
520 mdb_warn("Unable to read in fct_local_port\n");
521 return (NULL);
522 }
523
524 #if 0
525 mdb_printf("pwwn=%02x%02x%02x%02x%02x%02x%02x%02x\n",
526 fport.port_pwwn[0], fport.port_pwwn[1],
527 fport.port_pwwn[2], fport.port_pwwn[3],
528 fport.port_pwwn[4], fport.port_pwwn[5],
529 fport.port_pwwn[6], fport.port_pwwn[7]);
530 #endif
531 if (memcmp(fport.port_pwwn, wwn, 8) == 0) {
532 return (siport);
533 }
534 }
535
536 return (NULL);
537 }
538
539 /*ARGSUSED*/
540 static int
541 stmf_find_ilport(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
542 {
543 struct find_options *options;
544 struct stmf_i_local_port *siport;
545
546 options = parse_options(argc, argv);
547 /* need to free options manually ? */
548 if (options == NULL || ! options->lpname_defined) {
549 mdb_printf("lpname=<wwn.12345678 or 12345678> "
550 "should be specified\n");
551 return (DCMD_OK);
552 }
553
554 if ((siport = find_lport_by_wwn(options->lpname)) != NULL)
555 mdb_printf("%p\n", siport);
556
557 return (DCMD_OK);
558 }
559
560 static int
561 fct_irp_walk_i(mdb_walk_state_t *wsp)
562 {
563 struct fct_local_port port;
564 struct fct_i_local_port iport;
565
566 if (wsp->walk_addr == NULL) {
567 mdb_warn("Can not perform global walk");
568 return (WALK_ERR);
569 }
570
571 /*
572 * Input should be fct_i_local_port_t.
573 */
574 if (mdb_vread(&iport, sizeof (struct fct_i_local_port), wsp->walk_addr)
575 != sizeof (struct fct_i_local_port)) {
576 mdb_warn("Unable to read in fct_i_local_port\n");
577 return (WALK_ERR);
578 }
579
580 if (mdb_vread(&port, sizeof (struct fct_local_port),
581 (uintptr_t)iport.iport_port)
582 != sizeof (struct fct_local_port)) {
583 mdb_warn("Unable to read in fct_local_port\n");
584 return (WALK_ERR);
585 }
586
587 port_max_logins = port.port_max_logins;
588 rp_index = 0;
589 wsp->walk_addr = (uintptr_t)iport.iport_rp_slots;
590
591 return (WALK_NEXT);
592 }
593
594 static int
595 fct_irp_walk_s(mdb_walk_state_t *wsp)
596 {
597 int status = WALK_NEXT;
598 fct_i_remote_port_t *rp;
599
600 if (wsp->walk_addr == NULL)
601 return (WALK_DONE);
602
603 if (rp_index++ >= port_max_logins)
604 return (WALK_DONE);
605
606 if (mdb_vread(&rp, sizeof (fct_i_remote_port_t *),
607 wsp->walk_addr) == -1) {
608 mdb_warn("failed to read address of fct_i_remote_port_t at %p",
609 wsp->walk_addr);
610 return (WALK_DONE);
611 }
612
613 if (rp != NULL && wsp->walk_callback != NULL)
614 status = wsp->walk_callback((uintptr_t)rp, rp,
615 wsp->walk_cbdata);
616
617 wsp->walk_addr = (uintptr_t)
618 &(((fct_i_remote_port_t **)wsp->walk_addr)[1]);
619
620 return (status);
621 }
622
623 static void
624 fct_irp_walk_f(mdb_walk_state_t *wsp)
625 {
626 wsp->walk_addr = NULL;
627 }
628
629 /*
630 * to set remote_port
631 */
632 /*ARGSUSED*/
633 static int
634 walk_fct_irp_cb(uintptr_t p, const void * arg, void *cbdata)
635 {
636 *((uintptr_t *)cbdata) = p;
637 return (WALK_NEXT);
638 }
639
640 static int
641 fct_irps(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
642 {
643 static uint64_t cbdata = 0;
644 mdb_walk_state_t ws = {walk_fct_irp_cb, &cbdata, addr};
645 fct_i_remote_port_t *irpp;
646 int i;
647 int verbose = 0;
648
649 for (i = 0; i < argc; i++) {
650 char *ptr = (char *)argv[i].a_un.a_str;
651
652 if (ptr[0] == '-')
653 ptr++;
654 while (*ptr) {
655 if (*ptr == 'v')
656 verbose = 1;
657 ptr++;
658 }
659 }
660
661 if (!(flags & DCMD_ADDRSPEC)) {
662 mdb_warn("fct_i_local_port_t address should be specified");
663 return (DCMD_ERR);
664 }
665
666 fct_irp_walk_i(&ws);
667 while (fct_irp_walk_s(&ws) == WALK_NEXT) {
668 irpp = *((fct_i_remote_port_t **)ws.walk_cbdata);
669
670 if (irpp) {
671 *((fct_i_remote_port_t **)ws.walk_cbdata) = NULL;
672
673 mdb_printf("%p\n", irpp);
674 if (verbose) {
675 fct_i_remote_port_t irp;
676
677 if (mdb_vread(&irp, sizeof (irp),
678 (uintptr_t)irpp) != sizeof (irp)) {
679 mdb_warn("Unable to read in "
680 "fct_i_remote_port at %p\n", irpp);
681 return (DCMD_ERR);
682 }
683 mdb_printf(" remote port: %p\n", irp.irp_rp);
684 mdb_printf(" port id: %x\n", irp.irp_portid);
685 }
686 }
687 }
688 fct_irp_walk_f(&ws);
689
690 return (DCMD_OK);
691 }
692
693 static uintptr_t cur_iport_for_irp_loop = NULL;
694
695 static fct_i_remote_port_t *
696 next_rport(struct fct_i_local_port *iport)
697 {
698 static uint64_t cbdata = 0;
699 static mdb_walk_state_t ws = {walk_fct_irp_cb, &cbdata};
700 int ret;
701 fct_i_remote_port_t *irp;
702
703 if (ws.walk_addr == NULL || cur_iport_for_irp_loop !=
704 (uintptr_t)iport) {
705 *((fct_i_remote_port_t **)ws.walk_cbdata) = NULL;
706 cur_iport_for_irp_loop = (uintptr_t)iport;
707 ws.walk_addr = (uintptr_t)iport;
708 if (fct_irp_walk_i(&ws) == WALK_ERR) {
709 fct_irp_walk_f(&ws);
710 return (NULL);
711 }
712 if (ws.walk_addr == NULL) {
713 fct_irp_walk_f(&ws);
714 return (NULL);
715 }
716 }
717
718 while ((ret = fct_irp_walk_s(&ws)) == WALK_NEXT) {
719 if (*((fct_i_remote_port_t **)ws.walk_cbdata) != 0) {
720 irp = *((fct_i_remote_port_t **)ws.walk_cbdata);
721 *((fct_i_remote_port_t **)ws.walk_cbdata) = NULL;
722 return (irp);
723 }
724 }
725 fct_irp_walk_f(&ws);
726
727 /*
728 * If it is WALK_DONE, there may be one remote port there
729 */
730 if (ret == WALK_DONE) {
731 irp = *((fct_i_remote_port_t **)ws.walk_cbdata);
732 *((fct_i_remote_port_t **)ws.walk_cbdata) = NULL;
733 return (irp);
734 }
735 return (NULL);
736 }
737
738 static struct stmf_i_local_port *
739 irp_to_ilport(struct fct_i_remote_port *irpp)
740 {
741 struct fct_i_remote_port irp;
742 struct fct_remote_port rp;
743 struct fct_local_port port;
744 struct stmf_local_port lport;
745
746 if (mdb_vread(&irp, sizeof (struct fct_i_remote_port),
747 (uintptr_t)irpp)
748 != sizeof (struct fct_i_remote_port)) {
749 mdb_warn("Unable to read in fct_i_remote_port\n");
750 return (NULL);
751 }
752 if (mdb_vread(&rp, sizeof (struct fct_remote_port),
753 (uintptr_t)irp.irp_rp)
754 != sizeof (struct fct_remote_port)) {
755 mdb_warn("Unable to read in fct_remote_port\n");
756 return (NULL);
757 }
758
759 if (mdb_vread(&port, sizeof (struct fct_local_port),
760 (uintptr_t)rp.rp_port)
761 != sizeof (struct fct_local_port)) {
762 mdb_warn("Unable to read in fct_local_port\n");
763 return (NULL);
764 }
765 if (mdb_vread(&lport, sizeof (struct stmf_local_port),
766 (uintptr_t)port.port_lport)
767 != sizeof (struct stmf_local_port)) {
768 mdb_warn("Unable to read in stmf_local_port\n");
769 return (NULL);
770 }
771 return (lport.lport_stmf_private);
772 }
773
774 /*
775 * by wwn, we may find more than one remote port, so we need to know its
776 * corresponding local port
777 */
778 static struct fct_i_remote_port *
779 find_irp_by_wwn(struct stmf_i_local_port *siport, uint8_t wwn[8])
780 {
781 struct fct_i_local_port *fiport;
782 fct_i_remote_port_t *irpp;
783 struct fct_i_remote_port irp;
784 struct fct_remote_port rp;
785 fct_i_remote_port_t *ret = NULL;
786
787 fiport = __ilport2iport((uintptr_t)siport, DCMD_ADDRSPEC, 0, NULL);
788 if (fiport == NULL)
789 return (NULL);
790
791 while ((irpp = next_rport(fiport)) != NULL) {
792 if (mdb_vread(&irp, sizeof (struct fct_i_remote_port),
793 (uintptr_t)irpp)
794 != sizeof (struct fct_i_remote_port)) {
795 mdb_warn("Unable to read in fct_i_remote_port\n");
796 break;
797 }
798 if (mdb_vread(&rp, sizeof (struct fct_remote_port),
799 (uintptr_t)irp.irp_rp)
800 != sizeof (struct fct_remote_port)) {
801 mdb_warn("Unable to read in fct_remote_port\n");
802 break;
803 }
804
805 if (memcmp(rp.rp_pwwn, wwn, 8) == 0) {
806 ret = irpp;
807 break;
808 }
809 }
810 cur_iport_for_irp_loop = NULL;
811 return (ret);
812 }
813
814 /*ARGSUSED*/
815 static int
816 stmf_find_fct_irp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
817 {
818 struct stmf_i_local_port *siport;
819 struct find_options *options;
820 fct_i_remote_port_t *irpp;
821 mdb_walk_state_t ws = {NULL, };
822
823 options = parse_options(argc, argv);
824 /* need to free options manually ? */
825 if (options == NULL || (options->rpname_defined == 0 &&
826 options->rp_defined == 0)) {
827 mdb_printf("rpname=<wwn.12345678> or rp=<3000586778734>"
828 " should be specified\n");
829 return (DCMD_OK);
830 }
831 if (options->rpname_defined && options->rp_defined) {
832 mdb_printf("rpname=<wwn.12345678> or rp=<3000586778734>"
833 " should be specified, but not both\n");
834 return (DCMD_OK);
835 }
836
837 if (options->rp_defined) {
838 siport = irp_to_ilport(options->rp);
839 if (siport != NULL)
840 mdb_printf("stmf_i_local_port=%p,"
841 " fct_i_remote_port=%p\n",
842 siport, options->rp);
843 return (DCMD_OK);
844 }
845
846 /* if options->rpname_defined */
847 while ((siport = next_stmf_port(&ws)) != NULL) {
848 if ((irpp = find_irp_by_wwn(siport, options->rpname)) != NULL)
849 mdb_printf("stmf_i_local_port=%p, "
850 "fct_i_remote_port=%p\n",
851 siport, irpp);
852 }
853
854 return (DCMD_OK);
855 }
856
857 typedef void (*cmd_filter_t) (struct fct_i_cmd *,
858 struct find_options *, void *);
859
860 /*ARGSUSED*/
861 static void
862 print_tasks(struct fct_i_cmd *icmdp, struct find_options *options, void *arg)
863 {
864 struct fct_i_cmd icmd;
865 struct fct_cmd cmd;
866
867 if (mdb_vread(&icmd, sizeof (struct fct_i_cmd),
868 (uintptr_t)icmdp) != sizeof (struct fct_i_cmd)) {
869 mdb_warn("Unable to read in fct_i_cmd\n");
870 return;
871 }
872 if (mdb_vread(&cmd, sizeof (struct fct_cmd),
873 (uintptr_t)icmd.icmd_cmd) != sizeof (struct fct_cmd)) {
874 mdb_warn("Unable to read in fct_cmd\n");
875 return;
876 }
877
878 if (cmd.cmd_type == FCT_CMD_FCP_XCHG) {
879 struct scsi_task task;
880 int colon_printed = 0;
881
882 if (mdb_vread(&task, sizeof (struct scsi_task),
883 (uintptr_t)cmd.cmd_specific)
884 != sizeof (struct scsi_task)) {
885 mdb_warn("Unable to read in scsi_task\n");
886 return;
887 }
888
889 mdb_printf("%p", cmd.cmd_specific);
890 if (options->show_task_flags) {
891 mdb_printf(":");
892 colon_printed = 1;
893 mdb_printf(" task_flags=%x", task.task_flags);
894 }
895
896 if (options->show_lport) {
897 if (colon_printed == 0) {
898 mdb_printf(":");
899 colon_printed = 1;
900 }
901 mdb_printf(" lport=%p", task.task_lport);
902 }
903 mdb_printf("\n");
904 }
905 }
906
907 static void
908 print_tasks_on_rp(struct fct_i_cmd *icmdp, struct find_options *options,
909 void *arg)
910 {
911 struct fct_i_cmd icmd;
912 struct fct_cmd cmd;
913 fct_i_remote_port_t irp;
914
915 if (mdb_vread(&icmd, sizeof (struct fct_i_cmd),
916 (uintptr_t)icmdp) != sizeof (struct fct_i_cmd)) {
917 mdb_warn("Unable to read in fct_i_cmd\n");
918 return;
919 }
920 if (mdb_vread(&cmd, sizeof (struct fct_cmd),
921 (uintptr_t)icmd.icmd_cmd) != sizeof (struct fct_cmd)) {
922 mdb_warn("Unable to read in fct_cmd\n");
923 return;
924 }
925
926 /* arg is a pointer to fct_i_remote_port */
927 if (mdb_vread(&irp, sizeof (struct fct_i_remote_port),
928 (uintptr_t)arg) != sizeof (struct fct_i_remote_port)) {
929 mdb_warn("Unable to read in fct_i_remote_port\n");
930 return;
931 }
932
933 if (cmd.cmd_type == FCT_CMD_FCP_XCHG && cmd.cmd_rp == irp.irp_rp) {
934 struct scsi_task task;
935 int colon_printed = 0;
936
937 if (mdb_vread(&task, sizeof (struct scsi_task),
938 (uintptr_t)cmd.cmd_specific)
939 != sizeof (struct scsi_task)) {
940 mdb_warn("Unable to read in scsi_task\n");
941 return;
942 }
943
944 mdb_printf("%p", cmd.cmd_specific);
945 if (options->show_task_flags) {
946 mdb_printf(":");
947 colon_printed = 1;
948 mdb_printf(" task_flags=%x", task.task_flags);
949 }
950
951 if (options->show_lport) {
952 if (colon_printed == 0) {
953 mdb_printf(":");
954 colon_printed = 1;
955 }
956 mdb_printf(" lport=%p", task.task_lport);
957 }
958 mdb_printf("\n");
959 }
960 }
961
962 /*ARGSUSED*/
963 static void
964 print_all_cmds(struct fct_i_cmd *icmd, struct find_options *options, void *arg)
965 {
966 mdb_printf("%p\n", icmd);
967 }
968
969 /*
970 * find outstanding cmds (fct_i_cmd) on local port
971 */
972 static int
973 outstanding_cmds_on_lport(struct stmf_i_local_port *siport, cmd_filter_t filter,
974 struct find_options *options, void *arg)
975 {
976 struct fct_i_local_port *iportp;
977 struct fct_i_local_port iport;
978 struct fct_local_port port;
979 struct fct_cmd_slot *slotp;
980 struct fct_cmd_slot slot;
981 int i;
982
983 iportp = __ilport2iport((uintptr_t)siport, DCMD_ADDRSPEC, 0, NULL);
984 if (iportp == NULL)
985 return (DCMD_ERR);
986
987 if (mdb_vread(&iport, sizeof (struct fct_i_local_port),
988 (uintptr_t)iportp) != sizeof (struct fct_i_local_port)) {
989 mdb_warn("Unable to read in fct_i_local_port\n");
990 return (DCMD_ERR);
991 }
992 if (mdb_vread(&port, sizeof (struct fct_local_port),
993 (uintptr_t)iport.iport_port) != sizeof (struct fct_local_port)) {
994 mdb_warn("Unable to read in fct_local_port\n");
995 return (DCMD_ERR);
996 }
997
998 slotp = iport.iport_cmd_slots;
999 for (i = 0; i < port.port_max_xchges; i++) {
1000 if (mdb_vread(&slot, sizeof (struct fct_cmd_slot),
1001 (uintptr_t)slotp) != sizeof (struct fct_cmd_slot)) {
1002 mdb_warn("Unable to read in fct_cmd_slot\n");
1003 return (DCMD_ERR);
1004 }
1005 if (slot.slot_cmd != NULL) {
1006 if (filter == NULL)
1007 mdb_printf("%p\n", slot.slot_cmd);
1008 else
1009 filter(slot.slot_cmd, options, arg);
1010 }
1011 slotp ++;
1012 }
1013
1014 return (DCMD_OK);
1015 }
1016
1017 /*ARGSUSED*/
1018 static int
1019 stmf_find_tasks(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1020 {
1021 struct find_options *options;
1022 struct stmf_i_local_port *siport;
1023
1024 options = parse_options(argc, argv);
1025 if (options == NULL ||
1026 (options->lpname_defined == 0 && options->rpname_defined == 0)) {
1027 mdb_printf("lpname=<wwn.12345678> or rpname=<wwn.12345678>"
1028 " should be specified\n");
1029 return (DCMD_OK);
1030 }
1031
1032 if (options->lpname_defined) {
1033 siport = find_lport_by_wwn(options->lpname);
1034 if (siport == NULL)
1035 return (DCMD_ERR);
1036
1037 outstanding_cmds_on_lport(siport, print_tasks, options, NULL);
1038 return (DCMD_OK);
1039 }
1040
1041 if (options->rpname_defined) {
1042 mdb_walk_state_t ws = {NULL, };
1043 fct_i_remote_port_t *irpp;
1044
1045 while ((siport = next_stmf_port(&ws)) != NULL) {
1046 if ((irpp = find_irp_by_wwn(siport, options->rpname))
1047 != NULL) {
1048 outstanding_cmds_on_lport(siport,
1049 print_tasks_on_rp, options, irpp);
1050 }
1051 }
1052 }
1053
1054 return (DCMD_OK);
1055 }
1056
1057 /*ARGSUSED*/
1058 static int
1059 fct_find_cmds(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1060 {
1061 struct find_options *options;
1062 struct stmf_i_local_port *siport;
1063
1064 options = parse_options(argc, argv);
1065 if (options == NULL || options->lpname_defined == 0) {
1066 mdb_printf("lpname=<wwn.12345678> should be specified\n");
1067 return (DCMD_OK);
1068 }
1069
1070 siport = find_lport_by_wwn(options->lpname);
1071 if (siport == NULL)
1072 return (DCMD_ERR);
1073
1074 outstanding_cmds_on_lport(siport, print_all_cmds, options, NULL);
1075 return (DCMD_OK);
1076 }
1077
1078 static int
1079 fct_icmds(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1080 {
1081 struct fct_i_local_port iport;
1082 struct fct_i_cmd icmd;
1083 struct fct_i_cmd *icmdp;
1084 int i;
1085 int verbose = 0;
1086
1087 for (i = 0; i < argc; i++) {
1088 char *ptr = (char *)argv[i].a_un.a_str;
1089
1090 if (ptr[0] == '-')
1091 ptr++;
1092 while (*ptr) {
1093 if (*ptr == 'v')
1094 verbose = 1;
1095 ptr++;
1096 }
1097 }
1098
1099 if (!(flags & DCMD_ADDRSPEC)) {
1100 mdb_warn("fct_i_local_port_t address should be specified");
1101 return (DCMD_ERR);
1102 }
1103
1104 if (mdb_vread(&iport, sizeof (struct fct_i_local_port), addr)
1105 != sizeof (struct fct_i_local_port)) {
1106 mdb_warn("Unable to read in fct_i_local_port at %p\n", addr);
1107 return (DCMD_ERR);
1108 }
1109
1110 icmdp = list_head(&iport.iport_cached_cmdlist);
1111 while (icmdp) {
1112
1113 if (mdb_vread(&icmd, sizeof (struct fct_i_cmd),
1114 (uintptr_t)icmdp) == -1) {
1115 mdb_warn("failed to read fct_i_cmd at %p", icmdp);
1116 return (DCMD_ERR);
1117 }
1118
1119 mdb_printf("%p\n", icmdp);
1120 if (verbose) {
1121 mdb_printf(" fct cmd: %p\n", icmd.icmd_cmd);
1122 }
1123
1124 icmdp = list_next(&iport.iport_cached_cmdlist, icmdp);
1125 }
1126
1127 return (DCMD_OK);
1128 }
1129
1130 /*
1131 * Walker to list the addresses of all the active STMF scsi tasks (scsi_task_t),
1132 * given a stmf_worker address
1133 *
1134 * To list all the active STMF scsi tasks, use
1135 * "::walk stmf_worker |::walk stmf_scsi_task"
1136 * To list the active tasks of a particular worker, use
1137 * <stmf_worker addr>::walk stmf_scsi_task
1138 */
1139 static int
1140 stmf_scsi_task_walk_init(mdb_walk_state_t *wsp)
1141 {
1142 stmf_worker_t worker;
1143
1144 /*
1145 * Input should be a stmf_worker, so read it to get the
1146 * worker_task_head to get the start of the task list
1147 */
1148 if (wsp->walk_addr == NULL) {
1149 mdb_warn("<worker addr>::walk stmf_scsi_task\n");
1150 return (WALK_ERR);
1151 }
1152
1153 if (mdb_vread(&worker, sizeof (stmf_worker_t), wsp->walk_addr) !=
1154 sizeof (stmf_worker_t)) {
1155 mdb_warn("failed to read in the task address\n");
1156 return (WALK_ERR);
1157 }
1158
1159 wsp->walk_addr = (uintptr_t)(worker.worker_task_head);
1160 wsp->walk_data = mdb_alloc(sizeof (scsi_task_t), UM_SLEEP);
1161
1162 return (WALK_NEXT);
1163 }
1164
1165 static int
1166 stmf_scsi_task_walk_step(mdb_walk_state_t *wsp)
1167 {
1168 stmf_i_scsi_task_t itask;
1169 int status;
1170
1171 if (wsp->walk_addr == NULL) {
1172 return (WALK_DONE);
1173 }
1174
1175 /* Save the stmf_i_scsi_task for use later to get the next entry */
1176 if (mdb_vread(&itask, sizeof (stmf_i_scsi_task_t),
1177 wsp->walk_addr) != sizeof (stmf_i_scsi_task_t)) {
1178 mdb_warn("failed to read stmf_i_scsi_task at %p",
1179 wsp->walk_addr);
1180 return (WALK_DONE);
1181 }
1182
1183 wsp->walk_addr = (uintptr_t)itask.itask_task;
1184
1185 if (mdb_vread(wsp->walk_data, sizeof (scsi_task_t),
1186 wsp->walk_addr) != sizeof (scsi_task_t)) {
1187 mdb_warn("failed to read scsi_task_t at %p", wsp->walk_addr);
1188 return (DCMD_ERR);
1189 }
1190
1191 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
1192 wsp->walk_cbdata);
1193
1194 wsp->walk_addr = (uintptr_t)(itask.itask_worker_next);
1195
1196 return (status);
1197 }
1198
1199 static void
1200 stmf_scsi_task_walk_fini(mdb_walk_state_t *wsp)
1201 {
1202 mdb_free(wsp->walk_data, sizeof (scsi_task_t));
1203 }
1204
1205 /*ARGSUSED*/
1206 static int
1207 stmf_scsi_task(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1208 {
1209 stmf_worker_t worker;
1210 stmf_i_scsi_task_t itask;
1211 scsi_task_t *task_addr, task;
1212
1213 /*
1214 * A stmf_worker address is given to the left of ::stmf_scsi_task
1215 * i.e. display the scsi_task for the given worker
1216 */
1217 if (!(flags & DCMD_ADDRSPEC)) {
1218 if (mdb_walk_dcmd("stmf_worker", "stmf_scsi_task", argc,
1219 argv) == -1) {
1220 mdb_warn("Failed to walk the stmf_scsi_task entries");
1221 return (DCMD_ERR);
1222 }
1223 return (DCMD_OK);
1224 }
1225
1226 if (DCMD_HDRSPEC(flags) && (!(flags & DCMD_PIPE_OUT))) {
1227 mdb_printf("%<u>%-19s %-10s %-19s%</u>\n",
1228 "scsi_task_t", "Flags", "LPort");
1229 }
1230
1231 if (mdb_vread(&worker, sizeof (stmf_worker_t),
1232 addr) != sizeof (stmf_worker_t)) {
1233 mdb_warn("failed to read in the worker address");
1234 return (DCMD_ERR);
1235 }
1236
1237 /* Read the scsi_task */
1238 if (worker.worker_task_head == NULL) {
1239 return (DCMD_OK);
1240 }
1241
1242 if (mdb_vread(&itask, sizeof (stmf_i_scsi_task_t),
1243 (uintptr_t)worker.worker_task_head) == -1) {
1244 mdb_warn("failed to read stmf_i_scsi_task_t at %p",
1245 worker.worker_task_head);
1246 return (DCMD_ERR);
1247 }
1248
1249 task_addr = itask.itask_task;
1250
1251 if (mdb_vread(&task, sizeof (scsi_task_t),
1252 (uintptr_t)task_addr) != sizeof (scsi_task_t)) {
1253 mdb_warn("failed to read scsi_task_t at %p", task_addr);
1254 return (DCMD_ERR);
1255 }
1256
1257 if ((flags & DCMD_PIPE_OUT)) {
1258 mdb_printf("%p\n", task_addr);
1259 } else {
1260 /* pretty print */
1261 mdb_printf("%-19p %-10x %-19p\n",
1262 task_addr, task.task_flags, task.task_lport);
1263 }
1264
1265 return (DCMD_OK);
1266 }
1267
1268 /*
1269 * Walker to list the addresses of all the stmf_worker in the queue
1270 */
1271 typedef struct stmf_worker_walk_data {
1272 int worker_current;
1273 int worker_count;
1274 } stmf_worker_walk_data_t;
1275
1276 /* stmf_workers_state definition from stmf.c (static) */
1277 enum {
1278 STMF_WORKERS_DISABLED = 0,
1279 STMF_WORKERS_ENABLING,
1280 STMF_WORKERS_ENABLED
1281 } stmf_workers_state;
1282
1283 /*
1284 * Initialize the stmf_worker_t walker by either using the given starting
1285 * address, or reading the value of the kernel's global stmf_workers pointer.
1286 */
1287 /*ARGSUSED*/
1288 static int
1289 stmf_worker_walk_init(mdb_walk_state_t *wsp)
1290 {
1291 int worker_state;
1292 int nworkers;
1293 stmf_worker_t *worker;
1294 stmf_worker_walk_data_t *walk_data;
1295
1296 if (mdb_readvar(&worker_state, "stmf_workers_state") == -1) {
1297 mdb_warn("failed to read stmf_workers_state");
1298 return (WALK_ERR);
1299 }
1300 if (worker_state != STMF_WORKERS_ENABLED) {
1301 mdb_warn("stmf_workers_state not initialized");
1302 return (WALK_ERR);
1303 }
1304
1305 /*
1306 * Look up the stmf_nworkers_accepting_cmds to
1307 * determine number of entries in the worker queue
1308 */
1309 if (mdb_readvar(&nworkers, "stmf_nworkers_accepting_cmds") == -1) {
1310 mdb_warn("failed to read stmf_nworkers_accepting_cmds");
1311 return (WALK_ERR);
1312 }
1313
1314 if (mdb_readvar(&worker, "stmf_workers") == -1) {
1315 mdb_warn("failed to read stmf_workers");
1316 return (WALK_ERR);
1317 }
1318
1319 walk_data = mdb_alloc(sizeof (stmf_worker_walk_data_t), UM_SLEEP);
1320 walk_data->worker_current = 0;
1321 walk_data->worker_count = nworkers;
1322
1323 wsp->walk_addr = (uintptr_t)worker;
1324 wsp->walk_data = walk_data;
1325
1326 return (WALK_NEXT);
1327 }
1328
1329 static int
1330 stmf_worker_walk_step(mdb_walk_state_t *wsp)
1331 {
1332 stmf_worker_walk_data_t *walk_data = wsp->walk_data;
1333 int status;
1334
1335 if (wsp->walk_addr == NULL) {
1336 return (WALK_DONE);
1337 }
1338
1339 if (walk_data->worker_current >= walk_data->worker_count) {
1340 return (WALK_DONE);
1341 }
1342
1343 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
1344 wsp->walk_cbdata);
1345
1346 walk_data->worker_current++;
1347 wsp->walk_addr += sizeof (stmf_worker_t);
1348
1349 return (status);
1350 }
1351
1352 static void
1353 stmf_worker_walk_fini(mdb_walk_state_t *wsp)
1354 {
1355 mdb_free(wsp->walk_data, sizeof (stmf_worker_walk_data_t));
1356 }
1357
1358 int
1359 stmf_worker(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1360 {
1361 stmf_worker_t worker;
1362
1363 if (!(flags & DCMD_ADDRSPEC)) {
1364 if (mdb_walk_dcmd("stmf_worker", "stmf_worker", argc,
1365 argv) == -1) {
1366 mdb_warn("Failed to walk the stmf_worker entries");
1367 return (DCMD_ERR);
1368 }
1369 return (DCMD_OK);
1370 }
1371
1372 if (mdb_vread(&worker, sizeof (stmf_worker_t),
1373 addr) != sizeof (stmf_worker_t)) {
1374 mdb_warn("failed to read stmf_worker at %p", addr);
1375 return (DCMD_ERR);
1376 }
1377
1378 if (flags & DCMD_PIPE_OUT) {
1379 mdb_printf("%-19p\n", addr);
1380 } else {
1381 /* pretty print */
1382 if (DCMD_HDRSPEC(flags)) {
1383 mdb_printf("%<u>%-19s %-10s %-10s %-10s%</u>\n",
1384 "stmf_worker_t", "State", "Ref_Count", "Tasks");
1385 }
1386
1387 mdb_printf("%-19p %-10s %-10d %-5d%\n", addr,
1388 (worker.worker_flags == STMF_WORKER_STARTED) ? "STARTED" :
1389 (worker.worker_flags & STMF_WORKER_ACTIVE) ?
1390 "ACTIVE" : "TERMINATED",
1391 worker.worker_ref_count,
1392 worker.worker_queue_depth);
1393 }
1394
1395 return (DCMD_OK);
1396 }
1397
1398 struct find_options *
1399 parse_options(int argc, const mdb_arg_t *argv)
1400 {
1401 int i;
1402 struct find_options *options;
1403 int len;
1404 char *ptr;
1405 int ret;
1406
1407 if (argc == 0)
1408 return (NULL);
1409 options = mdb_zalloc(sizeof (struct find_options), UM_SLEEP);
1410 for (i = 0; i < argc; i++) {
1411 switch (argv[i].a_type) {
1412 case MDB_TYPE_STRING:
1413 break;
1414 case MDB_TYPE_IMMEDIATE:
1415 case MDB_TYPE_CHAR:
1416 mdb_printf("unknown type\n");
1417 }
1418 if ((ptr = strchr(argv[i].a_un.a_str, '=')) == NULL) {
1419 mdb_printf("invalid argument: %s\n",
1420 argv[i].a_un.a_str);
1421 goto out;
1422 }
1423 len = ptr - argv[i].a_un.a_str;
1424 ptr++; /* point to value now */
1425
1426 if (len == strlen("lpname") &&
1427 strncmp(argv[i].a_un.a_str, "lpname", len) == 0) {
1428 if (strstr(ptr, "wwn.") == ptr)
1429 ptr += 4;
1430 ret = string2wwn(ptr, options->lpname);
1431 if (ret == -1)
1432 goto out;
1433 #if 0
1434 mdb_printf("wwn=%02x%02x%02x%02x%02x%02x%02x%02x\n",
1435 wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
1436 #endif
1437 options->lpname_defined = 1;
1438
1439 } else if (len == strlen("rp") &&
1440 strncmp(argv[i].a_un.a_str, "rp", len) == 0) {
1441 options->rp_defined = 1;
1442 options->rp =
1443 (void *)(unsigned long)mdb_strtoull(ptr);
1444
1445 } else if (len == strlen("rpname") &&
1446 strncmp(argv[i].a_un.a_str, "rpname", len) == 0) {
1447 if (strstr(ptr, "wwn.") == ptr)
1448 ptr += 4;
1449 ret = string2wwn(ptr, options->rpname);
1450 if (ret == -1)
1451 goto out;
1452 options->rpname_defined = 1;
1453
1454 } else if (len == strlen("show") &&
1455 strncmp(argv[i].a_un.a_str, "show", len) == 0) {
1456 char *s;
1457 int l;
1458
1459 for (;;) {
1460 s = strchr(ptr, ',');
1461 if (s)
1462 l = s - ptr;
1463 else
1464 l = strlen(ptr);
1465 if (l == strlen("task_flags") &&
1466 strncmp(ptr, "task_flags", l) == 0)
1467 options->show_task_flags = 1;
1468 else if (l == strlen("lport") &&
1469 strncmp(ptr, "lport", l) == 0)
1470 options->show_lport = 1;
1471 else {
1472 mdb_printf("unknown shower: %s\n",
1473 ptr);
1474 goto out;
1475 }
1476 if (s == NULL)
1477 break;
1478 ptr = s + 1;
1479 }
1480 } else {
1481 mdb_printf("unknown argument: %s\n",
1482 argv[i].a_un.a_str);
1483 goto out;
1484 }
1485 }
1486
1487 return (options);
1488 out:
1489 mdb_free(options, sizeof (struct find_options));
1490 return (NULL);
1491 }
1492
1493 int
1494 string2wwn(const char *s, uint8_t wwn[8])
1495 {
1496 int i;
1497 char tmp[17];
1498 char *p;
1499
1500 if (strlen(s) > 16) {
1501 mdb_printf("invalid wwn %s\n", s);
1502 return (-1);
1503 }
1504
1505 strcpy(tmp, s);
1506 p = tmp + strlen(tmp) - 2;
1507 memset(wwn, 0, 8);
1508 /* figure out wwn from the tail to beginning */
1509 for (i = 7; i >= 0 && p >= tmp; i--, p -= 2) {
1510 wwn[i] = mdb_strtoull(p);
1511 *p = 0;
1512 }
1513 return (0);
1514 }
1515
1516 void
1517 fct_find_cmds_help(void)
1518 {
1519 mdb_printf(
1520 "Find all cached fct_i_cmd_t for a local port. If a local port \n"
1521 "name is specified, find all pending cmds for it and print the \n"
1522 "address. Example:\n"
1523 " fct_find_cmds lpname=<wwn.12345678 or 12345678>\n");
1524 }
1525 void
1526 stmf_find_ilport_help(void)
1527 {
1528 mdb_printf(
1529 "Find the fct_i_local_port if local port name is "
1530 "specified. Example:\n"
1531 " stmf_find_ilport lpname=<wwn.12345678 or 12345678>\n");
1532 }
1533 void
1534 stmf_find_fct_irp_help(void)
1535 {
1536 mdb_printf(
1537 "If a remote port name or stmf_i_remote_port_t address is\n"
1538 "specified, loop through all local ports, to which this remote \n"
1539 "port has logged in, print address for stmf_i_local_port_t and \n"
1540 "stmf_i_remote_port. Example:\n"
1541 " stmf_find_fct_irp rpname=<wwn.12345678 or 12345678>\n"
1542 " stmf_find_fct_irp rp=<3000586778734>\n");
1543 }
1544
1545 void
1546 stmf_find_tasks_help(void)
1547 {
1548 mdb_printf(
1549 "Find all pending scsi_task_t for a given local port and/or\n"
1550 "remote port. Various different fields for each task are printed\n"
1551 "depending on what is requested. Example:\n"
1552 " stmf_find_tasks rpname=<wwn.12345678 or 12345678>\n"
1553 " stmf_find_tasks lpname=<wwn.12345678 or 12345678> "
1554 "show=task_flags,lport\n");
1555 }
1556
1557 void
1558 stmf_scsi_task_help(void)
1559 {
1560 mdb_printf(
1561 "List all active scsi_task_t on a given stmf_worker_t. Example\n"
1562 " addr::stmf_scsi_task\n");
1563 }
1564
1565 static const mdb_dcmd_t dcmds[] = {
1566 { "stmf_ilports", "[-v]",
1567 "Print a list of stmf_i_local_port", stmf_ilports },
1568 { "ilport2iport", "?[-v]",
1569 "Convert stmf_i_local_port to corresponding fct_i_local_port",
1570 ilport2iport },
1571 { "stmf_iss", "?[-v]",
1572 "List all active sessions for a given local port",
1573 stmf_iss },
1574 { "stmf_ilus", "[-v]", "Print a list of stmf_i_lu", stmf_ilus },
1575 { "stmf_i_lu_providers", "[-v]",
1576 "Print a list of stmf_i_lu_provider", stmf_i_lu_providers },
1577 { "stmf_i_port_providers", "[-v]",
1578 "Print a list of stmf_i_port_provider", stmf_i_port_providers },
1579 { "fct_irps", "?[-v]",
1580 "Print all fct_i_remote_port for a given fct_i_local_port",
1581 fct_irps },
1582 { "fct_icmds", "?[-v]",
1583 "Print all cached fct_i_cmd_t on fct_i_local_port",
1584 fct_icmds },
1585 { "fct_find_cmds", "lpname",
1586 "Find all fct_i_cmd_t for a given local port",
1587 fct_find_cmds, fct_find_cmds_help},
1588 { "stmf_find_ilport", "lpname",
1589 "Find local port information based on its wwn",
1590 stmf_find_ilport, stmf_find_ilport_help},
1591 { "stmf_find_fct_irp", "rpname|rp",
1592 "Print fct remote port information based on its wwn",
1593 stmf_find_fct_irp, stmf_find_fct_irp_help},
1594 { "stmf_find_tasks", "lpname|rpname [show]",
1595 "Find all pending task for a local port or remote port",
1596 stmf_find_tasks, stmf_find_tasks_help},
1597 { "stmf_worker", "?", "List all the stmf_worker entries", stmf_worker},
1598 { "stmf_scsi_task", ":",
1599 "List all the active STMF SCSI tasks per worker", stmf_scsi_task,
1600 stmf_scsi_task_help},
1601 { NULL }
1602 };
1603
1604 static const mdb_walker_t walkers[] = {
1605 { "stmf_worker", "Walk STMF worker queue", stmf_worker_walk_init,
1606 stmf_worker_walk_step, stmf_worker_walk_fini},
1607 { "stmf_scsi_task", "Walk active STMF SCSI tasks per worker",
1608 stmf_scsi_task_walk_init,
1609 stmf_scsi_task_walk_step, stmf_scsi_task_walk_fini },
1610 { NULL }
1611 };
1612
1613 static const mdb_modinfo_t modinfo = {
1614 MDB_API_VERSION, dcmds, walkers
1615 };
1616
1617 const mdb_modinfo_t *
1618 _mdb_init(void)
1619 {
1620 return (&modinfo);
1621 }