1ac88567aSHyon Kim /*
2ac88567aSHyon Kim * CDDL HEADER START
3ac88567aSHyon Kim *
4ac88567aSHyon Kim * The contents of this file are subject to the terms of the
5ac88567aSHyon Kim * Common Development and Distribution License (the "License").
6ac88567aSHyon Kim * You may not use this file except in compliance with the License.
7ac88567aSHyon Kim *
8ac88567aSHyon Kim * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9ac88567aSHyon Kim * or http://www.opensolaris.org/os/licensing.
10ac88567aSHyon Kim * See the License for the specific language governing permissions
11ac88567aSHyon Kim * and limitations under the License.
12ac88567aSHyon Kim *
13ac88567aSHyon Kim * When distributing Covered Code, include this CDDL HEADER in each
14ac88567aSHyon Kim * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15ac88567aSHyon Kim * If applicable, add the following below this CDDL HEADER, with the
16ac88567aSHyon Kim * fields enclosed by brackets "[]" replaced with your own identifying
17ac88567aSHyon Kim * information: Portions Copyright [yyyy] [name of copyright owner]
18ac88567aSHyon Kim *
19ac88567aSHyon Kim * CDDL HEADER END
20ac88567aSHyon Kim */
21ac88567aSHyon Kim
22ac88567aSHyon Kim /*
23ac88567aSHyon Kim * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2424f5a376SRichard PALO * Copyright 2015 PALO, Richard
25*bde334a8SRobert Mustacchi * Copyright 2019, Joyent, Inc.
26ac88567aSHyon Kim */
27ac88567aSHyon Kim #include <sys/types.h>
28ac88567aSHyon Kim #include <sys/scsi/generic/smp_frames.h>
29ac88567aSHyon Kim #include <sys/scsi/generic/commands.h>
30ac88567aSHyon Kim #include <sys/scsi/impl/commands.h>
31ac88567aSHyon Kim #include <sys/ccompile.h>
32d0698e0dSDavid Hollister #include <sys/byteorder.h>
33ac88567aSHyon Kim
34ac88567aSHyon Kim #include <stdarg.h>
35ac88567aSHyon Kim #include <stdio.h>
36ac88567aSHyon Kim #include <string.h>
37ac88567aSHyon Kim #include <unistd.h>
38ac88567aSHyon Kim #include <stdlib.h>
39ac88567aSHyon Kim #include <errno.h>
40ac88567aSHyon Kim #include <strings.h>
41ac88567aSHyon Kim #include <ctype.h>
42ac88567aSHyon Kim
43ac88567aSHyon Kim #include <scsi/libsmp.h>
44ac88567aSHyon Kim #include <scsi/libsmp_plugin.h>
45ac88567aSHyon Kim
46d0698e0dSDavid Hollister static char *yes = "Yes";
47d0698e0dSDavid Hollister static char *no = "No";
48d0698e0dSDavid Hollister
49ac88567aSHyon Kim static void fatal(int, const char *, ...) __NORETURN;
50ac88567aSHyon Kim
51d0698e0dSDavid Hollister static smp_target_t *tp = NULL;
52d0698e0dSDavid Hollister static smp_action_t *ap = NULL;
53d0698e0dSDavid Hollister static smp_function_t func;
54d0698e0dSDavid Hollister static smp_result_t result;
55d0698e0dSDavid Hollister static smp_target_def_t tdef;
56d0698e0dSDavid Hollister static uint8_t *smp_resp;
57d0698e0dSDavid Hollister static size_t smp_resp_len;
58d0698e0dSDavid Hollister
59ac88567aSHyon Kim static void
fatal(int err,const char * fmt,...)60ac88567aSHyon Kim fatal(int err, const char *fmt, ...)
61ac88567aSHyon Kim {
62ac88567aSHyon Kim va_list ap;
63ac88567aSHyon Kim
64ac88567aSHyon Kim va_start(ap, fmt);
65ac88567aSHyon Kim (void) vfprintf(stderr, fmt, ap);
66ac88567aSHyon Kim va_end(ap);
67ac88567aSHyon Kim
68ac88567aSHyon Kim (void) fprintf(stderr, "\n");
69ac88567aSHyon Kim (void) fflush(stderr);
70ac88567aSHyon Kim
71ac88567aSHyon Kim _exit(err);
72ac88567aSHyon Kim }
73ac88567aSHyon Kim
74*bde334a8SRobert Mustacchi /*
75*bde334a8SRobert Mustacchi * Print out a buffer of SMP character array data. The data in str is guaranteed
76*bde334a8SRobert Mustacchi * to be at most len bytes long. While it is supposed to be ascii, we should not
77*bde334a8SRobert Mustacchi * assume as such.
78*bde334a8SRobert Mustacchi */
79*bde334a8SRobert Mustacchi static void
smp_print_ascii(const char * header,const char * str,size_t len)80*bde334a8SRobert Mustacchi smp_print_ascii(const char *header, const char *str, size_t len)
81*bde334a8SRobert Mustacchi {
82*bde334a8SRobert Mustacchi size_t i, last = len;
83*bde334a8SRobert Mustacchi
84*bde334a8SRobert Mustacchi while (last > 0 && str[last - 1] == ' ')
85*bde334a8SRobert Mustacchi last--;
86*bde334a8SRobert Mustacchi
87*bde334a8SRobert Mustacchi (void) printf("%s: ", header);
88*bde334a8SRobert Mustacchi for (i = 0; i < last; i++) {
89*bde334a8SRobert Mustacchi if (isascii(str[i]) != 0 && isalnum(str[i]) != 0) {
90*bde334a8SRobert Mustacchi (void) putchar(str[i]);
91*bde334a8SRobert Mustacchi } else {
92*bde334a8SRobert Mustacchi (void) printf("\\x%x", str[i]);
93*bde334a8SRobert Mustacchi }
94*bde334a8SRobert Mustacchi }
95*bde334a8SRobert Mustacchi
96*bde334a8SRobert Mustacchi (void) putchar('\n');
97*bde334a8SRobert Mustacchi }
98*bde334a8SRobert Mustacchi
99d0698e0dSDavid Hollister static char *
smp_get_result(smp_result_t result)100d0698e0dSDavid Hollister smp_get_result(smp_result_t result)
101ac88567aSHyon Kim {
102d0698e0dSDavid Hollister switch (result) {
103d0698e0dSDavid Hollister case SMP_RES_FUNCTION_ACCEPTED:
104d0698e0dSDavid Hollister return ("Function accepted");
105d0698e0dSDavid Hollister break;
106d0698e0dSDavid Hollister case SMP_RES_UNKNOWN_FUNCTION:
107d0698e0dSDavid Hollister return ("Unknown function");
108d0698e0dSDavid Hollister break;
109d0698e0dSDavid Hollister case SMP_RES_FUNCTION_FAILED:
110d0698e0dSDavid Hollister return ("Function failed");
111d0698e0dSDavid Hollister break;
112d0698e0dSDavid Hollister case SMP_RES_INVALID_REQUEST_FRAME_LENGTH:
113d0698e0dSDavid Hollister return ("Invalid request frame length");
114d0698e0dSDavid Hollister break;
115d0698e0dSDavid Hollister case SMP_RES_INVALID_EXPANDER_CHANGE_COUNT:
116d0698e0dSDavid Hollister return ("Invalid expander change count");
117d0698e0dSDavid Hollister break;
118d0698e0dSDavid Hollister case SMP_RES_BUSY:
119d0698e0dSDavid Hollister return ("Busy");
120d0698e0dSDavid Hollister break;
121d0698e0dSDavid Hollister case SMP_RES_INCOMPLETE_DESCRIPTOR_LIST:
122d0698e0dSDavid Hollister return ("Incomplete descriptor list");
123d0698e0dSDavid Hollister break;
124d0698e0dSDavid Hollister case SMP_RES_PHY_DOES_NOT_EXIST:
125d0698e0dSDavid Hollister return ("PHY does not exist");
126d0698e0dSDavid Hollister break;
127d0698e0dSDavid Hollister case SMP_RES_INDEX_DOES_NOT_EXIST:
128d0698e0dSDavid Hollister return ("Index does not exist");
129d0698e0dSDavid Hollister break;
130d0698e0dSDavid Hollister case SMP_RES_PHY_DOES_NOT_SUPPORT_SATA:
131d0698e0dSDavid Hollister return ("PHY does not support SATA");
132d0698e0dSDavid Hollister break;
133d0698e0dSDavid Hollister case SMP_RES_UNKNOWN_PHY_OPERATION:
134d0698e0dSDavid Hollister return ("Unknown PHY operation");
135d0698e0dSDavid Hollister break;
136d0698e0dSDavid Hollister case SMP_RES_UNKNOWN_PHY_TEST_FUNCTION:
137d0698e0dSDavid Hollister return ("Unknown PHY test function");
138d0698e0dSDavid Hollister break;
139d0698e0dSDavid Hollister case SMP_RES_PHY_TEST_IN_PROGRESS:
140d0698e0dSDavid Hollister return ("PHY test in progress");
141d0698e0dSDavid Hollister break;
142d0698e0dSDavid Hollister case SMP_RES_PHY_VACANT:
143d0698e0dSDavid Hollister return ("PHY vacant");
144d0698e0dSDavid Hollister break;
145d0698e0dSDavid Hollister case SMP_RES_UNKNOWN_PHY_EVENT_SOURCE:
146d0698e0dSDavid Hollister return ("Unknown PHY event source");
147d0698e0dSDavid Hollister break;
148d0698e0dSDavid Hollister case SMP_RES_UNKNOWN_DESCRIPTOR_TYPE:
149d0698e0dSDavid Hollister return ("Unknown descriptor type");
150d0698e0dSDavid Hollister break;
151d0698e0dSDavid Hollister case SMP_RES_UNKNOWN_PHY_FILTER:
152d0698e0dSDavid Hollister return ("Unknown PHY filter");
153d0698e0dSDavid Hollister break;
154d0698e0dSDavid Hollister case SMP_RES_AFFILIATION_VIOLATION:
155d0698e0dSDavid Hollister return ("Affiliation violation");
156d0698e0dSDavid Hollister break;
157d0698e0dSDavid Hollister case SMP_RES_ZONE_VIOLATION:
158d0698e0dSDavid Hollister return ("Zone violation");
159d0698e0dSDavid Hollister break;
160d0698e0dSDavid Hollister case SMP_RES_NO_MANAGEMENT_ACCESS_RIGHTS:
161d0698e0dSDavid Hollister return ("No management access rights");
162d0698e0dSDavid Hollister break;
163d0698e0dSDavid Hollister case SMP_RES_UNKNOWN_ENABLE_DISABLE_ZONING:
164d0698e0dSDavid Hollister return ("Unknown enable/disable zoning value");
165d0698e0dSDavid Hollister break;
166d0698e0dSDavid Hollister case SMP_RES_ZONE_LOCK_VIOLATION:
167d0698e0dSDavid Hollister return ("Zone lock violation");
168d0698e0dSDavid Hollister break;
169d0698e0dSDavid Hollister case SMP_RES_NOT_ACTIVATED:
170d0698e0dSDavid Hollister return ("Not activated");
171d0698e0dSDavid Hollister break;
172d0698e0dSDavid Hollister case SMP_RES_ZONE_GROUP_OUT_OF_RANGE:
173d0698e0dSDavid Hollister return ("Zone group out of range");
174d0698e0dSDavid Hollister break;
175d0698e0dSDavid Hollister case SMP_RES_NO_PHYSICAL_PRESENCE:
176d0698e0dSDavid Hollister return ("No physical presence");
177d0698e0dSDavid Hollister break;
178d0698e0dSDavid Hollister case SMP_RES_SAVING_NOT_SUPPORTED:
179d0698e0dSDavid Hollister return ("Saving not supported");
180d0698e0dSDavid Hollister break;
181d0698e0dSDavid Hollister case SMP_RES_SOURCE_ZONE_GROUP_DNE:
182d0698e0dSDavid Hollister return ("Source zone group does not exist");
183d0698e0dSDavid Hollister break;
184d0698e0dSDavid Hollister case SMP_RES_DISABLED_PW_NOT_SUPPORTED:
185d0698e0dSDavid Hollister return ("Disabled password not supported");
186d0698e0dSDavid Hollister break;
187d0698e0dSDavid Hollister default:
188d0698e0dSDavid Hollister break;
189d0698e0dSDavid Hollister }
190d0698e0dSDavid Hollister
191d0698e0dSDavid Hollister return (NULL);
192d0698e0dSDavid Hollister }
193d0698e0dSDavid Hollister
194d0698e0dSDavid Hollister static void
smp_execute()195d0698e0dSDavid Hollister smp_execute()
196d0698e0dSDavid Hollister {
197d0698e0dSDavid Hollister if (smp_exec(ap, tp) != 0) {
198d0698e0dSDavid Hollister smp_close(tp);
199d0698e0dSDavid Hollister smp_action_free(ap);
200d0698e0dSDavid Hollister smp_fini();
201d0698e0dSDavid Hollister fatal(-4, "exec failed: %s", smp_errmsg());
202d0698e0dSDavid Hollister }
203d0698e0dSDavid Hollister }
204d0698e0dSDavid Hollister
205d0698e0dSDavid Hollister static void
smp_cmd_failed(smp_result_t result)206d0698e0dSDavid Hollister smp_cmd_failed(smp_result_t result)
207d0698e0dSDavid Hollister {
208d0698e0dSDavid Hollister char *smp_result_str = smp_get_result(result);
209d0698e0dSDavid Hollister
21024f5a376SRichard PALO if (smp_result_str == NULL) {
211d0698e0dSDavid Hollister fatal(-5, "Command failed: Unknown result (0x%x)",
212d0698e0dSDavid Hollister result);
213d0698e0dSDavid Hollister } else {
214d0698e0dSDavid Hollister fatal(-5, "Command failed: %s", smp_result_str);
215d0698e0dSDavid Hollister }
216d0698e0dSDavid Hollister }
217d0698e0dSDavid Hollister
218d0698e0dSDavid Hollister static void
smp_get_response(boolean_t close_on_fail)219d0698e0dSDavid Hollister smp_get_response(boolean_t close_on_fail)
220d0698e0dSDavid Hollister {
221d0698e0dSDavid Hollister smp_action_get_response(ap, &result, (void **)&smp_resp, &smp_resp_len);
222d0698e0dSDavid Hollister
223d0698e0dSDavid Hollister if (close_on_fail && (result != SMP_RES_FUNCTION_ACCEPTED)) {
224d0698e0dSDavid Hollister smp_close(tp);
225d0698e0dSDavid Hollister smp_action_free(ap);
226d0698e0dSDavid Hollister smp_fini();
227d0698e0dSDavid Hollister smp_cmd_failed(result);
228d0698e0dSDavid Hollister }
229d0698e0dSDavid Hollister }
230d0698e0dSDavid Hollister
231d0698e0dSDavid Hollister static void
smp_cleanup()232d0698e0dSDavid Hollister smp_cleanup()
233d0698e0dSDavid Hollister {
234d0698e0dSDavid Hollister if (tp) {
235d0698e0dSDavid Hollister smp_close(tp);
236d0698e0dSDavid Hollister tp = NULL;
237d0698e0dSDavid Hollister }
238d0698e0dSDavid Hollister smp_action_free(ap);
239d0698e0dSDavid Hollister smp_fini();
240d0698e0dSDavid Hollister }
241d0698e0dSDavid Hollister
24224f5a376SRichard PALO /* ARGSUSED */
243d0698e0dSDavid Hollister static void
smp_handle_report_route_info(int argc,char * argv[])244d0698e0dSDavid Hollister smp_handle_report_route_info(int argc, char *argv[])
245d0698e0dSDavid Hollister {
246d0698e0dSDavid Hollister smp_report_route_info_req_t *rp;
247d0698e0dSDavid Hollister smp_report_route_info_resp_t *rirp;
248d0698e0dSDavid Hollister uint16_t route_indexes = smp_target_get_exp_route_indexes(tp);
249d0698e0dSDavid Hollister uint8_t num_phys = smp_target_get_number_of_phys(tp);
250d0698e0dSDavid Hollister uint16_t rt_idx_req, ri_idx, ri_end;
251d0698e0dSDavid Hollister uint8_t phy_id_req, pi_idx, pi_end;
252d0698e0dSDavid Hollister boolean_t enabled_entries = B_FALSE;
253d0698e0dSDavid Hollister
254d0698e0dSDavid Hollister /*
255d0698e0dSDavid Hollister * Verify the expander supports the PHY-based expander route table
256d0698e0dSDavid Hollister */
257d0698e0dSDavid Hollister if (route_indexes == 0) {
258d0698e0dSDavid Hollister smp_cleanup();
259d0698e0dSDavid Hollister fatal(-6, "Expander does not support PHY-based route table\n");
260d0698e0dSDavid Hollister }
261d0698e0dSDavid Hollister
262d0698e0dSDavid Hollister rt_idx_req = strtol(argv[3], NULL, 0);
263d0698e0dSDavid Hollister phy_id_req = strtol(argv[4], NULL, 0);
264d0698e0dSDavid Hollister
265d0698e0dSDavid Hollister if (((int16_t)rt_idx_req == -1) && ((int8_t)phy_id_req == -1)) {
266d0698e0dSDavid Hollister ri_idx = 0;
267d0698e0dSDavid Hollister ri_end = route_indexes - 1;
268d0698e0dSDavid Hollister pi_idx = 0;
269d0698e0dSDavid Hollister pi_end = num_phys - 1;
270d0698e0dSDavid Hollister } else if (((int16_t)rt_idx_req < 0) || (rt_idx_req >= route_indexes) ||
271d0698e0dSDavid Hollister ((int8_t)phy_id_req < 0) || (phy_id_req >= num_phys)) {
272d0698e0dSDavid Hollister smp_cleanup();
273d0698e0dSDavid Hollister fatal(-1, "Invalid route index (%d) or PHY ID (%d)\n",
274d0698e0dSDavid Hollister rt_idx_req, phy_id_req);
275d0698e0dSDavid Hollister } else {
276d0698e0dSDavid Hollister ri_end = ri_idx = rt_idx_req;
277d0698e0dSDavid Hollister pi_end = pi_idx = phy_id_req;
278d0698e0dSDavid Hollister }
279d0698e0dSDavid Hollister
280d0698e0dSDavid Hollister (void) printf("%6s %6s %3s %14s\n",
281d0698e0dSDavid Hollister "RT Idx", "PHY ID", "DIS", "Routed SASAddr");
282d0698e0dSDavid Hollister
283d0698e0dSDavid Hollister smp_action_get_request(ap, (void **)&rp, NULL);
284d0698e0dSDavid Hollister
285d0698e0dSDavid Hollister while (ri_idx <= ri_end) {
286d0698e0dSDavid Hollister while (pi_idx <= pi_end) {
287d0698e0dSDavid Hollister rp->srrir_phy_identifier = pi_idx;
288d0698e0dSDavid Hollister rp->srrir_exp_route_index = ri_idx;
289d0698e0dSDavid Hollister
290d0698e0dSDavid Hollister smp_execute();
291d0698e0dSDavid Hollister smp_get_response(B_FALSE);
292d0698e0dSDavid Hollister
293d0698e0dSDavid Hollister if (result != SMP_RES_FUNCTION_ACCEPTED) {
294d0698e0dSDavid Hollister pi_idx++;
295d0698e0dSDavid Hollister continue;
296d0698e0dSDavid Hollister }
297d0698e0dSDavid Hollister
298d0698e0dSDavid Hollister rirp = (smp_report_route_info_resp_t *)smp_resp;
299d0698e0dSDavid Hollister
300d0698e0dSDavid Hollister if (rirp->srrir_exp_route_entry_disabled == 0) {
301d0698e0dSDavid Hollister enabled_entries = B_TRUE;
302d0698e0dSDavid Hollister (void) printf("%6d %6d %3d %016llx\n",
303d0698e0dSDavid Hollister rirp->srrir_exp_route_index,
304d0698e0dSDavid Hollister rirp->srrir_phy_identifier,
305d0698e0dSDavid Hollister rirp->srrir_exp_route_entry_disabled,
306d0698e0dSDavid Hollister BE_64(rirp->srrir_routed_sas_addr));
307d0698e0dSDavid Hollister }
308d0698e0dSDavid Hollister
309d0698e0dSDavid Hollister pi_idx++;
310d0698e0dSDavid Hollister }
311d0698e0dSDavid Hollister
312d0698e0dSDavid Hollister ri_idx++;
313d0698e0dSDavid Hollister pi_idx = 0;
314d0698e0dSDavid Hollister }
315d0698e0dSDavid Hollister
316d0698e0dSDavid Hollister if (!enabled_entries) {
317d0698e0dSDavid Hollister (void) printf("No enabled entries in the table.\n");
318d0698e0dSDavid Hollister }
319d0698e0dSDavid Hollister
320d0698e0dSDavid Hollister smp_cleanup();
321d0698e0dSDavid Hollister exit(0);
322d0698e0dSDavid Hollister }
323d0698e0dSDavid Hollister
324d0698e0dSDavid Hollister static char *
smp_phy_event_src_str(smp_phy_event_source_t src,boolean_t * peak_detector)325d0698e0dSDavid Hollister smp_phy_event_src_str(smp_phy_event_source_t src, boolean_t *peak_detector)
326d0698e0dSDavid Hollister {
327d0698e0dSDavid Hollister char *src_str;
328d0698e0dSDavid Hollister
329d0698e0dSDavid Hollister *peak_detector = B_FALSE;
330d0698e0dSDavid Hollister
331d0698e0dSDavid Hollister switch (src) {
332d0698e0dSDavid Hollister case SMP_PHY_EVENT_NO_EVENT:
333d0698e0dSDavid Hollister src_str = "No event";
334d0698e0dSDavid Hollister break;
335d0698e0dSDavid Hollister case SMP_PHY_EVENT_INVALID_DWORD_COUNT:
336d0698e0dSDavid Hollister src_str = "Invalid DWORD count";
337d0698e0dSDavid Hollister break;
338d0698e0dSDavid Hollister case SMP_PHY_EVENT_RUNNING_DISPARITY_ERROR_COUNT:
339d0698e0dSDavid Hollister src_str = "Running disparity error count";
340d0698e0dSDavid Hollister break;
341d0698e0dSDavid Hollister case SMP_PHY_EVENT_LOSS_OF_DWORD_SYNC_COUNT:
342d0698e0dSDavid Hollister src_str = "Loss of DWORD sync count";
343d0698e0dSDavid Hollister break;
344d0698e0dSDavid Hollister case SMP_PHY_EVENT_PHY_RESET_PROBLEM_COUNT:
345d0698e0dSDavid Hollister src_str = "PHY reset problem count";
346d0698e0dSDavid Hollister break;
347d0698e0dSDavid Hollister case SMP_PHY_EVENT_ELASTICITY_BUFFER_OVERFLOW_COUNT:
348d0698e0dSDavid Hollister src_str = "Elasticity buffer overflow count";
349d0698e0dSDavid Hollister break;
350d0698e0dSDavid Hollister case SMP_PHY_EVENT_RX_ERROR_COUNT:
351d0698e0dSDavid Hollister src_str = "Received ERROR count";
352d0698e0dSDavid Hollister break;
353d0698e0dSDavid Hollister case SMP_PHY_EVENT_RX_ADDR_FRAME_ERROR_COUNT:
354d0698e0dSDavid Hollister src_str = "Received address frame error count";
355d0698e0dSDavid Hollister break;
356d0698e0dSDavid Hollister case SMP_PHY_EVENT_TX_ABANDON_CLASS_OPEN_REJ_COUNT:
357d0698e0dSDavid Hollister src_str = "Transmitted abandon-class OPEN_REJECT count";
358d0698e0dSDavid Hollister break;
359d0698e0dSDavid Hollister case SMP_PHY_EVENT_RX_ABANDON_CLASS_OPEN_REJ_COUNT:
360d0698e0dSDavid Hollister src_str = "Received abandon-class OPEN_REJECT count";
361d0698e0dSDavid Hollister break;
362d0698e0dSDavid Hollister case SMP_PHY_EVENT_TX_RETRY_CLASS_OPEN_REJ_COUNT:
363d0698e0dSDavid Hollister src_str = "Transmitted retry-class OPEN_REJECT count";
364d0698e0dSDavid Hollister break;
365d0698e0dSDavid Hollister case SMP_PHY_EVENT_RX_RETRY_CLASS_OPEN_REJ_COUNT:
366d0698e0dSDavid Hollister src_str = "Received retry-class OPEN_REJECT count";
367d0698e0dSDavid Hollister break;
368d0698e0dSDavid Hollister case SMP_PHY_EVENT_RX_AIP_W_O_PARTIAL_COUNT:
369d0698e0dSDavid Hollister src_str = "Received AIP (WAITING ON PARTIAL) count";
370d0698e0dSDavid Hollister break;
371d0698e0dSDavid Hollister case SMP_PHY_EVENT_RX_AIP_W_O_CONN_COUNT:
372d0698e0dSDavid Hollister src_str = "Received AIP (WAITING ON CONNECTION) count";
373d0698e0dSDavid Hollister break;
374d0698e0dSDavid Hollister case SMP_PHY_EVENT_TX_BREAK_COUNT:
375d0698e0dSDavid Hollister src_str = "Transmitted BREAK count";
376d0698e0dSDavid Hollister break;
377d0698e0dSDavid Hollister case SMP_PHY_EVENT_RX_BREAK_COUNT:
378d0698e0dSDavid Hollister src_str = "Received BREAK count";
379d0698e0dSDavid Hollister break;
380d0698e0dSDavid Hollister case SMP_PHY_EVENT_BREAK_TIMEOUT_COUNT:
381d0698e0dSDavid Hollister src_str = "BREAK timeout count";
382d0698e0dSDavid Hollister break;
383d0698e0dSDavid Hollister case SMP_PHY_EVENT_CONNECTION_COUNT:
384d0698e0dSDavid Hollister src_str = "Connection count";
385d0698e0dSDavid Hollister break;
386d0698e0dSDavid Hollister case SMP_PHY_EVENT_PEAK_TX_PATHWAY_BLOCKED_COUNT:
387d0698e0dSDavid Hollister src_str = "Peak transmitted pathway blocked count";
388d0698e0dSDavid Hollister *peak_detector = B_TRUE;
389d0698e0dSDavid Hollister break;
390d0698e0dSDavid Hollister case SMP_PHY_EVENT_PEAK_TX_ARB_WAIT_TIME:
391d0698e0dSDavid Hollister src_str = "Peak transmitted arbitration wait time";
392d0698e0dSDavid Hollister *peak_detector = B_TRUE;
393d0698e0dSDavid Hollister break;
394d0698e0dSDavid Hollister case SMP_PHY_EVENT_PEAK_ARB_TIME:
395d0698e0dSDavid Hollister src_str = "Peak arbitration time";
396d0698e0dSDavid Hollister *peak_detector = B_TRUE;
397d0698e0dSDavid Hollister break;
398d0698e0dSDavid Hollister case SMP_PHY_EVENT_PEAK_CONNECTION_TIME:
399d0698e0dSDavid Hollister src_str = "Peak connection time";
400d0698e0dSDavid Hollister *peak_detector = B_TRUE;
401d0698e0dSDavid Hollister break;
402d0698e0dSDavid Hollister case SMP_PHY_EVENT_TX_SSP_FRAME_COUNT:
403d0698e0dSDavid Hollister src_str = "Transmitted SSP frame count";
404d0698e0dSDavid Hollister break;
405d0698e0dSDavid Hollister case SMP_PHY_EVENT_RX_SSP_FRAME_COUNT:
406d0698e0dSDavid Hollister src_str = "Received SSP frame count";
407d0698e0dSDavid Hollister break;
408d0698e0dSDavid Hollister case SMP_PHY_EVENT_TX_SSP_FRAME_ERROR_COUNT:
409d0698e0dSDavid Hollister src_str = "Transmitted SSP frame error count";
410d0698e0dSDavid Hollister break;
411d0698e0dSDavid Hollister case SMP_PHY_EVENT_RX_SSP_FRAME_ERROR_COUNT:
412d0698e0dSDavid Hollister src_str = "Received SSP frame error count";
413d0698e0dSDavid Hollister break;
414d0698e0dSDavid Hollister case SMP_PHY_EVENT_TX_CREDIT_BLOCKED_COUNT:
415d0698e0dSDavid Hollister src_str = "Transmitted CREDIT_BLOCKED count";
416d0698e0dSDavid Hollister break;
417d0698e0dSDavid Hollister case SMP_PHY_EVENT_RX_CREDIT_BLOCKED_COUNT:
418d0698e0dSDavid Hollister src_str = "Received CREDIT_BLOCKED count";
419d0698e0dSDavid Hollister break;
420d0698e0dSDavid Hollister case SMP_PHY_EVENT_TX_SATA_FRAME_COUNT:
421d0698e0dSDavid Hollister src_str = "Transmitted SATA frame count";
422d0698e0dSDavid Hollister break;
423d0698e0dSDavid Hollister case SMP_PHY_EVENT_RX_SATA_FRAME_COUNT:
424d0698e0dSDavid Hollister src_str = "Received SATA frame count";
425d0698e0dSDavid Hollister break;
426d0698e0dSDavid Hollister case SMP_PHY_EVENT_SATA_FLOW_CTRL_BUF_OVERFLOW_COUNT:
427d0698e0dSDavid Hollister src_str = "SATA flow control buffer overflow count";
428d0698e0dSDavid Hollister break;
429d0698e0dSDavid Hollister case SMP_PHY_EVENT_TX_SMP_FRAME_COUNT:
430d0698e0dSDavid Hollister src_str = "Transmitted SMP frame count";
431d0698e0dSDavid Hollister break;
432d0698e0dSDavid Hollister case SMP_PHY_EVENT_RX_SMP_FRAME_COUNT:
433d0698e0dSDavid Hollister src_str = "Received SMP frame count";
434d0698e0dSDavid Hollister break;
435d0698e0dSDavid Hollister case SMP_PHY_EVENT_RX_SMP_FRAME_ERROR_COUNT:
436d0698e0dSDavid Hollister src_str = "Received SMP frame error count";
437d0698e0dSDavid Hollister break;
438d0698e0dSDavid Hollister default:
439d0698e0dSDavid Hollister src_str = "<Unknown>";
440d0698e0dSDavid Hollister break;
441d0698e0dSDavid Hollister }
442d0698e0dSDavid Hollister
443d0698e0dSDavid Hollister return (src_str);
444d0698e0dSDavid Hollister }
445d0698e0dSDavid Hollister
446d0698e0dSDavid Hollister static void
smp_validate_args(int argc,char * argv[])447d0698e0dSDavid Hollister smp_validate_args(int argc, char *argv[])
448d0698e0dSDavid Hollister {
449d0698e0dSDavid Hollister errno = 0;
450ac88567aSHyon Kim
451ac88567aSHyon Kim if (argc < 3)
452ac88567aSHyon Kim fatal(-1, "Usage: %s <device> <function> ...\n", argv[0]);
453ac88567aSHyon Kim
454ac88567aSHyon Kim func = strtoul(argv[2], NULL, 0);
455d0698e0dSDavid Hollister
456ac88567aSHyon Kim if (errno != 0)
457ac88567aSHyon Kim fatal(-1, "Usage: %s <device> <function> ...\n", argv[0]);
458ac88567aSHyon Kim
459d0698e0dSDavid Hollister switch (func) {
460*bde334a8SRobert Mustacchi case SMP_FUNC_REPORT_GENERAL:
461*bde334a8SRobert Mustacchi case SMP_FUNC_REPORT_MANUFACTURER_INFO:
462*bde334a8SRobert Mustacchi if (argc != 3) {
463*bde334a8SRobert Mustacchi fatal(-1, "Usage: %s <device> 0x%x\n", argv[0], func);
464*bde334a8SRobert Mustacchi }
465*bde334a8SRobert Mustacchi break;
466d0698e0dSDavid Hollister case SMP_FUNC_DISCOVER:
467d0698e0dSDavid Hollister case SMP_FUNC_REPORT_PHY_EVENT:
468d0698e0dSDavid Hollister case SMP_FUNC_REPORT_PHY_ERROR_LOG: {
469d0698e0dSDavid Hollister if (argc != 4) {
470d0698e0dSDavid Hollister fatal(-1,
471d0698e0dSDavid Hollister "Usage: %s <device> 0x%x <phy identifier>\n",
472d0698e0dSDavid Hollister argv[0], func);
473d0698e0dSDavid Hollister }
474d0698e0dSDavid Hollister break;
475d0698e0dSDavid Hollister }
476d0698e0dSDavid Hollister case SMP_FUNC_REPORT_EXP_ROUTE_TABLE_LIST: {
477d0698e0dSDavid Hollister if (argc < 4) {
478d0698e0dSDavid Hollister fatal(-1,
479d0698e0dSDavid Hollister "Usage: %s <device> 0x%x <SAS Address Index>\n",
480d0698e0dSDavid Hollister argv[0], func);
481d0698e0dSDavid Hollister }
482d0698e0dSDavid Hollister break;
483d0698e0dSDavid Hollister }
484d0698e0dSDavid Hollister case SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD: {
485d0698e0dSDavid Hollister if (argc < 4) {
486d0698e0dSDavid Hollister fatal(-1,
487d0698e0dSDavid Hollister "Usage: %s <device> 0x%x <report type>\n",
488d0698e0dSDavid Hollister argv[0], func);
489d0698e0dSDavid Hollister }
490d0698e0dSDavid Hollister break;
491d0698e0dSDavid Hollister }
492d0698e0dSDavid Hollister case SMP_FUNC_ENABLE_DISABLE_ZONING: {
493d0698e0dSDavid Hollister if (argc != 4) {
494d0698e0dSDavid Hollister fatal(-1,
495d0698e0dSDavid Hollister "Usage: %s <device> 0x%x "
496d0698e0dSDavid Hollister "[0(no change) | 1(enable)| 2(disable)]\n",
497d0698e0dSDavid Hollister argv[0], func);
498d0698e0dSDavid Hollister }
499d0698e0dSDavid Hollister break;
500d0698e0dSDavid Hollister }
501d0698e0dSDavid Hollister case SMP_FUNC_REPORT_BROADCAST: {
502d0698e0dSDavid Hollister if (argc != 4) {
503d0698e0dSDavid Hollister fatal(-1, "Usage: %s <device> 0x%x <bcast type>\n",
504d0698e0dSDavid Hollister argv[0], func);
505d0698e0dSDavid Hollister }
506d0698e0dSDavid Hollister break;
507d0698e0dSDavid Hollister }
508d0698e0dSDavid Hollister case SMP_FUNC_REPORT_ROUTE_INFO: {
509d0698e0dSDavid Hollister if (argc != 5) {
510d0698e0dSDavid Hollister fatal(-1,
511d0698e0dSDavid Hollister "Usage: %s <device> 0x%x <exp_route_idx> "
512d0698e0dSDavid Hollister "<phy_identifier>\n", argv[0], func);
513d0698e0dSDavid Hollister }
514d0698e0dSDavid Hollister break;
515d0698e0dSDavid Hollister }
516d0698e0dSDavid Hollister case SMP_FUNC_PHY_CONTROL: {
517d0698e0dSDavid Hollister if (argc != 5) {
518d0698e0dSDavid Hollister fatal(-1,
519d0698e0dSDavid Hollister "Usage: %s <device> 0x%x <phy identifier> "
520d0698e0dSDavid Hollister " <phy operation>\n",
521d0698e0dSDavid Hollister argv[0], func);
522d0698e0dSDavid Hollister }
523d0698e0dSDavid Hollister break;
524d0698e0dSDavid Hollister }
525d0698e0dSDavid Hollister default: {
526d0698e0dSDavid Hollister fatal(-1, "Usage: %s <device> <function> ...\n", argv[0]);
527d0698e0dSDavid Hollister break;
528d0698e0dSDavid Hollister }
529d0698e0dSDavid Hollister }
530d0698e0dSDavid Hollister }
531d0698e0dSDavid Hollister
532d0698e0dSDavid Hollister int
main(int argc,char * argv[])533d0698e0dSDavid Hollister main(int argc, char *argv[])
534d0698e0dSDavid Hollister {
535d0698e0dSDavid Hollister uint_t i, j;
536d0698e0dSDavid Hollister char *yesorno;
537d0698e0dSDavid Hollister uint16_t exp_change_count;
538d0698e0dSDavid Hollister
539d0698e0dSDavid Hollister /*
540d0698e0dSDavid Hollister * If the arguments are invalid, this function will not return.
541d0698e0dSDavid Hollister */
542d0698e0dSDavid Hollister smp_validate_args(argc, argv);
543d0698e0dSDavid Hollister
544ac88567aSHyon Kim if (smp_init(LIBSMP_VERSION) != 0)
545ac88567aSHyon Kim fatal(-1, "libsmp initialization failed: %s", smp_errmsg());
546ac88567aSHyon Kim
547ac88567aSHyon Kim bzero(&tdef, sizeof (smp_target_def_t));
548ac88567aSHyon Kim tdef.std_def = argv[1];
549ac88567aSHyon Kim
550ac88567aSHyon Kim if ((tp = smp_open(&tdef)) == NULL) {
551ac88567aSHyon Kim smp_fini();
552ac88567aSHyon Kim fatal(-2, "failed to open %s: %s", argv[1], smp_errmsg());
553ac88567aSHyon Kim }
554ac88567aSHyon Kim
555d0698e0dSDavid Hollister exp_change_count = smp_target_get_change_count(tp);
556d0698e0dSDavid Hollister
557d0698e0dSDavid Hollister (void) printf("%s\n", argv[0]);
558d0698e0dSDavid Hollister (void) printf("\tSAS Address: %016llx\n", smp_target_addr(tp));
559d0698e0dSDavid Hollister (void) printf("\tVendor/Product/Revision: %s/%s/%s\n",
560d0698e0dSDavid Hollister smp_target_vendor(tp), smp_target_product(tp),
561d0698e0dSDavid Hollister smp_target_revision(tp));
562d0698e0dSDavid Hollister (void) printf("\tExp Vendor/ID/Rev: %s/%04x/%02x\n",
563d0698e0dSDavid Hollister smp_target_component_vendor(tp), smp_target_component_id(tp),
564d0698e0dSDavid Hollister smp_target_component_revision(tp));
565d0698e0dSDavid Hollister (void) printf("\tExpander change count: 0x%04x\n", exp_change_count);
566d0698e0dSDavid Hollister
567ac88567aSHyon Kim ap = smp_action_alloc(func, tp, 0);
568ac88567aSHyon Kim if (ap == NULL) {
569ac88567aSHyon Kim smp_close(tp);
570ac88567aSHyon Kim smp_fini();
571ac88567aSHyon Kim fatal(-3, "failed to allocate action: %s", smp_errmsg());
572ac88567aSHyon Kim }
573ac88567aSHyon Kim
574d0698e0dSDavid Hollister switch (func) {
575*bde334a8SRobert Mustacchi case SMP_FUNC_REPORT_GENERAL:
576*bde334a8SRobert Mustacchi case SMP_FUNC_REPORT_MANUFACTURER_INFO:
577*bde334a8SRobert Mustacchi /*
578*bde334a8SRobert Mustacchi * These functions have no additional request bytes. therefore
579*bde334a8SRobert Mustacchi * there is nothing for us to get and fill in here.
580*bde334a8SRobert Mustacchi */
581*bde334a8SRobert Mustacchi break;
582d0698e0dSDavid Hollister case SMP_FUNC_DISCOVER: {
583ac88567aSHyon Kim smp_discover_req_t *dp;
584ac88567aSHyon Kim
585ac88567aSHyon Kim smp_action_get_request(ap, (void **)&dp, NULL);
586ac88567aSHyon Kim dp->sdr_phy_identifier = strtoul(argv[3], NULL, 0);
587d0698e0dSDavid Hollister break;
588d0698e0dSDavid Hollister }
589d0698e0dSDavid Hollister case SMP_FUNC_REPORT_ROUTE_INFO: {
590d0698e0dSDavid Hollister smp_handle_report_route_info(argc, argv);
591d0698e0dSDavid Hollister break;
592d0698e0dSDavid Hollister }
593d0698e0dSDavid Hollister case SMP_FUNC_ENABLE_DISABLE_ZONING: {
594ac88567aSHyon Kim smp_enable_disable_zoning_req_t *rp;
595ac88567aSHyon Kim
596ac88567aSHyon Kim smp_action_get_request(ap, (void **)&rp, NULL);
597ac88567aSHyon Kim rp->sedzr_enable_disable_zoning = strtoul(argv[3], NULL, 0);
598d0698e0dSDavid Hollister break;
599d0698e0dSDavid Hollister }
600d0698e0dSDavid Hollister case SMP_FUNC_PHY_CONTROL: {
601ac88567aSHyon Kim smp_phy_control_req_t *rp;
602ac88567aSHyon Kim
603ac88567aSHyon Kim smp_action_get_request(ap, (void **)&rp, NULL);
604ac88567aSHyon Kim rp->spcr_phy_identifier = strtoul(argv[3], NULL, 0);
605ac88567aSHyon Kim rp->spcr_phy_operation = strtoul(argv[4], NULL, 0);
606d0698e0dSDavid Hollister break;
607d0698e0dSDavid Hollister }
608d0698e0dSDavid Hollister case SMP_FUNC_REPORT_EXP_ROUTE_TABLE_LIST: {
609ac88567aSHyon Kim smp_report_exp_route_table_list_req_t *rp;
610ac88567aSHyon Kim
611ac88567aSHyon Kim smp_action_get_request(ap, (void **)&rp, NULL);
612ac88567aSHyon Kim SCSI_WRITE16(&rp->srertlr_max_descrs, 64);
613ac88567aSHyon Kim SCSI_WRITE16(&rp->srertlr_starting_routed_sas_addr_index,
614ac88567aSHyon Kim strtoull(argv[3], NULL, 0));
615ac88567aSHyon Kim rp->srertlr_starting_phy_identifier = 0;
616d0698e0dSDavid Hollister break;
617ac88567aSHyon Kim }
618d0698e0dSDavid Hollister case SMP_FUNC_REPORT_PHY_ERROR_LOG: {
619d0698e0dSDavid Hollister smp_report_phy_error_log_req_t *pelp;
620ac88567aSHyon Kim
621d0698e0dSDavid Hollister smp_action_get_request(ap, (void **)&pelp, NULL);
622d0698e0dSDavid Hollister pelp->srpelr_phy_identifier = strtoul(argv[3], NULL, 0);
623d0698e0dSDavid Hollister break;
624d0698e0dSDavid Hollister }
625d0698e0dSDavid Hollister case SMP_FUNC_REPORT_PHY_EVENT: {
626d0698e0dSDavid Hollister smp_report_phy_event_req_t *rpep;
627ac88567aSHyon Kim
628d0698e0dSDavid Hollister smp_action_get_request(ap, (void **)&rpep, NULL);
629d0698e0dSDavid Hollister rpep->srper_phy_identifier = strtoul(argv[3], NULL, 0);
630d0698e0dSDavid Hollister break;
631d0698e0dSDavid Hollister }
632d0698e0dSDavid Hollister case SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD: {
633d0698e0dSDavid Hollister smp_report_zone_mgr_password_req_t *rzmprp;
634d0698e0dSDavid Hollister
635d0698e0dSDavid Hollister smp_action_get_request(ap, (void **)&rzmprp, NULL);
636d0698e0dSDavid Hollister rzmprp->srzmpr_rpt_type = strtoul(argv[3], NULL, 0);
637d0698e0dSDavid Hollister break;
638d0698e0dSDavid Hollister }
639d0698e0dSDavid Hollister case SMP_FUNC_REPORT_BROADCAST: {
640d0698e0dSDavid Hollister smp_report_broadcast_req_t *rbrp;
641d0698e0dSDavid Hollister
642d0698e0dSDavid Hollister smp_action_get_request(ap, (void **)&rbrp, NULL);
643d0698e0dSDavid Hollister rbrp->srbr_broadcast_type = strtoul(argv[3], NULL, 0);
644d0698e0dSDavid Hollister break;
645d0698e0dSDavid Hollister }
646d0698e0dSDavid Hollister default:
647ac88567aSHyon Kim smp_close(tp);
648ac88567aSHyon Kim smp_action_free(ap);
649ac88567aSHyon Kim smp_fini();
650d0698e0dSDavid Hollister smp_cmd_failed(result);
651ac88567aSHyon Kim }
652ac88567aSHyon Kim
653d0698e0dSDavid Hollister smp_execute();
654d0698e0dSDavid Hollister smp_get_response(B_TRUE);
655ac88567aSHyon Kim
656d0698e0dSDavid Hollister switch (func) {
657*bde334a8SRobert Mustacchi case SMP_FUNC_REPORT_GENERAL: {
658*bde334a8SRobert Mustacchi smp_report_general_resp_t *gr =
659*bde334a8SRobert Mustacchi (smp_report_general_resp_t *)smp_resp;
660*bde334a8SRobert Mustacchi
661*bde334a8SRobert Mustacchi (void) printf("Expander Route Indexes: %u\n",
662*bde334a8SRobert Mustacchi SCSI_READ16(&gr->srgr_exp_route_indexes));
663*bde334a8SRobert Mustacchi (void) printf("Long Responses: %s\n",
664*bde334a8SRobert Mustacchi gr->srgr_long_response != 0 ? "Supported" : "Unsupported");
665*bde334a8SRobert Mustacchi (void) printf("Phys: %d\n", gr->srgr_number_of_phys);
666*bde334a8SRobert Mustacchi (void) printf("Features:\n");
667*bde334a8SRobert Mustacchi if (gr->srgr_externally_configurable_route_table != 0) {
668*bde334a8SRobert Mustacchi (void) printf("\tExternally Configurable Route "
669*bde334a8SRobert Mustacchi "Table\n");
670*bde334a8SRobert Mustacchi }
671*bde334a8SRobert Mustacchi if (gr->srgr_configuring != 0) {
672*bde334a8SRobert Mustacchi (void) printf("\tConfiguring\n");
673*bde334a8SRobert Mustacchi }
674*bde334a8SRobert Mustacchi if (gr->srgr_configures_others != 0) {
675*bde334a8SRobert Mustacchi (void) printf("\tConfigures Others\n");
676*bde334a8SRobert Mustacchi }
677*bde334a8SRobert Mustacchi if (gr->srgr_open_reject_retry_supported != 0) {
678*bde334a8SRobert Mustacchi (void) printf("\tOpen Reject Retry\n");
679*bde334a8SRobert Mustacchi }
680*bde334a8SRobert Mustacchi if (gr->srgr_stp_continue_awt != 0) {
681*bde334a8SRobert Mustacchi (void) printf("\tSTP Continue AWT\n");
682*bde334a8SRobert Mustacchi }
683*bde334a8SRobert Mustacchi if (gr->srgr_table_to_table_supported != 0) {
684*bde334a8SRobert Mustacchi (void) printf("\tTable to Table\n");
685*bde334a8SRobert Mustacchi }
686*bde334a8SRobert Mustacchi
687*bde334a8SRobert Mustacchi (void) printf("Logical Identify: %016llx\n",
688*bde334a8SRobert Mustacchi SCSI_READ64(&gr->srgr_enclosure_logical_identifier));
689*bde334a8SRobert Mustacchi
690*bde334a8SRobert Mustacchi (void) printf("STP Bus Inactivity Time Limit: %u us\n",
691*bde334a8SRobert Mustacchi SCSI_READ16(&gr->srgr_stp_bus_inactivity_time_limit) * 100);
692*bde334a8SRobert Mustacchi (void) printf("STP Maximum Connect Time Limit: %u us\n",
693*bde334a8SRobert Mustacchi SCSI_READ16(&gr->srgr_stp_maximum_connect_time_limit) *
694*bde334a8SRobert Mustacchi 100);
695*bde334a8SRobert Mustacchi (void) printf("STP SMP I_T Nexus Loss Time: ");
696*bde334a8SRobert Mustacchi if (gr->srgr_stp_smp_nexus_loss_time == 0) {
697*bde334a8SRobert Mustacchi (void) printf("Vendor Specific\n");
698*bde334a8SRobert Mustacchi } else if (gr->srgr_stp_smp_nexus_loss_time == UINT16_MAX) {
699*bde334a8SRobert Mustacchi (void) printf("Retries Forever\n");
700*bde334a8SRobert Mustacchi } else {
701*bde334a8SRobert Mustacchi (void) printf("%u ms\n",
702*bde334a8SRobert Mustacchi SCSI_READ16(&gr->srgr_stp_smp_nexus_loss_time));
703*bde334a8SRobert Mustacchi }
704*bde334a8SRobert Mustacchi
705*bde334a8SRobert Mustacchi (void) printf("Physical Presence: %s, %s\n",
706*bde334a8SRobert Mustacchi gr->srgr_physical_presence_supported ? "Supported" :
707*bde334a8SRobert Mustacchi "Unsupported",
708*bde334a8SRobert Mustacchi gr->srgr_physical_presence_asserted ? "Enabled" :
709*bde334a8SRobert Mustacchi "Disabled");
710*bde334a8SRobert Mustacchi
711*bde334a8SRobert Mustacchi (void) printf("Zoning:\n");
712*bde334a8SRobert Mustacchi if (gr->srgr_zoning_supported != 0) {
713*bde334a8SRobert Mustacchi (void) printf("\tSupported\n");
714*bde334a8SRobert Mustacchi } else {
715*bde334a8SRobert Mustacchi (void) printf("\tUnsupported\n");
716*bde334a8SRobert Mustacchi }
717*bde334a8SRobert Mustacchi if (gr->srgr_zoning_enabled != 0) {
718*bde334a8SRobert Mustacchi (void) printf("\tEnabled\n");
719*bde334a8SRobert Mustacchi } else {
720*bde334a8SRobert Mustacchi (void) printf("\tDisabled\n");
721*bde334a8SRobert Mustacchi }
722*bde334a8SRobert Mustacchi if (gr->srgr_zone_locked != 0) {
723*bde334a8SRobert Mustacchi (void) printf("\tLocked\n");
724*bde334a8SRobert Mustacchi } else {
725*bde334a8SRobert Mustacchi (void) printf("\tUnlocked\n");
726*bde334a8SRobert Mustacchi }
727*bde334a8SRobert Mustacchi if (gr->srgr_saving_zoning_enabled_supported != 0) {
728*bde334a8SRobert Mustacchi (void) printf("\tSaving Zoning Enabled Supported\n");
729*bde334a8SRobert Mustacchi }
730*bde334a8SRobert Mustacchi if (gr->srgr_saving_zone_perm_table_supported != 0) {
731*bde334a8SRobert Mustacchi (void) printf("\tSaving Zone Perm Table Supported\n");
732*bde334a8SRobert Mustacchi }
733*bde334a8SRobert Mustacchi if (gr->srgr_saving_zone_phy_info_supported != 0) {
734*bde334a8SRobert Mustacchi (void) printf("\tSaving Zone Phy Info Supported\n");
735*bde334a8SRobert Mustacchi }
736*bde334a8SRobert Mustacchi if (gr->srgr_saving != 0) {
737*bde334a8SRobert Mustacchi (void) printf("\tSaving\n");
738*bde334a8SRobert Mustacchi }
739*bde334a8SRobert Mustacchi (void) printf("\tActive Zone Manager SAS Address: %016llx\n",
740*bde334a8SRobert Mustacchi SCSI_READ64(&gr->srgr_active_zm_sas_addr));
741*bde334a8SRobert Mustacchi (void) printf("\tZone Lock Inactivity Limit: %u ms\n",
742*bde334a8SRobert Mustacchi SCSI_READ16(&gr->srgr_zone_lock_inactivity_limit) * 100);
743*bde334a8SRobert Mustacchi
744*bde334a8SRobert Mustacchi (void) printf("Maximum Routed SAS Addresses: %u\n",
745*bde334a8SRobert Mustacchi SCSI_READ16(&gr->srgr_max_routed_sas_addrs));
746*bde334a8SRobert Mustacchi
747*bde334a8SRobert Mustacchi (void) printf("First Enclosure Connector Element Index: %u\n",
748*bde334a8SRobert Mustacchi gr->srgr_first_encl_conn_elem_idx);
749*bde334a8SRobert Mustacchi (void) printf("Number of Enclosure Connector Elements: %u\n",
750*bde334a8SRobert Mustacchi gr->srgr_number_encl_conn_elem_idxs);
751*bde334a8SRobert Mustacchi
752*bde334a8SRobert Mustacchi if (gr->srgr_reduced_functionality != 0) {
753*bde334a8SRobert Mustacchi (void) printf("Time to Reduced Functionality: %u ms\n",
754*bde334a8SRobert Mustacchi gr->srgr_time_to_reduced_functionality * 100);
755*bde334a8SRobert Mustacchi }
756*bde334a8SRobert Mustacchi (void) printf("Initial Time to Reduced Functionality: %u ms\n",
757*bde334a8SRobert Mustacchi gr->srgr_initial_time_to_reduced_functionality * 100);
758*bde334a8SRobert Mustacchi (void) printf("Maximum Time to Reduced Functionality: %u ms\n",
759*bde334a8SRobert Mustacchi gr->srgr_max_reduced_functionality_time * 100);
760*bde334a8SRobert Mustacchi (void) printf("Last Self-configuration Status Index: %u\n",
761*bde334a8SRobert Mustacchi SCSI_READ16(&gr->srgr_last_self_conf_status_descr_idx));
762*bde334a8SRobert Mustacchi (void) printf("Maximum Stored Self-configuration Statuses: "
763*bde334a8SRobert Mustacchi "%u\n", SCSI_READ16(
764*bde334a8SRobert Mustacchi &gr->srgr_max_stored_self_config_status_descrs));
765*bde334a8SRobert Mustacchi (void) printf("Last Phy Event List Descriptor Index: %u\n",
766*bde334a8SRobert Mustacchi SCSI_READ16(&gr->srgr_last_phy_event_list_descr_idx));
767*bde334a8SRobert Mustacchi (void) printf("Maximum Stored Phy Event List Descriptors: "
768*bde334a8SRobert Mustacchi "%u\n", SCSI_READ16(
769*bde334a8SRobert Mustacchi &gr->srgr_max_stored_phy_event_list_descrs));
770*bde334a8SRobert Mustacchi (void) printf("STP Reject to Open Limit: %u us\n",
771*bde334a8SRobert Mustacchi SCSI_READ16(&gr->srgr_stp_reject_to_open_limit) * 10);
772*bde334a8SRobert Mustacchi break;
773*bde334a8SRobert Mustacchi }
774*bde334a8SRobert Mustacchi case SMP_FUNC_REPORT_MANUFACTURER_INFO: {
775*bde334a8SRobert Mustacchi smp_report_manufacturer_info_resp_t *mir =
776*bde334a8SRobert Mustacchi (smp_report_manufacturer_info_resp_t *)smp_resp;
777*bde334a8SRobert Mustacchi
778*bde334a8SRobert Mustacchi smp_print_ascii("Vendor", mir->srmir_vendor_identification,
779*bde334a8SRobert Mustacchi sizeof (mir->srmir_vendor_identification));
780*bde334a8SRobert Mustacchi smp_print_ascii("Product", mir->srmir_product_identification,
781*bde334a8SRobert Mustacchi sizeof (mir->srmir_product_identification));
782*bde334a8SRobert Mustacchi smp_print_ascii("Revision", mir->srmir_product_revision_level,
783*bde334a8SRobert Mustacchi sizeof (mir->srmir_product_revision_level));
784*bde334a8SRobert Mustacchi /*
785*bde334a8SRobert Mustacchi * The format of the following section was changed in the SAS
786*bde334a8SRobert Mustacchi * 1.1 specification. If this bit is not present, it is vendor
787*bde334a8SRobert Mustacchi * specific and therefore we don't print them.
788*bde334a8SRobert Mustacchi */
789*bde334a8SRobert Mustacchi if (mir->srmir_sas_1_1_format == 0) {
790*bde334a8SRobert Mustacchi break;
791*bde334a8SRobert Mustacchi }
792*bde334a8SRobert Mustacchi smp_print_ascii("Component Vendor",
793*bde334a8SRobert Mustacchi mir->srmir_component_vendor_identification,
794*bde334a8SRobert Mustacchi sizeof (mir->srmir_component_vendor_identification));
795*bde334a8SRobert Mustacchi (void) printf("Component ID: 0x%x\n",
796*bde334a8SRobert Mustacchi SCSI_READ16(&mir->srmir_component_id));
797*bde334a8SRobert Mustacchi (void) printf("Component Revision: 0x%x\n",
798*bde334a8SRobert Mustacchi mir->srmir_component_revision_level);
799*bde334a8SRobert Mustacchi break;
800*bde334a8SRobert Mustacchi }
801d0698e0dSDavid Hollister case SMP_FUNC_DISCOVER: {
802d0698e0dSDavid Hollister smp_discover_resp_t *rp = (smp_discover_resp_t *)smp_resp;
803ac88567aSHyon Kim (void) printf("Addr: %016llx Phy: %02x\n",
804ac88567aSHyon Kim SCSI_READ64(&rp->sdr_sas_addr), rp->sdr_phy_identifier);
805ac88567aSHyon Kim (void) printf("Peer: %016llx Phy: %02x\n",
806ac88567aSHyon Kim SCSI_READ64(&rp->sdr_attached_sas_addr),
807ac88567aSHyon Kim rp->sdr_attached_phy_identifier);
808ac88567aSHyon Kim (void) printf("Device type: %01x\n",
809ac88567aSHyon Kim rp->sdr_attached_device_type);
810d0698e0dSDavid Hollister break;
811d0698e0dSDavid Hollister }
812d0698e0dSDavid Hollister case SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD: {
813d0698e0dSDavid Hollister smp_report_zone_mgr_password_resp_t *rp =
814d0698e0dSDavid Hollister (smp_report_zone_mgr_password_resp_t *)smp_resp;
815d0698e0dSDavid Hollister char *rpt_type = NULL;
816d0698e0dSDavid Hollister int idx;
817d0698e0dSDavid Hollister switch (rp->srzmpr_rpt_type) {
818d0698e0dSDavid Hollister case SMP_ZMP_TYPE_CURRENT:
819d0698e0dSDavid Hollister rpt_type = "Current";
820d0698e0dSDavid Hollister break;
821d0698e0dSDavid Hollister case SMP_ZMP_TYPE_SAVED:
822d0698e0dSDavid Hollister rpt_type = "Saved";
823d0698e0dSDavid Hollister break;
824d0698e0dSDavid Hollister case SMP_ZMP_TYPE_DEFAULT:
825d0698e0dSDavid Hollister rpt_type = "Default";
826d0698e0dSDavid Hollister break;
827d0698e0dSDavid Hollister default:
828d0698e0dSDavid Hollister rpt_type = "(Unknown Type)";
829d0698e0dSDavid Hollister break;
830d0698e0dSDavid Hollister }
831d0698e0dSDavid Hollister (void) printf("%s zone manager password: 0x", rpt_type);
832d0698e0dSDavid Hollister for (idx = 0; idx < 32; idx++) {
833d0698e0dSDavid Hollister (void) printf("%02x",
834d0698e0dSDavid Hollister rp->srzmpr_zone_mgr_password[idx]);
835d0698e0dSDavid Hollister }
836d0698e0dSDavid Hollister (void) printf("\n");
837d0698e0dSDavid Hollister break;
838d0698e0dSDavid Hollister }
839d0698e0dSDavid Hollister case SMP_FUNC_REPORT_EXP_ROUTE_TABLE_LIST: {
840d0698e0dSDavid Hollister smp_report_exp_route_table_list_resp_t *rtlr =
841d0698e0dSDavid Hollister (smp_report_exp_route_table_list_resp_t *)smp_resp;
842d0698e0dSDavid Hollister smp_route_table_descr_t *descp = &rtlr->srertlr_descrs[0];
843d0698e0dSDavid Hollister int idx, idxx, ndescrs, zoning, startnum;
844d0698e0dSDavid Hollister
845d0698e0dSDavid Hollister (void) printf("Expander change count: 0x%04x\n",
846d0698e0dSDavid Hollister BE_16(rtlr->srertlr_exp_change_count));
847d0698e0dSDavid Hollister (void) printf("Expander route table change count: 0x%04x\n",
848d0698e0dSDavid Hollister BE_16(rtlr->srertlr_route_table_change_count));
849d0698e0dSDavid Hollister
850d0698e0dSDavid Hollister if (rtlr->srertlr_zoning_enabled) {
851d0698e0dSDavid Hollister yesorno = yes;
852d0698e0dSDavid Hollister zoning = 1;
853d0698e0dSDavid Hollister } else {
854d0698e0dSDavid Hollister yesorno = no;
855d0698e0dSDavid Hollister zoning = 0;
856d0698e0dSDavid Hollister }
857d0698e0dSDavid Hollister (void) printf("Zoning enabled: %s\n", yesorno);
858d0698e0dSDavid Hollister
859d0698e0dSDavid Hollister if (rtlr->srertlr_configuring) {
860d0698e0dSDavid Hollister yesorno = yes;
861d0698e0dSDavid Hollister } else {
862d0698e0dSDavid Hollister yesorno = no;
863d0698e0dSDavid Hollister }
864d0698e0dSDavid Hollister (void) printf("Configuring: %s\n", yesorno);
865d0698e0dSDavid Hollister
866d0698e0dSDavid Hollister ndescrs = rtlr->srertlr_n_descrs;
867d0698e0dSDavid Hollister (void) printf("Number of descriptors: %d\n", ndescrs);
868d0698e0dSDavid Hollister startnum = BE_16(rtlr->srertlr_first_routed_sas_addr_index);
869d0698e0dSDavid Hollister (void) printf("First/Last routed SAS address index: %d/%d\n",
870d0698e0dSDavid Hollister startnum, BE_16(rtlr->srertlr_last_routed_sas_addr_index));
871d0698e0dSDavid Hollister (void) printf("Starting PHY identifier: %d\n",
872d0698e0dSDavid Hollister rtlr->srertlr_starting_phy_identifier);
873d0698e0dSDavid Hollister
874d0698e0dSDavid Hollister for (idx = 0; idx < ndescrs; idx++, descp++) {
875d0698e0dSDavid Hollister (void) printf("#%03d: Routed SAS addr: %016llx ",
876d0698e0dSDavid Hollister idx + startnum, BE_64(descp->srtd_routed_sas_addr));
877d0698e0dSDavid Hollister (void) printf("PHY bitmap: 0x");
878d0698e0dSDavid Hollister for (idxx = 0; idxx < 6; idxx++) {
879d0698e0dSDavid Hollister (void) printf("%02x",
880d0698e0dSDavid Hollister descp->srtd_phy_bitmap[idxx]);
881d0698e0dSDavid Hollister }
882d0698e0dSDavid Hollister (void) printf("\n");
883d0698e0dSDavid Hollister if (zoning) {
884d0698e0dSDavid Hollister (void) printf("\tZone group: %d\n",
885d0698e0dSDavid Hollister descp->srtd_zone_group);
886d0698e0dSDavid Hollister }
887ac88567aSHyon Kim }
888ac88567aSHyon Kim
889d0698e0dSDavid Hollister (void) printf("\n");
890d0698e0dSDavid Hollister break;
891d0698e0dSDavid Hollister }
892d0698e0dSDavid Hollister case SMP_FUNC_REPORT_PHY_ERROR_LOG: {
893d0698e0dSDavid Hollister smp_report_phy_error_log_resp_t *pelr =
894d0698e0dSDavid Hollister (smp_report_phy_error_log_resp_t *)smp_resp;
895d0698e0dSDavid Hollister (void) printf("PHY error log for PHY %d:\n",
896d0698e0dSDavid Hollister pelr->srpelr_phy_identifier);
897d0698e0dSDavid Hollister (void) printf("\tInvalid DWORD count: %d\n",
898d0698e0dSDavid Hollister BE_32(pelr->srpelr_invalid_dword_count));
899d0698e0dSDavid Hollister (void) printf("\tRunning disparity error count: %d\n",
900d0698e0dSDavid Hollister BE_32(pelr->srpelr_running_disparity_error_count));
901d0698e0dSDavid Hollister (void) printf("\tLoss of DWORD sync count: %d\n",
902d0698e0dSDavid Hollister BE_32(pelr->srpelr_loss_dword_sync_count));
903d0698e0dSDavid Hollister (void) printf("\tPHY reset problem count: %d\n",
904d0698e0dSDavid Hollister BE_32(pelr->srpelr_phy_reset_problem_count));
905d0698e0dSDavid Hollister break;
906d0698e0dSDavid Hollister }
907d0698e0dSDavid Hollister case SMP_FUNC_REPORT_PHY_EVENT: {
908d0698e0dSDavid Hollister smp_report_phy_event_resp_t *rper =
909d0698e0dSDavid Hollister (smp_report_phy_event_resp_t *)smp_resp;
910d0698e0dSDavid Hollister smp_phy_event_report_descr_t *perd =
911d0698e0dSDavid Hollister &rper->srper_phy_event_descrs[0];
912d0698e0dSDavid Hollister boolean_t peak;
913d0698e0dSDavid Hollister int idx;
914ac88567aSHyon Kim
915d0698e0dSDavid Hollister (void) printf("PHY event for PHY %d:\n",
916d0698e0dSDavid Hollister rper->srper_phy_identifier);
917d0698e0dSDavid Hollister (void) printf("Number of PHY event descriptors: %d\n",
918d0698e0dSDavid Hollister rper->srper_n_phy_event_descrs);
919d0698e0dSDavid Hollister
920d0698e0dSDavid Hollister for (idx = 0; idx < rper->srper_n_phy_event_descrs; idx++) {
921d0698e0dSDavid Hollister (void) printf("%50s : %d\n",
922d0698e0dSDavid Hollister smp_phy_event_src_str(perd->sped_phy_event_source,
923d0698e0dSDavid Hollister &peak), BE_32(perd->sped_phy_event));
924d0698e0dSDavid Hollister if (peak) {
925d0698e0dSDavid Hollister (void) printf("\tPeak value detector "
926d0698e0dSDavid Hollister "threshold: %d\n",
927d0698e0dSDavid Hollister BE_32(perd->sped_peak_detector_threshold));
928d0698e0dSDavid Hollister }
929d0698e0dSDavid Hollister perd++;
930d0698e0dSDavid Hollister }
931d0698e0dSDavid Hollister
932d0698e0dSDavid Hollister break;
933d0698e0dSDavid Hollister }
934d0698e0dSDavid Hollister case SMP_FUNC_REPORT_BROADCAST: {
935d0698e0dSDavid Hollister smp_report_broadcast_resp_t *brp =
936d0698e0dSDavid Hollister (smp_report_broadcast_resp_t *)smp_resp;
937d0698e0dSDavid Hollister smp_broadcast_descr_t *bdp = &brp->srbr_descrs[0];
938d0698e0dSDavid Hollister uint16_t bcount, idx;
939d0698e0dSDavid Hollister
940d0698e0dSDavid Hollister bcount = brp->srbr_number_broadcast_descrs;
941d0698e0dSDavid Hollister
942d0698e0dSDavid Hollister (void) printf("\tNumber of broadcast descriptors: %d\n",
943d0698e0dSDavid Hollister bcount);
944d0698e0dSDavid Hollister (void) printf("\t%7s %5s %5s %8s\n",
945d0698e0dSDavid Hollister "BCType", "PhyID", "BCRsn", "BC Count");
946d0698e0dSDavid Hollister for (idx = 0; idx < bcount; idx++) {
947d0698e0dSDavid Hollister (void) printf("\t%7s %5s %5s %8s\n",
948d0698e0dSDavid Hollister bdp->sbd_broadcast_type, bdp->sbd_phy_identifier,
949d0698e0dSDavid Hollister bdp->sbd_broadcast_reason,
950d0698e0dSDavid Hollister bdp->sbd_broadcast_count);
951d0698e0dSDavid Hollister bdp++;
952d0698e0dSDavid Hollister }
953d0698e0dSDavid Hollister
954d0698e0dSDavid Hollister break;
955d0698e0dSDavid Hollister }
956d0698e0dSDavid Hollister default:
957d0698e0dSDavid Hollister (void) printf("Response: (len %d)\n", smp_resp_len);
958d0698e0dSDavid Hollister for (i = 0; i < smp_resp_len; i += 8) {
959d0698e0dSDavid Hollister (void) printf("%02x: ", i);
960d0698e0dSDavid Hollister for (j = i; j < i + 8; j++)
961d0698e0dSDavid Hollister if (j < smp_resp_len)
962d0698e0dSDavid Hollister (void) printf("%02x ", smp_resp[j]);
963d0698e0dSDavid Hollister else
964d0698e0dSDavid Hollister (void) printf(" ");
965d0698e0dSDavid Hollister for (j = i; j < i + 8; j++)
966d0698e0dSDavid Hollister (void) printf("%c",
967d0698e0dSDavid Hollister j < smp_resp_len && isprint(smp_resp[j]) ?
968d0698e0dSDavid Hollister smp_resp[j] : j < smp_resp_len ? '.' :
969d0698e0dSDavid Hollister '\0');
970d0698e0dSDavid Hollister (void) printf("\n");
971d0698e0dSDavid Hollister }
972d0698e0dSDavid Hollister break;
973d0698e0dSDavid Hollister }
974d0698e0dSDavid Hollister
975d0698e0dSDavid Hollister smp_cleanup();
976ac88567aSHyon Kim return (0);
977ac88567aSHyon Kim }
978