xref: /illumos-gate/usr/src/cmd/scsi/smp/common/smp.c (revision d019449136cec9f203f106de418421095790e4e2)
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  */
25 #include <sys/types.h>
26 #include <sys/scsi/generic/smp_frames.h>
27 #include <sys/scsi/generic/commands.h>
28 #include <sys/scsi/impl/commands.h>
29 #include <sys/ccompile.h>
30 
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <stdlib.h>
36 #include <errno.h>
37 #include <strings.h>
38 #include <ctype.h>
39 
40 #include <scsi/libsmp.h>
41 #include <scsi/libsmp_plugin.h>
42 
43 static void fatal(int, const char *, ...) __NORETURN;
44 
45 static void
46 fatal(int err, const char *fmt, ...)
47 {
48 	va_list ap;
49 
50 	va_start(ap, fmt);
51 	(void) vfprintf(stderr, fmt, ap);
52 	va_end(ap);
53 
54 	(void) fprintf(stderr, "\n");
55 	(void) fflush(stderr);
56 
57 	_exit(err);
58 }
59 
60 int
61 main(int argc, char *argv[])
62 {
63 	smp_target_t *tp;
64 	smp_action_t *ap;
65 	smp_errno_t err;
66 	smp_function_t func;
67 	smp_result_t result;
68 	smp_target_def_t tdef;
69 	smp_discover_resp_t *rp;
70 	smp_report_manufacturer_info_resp_t *ip;
71 	uint8_t *resp;
72 	size_t len;
73 	uint_t cap;
74 	void *x;
75 	uint_t i, j;
76 
77 	if (argc < 3)
78 		fatal(-1, "Usage: %s <device> <function> ...\n", argv[0]);
79 
80 	errno = 0;
81 	func = strtoul(argv[2], NULL, 0);
82 	if (errno != 0)
83 		fatal(-1, "Usage: %s <device> <function> ...\n", argv[0]);
84 
85 	if (smp_init(LIBSMP_VERSION) != 0)
86 		fatal(-1, "libsmp initialization failed: %s", smp_errmsg());
87 
88 	bzero(&tdef, sizeof (smp_target_def_t));
89 	tdef.std_def = argv[1];
90 
91 	if ((tp = smp_open(&tdef)) == NULL) {
92 		smp_fini();
93 		fatal(-2, "failed to open %s: %s", argv[1], smp_errmsg());
94 	}
95 
96 	cap = smp_target_getcap(tp);
97 	ap = smp_action_alloc(func, tp, 0);
98 	if (ap == NULL) {
99 		smp_close(tp);
100 		smp_fini();
101 		fatal(-3, "failed to allocate action: %s", smp_errmsg());
102 	}
103 
104 	if (func == SMP_FUNC_DISCOVER) {
105 		smp_discover_req_t *dp;
106 		if (argc < 4)
107 			fatal(-1,
108 			    "Usage: %s <device> 0x10 <phy identifier>\n",
109 			    argv[0]);
110 
111 		smp_action_get_request(ap, (void **)&dp, NULL);
112 		dp->sdr_phy_identifier = strtoul(argv[3], NULL, 0);
113 	} else if (func == SMP_FUNC_REPORT_ROUTE_INFO) {
114 		smp_report_route_info_req_t *rp;
115 		if (argc < 5)
116 			fatal(-1, "Usage: %s <device> 0x13 <expander route "
117 			    "index> <phy identifier>\n",
118 			    argv[0]);
119 
120 		smp_action_get_request(ap, (void **)&rp, NULL);
121 		rp->srrir_exp_route_index = strtoul(argv[3], NULL, 0);
122 		rp->srrir_phy_identifier = strtoul(argv[4], NULL, 0);
123 	} else if (func == SMP_FUNC_ENABLE_DISABLE_ZONING) {
124 		smp_enable_disable_zoning_req_t *rp;
125 		if (argc < 4)
126 			fatal(-1,
127 			    "Usage: %s <device> 0x81 "
128 			    "[0(no change) | 1(enable)| 2(disable)]\n",
129 			    argv[0]);
130 
131 		smp_action_get_request(ap, (void **)&rp, NULL);
132 		rp->sedzr_enable_disable_zoning = strtoul(argv[3], NULL, 0);
133 	} else if (func == SMP_FUNC_PHY_CONTROL) {
134 		smp_phy_control_req_t *rp;
135 		if (argc < 5)
136 			fatal(-1,
137 			    "Usage: %s <device> 0x91 <phy identifier> "
138 			    " <phy operation>\n",
139 			    argv[0]);
140 
141 		smp_action_get_request(ap, (void **)&rp, NULL);
142 
143 		smp_action_get_request(ap, (void **)&rp, NULL);
144 		rp->spcr_phy_identifier = strtoul(argv[3], NULL, 0);
145 		rp->spcr_phy_operation = strtoul(argv[4], NULL, 0);
146 	} else if (func == SMP_FUNC_REPORT_EXP_ROUTE_TABLE_LIST) {
147 		smp_report_exp_route_table_list_req_t *rp;
148 		if (argc < 4)
149 			fatal(-1,
150 			    "Usage: %s <device> 0x22 <SAS Address Index> \n",
151 			    argv[0]);
152 
153 		smp_action_get_request(ap, (void **)&rp, NULL);
154 		SCSI_WRITE16(&rp->srertlr_max_descrs, 64);
155 		SCSI_WRITE16(&rp->srertlr_starting_routed_sas_addr_index,
156 		    strtoull(argv[3], NULL, 0));
157 		rp->srertlr_starting_phy_identifier = 0;
158 	}
159 
160 	(void) printf("%s\n", argv[0]);
161 	(void) printf("\tSAS Address: %016llx\n", smp_target_addr(tp));
162 	(void) printf("\tVendor: %s\n", smp_target_vendor(tp));
163 	(void) printf("\tProduct: %s\n", smp_target_product(tp));
164 	(void) printf("\tRevision: %s\n", smp_target_revision(tp));
165 	(void) printf("\tExp Vendor: %s\n", smp_target_component_vendor(tp));
166 	(void) printf("\tExp ID: %04x\n", smp_target_component_id(tp));
167 	(void) printf("\tExp Rev: %02x\n", smp_target_component_revision(tp));
168 
169 	if (smp_exec(ap, tp) != 0) {
170 		smp_close(tp);
171 		smp_action_free(ap);
172 		smp_fini();
173 		fatal(-4, "exec failed: %s", smp_errmsg());
174 	}
175 
176 	smp_close(tp);
177 	smp_action_get_response(ap, &result, (void **)&resp, &len);
178 
179 	if (result != SMP_RES_FUNCTION_ACCEPTED) {
180 		smp_action_free(ap);
181 		smp_fini();
182 		fatal(-5, "command failed with status code %d", result);
183 	}
184 
185 	(void) printf("Response: (len %d)\n", len);
186 	for (i = 0; i < len; i += 8) {
187 		(void) printf("%02x: ", i);
188 		for (j = i; j < i + 8; j++)
189 			if (j < len)
190 				(void) printf("%02x ", resp[j]);
191 			else
192 				(void) printf("   ");
193 		for (j = i; j < i + 8; j++)
194 			(void) printf("%c",
195 			    j < len && isprint(resp[j]) ? resp[j] :
196 			    j < len ? '.' : '\0');
197 		(void) printf("\n");
198 	}
199 
200 	if (func == SMP_FUNC_DISCOVER) {
201 		rp = (smp_discover_resp_t *)resp;
202 		(void) printf("Addr: %016llx Phy: %02x\n",
203 		    SCSI_READ64(&rp->sdr_sas_addr), rp->sdr_phy_identifier);
204 		(void) printf("Peer: %016llx Phy: %02x\n",
205 		    SCSI_READ64(&rp->sdr_attached_sas_addr),
206 		    rp->sdr_attached_phy_identifier);
207 		(void) printf("Device type: %01x\n",
208 		    rp->sdr_attached_device_type);
209 	}
210 
211 	smp_action_free(ap);
212 	smp_fini();
213 
214 	return (0);
215 }
216