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 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2015 PALO, Richard
25 */
26 #include <sys/types.h>
27 #include <sys/scsi/generic/smp_frames.h>
28 #include <sys/scsi/generic/commands.h>
29 #include <sys/scsi/impl/commands.h>
30 #include <sys/ccompile.h>
31 #include <sys/byteorder.h>
32
33 #include <stdarg.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <stdlib.h>
38 #include <errno.h>
39 #include <strings.h>
40 #include <ctype.h>
41
42 #include <scsi/libsmp.h>
43 #include <scsi/libsmp_plugin.h>
44
45 static char *yes = "Yes";
46 static char *no = "No";
47
48 static void fatal(int, const char *, ...) __NORETURN;
49
50 static smp_target_t *tp = NULL;
51 static smp_action_t *ap = NULL;
52 static smp_function_t func;
53 static smp_result_t result;
54 static smp_target_def_t tdef;
55 static uint8_t *smp_resp;
56 static size_t smp_resp_len;
57
58 static void
fatal(int err,const char * fmt,...)59 fatal(int err, const char *fmt, ...)
60 {
61 va_list ap;
62
63 va_start(ap, fmt);
64 (void) vfprintf(stderr, fmt, ap);
65 va_end(ap);
66
67 (void) fprintf(stderr, "\n");
68 (void) fflush(stderr);
69
70 _exit(err);
71 }
72
73 static char *
smp_get_result(smp_result_t result)74 smp_get_result(smp_result_t result)
75 {
76 switch (result) {
77 case SMP_RES_FUNCTION_ACCEPTED:
78 return ("Function accepted");
79 break;
80 case SMP_RES_UNKNOWN_FUNCTION:
81 return ("Unknown function");
82 break;
83 case SMP_RES_FUNCTION_FAILED:
84 return ("Function failed");
85 break;
86 case SMP_RES_INVALID_REQUEST_FRAME_LENGTH:
87 return ("Invalid request frame length");
88 break;
89 case SMP_RES_INVALID_EXPANDER_CHANGE_COUNT:
90 return ("Invalid expander change count");
91 break;
92 case SMP_RES_BUSY:
93 return ("Busy");
94 break;
95 case SMP_RES_INCOMPLETE_DESCRIPTOR_LIST:
96 return ("Incomplete descriptor list");
97 break;
98 case SMP_RES_PHY_DOES_NOT_EXIST:
99 return ("PHY does not exist");
100 break;
101 case SMP_RES_INDEX_DOES_NOT_EXIST:
102 return ("Index does not exist");
103 break;
104 case SMP_RES_PHY_DOES_NOT_SUPPORT_SATA:
105 return ("PHY does not support SATA");
106 break;
107 case SMP_RES_UNKNOWN_PHY_OPERATION:
108 return ("Unknown PHY operation");
109 break;
110 case SMP_RES_UNKNOWN_PHY_TEST_FUNCTION:
111 return ("Unknown PHY test function");
112 break;
113 case SMP_RES_PHY_TEST_IN_PROGRESS:
114 return ("PHY test in progress");
115 break;
116 case SMP_RES_PHY_VACANT:
117 return ("PHY vacant");
118 break;
119 case SMP_RES_UNKNOWN_PHY_EVENT_SOURCE:
120 return ("Unknown PHY event source");
121 break;
122 case SMP_RES_UNKNOWN_DESCRIPTOR_TYPE:
123 return ("Unknown descriptor type");
124 break;
125 case SMP_RES_UNKNOWN_PHY_FILTER:
126 return ("Unknown PHY filter");
127 break;
128 case SMP_RES_AFFILIATION_VIOLATION:
129 return ("Affiliation violation");
130 break;
131 case SMP_RES_ZONE_VIOLATION:
132 return ("Zone violation");
133 break;
134 case SMP_RES_NO_MANAGEMENT_ACCESS_RIGHTS:
135 return ("No management access rights");
136 break;
137 case SMP_RES_UNKNOWN_ENABLE_DISABLE_ZONING:
138 return ("Unknown enable/disable zoning value");
139 break;
140 case SMP_RES_ZONE_LOCK_VIOLATION:
141 return ("Zone lock violation");
142 break;
143 case SMP_RES_NOT_ACTIVATED:
144 return ("Not activated");
145 break;
146 case SMP_RES_ZONE_GROUP_OUT_OF_RANGE:
147 return ("Zone group out of range");
148 break;
149 case SMP_RES_NO_PHYSICAL_PRESENCE:
150 return ("No physical presence");
151 break;
152 case SMP_RES_SAVING_NOT_SUPPORTED:
153 return ("Saving not supported");
154 break;
155 case SMP_RES_SOURCE_ZONE_GROUP_DNE:
156 return ("Source zone group does not exist");
157 break;
158 case SMP_RES_DISABLED_PW_NOT_SUPPORTED:
159 return ("Disabled password not supported");
160 break;
161 default:
162 break;
163 }
164
165 return (NULL);
166 }
167
168 static void
smp_execute()169 smp_execute()
170 {
171 if (smp_exec(ap, tp) != 0) {
172 smp_close(tp);
173 smp_action_free(ap);
174 smp_fini();
175 fatal(-4, "exec failed: %s", smp_errmsg());
176 }
177 }
178
179 static void
smp_cmd_failed(smp_result_t result)180 smp_cmd_failed(smp_result_t result)
181 {
182 char *smp_result_str = smp_get_result(result);
183
184 if (smp_result_str == NULL) {
185 fatal(-5, "Command failed: Unknown result (0x%x)",
186 result);
187 } else {
188 fatal(-5, "Command failed: %s", smp_result_str);
189 }
190 }
191
192 static void
smp_get_response(boolean_t close_on_fail)193 smp_get_response(boolean_t close_on_fail)
194 {
195 smp_action_get_response(ap, &result, (void **)&smp_resp, &smp_resp_len);
196
197 if (close_on_fail && (result != SMP_RES_FUNCTION_ACCEPTED)) {
198 smp_close(tp);
199 smp_action_free(ap);
200 smp_fini();
201 smp_cmd_failed(result);
202 }
203 }
204
205 static void
smp_cleanup()206 smp_cleanup()
207 {
208 if (tp) {
209 smp_close(tp);
210 tp = NULL;
211 }
212 smp_action_free(ap);
213 smp_fini();
214 }
215
216 /* ARGSUSED */
217 static void
smp_handle_report_route_info(int argc,char * argv[])218 smp_handle_report_route_info(int argc, char *argv[])
219 {
220 smp_report_route_info_req_t *rp;
221 smp_report_route_info_resp_t *rirp;
222 uint16_t route_indexes = smp_target_get_exp_route_indexes(tp);
223 uint8_t num_phys = smp_target_get_number_of_phys(tp);
224 uint16_t rt_idx_req, ri_idx, ri_end;
225 uint8_t phy_id_req, pi_idx, pi_end;
226 boolean_t enabled_entries = B_FALSE;
227
228 /*
229 * Verify the expander supports the PHY-based expander route table
230 */
231 if (route_indexes == 0) {
232 smp_cleanup();
233 fatal(-6, "Expander does not support PHY-based route table\n");
234 }
235
236 rt_idx_req = strtol(argv[3], NULL, 0);
237 phy_id_req = strtol(argv[4], NULL, 0);
238
239 if (((int16_t)rt_idx_req == -1) && ((int8_t)phy_id_req == -1)) {
240 ri_idx = 0;
241 ri_end = route_indexes - 1;
242 pi_idx = 0;
243 pi_end = num_phys - 1;
244 } else if (((int16_t)rt_idx_req < 0) || (rt_idx_req >= route_indexes) ||
245 ((int8_t)phy_id_req < 0) || (phy_id_req >= num_phys)) {
246 smp_cleanup();
247 fatal(-1, "Invalid route index (%d) or PHY ID (%d)\n",
248 rt_idx_req, phy_id_req);
249 } else {
250 ri_end = ri_idx = rt_idx_req;
251 pi_end = pi_idx = phy_id_req;
252 }
253
254 (void) printf("%6s %6s %3s %14s\n",
255 "RT Idx", "PHY ID", "DIS", "Routed SASAddr");
256
257 smp_action_get_request(ap, (void **)&rp, NULL);
258
259 while (ri_idx <= ri_end) {
260 while (pi_idx <= pi_end) {
261 rp->srrir_phy_identifier = pi_idx;
262 rp->srrir_exp_route_index = ri_idx;
263
264 smp_execute();
265 smp_get_response(B_FALSE);
266
267 if (result != SMP_RES_FUNCTION_ACCEPTED) {
268 pi_idx++;
269 continue;
270 }
271
272 rirp = (smp_report_route_info_resp_t *)smp_resp;
273
274 if (rirp->srrir_exp_route_entry_disabled == 0) {
275 enabled_entries = B_TRUE;
276 (void) printf("%6d %6d %3d %016llx\n",
277 rirp->srrir_exp_route_index,
278 rirp->srrir_phy_identifier,
279 rirp->srrir_exp_route_entry_disabled,
280 BE_64(rirp->srrir_routed_sas_addr));
281 }
282
283 pi_idx++;
284 }
285
286 ri_idx++;
287 pi_idx = 0;
288 }
289
290 if (!enabled_entries) {
291 (void) printf("No enabled entries in the table.\n");
292 }
293
294 smp_cleanup();
295 exit(0);
296 }
297
298 static char *
smp_phy_event_src_str(smp_phy_event_source_t src,boolean_t * peak_detector)299 smp_phy_event_src_str(smp_phy_event_source_t src, boolean_t *peak_detector)
300 {
301 char *src_str;
302
303 *peak_detector = B_FALSE;
304
305 switch (src) {
306 case SMP_PHY_EVENT_NO_EVENT:
307 src_str = "No event";
308 break;
309 case SMP_PHY_EVENT_INVALID_DWORD_COUNT:
310 src_str = "Invalid DWORD count";
311 break;
312 case SMP_PHY_EVENT_RUNNING_DISPARITY_ERROR_COUNT:
313 src_str = "Running disparity error count";
314 break;
315 case SMP_PHY_EVENT_LOSS_OF_DWORD_SYNC_COUNT:
316 src_str = "Loss of DWORD sync count";
317 break;
318 case SMP_PHY_EVENT_PHY_RESET_PROBLEM_COUNT:
319 src_str = "PHY reset problem count";
320 break;
321 case SMP_PHY_EVENT_ELASTICITY_BUFFER_OVERFLOW_COUNT:
322 src_str = "Elasticity buffer overflow count";
323 break;
324 case SMP_PHY_EVENT_RX_ERROR_COUNT:
325 src_str = "Received ERROR count";
326 break;
327 case SMP_PHY_EVENT_RX_ADDR_FRAME_ERROR_COUNT:
328 src_str = "Received address frame error count";
329 break;
330 case SMP_PHY_EVENT_TX_ABANDON_CLASS_OPEN_REJ_COUNT:
331 src_str = "Transmitted abandon-class OPEN_REJECT count";
332 break;
333 case SMP_PHY_EVENT_RX_ABANDON_CLASS_OPEN_REJ_COUNT:
334 src_str = "Received abandon-class OPEN_REJECT count";
335 break;
336 case SMP_PHY_EVENT_TX_RETRY_CLASS_OPEN_REJ_COUNT:
337 src_str = "Transmitted retry-class OPEN_REJECT count";
338 break;
339 case SMP_PHY_EVENT_RX_RETRY_CLASS_OPEN_REJ_COUNT:
340 src_str = "Received retry-class OPEN_REJECT count";
341 break;
342 case SMP_PHY_EVENT_RX_AIP_W_O_PARTIAL_COUNT:
343 src_str = "Received AIP (WAITING ON PARTIAL) count";
344 break;
345 case SMP_PHY_EVENT_RX_AIP_W_O_CONN_COUNT:
346 src_str = "Received AIP (WAITING ON CONNECTION) count";
347 break;
348 case SMP_PHY_EVENT_TX_BREAK_COUNT:
349 src_str = "Transmitted BREAK count";
350 break;
351 case SMP_PHY_EVENT_RX_BREAK_COUNT:
352 src_str = "Received BREAK count";
353 break;
354 case SMP_PHY_EVENT_BREAK_TIMEOUT_COUNT:
355 src_str = "BREAK timeout count";
356 break;
357 case SMP_PHY_EVENT_CONNECTION_COUNT:
358 src_str = "Connection count";
359 break;
360 case SMP_PHY_EVENT_PEAK_TX_PATHWAY_BLOCKED_COUNT:
361 src_str = "Peak transmitted pathway blocked count";
362 *peak_detector = B_TRUE;
363 break;
364 case SMP_PHY_EVENT_PEAK_TX_ARB_WAIT_TIME:
365 src_str = "Peak transmitted arbitration wait time";
366 *peak_detector = B_TRUE;
367 break;
368 case SMP_PHY_EVENT_PEAK_ARB_TIME:
369 src_str = "Peak arbitration time";
370 *peak_detector = B_TRUE;
371 break;
372 case SMP_PHY_EVENT_PEAK_CONNECTION_TIME:
373 src_str = "Peak connection time";
374 *peak_detector = B_TRUE;
375 break;
376 case SMP_PHY_EVENT_TX_SSP_FRAME_COUNT:
377 src_str = "Transmitted SSP frame count";
378 break;
379 case SMP_PHY_EVENT_RX_SSP_FRAME_COUNT:
380 src_str = "Received SSP frame count";
381 break;
382 case SMP_PHY_EVENT_TX_SSP_FRAME_ERROR_COUNT:
383 src_str = "Transmitted SSP frame error count";
384 break;
385 case SMP_PHY_EVENT_RX_SSP_FRAME_ERROR_COUNT:
386 src_str = "Received SSP frame error count";
387 break;
388 case SMP_PHY_EVENT_TX_CREDIT_BLOCKED_COUNT:
389 src_str = "Transmitted CREDIT_BLOCKED count";
390 break;
391 case SMP_PHY_EVENT_RX_CREDIT_BLOCKED_COUNT:
392 src_str = "Received CREDIT_BLOCKED count";
393 break;
394 case SMP_PHY_EVENT_TX_SATA_FRAME_COUNT:
395 src_str = "Transmitted SATA frame count";
396 break;
397 case SMP_PHY_EVENT_RX_SATA_FRAME_COUNT:
398 src_str = "Received SATA frame count";
399 break;
400 case SMP_PHY_EVENT_SATA_FLOW_CTRL_BUF_OVERFLOW_COUNT:
401 src_str = "SATA flow control buffer overflow count";
402 break;
403 case SMP_PHY_EVENT_TX_SMP_FRAME_COUNT:
404 src_str = "Transmitted SMP frame count";
405 break;
406 case SMP_PHY_EVENT_RX_SMP_FRAME_COUNT:
407 src_str = "Received SMP frame count";
408 break;
409 case SMP_PHY_EVENT_RX_SMP_FRAME_ERROR_COUNT:
410 src_str = "Received SMP frame error count";
411 break;
412 default:
413 src_str = "<Unknown>";
414 break;
415 }
416
417 return (src_str);
418 }
419
420 static void
smp_validate_args(int argc,char * argv[])421 smp_validate_args(int argc, char *argv[])
422 {
423 errno = 0;
424
425 if (argc < 3)
426 fatal(-1, "Usage: %s <device> <function> ...\n", argv[0]);
427
428 func = strtoul(argv[2], NULL, 0);
429
430 if (errno != 0)
431 fatal(-1, "Usage: %s <device> <function> ...\n", argv[0]);
432
433 switch (func) {
434 case SMP_FUNC_DISCOVER:
435 case SMP_FUNC_REPORT_PHY_EVENT:
436 case SMP_FUNC_REPORT_PHY_ERROR_LOG: {
437 if (argc != 4) {
438 fatal(-1,
439 "Usage: %s <device> 0x%x <phy identifier>\n",
440 argv[0], func);
441 }
442 break;
443 }
444 case SMP_FUNC_REPORT_EXP_ROUTE_TABLE_LIST: {
445 if (argc < 4) {
446 fatal(-1,
447 "Usage: %s <device> 0x%x <SAS Address Index>\n",
448 argv[0], func);
449 }
450 break;
451 }
452 case SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD: {
453 if (argc < 4) {
454 fatal(-1,
455 "Usage: %s <device> 0x%x <report type>\n",
456 argv[0], func);
457 }
458 break;
459 }
460 case SMP_FUNC_ENABLE_DISABLE_ZONING: {
461 if (argc != 4) {
462 fatal(-1,
463 "Usage: %s <device> 0x%x "
464 "[0(no change) | 1(enable)| 2(disable)]\n",
465 argv[0], func);
466 }
467 break;
468 }
469 case SMP_FUNC_REPORT_BROADCAST: {
470 if (argc != 4) {
471 fatal(-1, "Usage: %s <device> 0x%x <bcast type>\n",
472 argv[0], func);
473 }
474 break;
475 }
476 case SMP_FUNC_REPORT_ROUTE_INFO: {
477 if (argc != 5) {
478 fatal(-1,
479 "Usage: %s <device> 0x%x <exp_route_idx> "
480 "<phy_identifier>\n", argv[0], func);
481 }
482 break;
483 }
484 case SMP_FUNC_PHY_CONTROL: {
485 if (argc != 5) {
486 fatal(-1,
487 "Usage: %s <device> 0x%x <phy identifier> "
488 " <phy operation>\n",
489 argv[0], func);
490 }
491 break;
492 }
493 default: {
494 fatal(-1, "Usage: %s <device> <function> ...\n", argv[0]);
495 break;
496 }
497 }
498 }
499
500 int
main(int argc,char * argv[])501 main(int argc, char *argv[])
502 {
503 uint_t i, j;
504 char *yesorno;
505 uint16_t exp_change_count;
506
507 /*
508 * If the arguments are invalid, this function will not return.
509 */
510 smp_validate_args(argc, argv);
511
512 if (smp_init(LIBSMP_VERSION) != 0)
513 fatal(-1, "libsmp initialization failed: %s", smp_errmsg());
514
515 bzero(&tdef, sizeof (smp_target_def_t));
516 tdef.std_def = argv[1];
517
518 if ((tp = smp_open(&tdef)) == NULL) {
519 smp_fini();
520 fatal(-2, "failed to open %s: %s", argv[1], smp_errmsg());
521 }
522
523 exp_change_count = smp_target_get_change_count(tp);
524
525 (void) printf("%s\n", argv[0]);
526 (void) printf("\tSAS Address: %016llx\n", smp_target_addr(tp));
527 (void) printf("\tVendor/Product/Revision: %s/%s/%s\n",
528 smp_target_vendor(tp), smp_target_product(tp),
529 smp_target_revision(tp));
530 (void) printf("\tExp Vendor/ID/Rev: %s/%04x/%02x\n",
531 smp_target_component_vendor(tp), smp_target_component_id(tp),
532 smp_target_component_revision(tp));
533 (void) printf("\tExpander change count: 0x%04x\n", exp_change_count);
534
535 ap = smp_action_alloc(func, tp, 0);
536 if (ap == NULL) {
537 smp_close(tp);
538 smp_fini();
539 fatal(-3, "failed to allocate action: %s", smp_errmsg());
540 }
541
542 switch (func) {
543 case SMP_FUNC_DISCOVER: {
544 smp_discover_req_t *dp;
545
546 smp_action_get_request(ap, (void **)&dp, NULL);
547 dp->sdr_phy_identifier = strtoul(argv[3], NULL, 0);
548 break;
549 }
550 case SMP_FUNC_REPORT_ROUTE_INFO: {
551 smp_handle_report_route_info(argc, argv);
552 break;
553 }
554 case SMP_FUNC_ENABLE_DISABLE_ZONING: {
555 smp_enable_disable_zoning_req_t *rp;
556
557 smp_action_get_request(ap, (void **)&rp, NULL);
558 rp->sedzr_enable_disable_zoning = strtoul(argv[3], NULL, 0);
559 break;
560 }
561 case SMP_FUNC_PHY_CONTROL: {
562 smp_phy_control_req_t *rp;
563
564 smp_action_get_request(ap, (void **)&rp, NULL);
565 rp->spcr_phy_identifier = strtoul(argv[3], NULL, 0);
566 rp->spcr_phy_operation = strtoul(argv[4], NULL, 0);
567 break;
568 }
569 case SMP_FUNC_REPORT_EXP_ROUTE_TABLE_LIST: {
570 smp_report_exp_route_table_list_req_t *rp;
571
572 smp_action_get_request(ap, (void **)&rp, NULL);
573 SCSI_WRITE16(&rp->srertlr_max_descrs, 64);
574 SCSI_WRITE16(&rp->srertlr_starting_routed_sas_addr_index,
575 strtoull(argv[3], NULL, 0));
576 rp->srertlr_starting_phy_identifier = 0;
577 break;
578 }
579 case SMP_FUNC_REPORT_PHY_ERROR_LOG: {
580 smp_report_phy_error_log_req_t *pelp;
581
582 smp_action_get_request(ap, (void **)&pelp, NULL);
583 pelp->srpelr_phy_identifier = strtoul(argv[3], NULL, 0);
584 break;
585 }
586 case SMP_FUNC_REPORT_PHY_EVENT: {
587 smp_report_phy_event_req_t *rpep;
588
589 smp_action_get_request(ap, (void **)&rpep, NULL);
590 rpep->srper_phy_identifier = strtoul(argv[3], NULL, 0);
591 break;
592 }
593 case SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD: {
594 smp_report_zone_mgr_password_req_t *rzmprp;
595
596 smp_action_get_request(ap, (void **)&rzmprp, NULL);
597 rzmprp->srzmpr_rpt_type = strtoul(argv[3], NULL, 0);
598 break;
599 }
600 case SMP_FUNC_REPORT_BROADCAST: {
601 smp_report_broadcast_req_t *rbrp;
602
603 smp_action_get_request(ap, (void **)&rbrp, NULL);
604 rbrp->srbr_broadcast_type = strtoul(argv[3], NULL, 0);
605 break;
606 }
607 default:
608 smp_close(tp);
609 smp_action_free(ap);
610 smp_fini();
611 smp_cmd_failed(result);
612 }
613
614 smp_execute();
615 smp_get_response(B_TRUE);
616
617 switch (func) {
618 case SMP_FUNC_DISCOVER: {
619 smp_discover_resp_t *rp = (smp_discover_resp_t *)smp_resp;
620 (void) printf("Addr: %016llx Phy: %02x\n",
621 SCSI_READ64(&rp->sdr_sas_addr), rp->sdr_phy_identifier);
622 (void) printf("Peer: %016llx Phy: %02x\n",
623 SCSI_READ64(&rp->sdr_attached_sas_addr),
624 rp->sdr_attached_phy_identifier);
625 (void) printf("Device type: %01x\n",
626 rp->sdr_attached_device_type);
627 break;
628 }
629 case SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD: {
630 smp_report_zone_mgr_password_resp_t *rp =
631 (smp_report_zone_mgr_password_resp_t *)smp_resp;
632 char *rpt_type = NULL;
633 int idx;
634 switch (rp->srzmpr_rpt_type) {
635 case SMP_ZMP_TYPE_CURRENT:
636 rpt_type = "Current";
637 break;
638 case SMP_ZMP_TYPE_SAVED:
639 rpt_type = "Saved";
640 break;
641 case SMP_ZMP_TYPE_DEFAULT:
642 rpt_type = "Default";
643 break;
644 default:
645 rpt_type = "(Unknown Type)";
646 break;
647 }
648 (void) printf("%s zone manager password: 0x", rpt_type);
649 for (idx = 0; idx < 32; idx++) {
650 (void) printf("%02x",
651 rp->srzmpr_zone_mgr_password[idx]);
652 }
653 (void) printf("\n");
654 break;
655 }
656 case SMP_FUNC_REPORT_EXP_ROUTE_TABLE_LIST: {
657 smp_report_exp_route_table_list_resp_t *rtlr =
658 (smp_report_exp_route_table_list_resp_t *)smp_resp;
659 smp_route_table_descr_t *descp = &rtlr->srertlr_descrs[0];
660 int idx, idxx, ndescrs, zoning, startnum;
661
662 (void) printf("Expander change count: 0x%04x\n",
663 BE_16(rtlr->srertlr_exp_change_count));
664 (void) printf("Expander route table change count: 0x%04x\n",
665 BE_16(rtlr->srertlr_route_table_change_count));
666
667 if (rtlr->srertlr_zoning_enabled) {
668 yesorno = yes;
669 zoning = 1;
670 } else {
671 yesorno = no;
672 zoning = 0;
673 }
674 (void) printf("Zoning enabled: %s\n", yesorno);
675
676 if (rtlr->srertlr_configuring) {
677 yesorno = yes;
678 } else {
679 yesorno = no;
680 }
681 (void) printf("Configuring: %s\n", yesorno);
682
683 ndescrs = rtlr->srertlr_n_descrs;
684 (void) printf("Number of descriptors: %d\n", ndescrs);
685 startnum = BE_16(rtlr->srertlr_first_routed_sas_addr_index);
686 (void) printf("First/Last routed SAS address index: %d/%d\n",
687 startnum, BE_16(rtlr->srertlr_last_routed_sas_addr_index));
688 (void) printf("Starting PHY identifier: %d\n",
689 rtlr->srertlr_starting_phy_identifier);
690
691 for (idx = 0; idx < ndescrs; idx++, descp++) {
692 (void) printf("#%03d: Routed SAS addr: %016llx ",
693 idx + startnum, BE_64(descp->srtd_routed_sas_addr));
694 (void) printf("PHY bitmap: 0x");
695 for (idxx = 0; idxx < 6; idxx++) {
696 (void) printf("%02x",
697 descp->srtd_phy_bitmap[idxx]);
698 }
699 (void) printf("\n");
700 if (zoning) {
701 (void) printf("\tZone group: %d\n",
702 descp->srtd_zone_group);
703 }
704 }
705
706 (void) printf("\n");
707 break;
708 }
709 case SMP_FUNC_REPORT_PHY_ERROR_LOG: {
710 smp_report_phy_error_log_resp_t *pelr =
711 (smp_report_phy_error_log_resp_t *)smp_resp;
712 (void) printf("PHY error log for PHY %d:\n",
713 pelr->srpelr_phy_identifier);
714 (void) printf("\tInvalid DWORD count: %d\n",
715 BE_32(pelr->srpelr_invalid_dword_count));
716 (void) printf("\tRunning disparity error count: %d\n",
717 BE_32(pelr->srpelr_running_disparity_error_count));
718 (void) printf("\tLoss of DWORD sync count: %d\n",
719 BE_32(pelr->srpelr_loss_dword_sync_count));
720 (void) printf("\tPHY reset problem count: %d\n",
721 BE_32(pelr->srpelr_phy_reset_problem_count));
722 break;
723 }
724 case SMP_FUNC_REPORT_PHY_EVENT: {
725 smp_report_phy_event_resp_t *rper =
726 (smp_report_phy_event_resp_t *)smp_resp;
727 smp_phy_event_report_descr_t *perd =
728 &rper->srper_phy_event_descrs[0];
729 boolean_t peak;
730 int idx;
731
732 (void) printf("PHY event for PHY %d:\n",
733 rper->srper_phy_identifier);
734 (void) printf("Number of PHY event descriptors: %d\n",
735 rper->srper_n_phy_event_descrs);
736
737 for (idx = 0; idx < rper->srper_n_phy_event_descrs; idx++) {
738 (void) printf("%50s : %d\n",
739 smp_phy_event_src_str(perd->sped_phy_event_source,
740 &peak), BE_32(perd->sped_phy_event));
741 if (peak) {
742 (void) printf("\tPeak value detector "
743 "threshold: %d\n",
744 BE_32(perd->sped_peak_detector_threshold));
745 }
746 perd++;
747 }
748
749 break;
750 }
751 case SMP_FUNC_REPORT_BROADCAST: {
752 smp_report_broadcast_resp_t *brp =
753 (smp_report_broadcast_resp_t *)smp_resp;
754 smp_broadcast_descr_t *bdp = &brp->srbr_descrs[0];
755 uint16_t bcount, idx;
756
757 bcount = brp->srbr_number_broadcast_descrs;
758
759 (void) printf("\tNumber of broadcast descriptors: %d\n",
760 bcount);
761 (void) printf("\t%7s %5s %5s %8s\n",
762 "BCType", "PhyID", "BCRsn", "BC Count");
763 for (idx = 0; idx < bcount; idx++) {
764 (void) printf("\t%7s %5s %5s %8s\n",
765 bdp->sbd_broadcast_type, bdp->sbd_phy_identifier,
766 bdp->sbd_broadcast_reason,
767 bdp->sbd_broadcast_count);
768 bdp++;
769 }
770
771 break;
772 }
773 default:
774 (void) printf("Response: (len %d)\n", smp_resp_len);
775 for (i = 0; i < smp_resp_len; i += 8) {
776 (void) printf("%02x: ", i);
777 for (j = i; j < i + 8; j++)
778 if (j < smp_resp_len)
779 (void) printf("%02x ", smp_resp[j]);
780 else
781 (void) printf(" ");
782 for (j = i; j < i + 8; j++)
783 (void) printf("%c",
784 j < smp_resp_len && isprint(smp_resp[j]) ?
785 smp_resp[j] : j < smp_resp_len ? '.' :
786 '\0');
787 (void) printf("\n");
788 }
789 break;
790 }
791
792 smp_cleanup();
793 return (0);
794 }
795