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