1 /*
2 * Copyright (c) 1997-2007 Kenneth D. Merry
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/ioctl.h>
33 #include <sys/stdint.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <sys/endian.h>
37 #include <sys/sbuf.h>
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <inttypes.h>
44 #include <limits.h>
45 #include <fcntl.h>
46 #include <ctype.h>
47 #include <err.h>
48 #include <libutil.h>
49 #ifndef MINIMALISTIC
50 #include <limits.h>
51 #include <inttypes.h>
52 #endif
53
54 #include <cam/cam.h>
55 #include <cam/cam_debug.h>
56 #include <cam/cam_ccb.h>
57 #include <cam/scsi/scsi_all.h>
58 #include <cam/scsi/scsi_da.h>
59 #include <cam/scsi/scsi_pass.h>
60 #include <cam/scsi/scsi_message.h>
61 #include <cam/scsi/smp_all.h>
62 #include <cam/ata/ata_all.h>
63 #include <camlib.h>
64 #include "camcontrol.h"
65
66 typedef enum {
67 CAM_CMD_NONE = 0x00000000,
68 CAM_CMD_DEVLIST = 0x00000001,
69 CAM_CMD_TUR = 0x00000002,
70 CAM_CMD_INQUIRY = 0x00000003,
71 CAM_CMD_STARTSTOP = 0x00000004,
72 CAM_CMD_RESCAN = 0x00000005,
73 CAM_CMD_READ_DEFECTS = 0x00000006,
74 CAM_CMD_MODE_PAGE = 0x00000007,
75 CAM_CMD_SCSI_CMD = 0x00000008,
76 CAM_CMD_DEVTREE = 0x00000009,
77 CAM_CMD_USAGE = 0x0000000a,
78 CAM_CMD_DEBUG = 0x0000000b,
79 CAM_CMD_RESET = 0x0000000c,
80 CAM_CMD_FORMAT = 0x0000000d,
81 CAM_CMD_TAG = 0x0000000e,
82 CAM_CMD_RATE = 0x0000000f,
83 CAM_CMD_DETACH = 0x00000010,
84 CAM_CMD_REPORTLUNS = 0x00000011,
85 CAM_CMD_READCAP = 0x00000012,
86 CAM_CMD_IDENTIFY = 0x00000013,
87 CAM_CMD_IDLE = 0x00000014,
88 CAM_CMD_STANDBY = 0x00000015,
89 CAM_CMD_SLEEP = 0x00000016,
90 CAM_CMD_SMP_CMD = 0x00000017,
91 CAM_CMD_SMP_RG = 0x00000018,
92 CAM_CMD_SMP_PC = 0x00000019,
93 CAM_CMD_SMP_PHYLIST = 0x0000001a,
94 CAM_CMD_SMP_MANINFO = 0x0000001b,
95 CAM_CMD_DOWNLOAD_FW = 0x0000001c,
96 CAM_CMD_SECURITY = 0x0000001d,
97 CAM_CMD_HPA = 0x0000001e,
98 CAM_CMD_SANITIZE = 0x0000001f,
99 CAM_CMD_PERSIST = 0x00000020,
100 CAM_CMD_APM = 0x00000021,
101 CAM_CMD_AAM = 0x00000022,
102 CAM_CMD_ATTRIB = 0x00000023,
103 CAM_CMD_OPCODES = 0x00000024
104 } cam_cmdmask;
105
106 typedef enum {
107 CAM_ARG_NONE = 0x00000000,
108 CAM_ARG_VERBOSE = 0x00000001,
109 CAM_ARG_DEVICE = 0x00000002,
110 CAM_ARG_BUS = 0x00000004,
111 CAM_ARG_TARGET = 0x00000008,
112 CAM_ARG_LUN = 0x00000010,
113 CAM_ARG_EJECT = 0x00000020,
114 CAM_ARG_UNIT = 0x00000040,
115 CAM_ARG_FORMAT_BLOCK = 0x00000080,
116 CAM_ARG_FORMAT_BFI = 0x00000100,
117 CAM_ARG_FORMAT_PHYS = 0x00000200,
118 CAM_ARG_PLIST = 0x00000400,
119 CAM_ARG_GLIST = 0x00000800,
120 CAM_ARG_GET_SERIAL = 0x00001000,
121 CAM_ARG_GET_STDINQ = 0x00002000,
122 CAM_ARG_GET_XFERRATE = 0x00004000,
123 CAM_ARG_INQ_MASK = 0x00007000,
124 CAM_ARG_MODE_EDIT = 0x00008000,
125 CAM_ARG_PAGE_CNTL = 0x00010000,
126 CAM_ARG_TIMEOUT = 0x00020000,
127 CAM_ARG_CMD_IN = 0x00040000,
128 CAM_ARG_CMD_OUT = 0x00080000,
129 CAM_ARG_DBD = 0x00100000,
130 CAM_ARG_ERR_RECOVER = 0x00200000,
131 CAM_ARG_RETRIES = 0x00400000,
132 CAM_ARG_START_UNIT = 0x00800000,
133 CAM_ARG_DEBUG_INFO = 0x01000000,
134 CAM_ARG_DEBUG_TRACE = 0x02000000,
135 CAM_ARG_DEBUG_SUBTRACE = 0x04000000,
136 CAM_ARG_DEBUG_CDB = 0x08000000,
137 CAM_ARG_DEBUG_XPT = 0x10000000,
138 CAM_ARG_DEBUG_PERIPH = 0x20000000,
139 CAM_ARG_DEBUG_PROBE = 0x40000000,
140 } cam_argmask;
141
142 struct camcontrol_opts {
143 const char *optname;
144 uint32_t cmdnum;
145 cam_argmask argnum;
146 const char *subopt;
147 };
148
149 #ifndef MINIMALISTIC
150 struct ata_res_pass16 {
151 u_int16_t reserved[5];
152 u_int8_t flags;
153 u_int8_t error;
154 u_int8_t sector_count_exp;
155 u_int8_t sector_count;
156 u_int8_t lba_low_exp;
157 u_int8_t lba_low;
158 u_int8_t lba_mid_exp;
159 u_int8_t lba_mid;
160 u_int8_t lba_high_exp;
161 u_int8_t lba_high;
162 u_int8_t device;
163 u_int8_t status;
164 };
165
166 struct ata_set_max_pwd
167 {
168 u_int16_t reserved1;
169 u_int8_t password[32];
170 u_int16_t reserved2[239];
171 };
172
173 static const char scsicmd_opts[] = "a:c:dfi:o:r";
174 static const char readdefect_opts[] = "f:GPqsS:X";
175 static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
176 static const char smprg_opts[] = "l";
177 static const char smppc_opts[] = "a:A:d:lm:M:o:p:s:S:T:";
178 static const char smpphylist_opts[] = "lq";
179 static char pwd_opt;
180 #endif
181
182 static struct camcontrol_opts option_table[] = {
183 #ifndef MINIMALISTIC
184 {"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
185 {"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
186 {"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
187 {"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
188 {"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
189 {"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
190 {"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
191 {"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
192 {"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"},
193 #endif /* MINIMALISTIC */
194 {"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
195 {"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
196 #ifndef MINIMALISTIC
197 {"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
198 {"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
199 {"smpcmd", CAM_CMD_SMP_CMD, CAM_ARG_NONE, "r:R:"},
200 {"smprg", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
201 {"smpreportgeneral", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
202 {"smppc", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
203 {"smpphycontrol", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
204 {"smpplist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
205 {"smpphylist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
206 {"smpmaninfo", CAM_CMD_SMP_MANINFO, CAM_ARG_NONE, "l"},
207 {"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
208 {"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
209 #endif /* MINIMALISTIC */
210 {"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, "-b"},
211 #ifndef MINIMALISTIC
212 {"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
213 {"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
214 {"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
215 {"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
216 {"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
217 {"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXcp"},
218 {"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
219 {"sanitize", CAM_CMD_SANITIZE, CAM_ARG_NONE, "a:c:IP:qrUwy"},
220 {"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"},
221 {"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"},
222 {"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""},
223 {"apm", CAM_CMD_APM, CAM_ARG_NONE, "l:"},
224 {"aam", CAM_CMD_AAM, CAM_ARG_NONE, "l:"},
225 {"fwdownload", CAM_CMD_DOWNLOAD_FW, CAM_ARG_NONE, "f:qsy"},
226 {"security", CAM_CMD_SECURITY, CAM_ARG_NONE, "d:e:fh:k:l:qs:T:U:y"},
227 {"hpa", CAM_CMD_HPA, CAM_ARG_NONE, "Pflp:qs:U:y"},
228 {"persist", CAM_CMD_PERSIST, CAM_ARG_NONE, "ai:I:k:K:o:ps:ST:U"},
229 {"attrib", CAM_CMD_ATTRIB, CAM_ARG_NONE, "a:ce:F:p:r:s:T:w:V:"},
230 {"opcodes", CAM_CMD_OPCODES, CAM_ARG_NONE, "No:s:T"},
231 #endif /* MINIMALISTIC */
232 {"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
233 {"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
234 {"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
235 {NULL, 0, 0, NULL}
236 };
237
238 struct cam_devitem {
239 struct device_match_result dev_match;
240 int num_periphs;
241 struct periph_match_result *periph_matches;
242 struct scsi_vpd_device_id *device_id;
243 int device_id_len;
244 STAILQ_ENTRY(cam_devitem) links;
245 };
246
247 struct cam_devlist {
248 STAILQ_HEAD(, cam_devitem) dev_queue;
249 path_id_t path_id;
250 };
251
252 static cam_cmdmask cmdlist;
253 static cam_argmask arglist;
254
255 camcontrol_optret getoption(struct camcontrol_opts *table, char *arg,
256 uint32_t *cmdnum, cam_argmask *argnum,
257 const char **subopt);
258 #ifndef MINIMALISTIC
259 static int getdevlist(struct cam_device *device);
260 #endif /* MINIMALISTIC */
261 static int getdevtree(int argc, char **argv, char *combinedopt);
262 #ifndef MINIMALISTIC
263 static int testunitready(struct cam_device *device, int retry_count,
264 int timeout, int quiet);
265 static int scsistart(struct cam_device *device, int startstop, int loadeject,
266 int retry_count, int timeout);
267 static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
268 static int scsiserial(struct cam_device *device, int retry_count, int timeout);
269 #endif /* MINIMALISTIC */
270 static int parse_btl(char *tstr, path_id_t *bus, target_id_t *target,
271 lun_id_t *lun, cam_argmask *arglst);
272 static int dorescan_or_reset(int argc, char **argv, int rescan);
273 static int rescan_or_reset_bus(path_id_t bus, int rescan);
274 static int scanlun_or_reset_dev(path_id_t bus, target_id_t target,
275 lun_id_t lun, int scan);
276 #ifndef MINIMALISTIC
277 static int readdefects(struct cam_device *device, int argc, char **argv,
278 char *combinedopt, int retry_count, int timeout);
279 static void modepage(struct cam_device *device, int argc, char **argv,
280 char *combinedopt, int retry_count, int timeout);
281 static int scsicmd(struct cam_device *device, int argc, char **argv,
282 char *combinedopt, int retry_count, int timeout);
283 static int smpcmd(struct cam_device *device, int argc, char **argv,
284 char *combinedopt, int retry_count, int timeout);
285 static int smpreportgeneral(struct cam_device *device, int argc, char **argv,
286 char *combinedopt, int retry_count, int timeout);
287 static int smpphycontrol(struct cam_device *device, int argc, char **argv,
288 char *combinedopt, int retry_count, int timeout);
289 static int smpmaninfo(struct cam_device *device, int argc, char **argv,
290 char *combinedopt, int retry_count, int timeout);
291 static int getdevid(struct cam_devitem *item);
292 static int buildbusdevlist(struct cam_devlist *devlist);
293 static void freebusdevlist(struct cam_devlist *devlist);
294 static struct cam_devitem *findsasdevice(struct cam_devlist *devlist,
295 uint64_t sasaddr);
296 static int smpphylist(struct cam_device *device, int argc, char **argv,
297 char *combinedopt, int retry_count, int timeout);
298 static int tagcontrol(struct cam_device *device, int argc, char **argv,
299 char *combinedopt);
300 static void cts_print(struct cam_device *device,
301 struct ccb_trans_settings *cts);
302 static void cpi_print(struct ccb_pathinq *cpi);
303 static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
304 static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd);
305 static int get_print_cts(struct cam_device *device, int user_settings,
306 int quiet, struct ccb_trans_settings *cts);
307 static int ratecontrol(struct cam_device *device, int retry_count,
308 int timeout, int argc, char **argv, char *combinedopt);
309 static int scsiformat(struct cam_device *device, int argc, char **argv,
310 char *combinedopt, int retry_count, int timeout);
311 static int scsisanitize(struct cam_device *device, int argc, char **argv,
312 char *combinedopt, int retry_count, int timeout);
313 static int scsireportluns(struct cam_device *device, int argc, char **argv,
314 char *combinedopt, int retry_count, int timeout);
315 static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
316 char *combinedopt, int retry_count, int timeout);
317 static int atapm(struct cam_device *device, int argc, char **argv,
318 char *combinedopt, int retry_count, int timeout);
319 static int atasecurity(struct cam_device *device, int retry_count, int timeout,
320 int argc, char **argv, char *combinedopt);
321 static int atahpa(struct cam_device *device, int retry_count, int timeout,
322 int argc, char **argv, char *combinedopt);
323 static int scsiprintoneopcode(struct cam_device *device, int req_opcode,
324 int sa_set, int req_sa, uint8_t *buf,
325 uint32_t valid_len);
326 static int scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf,
327 uint32_t valid_len);
328 static int scsiopcodes(struct cam_device *device, int argc, char **argv,
329 char *combinedopt, int retry_count, int timeout,
330 int verbose);
331
332 #endif /* MINIMALISTIC */
333 #ifndef min
334 #define min(a,b) (((a)<(b))?(a):(b))
335 #endif
336 #ifndef max
337 #define max(a,b) (((a)>(b))?(a):(b))
338 #endif
339
340 camcontrol_optret
getoption(struct camcontrol_opts * table,char * arg,uint32_t * cmdnum,cam_argmask * argnum,const char ** subopt)341 getoption(struct camcontrol_opts *table, char *arg, uint32_t *cmdnum,
342 cam_argmask *argnum, const char **subopt)
343 {
344 struct camcontrol_opts *opts;
345 int num_matches = 0;
346
347 for (opts = table; (opts != NULL) && (opts->optname != NULL);
348 opts++) {
349 if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
350 *cmdnum = opts->cmdnum;
351 *argnum = opts->argnum;
352 *subopt = opts->subopt;
353 if (++num_matches > 1)
354 return(CC_OR_AMBIGUOUS);
355 }
356 }
357
358 if (num_matches > 0)
359 return(CC_OR_FOUND);
360 else
361 return(CC_OR_NOT_FOUND);
362 }
363
364 #ifndef MINIMALISTIC
365 static int
getdevlist(struct cam_device * device)366 getdevlist(struct cam_device *device)
367 {
368 union ccb *ccb;
369 char status[32];
370 int error = 0;
371
372 ccb = cam_getccb(device);
373
374 ccb->ccb_h.func_code = XPT_GDEVLIST;
375 ccb->ccb_h.flags = CAM_DIR_NONE;
376 ccb->ccb_h.retry_count = 1;
377 ccb->cgdl.index = 0;
378 ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
379 while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
380 if (cam_send_ccb(device, ccb) < 0) {
381 perror("error getting device list");
382 cam_freeccb(ccb);
383 return(1);
384 }
385
386 status[0] = '\0';
387
388 switch (ccb->cgdl.status) {
389 case CAM_GDEVLIST_MORE_DEVS:
390 strcpy(status, "MORE");
391 break;
392 case CAM_GDEVLIST_LAST_DEVICE:
393 strcpy(status, "LAST");
394 break;
395 case CAM_GDEVLIST_LIST_CHANGED:
396 strcpy(status, "CHANGED");
397 break;
398 case CAM_GDEVLIST_ERROR:
399 strcpy(status, "ERROR");
400 error = 1;
401 break;
402 }
403
404 fprintf(stdout, "%s%d: generation: %d index: %d status: %s\n",
405 ccb->cgdl.periph_name,
406 ccb->cgdl.unit_number,
407 ccb->cgdl.generation,
408 ccb->cgdl.index,
409 status);
410
411 /*
412 * If the list has changed, we need to start over from the
413 * beginning.
414 */
415 if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
416 ccb->cgdl.index = 0;
417 }
418
419 cam_freeccb(ccb);
420
421 return(error);
422 }
423 #endif /* MINIMALISTIC */
424
425 static int
getdevtree(int argc,char ** argv,char * combinedopt)426 getdevtree(int argc, char **argv, char *combinedopt)
427 {
428 union ccb ccb;
429 int bufsize, fd;
430 unsigned int i;
431 int need_close = 0;
432 int error = 0;
433 int skip_device = 0;
434 int busonly = 0;
435 int c;
436
437 while ((c = getopt(argc, argv, combinedopt)) != -1) {
438 switch(c) {
439 case 'b':
440 if ((arglist & CAM_ARG_VERBOSE) == 0)
441 busonly = 1;
442 break;
443 default:
444 break;
445 }
446 }
447
448 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
449 warn("couldn't open %s", XPT_DEVICE);
450 return(1);
451 }
452
453 bzero(&ccb, sizeof(union ccb));
454
455 ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
456 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
457 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
458
459 ccb.ccb_h.func_code = XPT_DEV_MATCH;
460 bufsize = sizeof(struct dev_match_result) * 100;
461 ccb.cdm.match_buf_len = bufsize;
462 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
463 if (ccb.cdm.matches == NULL) {
464 warnx("can't malloc memory for matches");
465 close(fd);
466 return(1);
467 }
468 ccb.cdm.num_matches = 0;
469
470 /*
471 * We fetch all nodes, since we display most of them in the default
472 * case, and all in the verbose case.
473 */
474 ccb.cdm.num_patterns = 0;
475 ccb.cdm.pattern_buf_len = 0;
476
477 /*
478 * We do the ioctl multiple times if necessary, in case there are
479 * more than 100 nodes in the EDT.
480 */
481 do {
482 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
483 warn("error sending CAMIOCOMMAND ioctl");
484 error = 1;
485 break;
486 }
487
488 if ((ccb.ccb_h.status != CAM_REQ_CMP)
489 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
490 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
491 warnx("got CAM error %#x, CDM error %d\n",
492 ccb.ccb_h.status, ccb.cdm.status);
493 error = 1;
494 break;
495 }
496
497 for (i = 0; i < ccb.cdm.num_matches; i++) {
498 switch (ccb.cdm.matches[i].type) {
499 case DEV_MATCH_BUS: {
500 struct bus_match_result *bus_result;
501
502 /*
503 * Only print the bus information if the
504 * user turns on the verbose flag.
505 */
506 if ((busonly == 0) &&
507 (arglist & CAM_ARG_VERBOSE) == 0)
508 break;
509
510 bus_result =
511 &ccb.cdm.matches[i].result.bus_result;
512
513 if (need_close) {
514 fprintf(stdout, ")\n");
515 need_close = 0;
516 }
517
518 fprintf(stdout, "scbus%d on %s%d bus %d%s\n",
519 bus_result->path_id,
520 bus_result->dev_name,
521 bus_result->unit_number,
522 bus_result->bus_id,
523 (busonly ? "" : ":"));
524 break;
525 }
526 case DEV_MATCH_DEVICE: {
527 struct device_match_result *dev_result;
528 char vendor[16], product[48], revision[16];
529 char fw[5], tmpstr[256];
530
531 if (busonly == 1)
532 break;
533
534 dev_result =
535 &ccb.cdm.matches[i].result.device_result;
536
537 if ((dev_result->flags
538 & DEV_RESULT_UNCONFIGURED)
539 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
540 skip_device = 1;
541 break;
542 } else
543 skip_device = 0;
544
545 if (dev_result->protocol == PROTO_SCSI) {
546 cam_strvis(vendor, dev_result->inq_data.vendor,
547 sizeof(dev_result->inq_data.vendor),
548 sizeof(vendor));
549 cam_strvis(product,
550 dev_result->inq_data.product,
551 sizeof(dev_result->inq_data.product),
552 sizeof(product));
553 cam_strvis(revision,
554 dev_result->inq_data.revision,
555 sizeof(dev_result->inq_data.revision),
556 sizeof(revision));
557 sprintf(tmpstr, "<%s %s %s>", vendor, product,
558 revision);
559 } else if (dev_result->protocol == PROTO_ATA ||
560 dev_result->protocol == PROTO_SATAPM) {
561 cam_strvis(product,
562 dev_result->ident_data.model,
563 sizeof(dev_result->ident_data.model),
564 sizeof(product));
565 cam_strvis(revision,
566 dev_result->ident_data.revision,
567 sizeof(dev_result->ident_data.revision),
568 sizeof(revision));
569 sprintf(tmpstr, "<%s %s>", product,
570 revision);
571 } else if (dev_result->protocol == PROTO_SEMB) {
572 struct sep_identify_data *sid;
573
574 sid = (struct sep_identify_data *)
575 &dev_result->ident_data;
576 cam_strvis(vendor, sid->vendor_id,
577 sizeof(sid->vendor_id),
578 sizeof(vendor));
579 cam_strvis(product, sid->product_id,
580 sizeof(sid->product_id),
581 sizeof(product));
582 cam_strvis(revision, sid->product_rev,
583 sizeof(sid->product_rev),
584 sizeof(revision));
585 cam_strvis(fw, sid->firmware_rev,
586 sizeof(sid->firmware_rev),
587 sizeof(fw));
588 sprintf(tmpstr, "<%s %s %s %s>",
589 vendor, product, revision, fw);
590 } else {
591 sprintf(tmpstr, "<>");
592 }
593 if (need_close) {
594 fprintf(stdout, ")\n");
595 need_close = 0;
596 }
597
598 fprintf(stdout, "%-33s at scbus%d "
599 "target %d lun %jx (",
600 tmpstr,
601 dev_result->path_id,
602 dev_result->target_id,
603 (uintmax_t)dev_result->target_lun);
604
605 need_close = 1;
606
607 break;
608 }
609 case DEV_MATCH_PERIPH: {
610 struct periph_match_result *periph_result;
611
612 periph_result =
613 &ccb.cdm.matches[i].result.periph_result;
614
615 if (busonly || skip_device != 0)
616 break;
617
618 if (need_close > 1)
619 fprintf(stdout, ",");
620
621 fprintf(stdout, "%s%d",
622 periph_result->periph_name,
623 periph_result->unit_number);
624
625 need_close++;
626 break;
627 }
628 default:
629 fprintf(stdout, "unknown match type\n");
630 break;
631 }
632 }
633
634 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
635 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
636
637 if (need_close)
638 fprintf(stdout, ")\n");
639
640 close(fd);
641
642 return(error);
643 }
644
645 #ifndef MINIMALISTIC
646 static int
testunitready(struct cam_device * device,int retry_count,int timeout,int quiet)647 testunitready(struct cam_device *device, int retry_count, int timeout,
648 int quiet)
649 {
650 int error = 0;
651 union ccb *ccb;
652
653 ccb = cam_getccb(device);
654
655 scsi_test_unit_ready(&ccb->csio,
656 /* retries */ retry_count,
657 /* cbfcnp */ NULL,
658 /* tag_action */ MSG_SIMPLE_Q_TAG,
659 /* sense_len */ SSD_FULL_SIZE,
660 /* timeout */ timeout ? timeout : 5000);
661
662 /* Disable freezing the device queue */
663 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
664
665 if (arglist & CAM_ARG_ERR_RECOVER)
666 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
667
668 if (cam_send_ccb(device, ccb) < 0) {
669 if (quiet == 0)
670 perror("error sending test unit ready");
671
672 if (arglist & CAM_ARG_VERBOSE) {
673 cam_error_print(device, ccb, CAM_ESF_ALL,
674 CAM_EPF_ALL, stderr);
675 }
676
677 cam_freeccb(ccb);
678 return(1);
679 }
680
681 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
682 if (quiet == 0)
683 fprintf(stdout, "Unit is ready\n");
684 } else {
685 if (quiet == 0)
686 fprintf(stdout, "Unit is not ready\n");
687 error = 1;
688
689 if (arglist & CAM_ARG_VERBOSE) {
690 cam_error_print(device, ccb, CAM_ESF_ALL,
691 CAM_EPF_ALL, stderr);
692 }
693 }
694
695 cam_freeccb(ccb);
696
697 return(error);
698 }
699
700 static int
scsistart(struct cam_device * device,int startstop,int loadeject,int retry_count,int timeout)701 scsistart(struct cam_device *device, int startstop, int loadeject,
702 int retry_count, int timeout)
703 {
704 union ccb *ccb;
705 int error = 0;
706
707 ccb = cam_getccb(device);
708
709 /*
710 * If we're stopping, send an ordered tag so the drive in question
711 * will finish any previously queued writes before stopping. If
712 * the device isn't capable of tagged queueing, or if tagged
713 * queueing is turned off, the tag action is a no-op.
714 */
715 scsi_start_stop(&ccb->csio,
716 /* retries */ retry_count,
717 /* cbfcnp */ NULL,
718 /* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
719 MSG_ORDERED_Q_TAG,
720 /* start/stop */ startstop,
721 /* load_eject */ loadeject,
722 /* immediate */ 0,
723 /* sense_len */ SSD_FULL_SIZE,
724 /* timeout */ timeout ? timeout : 120000);
725
726 /* Disable freezing the device queue */
727 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
728
729 if (arglist & CAM_ARG_ERR_RECOVER)
730 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
731
732 if (cam_send_ccb(device, ccb) < 0) {
733 perror("error sending start unit");
734
735 if (arglist & CAM_ARG_VERBOSE) {
736 cam_error_print(device, ccb, CAM_ESF_ALL,
737 CAM_EPF_ALL, stderr);
738 }
739
740 cam_freeccb(ccb);
741 return(1);
742 }
743
744 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
745 if (startstop) {
746 fprintf(stdout, "Unit started successfully");
747 if (loadeject)
748 fprintf(stdout,", Media loaded\n");
749 else
750 fprintf(stdout,"\n");
751 } else {
752 fprintf(stdout, "Unit stopped successfully");
753 if (loadeject)
754 fprintf(stdout, ", Media ejected\n");
755 else
756 fprintf(stdout, "\n");
757 }
758 else {
759 error = 1;
760 if (startstop)
761 fprintf(stdout,
762 "Error received from start unit command\n");
763 else
764 fprintf(stdout,
765 "Error received from stop unit command\n");
766
767 if (arglist & CAM_ARG_VERBOSE) {
768 cam_error_print(device, ccb, CAM_ESF_ALL,
769 CAM_EPF_ALL, stderr);
770 }
771 }
772
773 cam_freeccb(ccb);
774
775 return(error);
776 }
777
778 int
scsidoinquiry(struct cam_device * device,int argc,char ** argv,char * combinedopt,int retry_count,int timeout)779 scsidoinquiry(struct cam_device *device, int argc, char **argv,
780 char *combinedopt, int retry_count, int timeout)
781 {
782 int c;
783 int error = 0;
784
785 while ((c = getopt(argc, argv, combinedopt)) != -1) {
786 switch(c) {
787 case 'D':
788 arglist |= CAM_ARG_GET_STDINQ;
789 break;
790 case 'R':
791 arglist |= CAM_ARG_GET_XFERRATE;
792 break;
793 case 'S':
794 arglist |= CAM_ARG_GET_SERIAL;
795 break;
796 default:
797 break;
798 }
799 }
800
801 /*
802 * If the user didn't specify any inquiry options, he wants all of
803 * them.
804 */
805 if ((arglist & CAM_ARG_INQ_MASK) == 0)
806 arglist |= CAM_ARG_INQ_MASK;
807
808 if (arglist & CAM_ARG_GET_STDINQ)
809 error = scsiinquiry(device, retry_count, timeout);
810
811 if (error != 0)
812 return(error);
813
814 if (arglist & CAM_ARG_GET_SERIAL)
815 scsiserial(device, retry_count, timeout);
816
817 if (error != 0)
818 return(error);
819
820 if (arglist & CAM_ARG_GET_XFERRATE)
821 error = camxferrate(device);
822
823 return(error);
824 }
825
826 static int
scsiinquiry(struct cam_device * device,int retry_count,int timeout)827 scsiinquiry(struct cam_device *device, int retry_count, int timeout)
828 {
829 union ccb *ccb;
830 struct scsi_inquiry_data *inq_buf;
831 int error = 0;
832
833 ccb = cam_getccb(device);
834
835 if (ccb == NULL) {
836 warnx("couldn't allocate CCB");
837 return(1);
838 }
839
840 /* cam_getccb cleans up the header, caller has to zero the payload */
841 bzero(&(&ccb->ccb_h)[1],
842 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
843
844 inq_buf = (struct scsi_inquiry_data *)malloc(
845 sizeof(struct scsi_inquiry_data));
846
847 if (inq_buf == NULL) {
848 cam_freeccb(ccb);
849 warnx("can't malloc memory for inquiry\n");
850 return(1);
851 }
852 bzero(inq_buf, sizeof(*inq_buf));
853
854 /*
855 * Note that although the size of the inquiry buffer is the full
856 * 256 bytes specified in the SCSI spec, we only tell the device
857 * that we have allocated SHORT_INQUIRY_LENGTH bytes. There are
858 * two reasons for this:
859 *
860 * - The SCSI spec says that when a length field is only 1 byte,
861 * a value of 0 will be interpreted as 256. Therefore
862 * scsi_inquiry() will convert an inq_len (which is passed in as
863 * a u_int32_t, but the field in the CDB is only 1 byte) of 256
864 * to 0. Evidently, very few devices meet the spec in that
865 * regard. Some devices, like many Seagate disks, take the 0 as
866 * 0, and don't return any data. One Pioneer DVD-R drive
867 * returns more data than the command asked for.
868 *
869 * So, since there are numerous devices that just don't work
870 * right with the full inquiry size, we don't send the full size.
871 *
872 * - The second reason not to use the full inquiry data length is
873 * that we don't need it here. The only reason we issue a
874 * standard inquiry is to get the vendor name, device name,
875 * and revision so scsi_print_inquiry() can print them.
876 *
877 * If, at some point in the future, more inquiry data is needed for
878 * some reason, this code should use a procedure similar to the
879 * probe code. i.e., issue a short inquiry, and determine from
880 * the additional length passed back from the device how much
881 * inquiry data the device supports. Once the amount the device
882 * supports is determined, issue an inquiry for that amount and no
883 * more.
884 *
885 * KDM, 2/18/2000
886 */
887 scsi_inquiry(&ccb->csio,
888 /* retries */ retry_count,
889 /* cbfcnp */ NULL,
890 /* tag_action */ MSG_SIMPLE_Q_TAG,
891 /* inq_buf */ (u_int8_t *)inq_buf,
892 /* inq_len */ SHORT_INQUIRY_LENGTH,
893 /* evpd */ 0,
894 /* page_code */ 0,
895 /* sense_len */ SSD_FULL_SIZE,
896 /* timeout */ timeout ? timeout : 5000);
897
898 /* Disable freezing the device queue */
899 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
900
901 if (arglist & CAM_ARG_ERR_RECOVER)
902 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
903
904 if (cam_send_ccb(device, ccb) < 0) {
905 perror("error sending SCSI inquiry");
906
907 if (arglist & CAM_ARG_VERBOSE) {
908 cam_error_print(device, ccb, CAM_ESF_ALL,
909 CAM_EPF_ALL, stderr);
910 }
911
912 cam_freeccb(ccb);
913 return(1);
914 }
915
916 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
917 error = 1;
918
919 if (arglist & CAM_ARG_VERBOSE) {
920 cam_error_print(device, ccb, CAM_ESF_ALL,
921 CAM_EPF_ALL, stderr);
922 }
923 }
924
925 cam_freeccb(ccb);
926
927 if (error != 0) {
928 free(inq_buf);
929 return(error);
930 }
931
932 fprintf(stdout, "%s%d: ", device->device_name,
933 device->dev_unit_num);
934 scsi_print_inquiry(inq_buf);
935
936 free(inq_buf);
937
938 return(0);
939 }
940
941 static int
scsiserial(struct cam_device * device,int retry_count,int timeout)942 scsiserial(struct cam_device *device, int retry_count, int timeout)
943 {
944 union ccb *ccb;
945 struct scsi_vpd_unit_serial_number *serial_buf;
946 char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
947 int error = 0;
948
949 ccb = cam_getccb(device);
950
951 if (ccb == NULL) {
952 warnx("couldn't allocate CCB");
953 return(1);
954 }
955
956 /* cam_getccb cleans up the header, caller has to zero the payload */
957 bzero(&(&ccb->ccb_h)[1],
958 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
959
960 serial_buf = (struct scsi_vpd_unit_serial_number *)
961 malloc(sizeof(*serial_buf));
962
963 if (serial_buf == NULL) {
964 cam_freeccb(ccb);
965 warnx("can't malloc memory for serial number");
966 return(1);
967 }
968
969 scsi_inquiry(&ccb->csio,
970 /*retries*/ retry_count,
971 /*cbfcnp*/ NULL,
972 /* tag_action */ MSG_SIMPLE_Q_TAG,
973 /* inq_buf */ (u_int8_t *)serial_buf,
974 /* inq_len */ sizeof(*serial_buf),
975 /* evpd */ 1,
976 /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
977 /* sense_len */ SSD_FULL_SIZE,
978 /* timeout */ timeout ? timeout : 5000);
979
980 /* Disable freezing the device queue */
981 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
982
983 if (arglist & CAM_ARG_ERR_RECOVER)
984 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
985
986 if (cam_send_ccb(device, ccb) < 0) {
987 warn("error getting serial number");
988
989 if (arglist & CAM_ARG_VERBOSE) {
990 cam_error_print(device, ccb, CAM_ESF_ALL,
991 CAM_EPF_ALL, stderr);
992 }
993
994 cam_freeccb(ccb);
995 free(serial_buf);
996 return(1);
997 }
998
999 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1000 error = 1;
1001
1002 if (arglist & CAM_ARG_VERBOSE) {
1003 cam_error_print(device, ccb, CAM_ESF_ALL,
1004 CAM_EPF_ALL, stderr);
1005 }
1006 }
1007
1008 cam_freeccb(ccb);
1009
1010 if (error != 0) {
1011 free(serial_buf);
1012 return(error);
1013 }
1014
1015 bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
1016 serial_num[serial_buf->length] = '\0';
1017
1018 if ((arglist & CAM_ARG_GET_STDINQ)
1019 || (arglist & CAM_ARG_GET_XFERRATE))
1020 fprintf(stdout, "%s%d: Serial Number ",
1021 device->device_name, device->dev_unit_num);
1022
1023 fprintf(stdout, "%.60s\n", serial_num);
1024
1025 free(serial_buf);
1026
1027 return(0);
1028 }
1029
1030 int
camxferrate(struct cam_device * device)1031 camxferrate(struct cam_device *device)
1032 {
1033 struct ccb_pathinq cpi;
1034 u_int32_t freq = 0;
1035 u_int32_t speed = 0;
1036 union ccb *ccb;
1037 u_int mb;
1038 int retval = 0;
1039
1040 if ((retval = get_cpi(device, &cpi)) != 0)
1041 return (1);
1042
1043 ccb = cam_getccb(device);
1044
1045 if (ccb == NULL) {
1046 warnx("couldn't allocate CCB");
1047 return(1);
1048 }
1049
1050 bzero(&(&ccb->ccb_h)[1],
1051 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
1052
1053 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
1054 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
1055
1056 if (((retval = cam_send_ccb(device, ccb)) < 0)
1057 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1058 const char error_string[] = "error getting transfer settings";
1059
1060 if (retval < 0)
1061 warn(error_string);
1062 else
1063 warnx(error_string);
1064
1065 if (arglist & CAM_ARG_VERBOSE)
1066 cam_error_print(device, ccb, CAM_ESF_ALL,
1067 CAM_EPF_ALL, stderr);
1068
1069 retval = 1;
1070
1071 goto xferrate_bailout;
1072
1073 }
1074
1075 speed = cpi.base_transfer_speed;
1076 freq = 0;
1077 if (ccb->cts.transport == XPORT_SPI) {
1078 struct ccb_trans_settings_spi *spi =
1079 &ccb->cts.xport_specific.spi;
1080
1081 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
1082 freq = scsi_calc_syncsrate(spi->sync_period);
1083 speed = freq;
1084 }
1085 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
1086 speed *= (0x01 << spi->bus_width);
1087 }
1088 } else if (ccb->cts.transport == XPORT_FC) {
1089 struct ccb_trans_settings_fc *fc =
1090 &ccb->cts.xport_specific.fc;
1091
1092 if (fc->valid & CTS_FC_VALID_SPEED)
1093 speed = fc->bitrate;
1094 } else if (ccb->cts.transport == XPORT_SAS) {
1095 struct ccb_trans_settings_sas *sas =
1096 &ccb->cts.xport_specific.sas;
1097
1098 if (sas->valid & CTS_SAS_VALID_SPEED)
1099 speed = sas->bitrate;
1100 } else if (ccb->cts.transport == XPORT_ATA) {
1101 struct ccb_trans_settings_pata *pata =
1102 &ccb->cts.xport_specific.ata;
1103
1104 if (pata->valid & CTS_ATA_VALID_MODE)
1105 speed = ata_mode2speed(pata->mode);
1106 } else if (ccb->cts.transport == XPORT_SATA) {
1107 struct ccb_trans_settings_sata *sata =
1108 &ccb->cts.xport_specific.sata;
1109
1110 if (sata->valid & CTS_SATA_VALID_REVISION)
1111 speed = ata_revision2speed(sata->revision);
1112 }
1113
1114 mb = speed / 1000;
1115 if (mb > 0) {
1116 fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
1117 device->device_name, device->dev_unit_num,
1118 mb, speed % 1000);
1119 } else {
1120 fprintf(stdout, "%s%d: %dKB/s transfers",
1121 device->device_name, device->dev_unit_num,
1122 speed);
1123 }
1124
1125 if (ccb->cts.transport == XPORT_SPI) {
1126 struct ccb_trans_settings_spi *spi =
1127 &ccb->cts.xport_specific.spi;
1128
1129 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1130 && (spi->sync_offset != 0))
1131 fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
1132 freq % 1000, spi->sync_offset);
1133
1134 if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
1135 && (spi->bus_width > 0)) {
1136 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1137 && (spi->sync_offset != 0)) {
1138 fprintf(stdout, ", ");
1139 } else {
1140 fprintf(stdout, " (");
1141 }
1142 fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
1143 } else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1144 && (spi->sync_offset != 0)) {
1145 fprintf(stdout, ")");
1146 }
1147 } else if (ccb->cts.transport == XPORT_ATA) {
1148 struct ccb_trans_settings_pata *pata =
1149 &ccb->cts.xport_specific.ata;
1150
1151 printf(" (");
1152 if (pata->valid & CTS_ATA_VALID_MODE)
1153 printf("%s, ", ata_mode2string(pata->mode));
1154 if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0)
1155 printf("ATAPI %dbytes, ", pata->atapi);
1156 if (pata->valid & CTS_ATA_VALID_BYTECOUNT)
1157 printf("PIO %dbytes", pata->bytecount);
1158 printf(")");
1159 } else if (ccb->cts.transport == XPORT_SATA) {
1160 struct ccb_trans_settings_sata *sata =
1161 &ccb->cts.xport_specific.sata;
1162
1163 printf(" (");
1164 if (sata->valid & CTS_SATA_VALID_REVISION)
1165 printf("SATA %d.x, ", sata->revision);
1166 else
1167 printf("SATA, ");
1168 if (sata->valid & CTS_SATA_VALID_MODE)
1169 printf("%s, ", ata_mode2string(sata->mode));
1170 if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
1171 printf("ATAPI %dbytes, ", sata->atapi);
1172 if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1173 printf("PIO %dbytes", sata->bytecount);
1174 printf(")");
1175 }
1176
1177 if (ccb->cts.protocol == PROTO_SCSI) {
1178 struct ccb_trans_settings_scsi *scsi =
1179 &ccb->cts.proto_specific.scsi;
1180 if (scsi->valid & CTS_SCSI_VALID_TQ) {
1181 if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1182 fprintf(stdout, ", Command Queueing Enabled");
1183 }
1184 }
1185 }
1186
1187 fprintf(stdout, "\n");
1188
1189 xferrate_bailout:
1190
1191 cam_freeccb(ccb);
1192
1193 return(retval);
1194 }
1195
1196 static void
atahpa_print(struct ata_params * parm,u_int64_t hpasize,int header)1197 atahpa_print(struct ata_params *parm, u_int64_t hpasize, int header)
1198 {
1199 u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1200 ((u_int32_t)parm->lba_size_2 << 16);
1201
1202 u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1203 ((u_int64_t)parm->lba_size48_2 << 16) |
1204 ((u_int64_t)parm->lba_size48_3 << 32) |
1205 ((u_int64_t)parm->lba_size48_4 << 48);
1206
1207 if (header) {
1208 printf("\nFeature "
1209 "Support Enabled Value\n");
1210 }
1211
1212 printf("Host Protected Area (HPA) ");
1213 if (parm->support.command1 & ATA_SUPPORT_PROTECTED) {
1214 u_int64_t lba = lbasize48 ? lbasize48 : lbasize;
1215 printf("yes %s %ju/%ju\n", (hpasize > lba) ? "yes" : "no ",
1216 lba, hpasize);
1217
1218 printf("HPA - Security ");
1219 if (parm->support.command1 & ATA_SUPPORT_MAXSECURITY)
1220 printf("yes\n");
1221 else
1222 printf("no\n");
1223 } else {
1224 printf("no\n");
1225 }
1226 }
1227
1228 static int
atasata(struct ata_params * parm)1229 atasata(struct ata_params *parm)
1230 {
1231
1232
1233 if (parm->satacapabilities != 0xffff &&
1234 parm->satacapabilities != 0x0000)
1235 return 1;
1236
1237 return 0;
1238 }
1239
1240 static void
atacapprint(struct ata_params * parm)1241 atacapprint(struct ata_params *parm)
1242 {
1243 u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1244 ((u_int32_t)parm->lba_size_2 << 16);
1245
1246 u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1247 ((u_int64_t)parm->lba_size48_2 << 16) |
1248 ((u_int64_t)parm->lba_size48_3 << 32) |
1249 ((u_int64_t)parm->lba_size48_4 << 48);
1250
1251 printf("\n");
1252 printf("protocol ");
1253 printf("ATA/ATAPI-%d", ata_version(parm->version_major));
1254 if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1255 if (parm->satacapabilities & ATA_SATA_GEN3)
1256 printf(" SATA 3.x\n");
1257 else if (parm->satacapabilities & ATA_SATA_GEN2)
1258 printf(" SATA 2.x\n");
1259 else if (parm->satacapabilities & ATA_SATA_GEN1)
1260 printf(" SATA 1.x\n");
1261 else
1262 printf(" SATA\n");
1263 }
1264 else
1265 printf("\n");
1266 printf("device model %.40s\n", parm->model);
1267 printf("firmware revision %.8s\n", parm->revision);
1268 printf("serial number %.20s\n", parm->serial);
1269 if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
1270 printf("WWN %04x%04x%04x%04x\n",
1271 parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
1272 }
1273 if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
1274 printf("media serial number %.30s\n",
1275 parm->media_serial);
1276 }
1277
1278 printf("cylinders %d\n", parm->cylinders);
1279 printf("heads %d\n", parm->heads);
1280 printf("sectors/track %d\n", parm->sectors);
1281 printf("sector size logical %u, physical %lu, offset %lu\n",
1282 ata_logical_sector_size(parm),
1283 (unsigned long)ata_physical_sector_size(parm),
1284 (unsigned long)ata_logical_sector_offset(parm));
1285
1286 if (parm->config == ATA_PROTO_CFA ||
1287 (parm->support.command2 & ATA_SUPPORT_CFA))
1288 printf("CFA supported\n");
1289
1290 printf("LBA%ssupported ",
1291 parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1292 if (lbasize)
1293 printf("%d sectors\n", lbasize);
1294 else
1295 printf("\n");
1296
1297 printf("LBA48%ssupported ",
1298 parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1299 if (lbasize48)
1300 printf("%ju sectors\n", (uintmax_t)lbasize48);
1301 else
1302 printf("\n");
1303
1304 printf("PIO supported PIO");
1305 switch (ata_max_pmode(parm)) {
1306 case ATA_PIO4:
1307 printf("4");
1308 break;
1309 case ATA_PIO3:
1310 printf("3");
1311 break;
1312 case ATA_PIO2:
1313 printf("2");
1314 break;
1315 case ATA_PIO1:
1316 printf("1");
1317 break;
1318 default:
1319 printf("0");
1320 }
1321 if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0)
1322 printf(" w/o IORDY");
1323 printf("\n");
1324
1325 printf("DMA%ssupported ",
1326 parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1327 if (parm->capabilities1 & ATA_SUPPORT_DMA) {
1328 if (parm->mwdmamodes & 0xff) {
1329 printf("WDMA");
1330 if (parm->mwdmamodes & 0x04)
1331 printf("2");
1332 else if (parm->mwdmamodes & 0x02)
1333 printf("1");
1334 else if (parm->mwdmamodes & 0x01)
1335 printf("0");
1336 printf(" ");
1337 }
1338 if ((parm->atavalid & ATA_FLAG_88) &&
1339 (parm->udmamodes & 0xff)) {
1340 printf("UDMA");
1341 if (parm->udmamodes & 0x40)
1342 printf("6");
1343 else if (parm->udmamodes & 0x20)
1344 printf("5");
1345 else if (parm->udmamodes & 0x10)
1346 printf("4");
1347 else if (parm->udmamodes & 0x08)
1348 printf("3");
1349 else if (parm->udmamodes & 0x04)
1350 printf("2");
1351 else if (parm->udmamodes & 0x02)
1352 printf("1");
1353 else if (parm->udmamodes & 0x01)
1354 printf("0");
1355 printf(" ");
1356 }
1357 }
1358 printf("\n");
1359
1360 if (parm->media_rotation_rate == 1) {
1361 printf("media RPM non-rotating\n");
1362 } else if (parm->media_rotation_rate >= 0x0401 &&
1363 parm->media_rotation_rate <= 0xFFFE) {
1364 printf("media RPM %d\n",
1365 parm->media_rotation_rate);
1366 }
1367
1368 printf("\nFeature "
1369 "Support Enabled Value Vendor\n");
1370 printf("read ahead %s %s\n",
1371 parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1372 parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1373 printf("write cache %s %s\n",
1374 parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1375 parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1376 printf("flush cache %s %s\n",
1377 parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no",
1378 parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no");
1379 printf("overlap %s\n",
1380 parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no");
1381 printf("Tagged Command Queuing (TCQ) %s %s",
1382 parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1383 parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no");
1384 if (parm->support.command2 & ATA_SUPPORT_QUEUED) {
1385 printf(" %d tags\n",
1386 ATA_QUEUE_LEN(parm->queue) + 1);
1387 } else
1388 printf("\n");
1389 printf("Native Command Queuing (NCQ) ");
1390 if (parm->satacapabilities != 0xffff &&
1391 (parm->satacapabilities & ATA_SUPPORT_NCQ)) {
1392 printf("yes %d tags\n",
1393 ATA_QUEUE_LEN(parm->queue) + 1);
1394 } else
1395 printf("no\n");
1396
1397 printf("NCQ Queue Management %s\n", atasata(parm) &&
1398 parm->satacapabilities2 & ATA_SUPPORT_NCQ_QMANAGEMENT ?
1399 "yes" : "no");
1400 printf("NCQ Streaming %s\n", atasata(parm) &&
1401 parm->satacapabilities2 & ATA_SUPPORT_NCQ_STREAM ?
1402 "yes" : "no");
1403 printf("Receive & Send FPDMA Queued %s\n", atasata(parm) &&
1404 parm->satacapabilities2 & ATA_SUPPORT_RCVSND_FPDMA_QUEUED ?
1405 "yes" : "no");
1406
1407 printf("SMART %s %s\n",
1408 parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1409 parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1410 printf("microcode download %s %s\n",
1411 parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1412 parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1413 printf("security %s %s\n",
1414 parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1415 parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1416 printf("power management %s %s\n",
1417 parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1418 parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1419 printf("advanced power management %s %s",
1420 parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1421 parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no");
1422 if (parm->support.command2 & ATA_SUPPORT_APM) {
1423 printf(" %d/0x%02X\n",
1424 parm->apm_value & 0xff, parm->apm_value & 0xff);
1425 } else
1426 printf("\n");
1427 printf("automatic acoustic management %s %s",
1428 parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1429 parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no");
1430 if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) {
1431 printf(" %d/0x%02X %d/0x%02X\n",
1432 ATA_ACOUSTIC_CURRENT(parm->acoustic),
1433 ATA_ACOUSTIC_CURRENT(parm->acoustic),
1434 ATA_ACOUSTIC_VENDOR(parm->acoustic),
1435 ATA_ACOUSTIC_VENDOR(parm->acoustic));
1436 } else
1437 printf("\n");
1438 printf("media status notification %s %s\n",
1439 parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1440 parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1441 printf("power-up in Standby %s %s\n",
1442 parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1443 parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1444 printf("write-read-verify %s %s",
1445 parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1446 parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no");
1447 if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) {
1448 printf(" %d/0x%x\n",
1449 parm->wrv_mode, parm->wrv_mode);
1450 } else
1451 printf("\n");
1452 printf("unload %s %s\n",
1453 parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1454 parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1455 printf("general purpose logging %s %s\n",
1456 parm->support.extension & ATA_SUPPORT_GENLOG ? "yes" : "no",
1457 parm->enabled.extension & ATA_SUPPORT_GENLOG ? "yes" : "no");
1458 printf("free-fall %s %s\n",
1459 parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1460 parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1461 printf("Data Set Management (DSM/TRIM) ");
1462 if (parm->support_dsm & ATA_SUPPORT_DSM_TRIM) {
1463 printf("yes\n");
1464 printf("DSM - max 512byte blocks ");
1465 if (parm->max_dsm_blocks == 0x00)
1466 printf("yes not specified\n");
1467 else
1468 printf("yes %d\n",
1469 parm->max_dsm_blocks);
1470
1471 printf("DSM - deterministic read ");
1472 if (parm->support3 & ATA_SUPPORT_DRAT) {
1473 if (parm->support3 & ATA_SUPPORT_RZAT)
1474 printf("yes zeroed\n");
1475 else
1476 printf("yes any value\n");
1477 } else {
1478 printf("no\n");
1479 }
1480 } else {
1481 printf("no\n");
1482 }
1483 }
1484
1485 static int
scsi_cam_pass_16_send(struct cam_device * device,union ccb * ccb,int quiet)1486 scsi_cam_pass_16_send(struct cam_device *device, union ccb *ccb, int quiet)
1487 {
1488 struct ata_pass_16 *ata_pass_16;
1489 struct ata_cmd ata_cmd;
1490
1491 ata_pass_16 = (struct ata_pass_16 *)ccb->csio.cdb_io.cdb_bytes;
1492 ata_cmd.command = ata_pass_16->command;
1493 ata_cmd.control = ata_pass_16->control;
1494 ata_cmd.features = ata_pass_16->features;
1495
1496 if (arglist & CAM_ARG_VERBOSE) {
1497 warnx("sending ATA %s via pass_16 with timeout of %u msecs",
1498 ata_op_string(&ata_cmd),
1499 ccb->csio.ccb_h.timeout);
1500 }
1501
1502 /* Disable freezing the device queue */
1503 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1504
1505 if (arglist & CAM_ARG_ERR_RECOVER)
1506 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1507
1508 if (cam_send_ccb(device, ccb) < 0) {
1509 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1510 warn("error sending ATA %s via pass_16",
1511 ata_op_string(&ata_cmd));
1512 }
1513
1514 if (arglist & CAM_ARG_VERBOSE) {
1515 cam_error_print(device, ccb, CAM_ESF_ALL,
1516 CAM_EPF_ALL, stderr);
1517 }
1518
1519 return (1);
1520 }
1521
1522 if (!(ata_pass_16->flags & AP_FLAG_CHK_COND) &&
1523 (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1524 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1525 warnx("ATA %s via pass_16 failed",
1526 ata_op_string(&ata_cmd));
1527 }
1528 if (arglist & CAM_ARG_VERBOSE) {
1529 cam_error_print(device, ccb, CAM_ESF_ALL,
1530 CAM_EPF_ALL, stderr);
1531 }
1532
1533 return (1);
1534 }
1535
1536 return (0);
1537 }
1538
1539
1540 static int
ata_cam_send(struct cam_device * device,union ccb * ccb,int quiet)1541 ata_cam_send(struct cam_device *device, union ccb *ccb, int quiet)
1542 {
1543 if (arglist & CAM_ARG_VERBOSE) {
1544 warnx("sending ATA %s with timeout of %u msecs",
1545 ata_op_string(&(ccb->ataio.cmd)),
1546 ccb->ataio.ccb_h.timeout);
1547 }
1548
1549 /* Disable freezing the device queue */
1550 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1551
1552 if (arglist & CAM_ARG_ERR_RECOVER)
1553 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1554
1555 if (cam_send_ccb(device, ccb) < 0) {
1556 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1557 warn("error sending ATA %s",
1558 ata_op_string(&(ccb->ataio.cmd)));
1559 }
1560
1561 if (arglist & CAM_ARG_VERBOSE) {
1562 cam_error_print(device, ccb, CAM_ESF_ALL,
1563 CAM_EPF_ALL, stderr);
1564 }
1565
1566 return (1);
1567 }
1568
1569 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1570 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1571 warnx("ATA %s failed: %d",
1572 ata_op_string(&(ccb->ataio.cmd)), quiet);
1573 }
1574
1575 if (arglist & CAM_ARG_VERBOSE) {
1576 cam_error_print(device, ccb, CAM_ESF_ALL,
1577 CAM_EPF_ALL, stderr);
1578 }
1579
1580 return (1);
1581 }
1582
1583 return (0);
1584 }
1585
1586 static int
ata_do_pass_16(struct cam_device * device,union ccb * ccb,int retries,u_int32_t flags,u_int8_t protocol,u_int8_t ata_flags,u_int8_t tag_action,u_int8_t command,u_int8_t features,u_int64_t lba,u_int8_t sector_count,u_int8_t * data_ptr,u_int16_t dxfer_len,int timeout,int quiet)1587 ata_do_pass_16(struct cam_device *device, union ccb *ccb, int retries,
1588 u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
1589 u_int8_t tag_action, u_int8_t command, u_int8_t features,
1590 u_int64_t lba, u_int8_t sector_count, u_int8_t *data_ptr,
1591 u_int16_t dxfer_len, int timeout, int quiet)
1592 {
1593 if (data_ptr != NULL) {
1594 ata_flags |= AP_FLAG_BYT_BLOK_BYTES |
1595 AP_FLAG_TLEN_SECT_CNT;
1596 if (flags & CAM_DIR_OUT)
1597 ata_flags |= AP_FLAG_TDIR_TO_DEV;
1598 else
1599 ata_flags |= AP_FLAG_TDIR_FROM_DEV;
1600 } else {
1601 ata_flags |= AP_FLAG_TLEN_NO_DATA;
1602 }
1603
1604 bzero(&(&ccb->ccb_h)[1],
1605 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1606
1607 scsi_ata_pass_16(&ccb->csio,
1608 retries,
1609 NULL,
1610 flags,
1611 tag_action,
1612 protocol,
1613 ata_flags,
1614 features,
1615 sector_count,
1616 lba,
1617 command,
1618 /*control*/0,
1619 data_ptr,
1620 dxfer_len,
1621 /*sense_len*/SSD_FULL_SIZE,
1622 timeout);
1623
1624 return scsi_cam_pass_16_send(device, ccb, quiet);
1625 }
1626
1627 static int
ata_try_pass_16(struct cam_device * device)1628 ata_try_pass_16(struct cam_device *device)
1629 {
1630 struct ccb_pathinq cpi;
1631
1632 if (get_cpi(device, &cpi) != 0) {
1633 warnx("couldn't get CPI");
1634 return (-1);
1635 }
1636
1637 if (cpi.protocol == PROTO_SCSI) {
1638 /* possibly compatible with pass_16 */
1639 return (1);
1640 }
1641
1642 /* likely not compatible with pass_16 */
1643 return (0);
1644 }
1645
1646 static int
ata_do_28bit_cmd(struct cam_device * device,union ccb * ccb,int retries,u_int32_t flags,u_int8_t protocol,u_int8_t tag_action,u_int8_t command,u_int8_t features,u_int32_t lba,u_int8_t sector_count,u_int8_t * data_ptr,u_int16_t dxfer_len,int timeout,int quiet)1647 ata_do_28bit_cmd(struct cam_device *device, union ccb *ccb, int retries,
1648 u_int32_t flags, u_int8_t protocol, u_int8_t tag_action,
1649 u_int8_t command, u_int8_t features, u_int32_t lba,
1650 u_int8_t sector_count, u_int8_t *data_ptr, u_int16_t dxfer_len,
1651 int timeout, int quiet)
1652 {
1653
1654
1655 switch (ata_try_pass_16(device)) {
1656 case -1:
1657 return (1);
1658 case 1:
1659 /* Try using SCSI Passthrough */
1660 return ata_do_pass_16(device, ccb, retries, flags, protocol,
1661 0, tag_action, command, features, lba,
1662 sector_count, data_ptr, dxfer_len,
1663 timeout, quiet);
1664 }
1665
1666 bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) -
1667 sizeof(struct ccb_hdr));
1668 cam_fill_ataio(&ccb->ataio,
1669 retries,
1670 NULL,
1671 flags,
1672 tag_action,
1673 data_ptr,
1674 dxfer_len,
1675 timeout);
1676
1677 ata_28bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1678 return ata_cam_send(device, ccb, quiet);
1679 }
1680
1681 static int
ata_do_cmd(struct cam_device * device,union ccb * ccb,int retries,u_int32_t flags,u_int8_t protocol,u_int8_t ata_flags,u_int8_t tag_action,u_int8_t command,u_int8_t features,u_int64_t lba,u_int8_t sector_count,u_int8_t * data_ptr,u_int16_t dxfer_len,int timeout,int force48bit)1682 ata_do_cmd(struct cam_device *device, union ccb *ccb, int retries,
1683 u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
1684 u_int8_t tag_action, u_int8_t command, u_int8_t features,
1685 u_int64_t lba, u_int8_t sector_count, u_int8_t *data_ptr,
1686 u_int16_t dxfer_len, int timeout, int force48bit)
1687 {
1688 int retval;
1689
1690 retval = ata_try_pass_16(device);
1691 if (retval == -1)
1692 return (1);
1693
1694 if (retval == 1) {
1695 int error;
1696
1697 /* Try using SCSI Passthrough */
1698 error = ata_do_pass_16(device, ccb, retries, flags, protocol,
1699 ata_flags, tag_action, command, features,
1700 lba, sector_count, data_ptr, dxfer_len,
1701 timeout, 0);
1702
1703 if (ata_flags & AP_FLAG_CHK_COND) {
1704 /* Decode ata_res from sense data */
1705 struct ata_res_pass16 *res_pass16;
1706 struct ata_res *res;
1707 u_int i;
1708 u_int16_t *ptr;
1709
1710 /* sense_data is 4 byte aligned */
1711 ptr = (uint16_t*)(uintptr_t)&ccb->csio.sense_data;
1712 for (i = 0; i < sizeof(*res_pass16) / 2; i++)
1713 ptr[i] = le16toh(ptr[i]);
1714
1715 /* sense_data is 4 byte aligned */
1716 res_pass16 = (struct ata_res_pass16 *)(uintptr_t)
1717 &ccb->csio.sense_data;
1718 res = &ccb->ataio.res;
1719 res->flags = res_pass16->flags;
1720 res->status = res_pass16->status;
1721 res->error = res_pass16->error;
1722 res->lba_low = res_pass16->lba_low;
1723 res->lba_mid = res_pass16->lba_mid;
1724 res->lba_high = res_pass16->lba_high;
1725 res->device = res_pass16->device;
1726 res->lba_low_exp = res_pass16->lba_low_exp;
1727 res->lba_mid_exp = res_pass16->lba_mid_exp;
1728 res->lba_high_exp = res_pass16->lba_high_exp;
1729 res->sector_count = res_pass16->sector_count;
1730 res->sector_count_exp = res_pass16->sector_count_exp;
1731 }
1732
1733 return (error);
1734 }
1735
1736 bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) -
1737 sizeof(struct ccb_hdr));
1738 cam_fill_ataio(&ccb->ataio,
1739 retries,
1740 NULL,
1741 flags,
1742 tag_action,
1743 data_ptr,
1744 dxfer_len,
1745 timeout);
1746
1747 if (force48bit || lba > ATA_MAX_28BIT_LBA)
1748 ata_48bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1749 else
1750 ata_28bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1751
1752 if (ata_flags & AP_FLAG_CHK_COND)
1753 ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
1754
1755 return ata_cam_send(device, ccb, 0);
1756 }
1757
1758 static void
dump_data(uint16_t * ptr,uint32_t len)1759 dump_data(uint16_t *ptr, uint32_t len)
1760 {
1761 u_int i;
1762
1763 for (i = 0; i < len / 2; i++) {
1764 if ((i % 8) == 0)
1765 printf(" %3d: ", i);
1766 printf("%04hx ", ptr[i]);
1767 if ((i % 8) == 7)
1768 printf("\n");
1769 }
1770 if ((i % 8) != 7)
1771 printf("\n");
1772 }
1773
1774 static int
atahpa_proc_resp(struct cam_device * device,union ccb * ccb,int is48bit,u_int64_t * hpasize)1775 atahpa_proc_resp(struct cam_device *device, union ccb *ccb,
1776 int is48bit, u_int64_t *hpasize)
1777 {
1778 struct ata_res *res;
1779
1780 res = &ccb->ataio.res;
1781 if (res->status & ATA_STATUS_ERROR) {
1782 if (arglist & CAM_ARG_VERBOSE) {
1783 cam_error_print(device, ccb, CAM_ESF_ALL,
1784 CAM_EPF_ALL, stderr);
1785 printf("error = 0x%02x, sector_count = 0x%04x, "
1786 "device = 0x%02x, status = 0x%02x\n",
1787 res->error, res->sector_count,
1788 res->device, res->status);
1789 }
1790
1791 if (res->error & ATA_ERROR_ID_NOT_FOUND) {
1792 warnx("Max address has already been set since "
1793 "last power-on or hardware reset");
1794 }
1795
1796 return (1);
1797 }
1798
1799 if (arglist & CAM_ARG_VERBOSE) {
1800 fprintf(stdout, "%s%d: Raw native max data:\n",
1801 device->device_name, device->dev_unit_num);
1802 /* res is 4 byte aligned */
1803 dump_data((uint16_t*)(uintptr_t)res, sizeof(struct ata_res));
1804
1805 printf("error = 0x%02x, sector_count = 0x%04x, device = 0x%02x, "
1806 "status = 0x%02x\n", res->error, res->sector_count,
1807 res->device, res->status);
1808 }
1809
1810 if (hpasize != NULL) {
1811 if (is48bit) {
1812 *hpasize = (((u_int64_t)((res->lba_high_exp << 16) |
1813 (res->lba_mid_exp << 8) | res->lba_low_exp) << 24) |
1814 ((res->lba_high << 16) | (res->lba_mid << 8) |
1815 res->lba_low)) + 1;
1816 } else {
1817 *hpasize = (((res->device & 0x0f) << 24) |
1818 (res->lba_high << 16) | (res->lba_mid << 8) |
1819 res->lba_low) + 1;
1820 }
1821 }
1822
1823 return (0);
1824 }
1825
1826 static int
ata_read_native_max(struct cam_device * device,int retry_count,u_int32_t timeout,union ccb * ccb,struct ata_params * parm,u_int64_t * hpasize)1827 ata_read_native_max(struct cam_device *device, int retry_count,
1828 u_int32_t timeout, union ccb *ccb,
1829 struct ata_params *parm, u_int64_t *hpasize)
1830 {
1831 int error;
1832 u_int cmd, is48bit;
1833 u_int8_t protocol;
1834
1835 is48bit = parm->support.command2 & ATA_SUPPORT_ADDRESS48;
1836 protocol = AP_PROTO_NON_DATA;
1837
1838 if (is48bit) {
1839 cmd = ATA_READ_NATIVE_MAX_ADDRESS48;
1840 protocol |= AP_EXTEND;
1841 } else {
1842 cmd = ATA_READ_NATIVE_MAX_ADDRESS;
1843 }
1844
1845 error = ata_do_cmd(device,
1846 ccb,
1847 retry_count,
1848 /*flags*/CAM_DIR_NONE,
1849 /*protocol*/protocol,
1850 /*ata_flags*/AP_FLAG_CHK_COND,
1851 /*tag_action*/MSG_SIMPLE_Q_TAG,
1852 /*command*/cmd,
1853 /*features*/0,
1854 /*lba*/0,
1855 /*sector_count*/0,
1856 /*data_ptr*/NULL,
1857 /*dxfer_len*/0,
1858 timeout ? timeout : 1000,
1859 is48bit);
1860
1861 if (error)
1862 return (error);
1863
1864 return atahpa_proc_resp(device, ccb, is48bit, hpasize);
1865 }
1866
1867 static int
atahpa_set_max(struct cam_device * device,int retry_count,u_int32_t timeout,union ccb * ccb,int is48bit,u_int64_t maxsize,int persist)1868 atahpa_set_max(struct cam_device *device, int retry_count,
1869 u_int32_t timeout, union ccb *ccb,
1870 int is48bit, u_int64_t maxsize, int persist)
1871 {
1872 int error;
1873 u_int cmd;
1874 u_int8_t protocol;
1875
1876 protocol = AP_PROTO_NON_DATA;
1877
1878 if (is48bit) {
1879 cmd = ATA_SET_MAX_ADDRESS48;
1880 protocol |= AP_EXTEND;
1881 } else {
1882 cmd = ATA_SET_MAX_ADDRESS;
1883 }
1884
1885 /* lba's are zero indexed so the max lba is requested max - 1 */
1886 if (maxsize)
1887 maxsize--;
1888
1889 error = ata_do_cmd(device,
1890 ccb,
1891 retry_count,
1892 /*flags*/CAM_DIR_NONE,
1893 /*protocol*/protocol,
1894 /*ata_flags*/AP_FLAG_CHK_COND,
1895 /*tag_action*/MSG_SIMPLE_Q_TAG,
1896 /*command*/cmd,
1897 /*features*/ATA_HPA_FEAT_MAX_ADDR,
1898 /*lba*/maxsize,
1899 /*sector_count*/persist,
1900 /*data_ptr*/NULL,
1901 /*dxfer_len*/0,
1902 timeout ? timeout : 1000,
1903 is48bit);
1904
1905 if (error)
1906 return (error);
1907
1908 return atahpa_proc_resp(device, ccb, is48bit, NULL);
1909 }
1910
1911 static int
atahpa_password(struct cam_device * device,int retry_count,u_int32_t timeout,union ccb * ccb,int is48bit,struct ata_set_max_pwd * pwd)1912 atahpa_password(struct cam_device *device, int retry_count,
1913 u_int32_t timeout, union ccb *ccb,
1914 int is48bit, struct ata_set_max_pwd *pwd)
1915 {
1916 int error;
1917 u_int cmd;
1918 u_int8_t protocol;
1919
1920 protocol = AP_PROTO_PIO_OUT;
1921 cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1922
1923 error = ata_do_cmd(device,
1924 ccb,
1925 retry_count,
1926 /*flags*/CAM_DIR_OUT,
1927 /*protocol*/protocol,
1928 /*ata_flags*/AP_FLAG_CHK_COND,
1929 /*tag_action*/MSG_SIMPLE_Q_TAG,
1930 /*command*/cmd,
1931 /*features*/ATA_HPA_FEAT_SET_PWD,
1932 /*lba*/0,
1933 /*sector_count*/0,
1934 /*data_ptr*/(u_int8_t*)pwd,
1935 /*dxfer_len*/sizeof(struct ata_set_max_pwd),
1936 timeout ? timeout : 1000,
1937 is48bit);
1938
1939 if (error)
1940 return (error);
1941
1942 return atahpa_proc_resp(device, ccb, is48bit, NULL);
1943 }
1944
1945 static int
atahpa_lock(struct cam_device * device,int retry_count,u_int32_t timeout,union ccb * ccb,int is48bit)1946 atahpa_lock(struct cam_device *device, int retry_count,
1947 u_int32_t timeout, union ccb *ccb, int is48bit)
1948 {
1949 int error;
1950 u_int cmd;
1951 u_int8_t protocol;
1952
1953 protocol = AP_PROTO_NON_DATA;
1954 cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1955
1956 error = ata_do_cmd(device,
1957 ccb,
1958 retry_count,
1959 /*flags*/CAM_DIR_NONE,
1960 /*protocol*/protocol,
1961 /*ata_flags*/AP_FLAG_CHK_COND,
1962 /*tag_action*/MSG_SIMPLE_Q_TAG,
1963 /*command*/cmd,
1964 /*features*/ATA_HPA_FEAT_LOCK,
1965 /*lba*/0,
1966 /*sector_count*/0,
1967 /*data_ptr*/NULL,
1968 /*dxfer_len*/0,
1969 timeout ? timeout : 1000,
1970 is48bit);
1971
1972 if (error)
1973 return (error);
1974
1975 return atahpa_proc_resp(device, ccb, is48bit, NULL);
1976 }
1977
1978 static int
atahpa_unlock(struct cam_device * device,int retry_count,u_int32_t timeout,union ccb * ccb,int is48bit,struct ata_set_max_pwd * pwd)1979 atahpa_unlock(struct cam_device *device, int retry_count,
1980 u_int32_t timeout, union ccb *ccb,
1981 int is48bit, struct ata_set_max_pwd *pwd)
1982 {
1983 int error;
1984 u_int cmd;
1985 u_int8_t protocol;
1986
1987 protocol = AP_PROTO_PIO_OUT;
1988 cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1989
1990 error = ata_do_cmd(device,
1991 ccb,
1992 retry_count,
1993 /*flags*/CAM_DIR_OUT,
1994 /*protocol*/protocol,
1995 /*ata_flags*/AP_FLAG_CHK_COND,
1996 /*tag_action*/MSG_SIMPLE_Q_TAG,
1997 /*command*/cmd,
1998 /*features*/ATA_HPA_FEAT_UNLOCK,
1999 /*lba*/0,
2000 /*sector_count*/0,
2001 /*data_ptr*/(u_int8_t*)pwd,
2002 /*dxfer_len*/sizeof(struct ata_set_max_pwd),
2003 timeout ? timeout : 1000,
2004 is48bit);
2005
2006 if (error)
2007 return (error);
2008
2009 return atahpa_proc_resp(device, ccb, is48bit, NULL);
2010 }
2011
2012 static int
atahpa_freeze_lock(struct cam_device * device,int retry_count,u_int32_t timeout,union ccb * ccb,int is48bit)2013 atahpa_freeze_lock(struct cam_device *device, int retry_count,
2014 u_int32_t timeout, union ccb *ccb, int is48bit)
2015 {
2016 int error;
2017 u_int cmd;
2018 u_int8_t protocol;
2019
2020 protocol = AP_PROTO_NON_DATA;
2021 cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
2022
2023 error = ata_do_cmd(device,
2024 ccb,
2025 retry_count,
2026 /*flags*/CAM_DIR_NONE,
2027 /*protocol*/protocol,
2028 /*ata_flags*/AP_FLAG_CHK_COND,
2029 /*tag_action*/MSG_SIMPLE_Q_TAG,
2030 /*command*/cmd,
2031 /*features*/ATA_HPA_FEAT_FREEZE,
2032 /*lba*/0,
2033 /*sector_count*/0,
2034 /*data_ptr*/NULL,
2035 /*dxfer_len*/0,
2036 timeout ? timeout : 1000,
2037 is48bit);
2038
2039 if (error)
2040 return (error);
2041
2042 return atahpa_proc_resp(device, ccb, is48bit, NULL);
2043 }
2044
2045
2046 int
ata_do_identify(struct cam_device * device,int retry_count,int timeout,union ccb * ccb,struct ata_params ** ident_bufp)2047 ata_do_identify(struct cam_device *device, int retry_count, int timeout,
2048 union ccb *ccb, struct ata_params** ident_bufp)
2049 {
2050 struct ata_params *ident_buf;
2051 struct ccb_pathinq cpi;
2052 struct ccb_getdev cgd;
2053 u_int i, error;
2054 int16_t *ptr;
2055 u_int8_t command, retry_command;
2056
2057 if (get_cpi(device, &cpi) != 0) {
2058 warnx("couldn't get CPI");
2059 return (-1);
2060 }
2061
2062 /* Neither PROTO_ATAPI or PROTO_SATAPM are used in cpi.protocol */
2063 if (cpi.protocol == PROTO_ATA) {
2064 if (get_cgd(device, &cgd) != 0) {
2065 warnx("couldn't get CGD");
2066 return (-1);
2067 }
2068
2069 command = (cgd.protocol == PROTO_ATA) ?
2070 ATA_ATA_IDENTIFY : ATA_ATAPI_IDENTIFY;
2071 retry_command = 0;
2072 } else {
2073 /* We don't know which for sure so try both */
2074 command = ATA_ATA_IDENTIFY;
2075 retry_command = ATA_ATAPI_IDENTIFY;
2076 }
2077
2078 ptr = (uint16_t *)calloc(1, sizeof(struct ata_params));
2079 if (ptr == NULL) {
2080 warnx("can't calloc memory for identify\n");
2081 return (1);
2082 }
2083
2084 error = ata_do_28bit_cmd(device,
2085 ccb,
2086 /*retries*/retry_count,
2087 /*flags*/CAM_DIR_IN,
2088 /*protocol*/AP_PROTO_PIO_IN,
2089 /*tag_action*/MSG_SIMPLE_Q_TAG,
2090 /*command*/command,
2091 /*features*/0,
2092 /*lba*/0,
2093 /*sector_count*/(u_int8_t)sizeof(struct ata_params),
2094 /*data_ptr*/(u_int8_t *)ptr,
2095 /*dxfer_len*/sizeof(struct ata_params),
2096 /*timeout*/timeout ? timeout : 30 * 1000,
2097 /*quiet*/1);
2098
2099 if (error != 0) {
2100 if (retry_command == 0) {
2101 free(ptr);
2102 return (1);
2103 }
2104 error = ata_do_28bit_cmd(device,
2105 ccb,
2106 /*retries*/retry_count,
2107 /*flags*/CAM_DIR_IN,
2108 /*protocol*/AP_PROTO_PIO_IN,
2109 /*tag_action*/MSG_SIMPLE_Q_TAG,
2110 /*command*/retry_command,
2111 /*features*/0,
2112 /*lba*/0,
2113 /*sector_count*/(u_int8_t)
2114 sizeof(struct ata_params),
2115 /*data_ptr*/(u_int8_t *)ptr,
2116 /*dxfer_len*/sizeof(struct ata_params),
2117 /*timeout*/timeout ? timeout : 30 * 1000,
2118 /*quiet*/0);
2119
2120 if (error != 0) {
2121 free(ptr);
2122 return (1);
2123 }
2124 }
2125
2126 error = 1;
2127 for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
2128 ptr[i] = le16toh(ptr[i]);
2129 if (ptr[i] != 0)
2130 error = 0;
2131 }
2132
2133 if (arglist & CAM_ARG_VERBOSE) {
2134 fprintf(stdout, "%s%d: Raw identify data:\n",
2135 device->device_name, device->dev_unit_num);
2136 dump_data(ptr, sizeof(struct ata_params));
2137 }
2138
2139 /* check for invalid (all zero) response */
2140 if (error != 0) {
2141 warnx("Invalid identify response detected");
2142 free(ptr);
2143 return (error);
2144 }
2145
2146 ident_buf = (struct ata_params *)ptr;
2147 if (strncmp(ident_buf->model, "FX", 2) &&
2148 strncmp(ident_buf->model, "NEC", 3) &&
2149 strncmp(ident_buf->model, "Pioneer", 7) &&
2150 strncmp(ident_buf->model, "SHARP", 5)) {
2151 ata_bswap(ident_buf->model, sizeof(ident_buf->model));
2152 ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
2153 ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
2154 ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
2155 }
2156 ata_btrim(ident_buf->model, sizeof(ident_buf->model));
2157 ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
2158 ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
2159 ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
2160 ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
2161 ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
2162 ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
2163 ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
2164 sizeof(ident_buf->media_serial));
2165
2166 *ident_bufp = ident_buf;
2167
2168 return (0);
2169 }
2170
2171
2172 static int
ataidentify(struct cam_device * device,int retry_count,int timeout)2173 ataidentify(struct cam_device *device, int retry_count, int timeout)
2174 {
2175 union ccb *ccb;
2176 struct ata_params *ident_buf;
2177 u_int64_t hpasize;
2178
2179 if ((ccb = cam_getccb(device)) == NULL) {
2180 warnx("couldn't allocate CCB");
2181 return (1);
2182 }
2183
2184 if (ata_do_identify(device, retry_count, timeout, ccb, &ident_buf) != 0) {
2185 cam_freeccb(ccb);
2186 return (1);
2187 }
2188
2189 if (ident_buf->support.command1 & ATA_SUPPORT_PROTECTED) {
2190 if (ata_read_native_max(device, retry_count, timeout, ccb,
2191 ident_buf, &hpasize) != 0) {
2192 cam_freeccb(ccb);
2193 return (1);
2194 }
2195 } else {
2196 hpasize = 0;
2197 }
2198
2199 printf("%s%d: ", device->device_name, device->dev_unit_num);
2200 ata_print_ident(ident_buf);
2201 camxferrate(device);
2202 atacapprint(ident_buf);
2203 atahpa_print(ident_buf, hpasize, 0);
2204
2205 free(ident_buf);
2206 cam_freeccb(ccb);
2207
2208 return (0);
2209 }
2210 #endif /* MINIMALISTIC */
2211
2212
2213 #ifndef MINIMALISTIC
2214 enum {
2215 ATA_SECURITY_ACTION_PRINT,
2216 ATA_SECURITY_ACTION_FREEZE,
2217 ATA_SECURITY_ACTION_UNLOCK,
2218 ATA_SECURITY_ACTION_DISABLE,
2219 ATA_SECURITY_ACTION_ERASE,
2220 ATA_SECURITY_ACTION_ERASE_ENHANCED,
2221 ATA_SECURITY_ACTION_SET_PASSWORD
2222 };
2223
2224 static void
atasecurity_print_time(u_int16_t tw)2225 atasecurity_print_time(u_int16_t tw)
2226 {
2227
2228 if (tw == 0)
2229 printf("unspecified");
2230 else if (tw >= 255)
2231 printf("> 508 min");
2232 else
2233 printf("%i min", 2 * tw);
2234 }
2235
2236 static u_int32_t
atasecurity_erase_timeout_msecs(u_int16_t timeout)2237 atasecurity_erase_timeout_msecs(u_int16_t timeout)
2238 {
2239
2240 if (timeout == 0)
2241 return 2 * 3600 * 1000; /* default: two hours */
2242 else if (timeout > 255)
2243 return (508 + 60) * 60 * 1000; /* spec says > 508 minutes */
2244
2245 return ((2 * timeout) + 5) * 60 * 1000; /* add a 5min margin */
2246 }
2247
2248
2249 static void
atasecurity_notify(u_int8_t command,struct ata_security_password * pwd)2250 atasecurity_notify(u_int8_t command, struct ata_security_password *pwd)
2251 {
2252 struct ata_cmd cmd;
2253
2254 bzero(&cmd, sizeof(cmd));
2255 cmd.command = command;
2256 printf("Issuing %s", ata_op_string(&cmd));
2257
2258 if (pwd != NULL) {
2259 char pass[sizeof(pwd->password)+1];
2260
2261 /* pwd->password may not be null terminated */
2262 pass[sizeof(pwd->password)] = '\0';
2263 strncpy(pass, pwd->password, sizeof(pwd->password));
2264 printf(" password='%s', user='%s'",
2265 pass,
2266 (pwd->ctrl & ATA_SECURITY_PASSWORD_MASTER) ?
2267 "master" : "user");
2268
2269 if (command == ATA_SECURITY_SET_PASSWORD) {
2270 printf(", mode='%s'",
2271 (pwd->ctrl & ATA_SECURITY_LEVEL_MAXIMUM) ?
2272 "maximum" : "high");
2273 }
2274 }
2275
2276 printf("\n");
2277 }
2278
2279 static int
atasecurity_freeze(struct cam_device * device,union ccb * ccb,int retry_count,u_int32_t timeout,int quiet)2280 atasecurity_freeze(struct cam_device *device, union ccb *ccb,
2281 int retry_count, u_int32_t timeout, int quiet)
2282 {
2283
2284 if (quiet == 0)
2285 atasecurity_notify(ATA_SECURITY_FREEZE_LOCK, NULL);
2286
2287 return ata_do_28bit_cmd(device,
2288 ccb,
2289 retry_count,
2290 /*flags*/CAM_DIR_NONE,
2291 /*protocol*/AP_PROTO_NON_DATA,
2292 /*tag_action*/MSG_SIMPLE_Q_TAG,
2293 /*command*/ATA_SECURITY_FREEZE_LOCK,
2294 /*features*/0,
2295 /*lba*/0,
2296 /*sector_count*/0,
2297 /*data_ptr*/NULL,
2298 /*dxfer_len*/0,
2299 /*timeout*/timeout,
2300 /*quiet*/0);
2301 }
2302
2303 static int
atasecurity_unlock(struct cam_device * device,union ccb * ccb,int retry_count,u_int32_t timeout,struct ata_security_password * pwd,int quiet)2304 atasecurity_unlock(struct cam_device *device, union ccb *ccb,
2305 int retry_count, u_int32_t timeout,
2306 struct ata_security_password *pwd, int quiet)
2307 {
2308
2309 if (quiet == 0)
2310 atasecurity_notify(ATA_SECURITY_UNLOCK, pwd);
2311
2312 return ata_do_28bit_cmd(device,
2313 ccb,
2314 retry_count,
2315 /*flags*/CAM_DIR_OUT,
2316 /*protocol*/AP_PROTO_PIO_OUT,
2317 /*tag_action*/MSG_SIMPLE_Q_TAG,
2318 /*command*/ATA_SECURITY_UNLOCK,
2319 /*features*/0,
2320 /*lba*/0,
2321 /*sector_count*/0,
2322 /*data_ptr*/(u_int8_t *)pwd,
2323 /*dxfer_len*/sizeof(*pwd),
2324 /*timeout*/timeout,
2325 /*quiet*/0);
2326 }
2327
2328 static int
atasecurity_disable(struct cam_device * device,union ccb * ccb,int retry_count,u_int32_t timeout,struct ata_security_password * pwd,int quiet)2329 atasecurity_disable(struct cam_device *device, union ccb *ccb,
2330 int retry_count, u_int32_t timeout,
2331 struct ata_security_password *pwd, int quiet)
2332 {
2333
2334 if (quiet == 0)
2335 atasecurity_notify(ATA_SECURITY_DISABLE_PASSWORD, pwd);
2336 return ata_do_28bit_cmd(device,
2337 ccb,
2338 retry_count,
2339 /*flags*/CAM_DIR_OUT,
2340 /*protocol*/AP_PROTO_PIO_OUT,
2341 /*tag_action*/MSG_SIMPLE_Q_TAG,
2342 /*command*/ATA_SECURITY_DISABLE_PASSWORD,
2343 /*features*/0,
2344 /*lba*/0,
2345 /*sector_count*/0,
2346 /*data_ptr*/(u_int8_t *)pwd,
2347 /*dxfer_len*/sizeof(*pwd),
2348 /*timeout*/timeout,
2349 /*quiet*/0);
2350 }
2351
2352
2353 static int
atasecurity_erase_confirm(struct cam_device * device,struct ata_params * ident_buf)2354 atasecurity_erase_confirm(struct cam_device *device,
2355 struct ata_params* ident_buf)
2356 {
2357
2358 printf("\nYou are about to ERASE ALL DATA from the following"
2359 " device:\n%s%d,%s%d: ", device->device_name,
2360 device->dev_unit_num, device->given_dev_name,
2361 device->given_unit_number);
2362 ata_print_ident(ident_buf);
2363
2364 for(;;) {
2365 char str[50];
2366 printf("\nAre you SURE you want to ERASE ALL DATA? (yes/no) ");
2367
2368 if (fgets(str, sizeof(str), stdin) != NULL) {
2369 if (strncasecmp(str, "yes", 3) == 0) {
2370 return (1);
2371 } else if (strncasecmp(str, "no", 2) == 0) {
2372 return (0);
2373 } else {
2374 printf("Please answer \"yes\" or "
2375 "\"no\"\n");
2376 }
2377 }
2378 }
2379
2380 /* NOTREACHED */
2381 return (0);
2382 }
2383
2384 static int
atasecurity_erase(struct cam_device * device,union ccb * ccb,int retry_count,u_int32_t timeout,u_int32_t erase_timeout,struct ata_security_password * pwd,int quiet)2385 atasecurity_erase(struct cam_device *device, union ccb *ccb,
2386 int retry_count, u_int32_t timeout,
2387 u_int32_t erase_timeout,
2388 struct ata_security_password *pwd, int quiet)
2389 {
2390 int error;
2391
2392 if (quiet == 0)
2393 atasecurity_notify(ATA_SECURITY_ERASE_PREPARE, NULL);
2394
2395 error = ata_do_28bit_cmd(device,
2396 ccb,
2397 retry_count,
2398 /*flags*/CAM_DIR_NONE,
2399 /*protocol*/AP_PROTO_NON_DATA,
2400 /*tag_action*/MSG_SIMPLE_Q_TAG,
2401 /*command*/ATA_SECURITY_ERASE_PREPARE,
2402 /*features*/0,
2403 /*lba*/0,
2404 /*sector_count*/0,
2405 /*data_ptr*/NULL,
2406 /*dxfer_len*/0,
2407 /*timeout*/timeout,
2408 /*quiet*/0);
2409
2410 if (error != 0)
2411 return error;
2412
2413 if (quiet == 0)
2414 atasecurity_notify(ATA_SECURITY_ERASE_UNIT, pwd);
2415
2416 error = ata_do_28bit_cmd(device,
2417 ccb,
2418 retry_count,
2419 /*flags*/CAM_DIR_OUT,
2420 /*protocol*/AP_PROTO_PIO_OUT,
2421 /*tag_action*/MSG_SIMPLE_Q_TAG,
2422 /*command*/ATA_SECURITY_ERASE_UNIT,
2423 /*features*/0,
2424 /*lba*/0,
2425 /*sector_count*/0,
2426 /*data_ptr*/(u_int8_t *)pwd,
2427 /*dxfer_len*/sizeof(*pwd),
2428 /*timeout*/erase_timeout,
2429 /*quiet*/0);
2430
2431 if (error == 0 && quiet == 0)
2432 printf("\nErase Complete\n");
2433
2434 return error;
2435 }
2436
2437 static int
atasecurity_set_password(struct cam_device * device,union ccb * ccb,int retry_count,u_int32_t timeout,struct ata_security_password * pwd,int quiet)2438 atasecurity_set_password(struct cam_device *device, union ccb *ccb,
2439 int retry_count, u_int32_t timeout,
2440 struct ata_security_password *pwd, int quiet)
2441 {
2442
2443 if (quiet == 0)
2444 atasecurity_notify(ATA_SECURITY_SET_PASSWORD, pwd);
2445
2446 return ata_do_28bit_cmd(device,
2447 ccb,
2448 retry_count,
2449 /*flags*/CAM_DIR_OUT,
2450 /*protocol*/AP_PROTO_PIO_OUT,
2451 /*tag_action*/MSG_SIMPLE_Q_TAG,
2452 /*command*/ATA_SECURITY_SET_PASSWORD,
2453 /*features*/0,
2454 /*lba*/0,
2455 /*sector_count*/0,
2456 /*data_ptr*/(u_int8_t *)pwd,
2457 /*dxfer_len*/sizeof(*pwd),
2458 /*timeout*/timeout,
2459 /*quiet*/0);
2460 }
2461
2462 static void
atasecurity_print(struct ata_params * parm)2463 atasecurity_print(struct ata_params *parm)
2464 {
2465
2466 printf("\nSecurity Option Value\n");
2467 if (arglist & CAM_ARG_VERBOSE) {
2468 printf("status %04x\n",
2469 parm->security_status);
2470 }
2471 printf("supported %s\n",
2472 parm->security_status & ATA_SECURITY_SUPPORTED ? "yes" : "no");
2473 if (!(parm->security_status & ATA_SECURITY_SUPPORTED))
2474 return;
2475 printf("enabled %s\n",
2476 parm->security_status & ATA_SECURITY_ENABLED ? "yes" : "no");
2477 printf("drive locked %s\n",
2478 parm->security_status & ATA_SECURITY_LOCKED ? "yes" : "no");
2479 printf("security config frozen %s\n",
2480 parm->security_status & ATA_SECURITY_FROZEN ? "yes" : "no");
2481 printf("count expired %s\n",
2482 parm->security_status & ATA_SECURITY_COUNT_EXP ? "yes" : "no");
2483 printf("security level %s\n",
2484 parm->security_status & ATA_SECURITY_LEVEL ? "maximum" : "high");
2485 printf("enhanced erase supported %s\n",
2486 parm->security_status & ATA_SECURITY_ENH_SUPP ? "yes" : "no");
2487 printf("erase time ");
2488 atasecurity_print_time(parm->erase_time);
2489 printf("\n");
2490 printf("enhanced erase time ");
2491 atasecurity_print_time(parm->enhanced_erase_time);
2492 printf("\n");
2493 printf("master password rev %04x%s\n",
2494 parm->master_passwd_revision,
2495 parm->master_passwd_revision == 0x0000 ||
2496 parm->master_passwd_revision == 0xFFFF ? " (unsupported)" : "");
2497 }
2498
2499 /*
2500 * Validates and copies the password in optarg to the passed buffer.
2501 * If the password in optarg is the same length as the buffer then
2502 * the data will still be copied but no null termination will occur.
2503 */
2504 static int
ata_getpwd(u_int8_t * passwd,int max,char opt)2505 ata_getpwd(u_int8_t *passwd, int max, char opt)
2506 {
2507 int len;
2508
2509 len = strlen(optarg);
2510 if (len > max) {
2511 warnx("-%c password is too long", opt);
2512 return (1);
2513 } else if (len == 0) {
2514 warnx("-%c password is missing", opt);
2515 return (1);
2516 } else if (optarg[0] == '-'){
2517 warnx("-%c password starts with '-' (generic arg?)", opt);
2518 return (1);
2519 } else if (strlen(passwd) != 0 && strcmp(passwd, optarg) != 0) {
2520 warnx("-%c password conflicts with existing password from -%c",
2521 opt, pwd_opt);
2522 return (1);
2523 }
2524
2525 /* Callers pass in a buffer which does NOT need to be terminated */
2526 strncpy(passwd, optarg, max);
2527 pwd_opt = opt;
2528
2529 return (0);
2530 }
2531
2532 enum {
2533 ATA_HPA_ACTION_PRINT,
2534 ATA_HPA_ACTION_SET_MAX,
2535 ATA_HPA_ACTION_SET_PWD,
2536 ATA_HPA_ACTION_LOCK,
2537 ATA_HPA_ACTION_UNLOCK,
2538 ATA_HPA_ACTION_FREEZE_LOCK
2539 };
2540
2541 static int
atahpa_set_confirm(struct cam_device * device,struct ata_params * ident_buf,u_int64_t maxsize,int persist)2542 atahpa_set_confirm(struct cam_device *device, struct ata_params* ident_buf,
2543 u_int64_t maxsize, int persist)
2544 {
2545 printf("\nYou are about to configure HPA to limit the user accessible\n"
2546 "sectors to %ju %s on the device:\n%s%d,%s%d: ", maxsize,
2547 persist ? "persistently" : "temporarily",
2548 device->device_name, device->dev_unit_num,
2549 device->given_dev_name, device->given_unit_number);
2550 ata_print_ident(ident_buf);
2551
2552 for(;;) {
2553 char str[50];
2554 printf("\nAre you SURE you want to configure HPA? (yes/no) ");
2555
2556 if (NULL != fgets(str, sizeof(str), stdin)) {
2557 if (0 == strncasecmp(str, "yes", 3)) {
2558 return (1);
2559 } else if (0 == strncasecmp(str, "no", 2)) {
2560 return (0);
2561 } else {
2562 printf("Please answer \"yes\" or "
2563 "\"no\"\n");
2564 }
2565 }
2566 }
2567
2568 /* NOTREACHED */
2569 return (0);
2570 }
2571
2572 static int
atahpa(struct cam_device * device,int retry_count,int timeout,int argc,char ** argv,char * combinedopt)2573 atahpa(struct cam_device *device, int retry_count, int timeout,
2574 int argc, char **argv, char *combinedopt)
2575 {
2576 union ccb *ccb;
2577 struct ata_params *ident_buf;
2578 struct ccb_getdev cgd;
2579 struct ata_set_max_pwd pwd;
2580 int error, confirm, quiet, c, action, actions, persist;
2581 int security, is48bit, pwdsize;
2582 u_int64_t hpasize, maxsize;
2583
2584 actions = 0;
2585 confirm = 0;
2586 quiet = 0;
2587 maxsize = 0;
2588 persist = 0;
2589 security = 0;
2590
2591 memset(&pwd, 0, sizeof(pwd));
2592
2593 /* default action is to print hpa information */
2594 action = ATA_HPA_ACTION_PRINT;
2595 pwdsize = sizeof(pwd.password);
2596
2597 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2598 switch(c){
2599 case 's':
2600 action = ATA_HPA_ACTION_SET_MAX;
2601 maxsize = strtoumax(optarg, NULL, 0);
2602 actions++;
2603 break;
2604
2605 case 'p':
2606 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2607 return (1);
2608 action = ATA_HPA_ACTION_SET_PWD;
2609 security = 1;
2610 actions++;
2611 break;
2612
2613 case 'l':
2614 action = ATA_HPA_ACTION_LOCK;
2615 security = 1;
2616 actions++;
2617 break;
2618
2619 case 'U':
2620 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2621 return (1);
2622 action = ATA_HPA_ACTION_UNLOCK;
2623 security = 1;
2624 actions++;
2625 break;
2626
2627 case 'f':
2628 action = ATA_HPA_ACTION_FREEZE_LOCK;
2629 security = 1;
2630 actions++;
2631 break;
2632
2633 case 'P':
2634 persist = 1;
2635 break;
2636
2637 case 'y':
2638 confirm++;
2639 break;
2640
2641 case 'q':
2642 quiet++;
2643 break;
2644 }
2645 }
2646
2647 if (actions > 1) {
2648 warnx("too many hpa actions specified");
2649 return (1);
2650 }
2651
2652 if (get_cgd(device, &cgd) != 0) {
2653 warnx("couldn't get CGD");
2654 return (1);
2655 }
2656
2657 ccb = cam_getccb(device);
2658 if (ccb == NULL) {
2659 warnx("couldn't allocate CCB");
2660 return (1);
2661 }
2662
2663 error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf);
2664 if (error != 0) {
2665 cam_freeccb(ccb);
2666 return (1);
2667 }
2668
2669 if (quiet == 0) {
2670 printf("%s%d: ", device->device_name, device->dev_unit_num);
2671 ata_print_ident(ident_buf);
2672 camxferrate(device);
2673 }
2674
2675 if (action == ATA_HPA_ACTION_PRINT) {
2676 error = ata_read_native_max(device, retry_count, timeout, ccb,
2677 ident_buf, &hpasize);
2678 if (error == 0)
2679 atahpa_print(ident_buf, hpasize, 1);
2680
2681 cam_freeccb(ccb);
2682 free(ident_buf);
2683 return (error);
2684 }
2685
2686 if (!(ident_buf->support.command1 & ATA_SUPPORT_PROTECTED)) {
2687 warnx("HPA is not supported by this device");
2688 cam_freeccb(ccb);
2689 free(ident_buf);
2690 return (1);
2691 }
2692
2693 if (security && !(ident_buf->support.command1 & ATA_SUPPORT_MAXSECURITY)) {
2694 warnx("HPA Security is not supported by this device");
2695 cam_freeccb(ccb);
2696 free(ident_buf);
2697 return (1);
2698 }
2699
2700 is48bit = ident_buf->support.command2 & ATA_SUPPORT_ADDRESS48;
2701
2702 /*
2703 * The ATA spec requires:
2704 * 1. Read native max addr is called directly before set max addr
2705 * 2. Read native max addr is NOT called before any other set max call
2706 */
2707 switch(action) {
2708 case ATA_HPA_ACTION_SET_MAX:
2709 if (confirm == 0 &&
2710 atahpa_set_confirm(device, ident_buf, maxsize,
2711 persist) == 0) {
2712 cam_freeccb(ccb);
2713 free(ident_buf);
2714 return (1);
2715 }
2716
2717 error = ata_read_native_max(device, retry_count, timeout,
2718 ccb, ident_buf, &hpasize);
2719 if (error == 0) {
2720 error = atahpa_set_max(device, retry_count, timeout,
2721 ccb, is48bit, maxsize, persist);
2722 if (error == 0) {
2723 /* redo identify to get new lba values */
2724 error = ata_do_identify(device, retry_count,
2725 timeout, ccb,
2726 &ident_buf);
2727 atahpa_print(ident_buf, hpasize, 1);
2728 }
2729 }
2730 break;
2731
2732 case ATA_HPA_ACTION_SET_PWD:
2733 error = atahpa_password(device, retry_count, timeout,
2734 ccb, is48bit, &pwd);
2735 if (error == 0)
2736 printf("HPA password has been set\n");
2737 break;
2738
2739 case ATA_HPA_ACTION_LOCK:
2740 error = atahpa_lock(device, retry_count, timeout,
2741 ccb, is48bit);
2742 if (error == 0)
2743 printf("HPA has been locked\n");
2744 break;
2745
2746 case ATA_HPA_ACTION_UNLOCK:
2747 error = atahpa_unlock(device, retry_count, timeout,
2748 ccb, is48bit, &pwd);
2749 if (error == 0)
2750 printf("HPA has been unlocked\n");
2751 break;
2752
2753 case ATA_HPA_ACTION_FREEZE_LOCK:
2754 error = atahpa_freeze_lock(device, retry_count, timeout,
2755 ccb, is48bit);
2756 if (error == 0)
2757 printf("HPA has been frozen\n");
2758 break;
2759
2760 default:
2761 errx(1, "Option currently not supported");
2762 }
2763
2764 cam_freeccb(ccb);
2765 free(ident_buf);
2766
2767 return (error);
2768 }
2769
2770 static int
atasecurity(struct cam_device * device,int retry_count,int timeout,int argc,char ** argv,char * combinedopt)2771 atasecurity(struct cam_device *device, int retry_count, int timeout,
2772 int argc, char **argv, char *combinedopt)
2773 {
2774 union ccb *ccb;
2775 struct ata_params *ident_buf;
2776 int error, confirm, quiet, c, action, actions, setpwd;
2777 int security_enabled, erase_timeout, pwdsize;
2778 struct ata_security_password pwd;
2779
2780 actions = 0;
2781 setpwd = 0;
2782 erase_timeout = 0;
2783 confirm = 0;
2784 quiet = 0;
2785
2786 memset(&pwd, 0, sizeof(pwd));
2787
2788 /* default action is to print security information */
2789 action = ATA_SECURITY_ACTION_PRINT;
2790
2791 /* user is master by default as its safer that way */
2792 pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER;
2793 pwdsize = sizeof(pwd.password);
2794
2795 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2796 switch(c){
2797 case 'f':
2798 action = ATA_SECURITY_ACTION_FREEZE;
2799 actions++;
2800 break;
2801
2802 case 'U':
2803 if (strcasecmp(optarg, "user") == 0) {
2804 pwd.ctrl |= ATA_SECURITY_PASSWORD_USER;
2805 pwd.ctrl &= ~ATA_SECURITY_PASSWORD_MASTER;
2806 } else if (strcasecmp(optarg, "master") == 0) {
2807 pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER;
2808 pwd.ctrl &= ~ATA_SECURITY_PASSWORD_USER;
2809 } else {
2810 warnx("-U argument '%s' is invalid (must be "
2811 "'user' or 'master')", optarg);
2812 return (1);
2813 }
2814 break;
2815
2816 case 'l':
2817 if (strcasecmp(optarg, "high") == 0) {
2818 pwd.ctrl |= ATA_SECURITY_LEVEL_HIGH;
2819 pwd.ctrl &= ~ATA_SECURITY_LEVEL_MAXIMUM;
2820 } else if (strcasecmp(optarg, "maximum") == 0) {
2821 pwd.ctrl |= ATA_SECURITY_LEVEL_MAXIMUM;
2822 pwd.ctrl &= ~ATA_SECURITY_LEVEL_HIGH;
2823 } else {
2824 warnx("-l argument '%s' is unknown (must be "
2825 "'high' or 'maximum')", optarg);
2826 return (1);
2827 }
2828 break;
2829
2830 case 'k':
2831 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2832 return (1);
2833 action = ATA_SECURITY_ACTION_UNLOCK;
2834 actions++;
2835 break;
2836
2837 case 'd':
2838 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2839 return (1);
2840 action = ATA_SECURITY_ACTION_DISABLE;
2841 actions++;
2842 break;
2843
2844 case 'e':
2845 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2846 return (1);
2847 action = ATA_SECURITY_ACTION_ERASE;
2848 actions++;
2849 break;
2850
2851 case 'h':
2852 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2853 return (1);
2854 pwd.ctrl |= ATA_SECURITY_ERASE_ENHANCED;
2855 action = ATA_SECURITY_ACTION_ERASE_ENHANCED;
2856 actions++;
2857 break;
2858
2859 case 's':
2860 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2861 return (1);
2862 setpwd = 1;
2863 if (action == ATA_SECURITY_ACTION_PRINT)
2864 action = ATA_SECURITY_ACTION_SET_PASSWORD;
2865 /*
2866 * Don't increment action as this can be combined
2867 * with other actions.
2868 */
2869 break;
2870
2871 case 'y':
2872 confirm++;
2873 break;
2874
2875 case 'q':
2876 quiet++;
2877 break;
2878
2879 case 'T':
2880 erase_timeout = atoi(optarg) * 1000;
2881 break;
2882 }
2883 }
2884
2885 if (actions > 1) {
2886 warnx("too many security actions specified");
2887 return (1);
2888 }
2889
2890 if ((ccb = cam_getccb(device)) == NULL) {
2891 warnx("couldn't allocate CCB");
2892 return (1);
2893 }
2894
2895 error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf);
2896 if (error != 0) {
2897 cam_freeccb(ccb);
2898 return (1);
2899 }
2900
2901 if (quiet == 0) {
2902 printf("%s%d: ", device->device_name, device->dev_unit_num);
2903 ata_print_ident(ident_buf);
2904 camxferrate(device);
2905 }
2906
2907 if (action == ATA_SECURITY_ACTION_PRINT) {
2908 atasecurity_print(ident_buf);
2909 free(ident_buf);
2910 cam_freeccb(ccb);
2911 return (0);
2912 }
2913
2914 if ((ident_buf->support.command1 & ATA_SUPPORT_SECURITY) == 0) {
2915 warnx("Security not supported");
2916 free(ident_buf);
2917 cam_freeccb(ccb);
2918 return (1);
2919 }
2920
2921 /* default timeout 15 seconds the same as linux hdparm */
2922 timeout = timeout ? timeout : 15 * 1000;
2923
2924 security_enabled = ident_buf->security_status & ATA_SECURITY_ENABLED;
2925
2926 /* first set the password if requested */
2927 if (setpwd == 1) {
2928 /* confirm we can erase before setting the password if erasing */
2929 if (confirm == 0 &&
2930 (action == ATA_SECURITY_ACTION_ERASE_ENHANCED ||
2931 action == ATA_SECURITY_ACTION_ERASE) &&
2932 atasecurity_erase_confirm(device, ident_buf) == 0) {
2933 cam_freeccb(ccb);
2934 free(ident_buf);
2935 return (error);
2936 }
2937
2938 if (pwd.ctrl & ATA_SECURITY_PASSWORD_MASTER) {
2939 pwd.revision = ident_buf->master_passwd_revision;
2940 if (pwd.revision != 0 && pwd.revision != 0xfff &&
2941 --pwd.revision == 0) {
2942 pwd.revision = 0xfffe;
2943 }
2944 }
2945 error = atasecurity_set_password(device, ccb, retry_count,
2946 timeout, &pwd, quiet);
2947 if (error != 0) {
2948 cam_freeccb(ccb);
2949 free(ident_buf);
2950 return (error);
2951 }
2952 security_enabled = 1;
2953 }
2954
2955 switch(action) {
2956 case ATA_SECURITY_ACTION_FREEZE:
2957 error = atasecurity_freeze(device, ccb, retry_count,
2958 timeout, quiet);
2959 break;
2960
2961 case ATA_SECURITY_ACTION_UNLOCK:
2962 if (security_enabled) {
2963 if (ident_buf->security_status & ATA_SECURITY_LOCKED) {
2964 error = atasecurity_unlock(device, ccb,
2965 retry_count, timeout, &pwd, quiet);
2966 } else {
2967 warnx("Can't unlock, drive is not locked");
2968 error = 1;
2969 }
2970 } else {
2971 warnx("Can't unlock, security is disabled");
2972 error = 1;
2973 }
2974 break;
2975
2976 case ATA_SECURITY_ACTION_DISABLE:
2977 if (security_enabled) {
2978 /* First unlock the drive if its locked */
2979 if (ident_buf->security_status & ATA_SECURITY_LOCKED) {
2980 error = atasecurity_unlock(device, ccb,
2981 retry_count,
2982 timeout,
2983 &pwd,
2984 quiet);
2985 }
2986
2987 if (error == 0) {
2988 error = atasecurity_disable(device,
2989 ccb,
2990 retry_count,
2991 timeout,
2992 &pwd,
2993 quiet);
2994 }
2995 } else {
2996 warnx("Can't disable security (already disabled)");
2997 error = 1;
2998 }
2999 break;
3000
3001 case ATA_SECURITY_ACTION_ERASE:
3002 if (security_enabled) {
3003 if (erase_timeout == 0) {
3004 erase_timeout = atasecurity_erase_timeout_msecs(
3005 ident_buf->erase_time);
3006 }
3007
3008 error = atasecurity_erase(device, ccb, retry_count,
3009 timeout, erase_timeout, &pwd,
3010 quiet);
3011 } else {
3012 warnx("Can't secure erase (security is disabled)");
3013 error = 1;
3014 }
3015 break;
3016
3017 case ATA_SECURITY_ACTION_ERASE_ENHANCED:
3018 if (security_enabled) {
3019 if (ident_buf->security_status & ATA_SECURITY_ENH_SUPP) {
3020 if (erase_timeout == 0) {
3021 erase_timeout =
3022 atasecurity_erase_timeout_msecs(
3023 ident_buf->enhanced_erase_time);
3024 }
3025
3026 error = atasecurity_erase(device, ccb,
3027 retry_count, timeout,
3028 erase_timeout, &pwd,
3029 quiet);
3030 } else {
3031 warnx("Enhanced erase is not supported");
3032 error = 1;
3033 }
3034 } else {
3035 warnx("Can't secure erase (enhanced), "
3036 "(security is disabled)");
3037 error = 1;
3038 }
3039 break;
3040 }
3041
3042 cam_freeccb(ccb);
3043 free(ident_buf);
3044
3045 return (error);
3046 }
3047 #endif /* MINIMALISTIC */
3048
3049 /*
3050 * Parse out a bus, or a bus, target and lun in the following
3051 * format:
3052 * bus
3053 * bus:target
3054 * bus:target:lun
3055 *
3056 * Returns the number of parsed components, or 0.
3057 */
3058 static int
parse_btl(char * tstr,path_id_t * bus,target_id_t * target,lun_id_t * lun,cam_argmask * arglst)3059 parse_btl(char *tstr, path_id_t *bus, target_id_t *target, lun_id_t *lun,
3060 cam_argmask *arglst)
3061 {
3062 char *tmpstr;
3063 int convs = 0;
3064
3065 while (isspace(*tstr) && (*tstr != '\0'))
3066 tstr++;
3067
3068 tmpstr = (char *)strtok(tstr, ":");
3069 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3070 *bus = strtol(tmpstr, NULL, 0);
3071 *arglst |= CAM_ARG_BUS;
3072 convs++;
3073 tmpstr = (char *)strtok(NULL, ":");
3074 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3075 *target = strtol(tmpstr, NULL, 0);
3076 *arglst |= CAM_ARG_TARGET;
3077 convs++;
3078 tmpstr = (char *)strtok(NULL, ":");
3079 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3080 *lun = strtol(tmpstr, NULL, 0);
3081 *arglst |= CAM_ARG_LUN;
3082 convs++;
3083 }
3084 }
3085 }
3086
3087 return convs;
3088 }
3089
3090 static int
dorescan_or_reset(int argc,char ** argv,int rescan)3091 dorescan_or_reset(int argc, char **argv, int rescan)
3092 {
3093 static const char must[] =
3094 "you must specify \"all\", a bus, or a bus:target:lun to %s";
3095 int rv, error = 0;
3096 path_id_t bus = CAM_BUS_WILDCARD;
3097 target_id_t target = CAM_TARGET_WILDCARD;
3098 lun_id_t lun = CAM_LUN_WILDCARD;
3099 char *tstr;
3100
3101 if (argc < 3) {
3102 warnx(must, rescan? "rescan" : "reset");
3103 return(1);
3104 }
3105
3106 tstr = argv[optind];
3107 while (isspace(*tstr) && (*tstr != '\0'))
3108 tstr++;
3109 if (strncasecmp(tstr, "all", strlen("all")) == 0)
3110 arglist |= CAM_ARG_BUS;
3111 else {
3112 rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
3113 if (rv != 1 && rv != 3) {
3114 warnx(must, rescan? "rescan" : "reset");
3115 return(1);
3116 }
3117 }
3118
3119 if ((arglist & CAM_ARG_BUS)
3120 && (arglist & CAM_ARG_TARGET)
3121 && (arglist & CAM_ARG_LUN))
3122 error = scanlun_or_reset_dev(bus, target, lun, rescan);
3123 else
3124 error = rescan_or_reset_bus(bus, rescan);
3125
3126 return(error);
3127 }
3128
3129 static int
rescan_or_reset_bus(path_id_t bus,int rescan)3130 rescan_or_reset_bus(path_id_t bus, int rescan)
3131 {
3132 union ccb ccb, matchccb;
3133 int fd, retval;
3134 int bufsize;
3135
3136 retval = 0;
3137
3138 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3139 warnx("error opening transport layer device %s", XPT_DEVICE);
3140 warn("%s", XPT_DEVICE);
3141 return(1);
3142 }
3143
3144 if (bus != CAM_BUS_WILDCARD) {
3145 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
3146 ccb.ccb_h.path_id = bus;
3147 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
3148 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
3149 ccb.crcn.flags = CAM_FLAG_NONE;
3150
3151 /* run this at a low priority */
3152 ccb.ccb_h.pinfo.priority = 5;
3153
3154 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
3155 warn("CAMIOCOMMAND ioctl failed");
3156 close(fd);
3157 return(1);
3158 }
3159
3160 if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
3161 fprintf(stdout, "%s of bus %d was successful\n",
3162 rescan ? "Re-scan" : "Reset", bus);
3163 } else {
3164 fprintf(stdout, "%s of bus %d returned error %#x\n",
3165 rescan ? "Re-scan" : "Reset", bus,
3166 ccb.ccb_h.status & CAM_STATUS_MASK);
3167 retval = 1;
3168 }
3169
3170 close(fd);
3171 return(retval);
3172
3173 }
3174
3175
3176 /*
3177 * The right way to handle this is to modify the xpt so that it can
3178 * handle a wildcarded bus in a rescan or reset CCB. At the moment
3179 * that isn't implemented, so instead we enumerate the busses and
3180 * send the rescan or reset to those busses in the case where the
3181 * given bus is -1 (wildcard). We don't send a rescan or reset
3182 * to the xpt bus; sending a rescan to the xpt bus is effectively a
3183 * no-op, sending a rescan to the xpt bus would result in a status of
3184 * CAM_REQ_INVALID.
3185 */
3186 bzero(&(&matchccb.ccb_h)[1],
3187 sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
3188 matchccb.ccb_h.func_code = XPT_DEV_MATCH;
3189 matchccb.ccb_h.path_id = CAM_BUS_WILDCARD;
3190 bufsize = sizeof(struct dev_match_result) * 20;
3191 matchccb.cdm.match_buf_len = bufsize;
3192 matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
3193 if (matchccb.cdm.matches == NULL) {
3194 warnx("can't malloc memory for matches");
3195 retval = 1;
3196 goto bailout;
3197 }
3198 matchccb.cdm.num_matches = 0;
3199
3200 matchccb.cdm.num_patterns = 1;
3201 matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
3202
3203 matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
3204 matchccb.cdm.pattern_buf_len);
3205 if (matchccb.cdm.patterns == NULL) {
3206 warnx("can't malloc memory for patterns");
3207 retval = 1;
3208 goto bailout;
3209 }
3210 matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
3211 matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
3212
3213 do {
3214 unsigned int i;
3215
3216 if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
3217 warn("CAMIOCOMMAND ioctl failed");
3218 retval = 1;
3219 goto bailout;
3220 }
3221
3222 if ((matchccb.ccb_h.status != CAM_REQ_CMP)
3223 || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
3224 && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
3225 warnx("got CAM error %#x, CDM error %d\n",
3226 matchccb.ccb_h.status, matchccb.cdm.status);
3227 retval = 1;
3228 goto bailout;
3229 }
3230
3231 for (i = 0; i < matchccb.cdm.num_matches; i++) {
3232 struct bus_match_result *bus_result;
3233
3234 /* This shouldn't happen. */
3235 if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
3236 continue;
3237
3238 bus_result = &matchccb.cdm.matches[i].result.bus_result;
3239
3240 /*
3241 * We don't want to rescan or reset the xpt bus.
3242 * See above.
3243 */
3244 if (bus_result->path_id == CAM_XPT_PATH_ID)
3245 continue;
3246
3247 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
3248 XPT_RESET_BUS;
3249 ccb.ccb_h.path_id = bus_result->path_id;
3250 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
3251 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
3252 ccb.crcn.flags = CAM_FLAG_NONE;
3253
3254 /* run this at a low priority */
3255 ccb.ccb_h.pinfo.priority = 5;
3256
3257 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
3258 warn("CAMIOCOMMAND ioctl failed");
3259 retval = 1;
3260 goto bailout;
3261 }
3262
3263 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
3264 fprintf(stdout, "%s of bus %d was successful\n",
3265 rescan? "Re-scan" : "Reset",
3266 bus_result->path_id);
3267 } else {
3268 /*
3269 * Don't bail out just yet, maybe the other
3270 * rescan or reset commands will complete
3271 * successfully.
3272 */
3273 fprintf(stderr, "%s of bus %d returned error "
3274 "%#x\n", rescan? "Re-scan" : "Reset",
3275 bus_result->path_id,
3276 ccb.ccb_h.status & CAM_STATUS_MASK);
3277 retval = 1;
3278 }
3279 }
3280 } while ((matchccb.ccb_h.status == CAM_REQ_CMP)
3281 && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
3282
3283 bailout:
3284
3285 if (fd != -1)
3286 close(fd);
3287
3288 if (matchccb.cdm.patterns != NULL)
3289 free(matchccb.cdm.patterns);
3290 if (matchccb.cdm.matches != NULL)
3291 free(matchccb.cdm.matches);
3292
3293 return(retval);
3294 }
3295
3296 static int
scanlun_or_reset_dev(path_id_t bus,target_id_t target,lun_id_t lun,int scan)3297 scanlun_or_reset_dev(path_id_t bus, target_id_t target, lun_id_t lun, int scan)
3298 {
3299 union ccb ccb;
3300 struct cam_device *device;
3301 int fd;
3302
3303 device = NULL;
3304
3305 if (bus == CAM_BUS_WILDCARD) {
3306 warnx("invalid bus number %d", bus);
3307 return(1);
3308 }
3309
3310 if (target == CAM_TARGET_WILDCARD) {
3311 warnx("invalid target number %d", target);
3312 return(1);
3313 }
3314
3315 if (lun == CAM_LUN_WILDCARD) {
3316 warnx("invalid lun number %jx", (uintmax_t)lun);
3317 return(1);
3318 }
3319
3320 fd = -1;
3321
3322 bzero(&ccb, sizeof(union ccb));
3323
3324 if (scan) {
3325 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3326 warnx("error opening transport layer device %s\n",
3327 XPT_DEVICE);
3328 warn("%s", XPT_DEVICE);
3329 return(1);
3330 }
3331 } else {
3332 device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
3333 if (device == NULL) {
3334 warnx("%s", cam_errbuf);
3335 return(1);
3336 }
3337 }
3338
3339 ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
3340 ccb.ccb_h.path_id = bus;
3341 ccb.ccb_h.target_id = target;
3342 ccb.ccb_h.target_lun = lun;
3343 ccb.ccb_h.timeout = 5000;
3344 ccb.crcn.flags = CAM_FLAG_NONE;
3345
3346 /* run this at a low priority */
3347 ccb.ccb_h.pinfo.priority = 5;
3348
3349 if (scan) {
3350 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
3351 warn("CAMIOCOMMAND ioctl failed");
3352 close(fd);
3353 return(1);
3354 }
3355 } else {
3356 if (cam_send_ccb(device, &ccb) < 0) {
3357 warn("error sending XPT_RESET_DEV CCB");
3358 cam_close_device(device);
3359 return(1);
3360 }
3361 }
3362
3363 if (scan)
3364 close(fd);
3365 else
3366 cam_close_device(device);
3367
3368 /*
3369 * An error code of CAM_BDR_SENT is normal for a BDR request.
3370 */
3371 if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
3372 || ((!scan)
3373 && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
3374 fprintf(stdout, "%s of %d:%d:%jx was successful\n",
3375 scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun);
3376 return(0);
3377 } else {
3378 fprintf(stdout, "%s of %d:%d:%jx returned error %#x\n",
3379 scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun,
3380 ccb.ccb_h.status & CAM_STATUS_MASK);
3381 return(1);
3382 }
3383 }
3384
3385 #ifndef MINIMALISTIC
3386
3387 static struct scsi_nv defect_list_type_map[] = {
3388 { "block", SRDD10_BLOCK_FORMAT },
3389 { "extbfi", SRDD10_EXT_BFI_FORMAT },
3390 { "extphys", SRDD10_EXT_PHYS_FORMAT },
3391 { "longblock", SRDD10_LONG_BLOCK_FORMAT },
3392 { "bfi", SRDD10_BYTES_FROM_INDEX_FORMAT },
3393 { "phys", SRDD10_PHYSICAL_SECTOR_FORMAT }
3394 };
3395
3396 static int
readdefects(struct cam_device * device,int argc,char ** argv,char * combinedopt,int retry_count,int timeout)3397 readdefects(struct cam_device *device, int argc, char **argv,
3398 char *combinedopt, int retry_count, int timeout)
3399 {
3400 union ccb *ccb = NULL;
3401 struct scsi_read_defect_data_hdr_10 *hdr10 = NULL;
3402 struct scsi_read_defect_data_hdr_12 *hdr12 = NULL;
3403 size_t hdr_size = 0, entry_size = 0;
3404 int use_12byte = 0;
3405 int hex_format = 0;
3406 u_int8_t *defect_list = NULL;
3407 u_int8_t list_format = 0;
3408 int list_type_set = 0;
3409 u_int32_t dlist_length = 0;
3410 u_int32_t returned_length = 0, valid_len = 0;
3411 u_int32_t num_returned = 0, num_valid = 0;
3412 u_int32_t max_possible_size = 0, hdr_max = 0;
3413 u_int32_t starting_offset = 0;
3414 u_int8_t returned_format, returned_type;
3415 unsigned int i;
3416 int summary = 0, quiet = 0;
3417 int c, error = 0;
3418 int lists_specified = 0;
3419 int get_length = 1, first_pass = 1;
3420 int mads = 0;
3421
3422 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3423 switch(c){
3424 case 'f':
3425 {
3426 scsi_nv_status status;
3427 int entry_num = 0;
3428
3429 status = scsi_get_nv(defect_list_type_map,
3430 sizeof(defect_list_type_map) /
3431 sizeof(defect_list_type_map[0]), optarg,
3432 &entry_num, SCSI_NV_FLAG_IG_CASE);
3433
3434 if (status == SCSI_NV_FOUND) {
3435 list_format = defect_list_type_map[
3436 entry_num].value;
3437 list_type_set = 1;
3438 } else {
3439 warnx("%s: %s %s option %s", __func__,
3440 (status == SCSI_NV_AMBIGUOUS) ?
3441 "ambiguous" : "invalid", "defect list type",
3442 optarg);
3443 error = 1;
3444 goto defect_bailout;
3445 }
3446 break;
3447 }
3448 case 'G':
3449 arglist |= CAM_ARG_GLIST;
3450 break;
3451 case 'P':
3452 arglist |= CAM_ARG_PLIST;
3453 break;
3454 case 'q':
3455 quiet = 1;
3456 break;
3457 case 's':
3458 summary = 1;
3459 break;
3460 case 'S': {
3461 char *endptr;
3462
3463 starting_offset = strtoul(optarg, &endptr, 0);
3464 if (*endptr != '\0') {
3465 error = 1;
3466 warnx("invalid starting offset %s", optarg);
3467 goto defect_bailout;
3468 }
3469 break;
3470 }
3471 case 'X':
3472 hex_format = 1;
3473 break;
3474 default:
3475 break;
3476 }
3477 }
3478
3479 if (list_type_set == 0) {
3480 error = 1;
3481 warnx("no defect list format specified");
3482 goto defect_bailout;
3483 }
3484
3485 if (arglist & CAM_ARG_PLIST) {
3486 list_format |= SRDD10_PLIST;
3487 lists_specified++;
3488 }
3489
3490 if (arglist & CAM_ARG_GLIST) {
3491 list_format |= SRDD10_GLIST;
3492 lists_specified++;
3493 }
3494
3495 /*
3496 * This implies a summary, and was the previous behavior.
3497 */
3498 if (lists_specified == 0)
3499 summary = 1;
3500
3501 ccb = cam_getccb(device);
3502
3503 retry_12byte:
3504
3505 /*
3506 * We start off asking for just the header to determine how much
3507 * defect data is available. Some Hitachi drives return an error
3508 * if you ask for more data than the drive has. Once we know the
3509 * length, we retry the command with the returned length.
3510 */
3511 if (use_12byte == 0)
3512 dlist_length = sizeof(*hdr10);
3513 else
3514 dlist_length = sizeof(*hdr12);
3515
3516 retry:
3517 if (defect_list != NULL) {
3518 free(defect_list);
3519 defect_list = NULL;
3520 }
3521 defect_list = malloc(dlist_length);
3522 if (defect_list == NULL) {
3523 warnx("can't malloc memory for defect list");
3524 error = 1;
3525 goto defect_bailout;
3526 }
3527
3528 next_batch:
3529 bzero(defect_list, dlist_length);
3530
3531 /*
3532 * cam_getccb() zeros the CCB header only. So we need to zero the
3533 * payload portion of the ccb.
3534 */
3535 bzero(&(&ccb->ccb_h)[1],
3536 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3537
3538 scsi_read_defects(&ccb->csio,
3539 /*retries*/ retry_count,
3540 /*cbfcnp*/ NULL,
3541 /*tag_action*/ MSG_SIMPLE_Q_TAG,
3542 /*list_format*/ list_format,
3543 /*addr_desc_index*/ starting_offset,
3544 /*data_ptr*/ defect_list,
3545 /*dxfer_len*/ dlist_length,
3546 /*minimum_cmd_size*/ use_12byte ? 12 : 0,
3547 /*sense_len*/ SSD_FULL_SIZE,
3548 /*timeout*/ timeout ? timeout : 5000);
3549
3550 /* Disable freezing the device queue */
3551 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3552
3553 if (cam_send_ccb(device, ccb) < 0) {
3554 perror("error reading defect list");
3555
3556 if (arglist & CAM_ARG_VERBOSE) {
3557 cam_error_print(device, ccb, CAM_ESF_ALL,
3558 CAM_EPF_ALL, stderr);
3559 }
3560
3561 error = 1;
3562 goto defect_bailout;
3563 }
3564
3565 valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
3566
3567 if (use_12byte == 0) {
3568 hdr10 = (struct scsi_read_defect_data_hdr_10 *)defect_list;
3569 hdr_size = sizeof(*hdr10);
3570 hdr_max = SRDDH10_MAX_LENGTH;
3571
3572 if (valid_len >= hdr_size) {
3573 returned_length = scsi_2btoul(hdr10->length);
3574 returned_format = hdr10->format;
3575 } else {
3576 returned_length = 0;
3577 returned_format = 0;
3578 }
3579 } else {
3580 hdr12 = (struct scsi_read_defect_data_hdr_12 *)defect_list;
3581 hdr_size = sizeof(*hdr12);
3582 hdr_max = SRDDH12_MAX_LENGTH;
3583
3584 if (valid_len >= hdr_size) {
3585 returned_length = scsi_4btoul(hdr12->length);
3586 returned_format = hdr12->format;
3587 } else {
3588 returned_length = 0;
3589 returned_format = 0;
3590 }
3591 }
3592
3593 returned_type = returned_format & SRDDH10_DLIST_FORMAT_MASK;
3594 switch (returned_type) {
3595 case SRDD10_BLOCK_FORMAT:
3596 entry_size = sizeof(struct scsi_defect_desc_block);
3597 break;
3598 case SRDD10_LONG_BLOCK_FORMAT:
3599 entry_size = sizeof(struct scsi_defect_desc_long_block);
3600 break;
3601 case SRDD10_EXT_PHYS_FORMAT:
3602 case SRDD10_PHYSICAL_SECTOR_FORMAT:
3603 entry_size = sizeof(struct scsi_defect_desc_phys_sector);
3604 break;
3605 case SRDD10_EXT_BFI_FORMAT:
3606 case SRDD10_BYTES_FROM_INDEX_FORMAT:
3607 entry_size = sizeof(struct scsi_defect_desc_bytes_from_index);
3608 break;
3609 default:
3610 warnx("Unknown defect format 0x%x\n", returned_type);
3611 error = 1;
3612 goto defect_bailout;
3613 break;
3614 }
3615
3616 max_possible_size = (hdr_max / entry_size) * entry_size;
3617 num_returned = returned_length / entry_size;
3618 num_valid = min(returned_length, valid_len - hdr_size);
3619 num_valid /= entry_size;
3620
3621 if (get_length != 0) {
3622 get_length = 0;
3623
3624 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
3625 CAM_SCSI_STATUS_ERROR) {
3626 struct scsi_sense_data *sense;
3627 int error_code, sense_key, asc, ascq;
3628
3629 sense = &ccb->csio.sense_data;
3630 scsi_extract_sense_len(sense, ccb->csio.sense_len -
3631 ccb->csio.sense_resid, &error_code, &sense_key,
3632 &asc, &ascq, /*show_errors*/ 1);
3633
3634 /*
3635 * If the drive is reporting that it just doesn't
3636 * support the defect list format, go ahead and use
3637 * the length it reported. Otherwise, the length
3638 * may not be valid, so use the maximum.
3639 */
3640 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3641 && (asc == 0x1c) && (ascq == 0x00)
3642 && (returned_length > 0)) {
3643 if ((use_12byte == 0)
3644 && (returned_length >= max_possible_size)) {
3645 get_length = 1;
3646 use_12byte = 1;
3647 goto retry_12byte;
3648 }
3649 dlist_length = returned_length + hdr_size;
3650 } else if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3651 && (asc == 0x1f) && (ascq == 0x00)
3652 && (returned_length > 0)) {
3653 /* Partial defect list transfer */
3654 /*
3655 * Hitachi drives return this error
3656 * along with a partial defect list if they
3657 * have more defects than the 10 byte
3658 * command can support. Retry with the 12
3659 * byte command.
3660 */
3661 if (use_12byte == 0) {
3662 get_length = 1;
3663 use_12byte = 1;
3664 goto retry_12byte;
3665 }
3666 dlist_length = returned_length + hdr_size;
3667 } else if ((sense_key == SSD_KEY_ILLEGAL_REQUEST)
3668 && (asc == 0x24) && (ascq == 0x00)) {
3669 /* Invalid field in CDB */
3670 /*
3671 * SBC-3 says that if the drive has more
3672 * defects than can be reported with the
3673 * 10 byte command, it should return this
3674 * error and no data. Retry with the 12
3675 * byte command.
3676 */
3677 if (use_12byte == 0) {
3678 get_length = 1;
3679 use_12byte = 1;
3680 goto retry_12byte;
3681 }
3682 dlist_length = returned_length + hdr_size;
3683 } else {
3684 /*
3685 * If we got a SCSI error and no valid length,
3686 * just use the 10 byte maximum. The 12
3687 * byte maximum is too large.
3688 */
3689 if (returned_length == 0)
3690 dlist_length = SRDD10_MAX_LENGTH;
3691 else {
3692 if ((use_12byte == 0)
3693 && (returned_length >=
3694 max_possible_size)) {
3695 get_length = 1;
3696 use_12byte = 1;
3697 goto retry_12byte;
3698 }
3699 dlist_length = returned_length +
3700 hdr_size;
3701 }
3702 }
3703 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
3704 CAM_REQ_CMP){
3705 error = 1;
3706 warnx("Error reading defect header");
3707 if (arglist & CAM_ARG_VERBOSE)
3708 cam_error_print(device, ccb, CAM_ESF_ALL,
3709 CAM_EPF_ALL, stderr);
3710 goto defect_bailout;
3711 } else {
3712 if ((use_12byte == 0)
3713 && (returned_length >= max_possible_size)) {
3714 get_length = 1;
3715 use_12byte = 1;
3716 goto retry_12byte;
3717 }
3718 dlist_length = returned_length + hdr_size;
3719 }
3720 if (summary != 0) {
3721 fprintf(stdout, "%u", num_returned);
3722 if (quiet == 0) {
3723 fprintf(stdout, " defect%s",
3724 (num_returned != 1) ? "s" : "");
3725 }
3726 fprintf(stdout, "\n");
3727
3728 goto defect_bailout;
3729 }
3730
3731 /*
3732 * We always limit the list length to the 10-byte maximum
3733 * length (0xffff). The reason is that some controllers
3734 * can't handle larger I/Os, and we can transfer the entire
3735 * 10 byte list in one shot. For drives that support the 12
3736 * byte read defects command, we'll step through the list
3737 * by specifying a starting offset. For drives that don't
3738 * support the 12 byte command's starting offset, we'll
3739 * just display the first 64K.
3740 */
3741 dlist_length = min(dlist_length, SRDD10_MAX_LENGTH);
3742
3743 goto retry;
3744 }
3745
3746
3747 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
3748 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
3749 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3750 struct scsi_sense_data *sense;
3751 int error_code, sense_key, asc, ascq;
3752
3753 sense = &ccb->csio.sense_data;
3754 scsi_extract_sense_len(sense, ccb->csio.sense_len -
3755 ccb->csio.sense_resid, &error_code, &sense_key, &asc,
3756 &ascq, /*show_errors*/ 1);
3757
3758 /*
3759 * According to the SCSI spec, if the disk doesn't support
3760 * the requested format, it will generally return a sense
3761 * key of RECOVERED ERROR, and an additional sense code
3762 * of "DEFECT LIST NOT FOUND". HGST drives also return
3763 * Primary/Grown defect list not found errors. So just
3764 * check for an ASC of 0x1c.
3765 */
3766 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3767 && (asc == 0x1c)) {
3768 const char *format_str;
3769
3770 format_str = scsi_nv_to_str(defect_list_type_map,
3771 sizeof(defect_list_type_map) /
3772 sizeof(defect_list_type_map[0]),
3773 list_format & SRDD10_DLIST_FORMAT_MASK);
3774 warnx("requested defect format %s not available",
3775 format_str ? format_str : "unknown");
3776
3777 format_str = scsi_nv_to_str(defect_list_type_map,
3778 sizeof(defect_list_type_map) /
3779 sizeof(defect_list_type_map[0]), returned_type);
3780 if (format_str != NULL) {
3781 warnx("Device returned %s format",
3782 format_str);
3783 } else {
3784 error = 1;
3785 warnx("Device returned unknown defect"
3786 " data format %#x", returned_type);
3787 goto defect_bailout;
3788 }
3789 } else {
3790 error = 1;
3791 warnx("Error returned from read defect data command");
3792 if (arglist & CAM_ARG_VERBOSE)
3793 cam_error_print(device, ccb, CAM_ESF_ALL,
3794 CAM_EPF_ALL, stderr);
3795 goto defect_bailout;
3796 }
3797 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3798 error = 1;
3799 warnx("Error returned from read defect data command");
3800 if (arglist & CAM_ARG_VERBOSE)
3801 cam_error_print(device, ccb, CAM_ESF_ALL,
3802 CAM_EPF_ALL, stderr);
3803 goto defect_bailout;
3804 }
3805
3806 if (first_pass != 0) {
3807 fprintf(stderr, "Got %d defect", num_returned);
3808
3809 if ((lists_specified == 0) || (num_returned == 0)) {
3810 fprintf(stderr, "s.\n");
3811 goto defect_bailout;
3812 } else if (num_returned == 1)
3813 fprintf(stderr, ":\n");
3814 else
3815 fprintf(stderr, "s:\n");
3816
3817 first_pass = 0;
3818 }
3819
3820 /*
3821 * XXX KDM I should probably clean up the printout format for the
3822 * disk defects.
3823 */
3824 switch (returned_type) {
3825 case SRDD10_PHYSICAL_SECTOR_FORMAT:
3826 case SRDD10_EXT_PHYS_FORMAT:
3827 {
3828 struct scsi_defect_desc_phys_sector *dlist;
3829
3830 dlist = (struct scsi_defect_desc_phys_sector *)
3831 (defect_list + hdr_size);
3832
3833 for (i = 0; i < num_valid; i++) {
3834 uint32_t sector;
3835
3836 sector = scsi_4btoul(dlist[i].sector);
3837 if (returned_type == SRDD10_EXT_PHYS_FORMAT) {
3838 mads = (sector & SDD_EXT_PHYS_MADS) ?
3839 0 : 1;
3840 sector &= ~SDD_EXT_PHYS_FLAG_MASK;
3841 }
3842 if (hex_format == 0)
3843 fprintf(stdout, "%d:%d:%d%s",
3844 scsi_3btoul(dlist[i].cylinder),
3845 dlist[i].head,
3846 scsi_4btoul(dlist[i].sector),
3847 mads ? " - " : "\n");
3848 else
3849 fprintf(stdout, "0x%x:0x%x:0x%x%s",
3850 scsi_3btoul(dlist[i].cylinder),
3851 dlist[i].head,
3852 scsi_4btoul(dlist[i].sector),
3853 mads ? " - " : "\n");
3854 mads = 0;
3855 }
3856 if (num_valid < num_returned) {
3857 starting_offset += num_valid;
3858 goto next_batch;
3859 }
3860 break;
3861 }
3862 case SRDD10_BYTES_FROM_INDEX_FORMAT:
3863 case SRDD10_EXT_BFI_FORMAT:
3864 {
3865 struct scsi_defect_desc_bytes_from_index *dlist;
3866
3867 dlist = (struct scsi_defect_desc_bytes_from_index *)
3868 (defect_list + hdr_size);
3869
3870 for (i = 0; i < num_valid; i++) {
3871 uint32_t bfi;
3872
3873 bfi = scsi_4btoul(dlist[i].bytes_from_index);
3874 if (returned_type == SRDD10_EXT_BFI_FORMAT) {
3875 mads = (bfi & SDD_EXT_BFI_MADS) ? 1 : 0;
3876 bfi &= ~SDD_EXT_BFI_FLAG_MASK;
3877 }
3878 if (hex_format == 0)
3879 fprintf(stdout, "%d:%d:%d%s",
3880 scsi_3btoul(dlist[i].cylinder),
3881 dlist[i].head,
3882 scsi_4btoul(dlist[i].bytes_from_index),
3883 mads ? " - " : "\n");
3884 else
3885 fprintf(stdout, "0x%x:0x%x:0x%x%s",
3886 scsi_3btoul(dlist[i].cylinder),
3887 dlist[i].head,
3888 scsi_4btoul(dlist[i].bytes_from_index),
3889 mads ? " - " : "\n");
3890
3891 mads = 0;
3892 }
3893 if (num_valid < num_returned) {
3894 starting_offset += num_valid;
3895 goto next_batch;
3896 }
3897 break;
3898 }
3899 case SRDDH10_BLOCK_FORMAT:
3900 {
3901 struct scsi_defect_desc_block *dlist;
3902
3903 dlist = (struct scsi_defect_desc_block *)
3904 (defect_list + hdr_size);
3905
3906 for (i = 0; i < num_valid; i++) {
3907 if (hex_format == 0)
3908 fprintf(stdout, "%u\n",
3909 scsi_4btoul(dlist[i].address));
3910 else
3911 fprintf(stdout, "0x%x\n",
3912 scsi_4btoul(dlist[i].address));
3913 }
3914
3915 if (num_valid < num_returned) {
3916 starting_offset += num_valid;
3917 goto next_batch;
3918 }
3919
3920 break;
3921 }
3922 case SRDD10_LONG_BLOCK_FORMAT:
3923 {
3924 struct scsi_defect_desc_long_block *dlist;
3925
3926 dlist = (struct scsi_defect_desc_long_block *)
3927 (defect_list + hdr_size);
3928
3929 for (i = 0; i < num_valid; i++) {
3930 if (hex_format == 0)
3931 fprintf(stdout, "%ju\n",
3932 (uintmax_t)scsi_8btou64(
3933 dlist[i].address));
3934 else
3935 fprintf(stdout, "0x%jx\n",
3936 (uintmax_t)scsi_8btou64(
3937 dlist[i].address));
3938 }
3939
3940 if (num_valid < num_returned) {
3941 starting_offset += num_valid;
3942 goto next_batch;
3943 }
3944 break;
3945 }
3946 default:
3947 fprintf(stderr, "Unknown defect format 0x%x\n",
3948 returned_type);
3949 error = 1;
3950 break;
3951 }
3952 defect_bailout:
3953
3954 if (defect_list != NULL)
3955 free(defect_list);
3956
3957 if (ccb != NULL)
3958 cam_freeccb(ccb);
3959
3960 return(error);
3961 }
3962 #endif /* MINIMALISTIC */
3963
3964 #if 0
3965 void
3966 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
3967 {
3968 union ccb *ccb;
3969
3970 ccb = cam_getccb(device);
3971
3972 cam_freeccb(ccb);
3973 }
3974 #endif
3975
3976 #ifndef MINIMALISTIC
3977 void
mode_sense(struct cam_device * device,int mode_page,int page_control,int dbd,int retry_count,int timeout,u_int8_t * data,int datalen)3978 mode_sense(struct cam_device *device, int mode_page, int page_control,
3979 int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
3980 {
3981 union ccb *ccb;
3982 int retval;
3983
3984 ccb = cam_getccb(device);
3985
3986 if (ccb == NULL)
3987 errx(1, "mode_sense: couldn't allocate CCB");
3988
3989 bzero(&(&ccb->ccb_h)[1],
3990 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3991
3992 scsi_mode_sense(&ccb->csio,
3993 /* retries */ retry_count,
3994 /* cbfcnp */ NULL,
3995 /* tag_action */ MSG_SIMPLE_Q_TAG,
3996 /* dbd */ dbd,
3997 /* page_code */ page_control << 6,
3998 /* page */ mode_page,
3999 /* param_buf */ data,
4000 /* param_len */ datalen,
4001 /* sense_len */ SSD_FULL_SIZE,
4002 /* timeout */ timeout ? timeout : 5000);
4003
4004 if (arglist & CAM_ARG_ERR_RECOVER)
4005 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4006
4007 /* Disable freezing the device queue */
4008 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4009
4010 if (((retval = cam_send_ccb(device, ccb)) < 0)
4011 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4012 if (arglist & CAM_ARG_VERBOSE) {
4013 cam_error_print(device, ccb, CAM_ESF_ALL,
4014 CAM_EPF_ALL, stderr);
4015 }
4016 cam_freeccb(ccb);
4017 cam_close_device(device);
4018 if (retval < 0)
4019 err(1, "error sending mode sense command");
4020 else
4021 errx(1, "error sending mode sense command");
4022 }
4023
4024 cam_freeccb(ccb);
4025 }
4026
4027 void
mode_select(struct cam_device * device,int save_pages,int retry_count,int timeout,u_int8_t * data,int datalen)4028 mode_select(struct cam_device *device, int save_pages, int retry_count,
4029 int timeout, u_int8_t *data, int datalen)
4030 {
4031 union ccb *ccb;
4032 int retval;
4033
4034 ccb = cam_getccb(device);
4035
4036 if (ccb == NULL)
4037 errx(1, "mode_select: couldn't allocate CCB");
4038
4039 bzero(&(&ccb->ccb_h)[1],
4040 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4041
4042 scsi_mode_select(&ccb->csio,
4043 /* retries */ retry_count,
4044 /* cbfcnp */ NULL,
4045 /* tag_action */ MSG_SIMPLE_Q_TAG,
4046 /* scsi_page_fmt */ 1,
4047 /* save_pages */ save_pages,
4048 /* param_buf */ data,
4049 /* param_len */ datalen,
4050 /* sense_len */ SSD_FULL_SIZE,
4051 /* timeout */ timeout ? timeout : 5000);
4052
4053 if (arglist & CAM_ARG_ERR_RECOVER)
4054 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4055
4056 /* Disable freezing the device queue */
4057 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4058
4059 if (((retval = cam_send_ccb(device, ccb)) < 0)
4060 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4061 if (arglist & CAM_ARG_VERBOSE) {
4062 cam_error_print(device, ccb, CAM_ESF_ALL,
4063 CAM_EPF_ALL, stderr);
4064 }
4065 cam_freeccb(ccb);
4066 cam_close_device(device);
4067
4068 if (retval < 0)
4069 err(1, "error sending mode select command");
4070 else
4071 errx(1, "error sending mode select command");
4072
4073 }
4074
4075 cam_freeccb(ccb);
4076 }
4077
4078 void
modepage(struct cam_device * device,int argc,char ** argv,char * combinedopt,int retry_count,int timeout)4079 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
4080 int retry_count, int timeout)
4081 {
4082 int c, mode_page = -1, page_control = 0;
4083 int binary = 0, list = 0;
4084
4085 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4086 switch(c) {
4087 case 'b':
4088 binary = 1;
4089 break;
4090 case 'd':
4091 arglist |= CAM_ARG_DBD;
4092 break;
4093 case 'e':
4094 arglist |= CAM_ARG_MODE_EDIT;
4095 break;
4096 case 'l':
4097 list = 1;
4098 break;
4099 case 'm':
4100 mode_page = strtol(optarg, NULL, 0);
4101 if (mode_page < 0)
4102 errx(1, "invalid mode page %d", mode_page);
4103 break;
4104 case 'P':
4105 page_control = strtol(optarg, NULL, 0);
4106 if ((page_control < 0) || (page_control > 3))
4107 errx(1, "invalid page control field %d",
4108 page_control);
4109 arglist |= CAM_ARG_PAGE_CNTL;
4110 break;
4111 default:
4112 break;
4113 }
4114 }
4115
4116 if (mode_page == -1 && list == 0)
4117 errx(1, "you must specify a mode page!");
4118
4119 if (list) {
4120 mode_list(device, page_control, arglist & CAM_ARG_DBD,
4121 retry_count, timeout);
4122 } else {
4123 mode_edit(device, mode_page, page_control,
4124 arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
4125 retry_count, timeout);
4126 }
4127 }
4128
4129 static int
scsicmd(struct cam_device * device,int argc,char ** argv,char * combinedopt,int retry_count,int timeout)4130 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
4131 int retry_count, int timeout)
4132 {
4133 union ccb *ccb;
4134 u_int32_t flags = CAM_DIR_NONE;
4135 u_int8_t *data_ptr = NULL;
4136 u_int8_t cdb[20];
4137 u_int8_t atacmd[12];
4138 struct get_hook hook;
4139 int c, data_bytes = 0;
4140 int cdb_len = 0;
4141 int atacmd_len = 0;
4142 int dmacmd = 0;
4143 int fpdmacmd = 0;
4144 int need_res = 0;
4145 char *datastr = NULL, *tstr, *resstr = NULL;
4146 int error = 0;
4147 int fd_data = 0, fd_res = 0;
4148 int retval;
4149
4150 ccb = cam_getccb(device);
4151
4152 if (ccb == NULL) {
4153 warnx("scsicmd: error allocating ccb");
4154 return(1);
4155 }
4156
4157 bzero(&(&ccb->ccb_h)[1],
4158 sizeof(union ccb) - sizeof(struct ccb_hdr));
4159
4160 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4161 switch(c) {
4162 case 'a':
4163 tstr = optarg;
4164 while (isspace(*tstr) && (*tstr != '\0'))
4165 tstr++;
4166 hook.argc = argc - optind;
4167 hook.argv = argv + optind;
4168 hook.got = 0;
4169 atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
4170 iget, &hook);
4171 /*
4172 * Increment optind by the number of arguments the
4173 * encoding routine processed. After each call to
4174 * getopt(3), optind points to the argument that
4175 * getopt should process _next_. In this case,
4176 * that means it points to the first command string
4177 * argument, if there is one. Once we increment
4178 * this, it should point to either the next command
4179 * line argument, or it should be past the end of
4180 * the list.
4181 */
4182 optind += hook.got;
4183 break;
4184 case 'c':
4185 tstr = optarg;
4186 while (isspace(*tstr) && (*tstr != '\0'))
4187 tstr++;
4188 hook.argc = argc - optind;
4189 hook.argv = argv + optind;
4190 hook.got = 0;
4191 cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
4192 iget, &hook);
4193 /*
4194 * Increment optind by the number of arguments the
4195 * encoding routine processed. After each call to
4196 * getopt(3), optind points to the argument that
4197 * getopt should process _next_. In this case,
4198 * that means it points to the first command string
4199 * argument, if there is one. Once we increment
4200 * this, it should point to either the next command
4201 * line argument, or it should be past the end of
4202 * the list.
4203 */
4204 optind += hook.got;
4205 break;
4206 case 'd':
4207 dmacmd = 1;
4208 break;
4209 case 'f':
4210 fpdmacmd = 1;
4211 break;
4212 case 'i':
4213 if (arglist & CAM_ARG_CMD_OUT) {
4214 warnx("command must either be "
4215 "read or write, not both");
4216 error = 1;
4217 goto scsicmd_bailout;
4218 }
4219 arglist |= CAM_ARG_CMD_IN;
4220 flags = CAM_DIR_IN;
4221 data_bytes = strtol(optarg, NULL, 0);
4222 if (data_bytes <= 0) {
4223 warnx("invalid number of input bytes %d",
4224 data_bytes);
4225 error = 1;
4226 goto scsicmd_bailout;
4227 }
4228 hook.argc = argc - optind;
4229 hook.argv = argv + optind;
4230 hook.got = 0;
4231 optind++;
4232 datastr = cget(&hook, NULL);
4233 /*
4234 * If the user supplied "-" instead of a format, he
4235 * wants the data to be written to stdout.
4236 */
4237 if ((datastr != NULL)
4238 && (datastr[0] == '-'))
4239 fd_data = 1;
4240
4241 data_ptr = (u_int8_t *)malloc(data_bytes);
4242 if (data_ptr == NULL) {
4243 warnx("can't malloc memory for data_ptr");
4244 error = 1;
4245 goto scsicmd_bailout;
4246 }
4247 break;
4248 case 'o':
4249 if (arglist & CAM_ARG_CMD_IN) {
4250 warnx("command must either be "
4251 "read or write, not both");
4252 error = 1;
4253 goto scsicmd_bailout;
4254 }
4255 arglist |= CAM_ARG_CMD_OUT;
4256 flags = CAM_DIR_OUT;
4257 data_bytes = strtol(optarg, NULL, 0);
4258 if (data_bytes <= 0) {
4259 warnx("invalid number of output bytes %d",
4260 data_bytes);
4261 error = 1;
4262 goto scsicmd_bailout;
4263 }
4264 hook.argc = argc - optind;
4265 hook.argv = argv + optind;
4266 hook.got = 0;
4267 datastr = cget(&hook, NULL);
4268 data_ptr = (u_int8_t *)malloc(data_bytes);
4269 if (data_ptr == NULL) {
4270 warnx("can't malloc memory for data_ptr");
4271 error = 1;
4272 goto scsicmd_bailout;
4273 }
4274 bzero(data_ptr, data_bytes);
4275 /*
4276 * If the user supplied "-" instead of a format, he
4277 * wants the data to be read from stdin.
4278 */
4279 if ((datastr != NULL)
4280 && (datastr[0] == '-'))
4281 fd_data = 1;
4282 else
4283 buff_encode_visit(data_ptr, data_bytes, datastr,
4284 iget, &hook);
4285 optind += hook.got;
4286 break;
4287 case 'r':
4288 need_res = 1;
4289 hook.argc = argc - optind;
4290 hook.argv = argv + optind;
4291 hook.got = 0;
4292 resstr = cget(&hook, NULL);
4293 if ((resstr != NULL) && (resstr[0] == '-'))
4294 fd_res = 1;
4295 optind += hook.got;
4296 break;
4297 default:
4298 break;
4299 }
4300 }
4301
4302 /*
4303 * If fd_data is set, and we're writing to the device, we need to
4304 * read the data the user wants written from stdin.
4305 */
4306 if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4307 ssize_t amt_read;
4308 int amt_to_read = data_bytes;
4309 u_int8_t *buf_ptr = data_ptr;
4310
4311 for (amt_read = 0; amt_to_read > 0;
4312 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4313 if (amt_read == -1) {
4314 warn("error reading data from stdin");
4315 error = 1;
4316 goto scsicmd_bailout;
4317 }
4318 amt_to_read -= amt_read;
4319 buf_ptr += amt_read;
4320 }
4321 }
4322
4323 if (arglist & CAM_ARG_ERR_RECOVER)
4324 flags |= CAM_PASS_ERR_RECOVER;
4325
4326 /* Disable freezing the device queue */
4327 flags |= CAM_DEV_QFRZDIS;
4328
4329 if (cdb_len) {
4330 /*
4331 * This is taken from the SCSI-3 draft spec.
4332 * (T10/1157D revision 0.3)
4333 * The top 3 bits of an opcode are the group code.
4334 * The next 5 bits are the command code.
4335 * Group 0: six byte commands
4336 * Group 1: ten byte commands
4337 * Group 2: ten byte commands
4338 * Group 3: reserved
4339 * Group 4: sixteen byte commands
4340 * Group 5: twelve byte commands
4341 * Group 6: vendor specific
4342 * Group 7: vendor specific
4343 */
4344 switch((cdb[0] >> 5) & 0x7) {
4345 case 0:
4346 cdb_len = 6;
4347 break;
4348 case 1:
4349 case 2:
4350 cdb_len = 10;
4351 break;
4352 case 3:
4353 case 6:
4354 case 7:
4355 /* computed by buff_encode_visit */
4356 break;
4357 case 4:
4358 cdb_len = 16;
4359 break;
4360 case 5:
4361 cdb_len = 12;
4362 break;
4363 }
4364
4365 /*
4366 * We should probably use csio_build_visit or something like that
4367 * here, but it's easier to encode arguments as you go. The
4368 * alternative would be skipping the CDB argument and then encoding
4369 * it here, since we've got the data buffer argument by now.
4370 */
4371 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
4372
4373 cam_fill_csio(&ccb->csio,
4374 /*retries*/ retry_count,
4375 /*cbfcnp*/ NULL,
4376 /*flags*/ flags,
4377 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4378 /*data_ptr*/ data_ptr,
4379 /*dxfer_len*/ data_bytes,
4380 /*sense_len*/ SSD_FULL_SIZE,
4381 /*cdb_len*/ cdb_len,
4382 /*timeout*/ timeout ? timeout : 5000);
4383 } else {
4384 atacmd_len = 12;
4385 bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
4386 if (need_res)
4387 ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
4388 if (dmacmd)
4389 ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
4390 if (fpdmacmd)
4391 ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
4392
4393 cam_fill_ataio(&ccb->ataio,
4394 /*retries*/ retry_count,
4395 /*cbfcnp*/ NULL,
4396 /*flags*/ flags,
4397 /*tag_action*/ 0,
4398 /*data_ptr*/ data_ptr,
4399 /*dxfer_len*/ data_bytes,
4400 /*timeout*/ timeout ? timeout : 5000);
4401 }
4402
4403 if (((retval = cam_send_ccb(device, ccb)) < 0)
4404 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4405 const char warnstr[] = "error sending command";
4406
4407 if (retval < 0)
4408 warn(warnstr);
4409 else
4410 warnx(warnstr);
4411
4412 if (arglist & CAM_ARG_VERBOSE) {
4413 cam_error_print(device, ccb, CAM_ESF_ALL,
4414 CAM_EPF_ALL, stderr);
4415 }
4416
4417 error = 1;
4418 goto scsicmd_bailout;
4419 }
4420
4421 if (atacmd_len && need_res) {
4422 if (fd_res == 0) {
4423 buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
4424 arg_put, NULL);
4425 fprintf(stdout, "\n");
4426 } else {
4427 fprintf(stdout,
4428 "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
4429 ccb->ataio.res.status,
4430 ccb->ataio.res.error,
4431 ccb->ataio.res.lba_low,
4432 ccb->ataio.res.lba_mid,
4433 ccb->ataio.res.lba_high,
4434 ccb->ataio.res.device,
4435 ccb->ataio.res.lba_low_exp,
4436 ccb->ataio.res.lba_mid_exp,
4437 ccb->ataio.res.lba_high_exp,
4438 ccb->ataio.res.sector_count,
4439 ccb->ataio.res.sector_count_exp);
4440 fflush(stdout);
4441 }
4442 }
4443
4444 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4445 && (arglist & CAM_ARG_CMD_IN)
4446 && (data_bytes > 0)) {
4447 if (fd_data == 0) {
4448 buff_decode_visit(data_ptr, data_bytes, datastr,
4449 arg_put, NULL);
4450 fprintf(stdout, "\n");
4451 } else {
4452 ssize_t amt_written;
4453 int amt_to_write = data_bytes;
4454 u_int8_t *buf_ptr = data_ptr;
4455
4456 for (amt_written = 0; (amt_to_write > 0) &&
4457 (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
4458 amt_to_write -= amt_written;
4459 buf_ptr += amt_written;
4460 }
4461 if (amt_written == -1) {
4462 warn("error writing data to stdout");
4463 error = 1;
4464 goto scsicmd_bailout;
4465 } else if ((amt_written == 0)
4466 && (amt_to_write > 0)) {
4467 warnx("only wrote %u bytes out of %u",
4468 data_bytes - amt_to_write, data_bytes);
4469 }
4470 }
4471 }
4472
4473 scsicmd_bailout:
4474
4475 if ((data_bytes > 0) && (data_ptr != NULL))
4476 free(data_ptr);
4477
4478 cam_freeccb(ccb);
4479
4480 return(error);
4481 }
4482
4483 static int
camdebug(int argc,char ** argv,char * combinedopt)4484 camdebug(int argc, char **argv, char *combinedopt)
4485 {
4486 int c, fd;
4487 path_id_t bus = CAM_BUS_WILDCARD;
4488 target_id_t target = CAM_TARGET_WILDCARD;
4489 lun_id_t lun = CAM_LUN_WILDCARD;
4490 char *tstr, *tmpstr = NULL;
4491 union ccb ccb;
4492 int error = 0;
4493
4494 bzero(&ccb, sizeof(union ccb));
4495
4496 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4497 switch(c) {
4498 case 'I':
4499 arglist |= CAM_ARG_DEBUG_INFO;
4500 ccb.cdbg.flags |= CAM_DEBUG_INFO;
4501 break;
4502 case 'P':
4503 arglist |= CAM_ARG_DEBUG_PERIPH;
4504 ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
4505 break;
4506 case 'S':
4507 arglist |= CAM_ARG_DEBUG_SUBTRACE;
4508 ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
4509 break;
4510 case 'T':
4511 arglist |= CAM_ARG_DEBUG_TRACE;
4512 ccb.cdbg.flags |= CAM_DEBUG_TRACE;
4513 break;
4514 case 'X':
4515 arglist |= CAM_ARG_DEBUG_XPT;
4516 ccb.cdbg.flags |= CAM_DEBUG_XPT;
4517 break;
4518 case 'c':
4519 arglist |= CAM_ARG_DEBUG_CDB;
4520 ccb.cdbg.flags |= CAM_DEBUG_CDB;
4521 break;
4522 case 'p':
4523 arglist |= CAM_ARG_DEBUG_PROBE;
4524 ccb.cdbg.flags |= CAM_DEBUG_PROBE;
4525 break;
4526 default:
4527 break;
4528 }
4529 }
4530
4531 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
4532 warnx("error opening transport layer device %s", XPT_DEVICE);
4533 warn("%s", XPT_DEVICE);
4534 return(1);
4535 }
4536 argc -= optind;
4537 argv += optind;
4538
4539 if (argc <= 0) {
4540 warnx("you must specify \"off\", \"all\" or a bus,");
4541 warnx("bus:target, or bus:target:lun");
4542 close(fd);
4543 return(1);
4544 }
4545
4546 tstr = *argv;
4547
4548 while (isspace(*tstr) && (*tstr != '\0'))
4549 tstr++;
4550
4551 if (strncmp(tstr, "off", 3) == 0) {
4552 ccb.cdbg.flags = CAM_DEBUG_NONE;
4553 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
4554 CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
4555 CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE);
4556 } else if (strncmp(tstr, "all", 3) != 0) {
4557 tmpstr = (char *)strtok(tstr, ":");
4558 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4559 bus = strtol(tmpstr, NULL, 0);
4560 arglist |= CAM_ARG_BUS;
4561 tmpstr = (char *)strtok(NULL, ":");
4562 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4563 target = strtol(tmpstr, NULL, 0);
4564 arglist |= CAM_ARG_TARGET;
4565 tmpstr = (char *)strtok(NULL, ":");
4566 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4567 lun = strtol(tmpstr, NULL, 0);
4568 arglist |= CAM_ARG_LUN;
4569 }
4570 }
4571 } else {
4572 error = 1;
4573 warnx("you must specify \"all\", \"off\", or a bus,");
4574 warnx("bus:target, or bus:target:lun to debug");
4575 }
4576 }
4577
4578 if (error == 0) {
4579
4580 ccb.ccb_h.func_code = XPT_DEBUG;
4581 ccb.ccb_h.path_id = bus;
4582 ccb.ccb_h.target_id = target;
4583 ccb.ccb_h.target_lun = lun;
4584
4585 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
4586 warn("CAMIOCOMMAND ioctl failed");
4587 error = 1;
4588 }
4589
4590 if (error == 0) {
4591 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
4592 CAM_FUNC_NOTAVAIL) {
4593 warnx("CAM debugging not available");
4594 warnx("you need to put options CAMDEBUG in"
4595 " your kernel config file!");
4596 error = 1;
4597 } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
4598 CAM_REQ_CMP) {
4599 warnx("XPT_DEBUG CCB failed with status %#x",
4600 ccb.ccb_h.status);
4601 error = 1;
4602 } else {
4603 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
4604 fprintf(stderr,
4605 "Debugging turned off\n");
4606 } else {
4607 fprintf(stderr,
4608 "Debugging enabled for "
4609 "%d:%d:%jx\n",
4610 bus, target, (uintmax_t)lun);
4611 }
4612 }
4613 }
4614 close(fd);
4615 }
4616
4617 return(error);
4618 }
4619
4620 static int
tagcontrol(struct cam_device * device,int argc,char ** argv,char * combinedopt)4621 tagcontrol(struct cam_device *device, int argc, char **argv,
4622 char *combinedopt)
4623 {
4624 int c;
4625 union ccb *ccb;
4626 int numtags = -1;
4627 int retval = 0;
4628 int quiet = 0;
4629 char pathstr[1024];
4630
4631 ccb = cam_getccb(device);
4632
4633 if (ccb == NULL) {
4634 warnx("tagcontrol: error allocating ccb");
4635 return(1);
4636 }
4637
4638 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4639 switch(c) {
4640 case 'N':
4641 numtags = strtol(optarg, NULL, 0);
4642 if (numtags < 0) {
4643 warnx("tag count %d is < 0", numtags);
4644 retval = 1;
4645 goto tagcontrol_bailout;
4646 }
4647 break;
4648 case 'q':
4649 quiet++;
4650 break;
4651 default:
4652 break;
4653 }
4654 }
4655
4656 cam_path_string(device, pathstr, sizeof(pathstr));
4657
4658 if (numtags >= 0) {
4659 bzero(&(&ccb->ccb_h)[1],
4660 sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
4661 ccb->ccb_h.func_code = XPT_REL_SIMQ;
4662 ccb->ccb_h.flags = CAM_DEV_QFREEZE;
4663 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
4664 ccb->crs.openings = numtags;
4665
4666
4667 if (cam_send_ccb(device, ccb) < 0) {
4668 perror("error sending XPT_REL_SIMQ CCB");
4669 retval = 1;
4670 goto tagcontrol_bailout;
4671 }
4672
4673 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4674 warnx("XPT_REL_SIMQ CCB failed");
4675 cam_error_print(device, ccb, CAM_ESF_ALL,
4676 CAM_EPF_ALL, stderr);
4677 retval = 1;
4678 goto tagcontrol_bailout;
4679 }
4680
4681
4682 if (quiet == 0)
4683 fprintf(stdout, "%stagged openings now %d\n",
4684 pathstr, ccb->crs.openings);
4685 }
4686
4687 bzero(&(&ccb->ccb_h)[1],
4688 sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
4689
4690 ccb->ccb_h.func_code = XPT_GDEV_STATS;
4691
4692 if (cam_send_ccb(device, ccb) < 0) {
4693 perror("error sending XPT_GDEV_STATS CCB");
4694 retval = 1;
4695 goto tagcontrol_bailout;
4696 }
4697
4698 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4699 warnx("XPT_GDEV_STATS CCB failed");
4700 cam_error_print(device, ccb, CAM_ESF_ALL,
4701 CAM_EPF_ALL, stderr);
4702 retval = 1;
4703 goto tagcontrol_bailout;
4704 }
4705
4706 if (arglist & CAM_ARG_VERBOSE) {
4707 fprintf(stdout, "%s", pathstr);
4708 fprintf(stdout, "dev_openings %d\n", ccb->cgds.dev_openings);
4709 fprintf(stdout, "%s", pathstr);
4710 fprintf(stdout, "dev_active %d\n", ccb->cgds.dev_active);
4711 fprintf(stdout, "%s", pathstr);
4712 fprintf(stdout, "allocated %d\n", ccb->cgds.allocated);
4713 fprintf(stdout, "%s", pathstr);
4714 fprintf(stdout, "queued %d\n", ccb->cgds.queued);
4715 fprintf(stdout, "%s", pathstr);
4716 fprintf(stdout, "held %d\n", ccb->cgds.held);
4717 fprintf(stdout, "%s", pathstr);
4718 fprintf(stdout, "mintags %d\n", ccb->cgds.mintags);
4719 fprintf(stdout, "%s", pathstr);
4720 fprintf(stdout, "maxtags %d\n", ccb->cgds.maxtags);
4721 } else {
4722 if (quiet == 0) {
4723 fprintf(stdout, "%s", pathstr);
4724 fprintf(stdout, "device openings: ");
4725 }
4726 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
4727 ccb->cgds.dev_active);
4728 }
4729
4730 tagcontrol_bailout:
4731
4732 cam_freeccb(ccb);
4733 return(retval);
4734 }
4735
4736 static void
cts_print(struct cam_device * device,struct ccb_trans_settings * cts)4737 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
4738 {
4739 char pathstr[1024];
4740
4741 cam_path_string(device, pathstr, sizeof(pathstr));
4742
4743 if (cts->transport == XPORT_SPI) {
4744 struct ccb_trans_settings_spi *spi =
4745 &cts->xport_specific.spi;
4746
4747 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
4748
4749 fprintf(stdout, "%ssync parameter: %d\n", pathstr,
4750 spi->sync_period);
4751
4752 if (spi->sync_offset != 0) {
4753 u_int freq;
4754
4755 freq = scsi_calc_syncsrate(spi->sync_period);
4756 fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
4757 pathstr, freq / 1000, freq % 1000);
4758 }
4759 }
4760
4761 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
4762 fprintf(stdout, "%soffset: %d\n", pathstr,
4763 spi->sync_offset);
4764 }
4765
4766 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
4767 fprintf(stdout, "%sbus width: %d bits\n", pathstr,
4768 (0x01 << spi->bus_width) * 8);
4769 }
4770
4771 if (spi->valid & CTS_SPI_VALID_DISC) {
4772 fprintf(stdout, "%sdisconnection is %s\n", pathstr,
4773 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
4774 "enabled" : "disabled");
4775 }
4776 }
4777 if (cts->transport == XPORT_FC) {
4778 struct ccb_trans_settings_fc *fc =
4779 &cts->xport_specific.fc;
4780
4781 if (fc->valid & CTS_FC_VALID_WWNN)
4782 fprintf(stdout, "%sWWNN: 0x%llx\n", pathstr,
4783 (long long) fc->wwnn);
4784 if (fc->valid & CTS_FC_VALID_WWPN)
4785 fprintf(stdout, "%sWWPN: 0x%llx\n", pathstr,
4786 (long long) fc->wwpn);
4787 if (fc->valid & CTS_FC_VALID_PORT)
4788 fprintf(stdout, "%sPortID: 0x%x\n", pathstr, fc->port);
4789 if (fc->valid & CTS_FC_VALID_SPEED)
4790 fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4791 pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
4792 }
4793 if (cts->transport == XPORT_SAS) {
4794 struct ccb_trans_settings_sas *sas =
4795 &cts->xport_specific.sas;
4796
4797 if (sas->valid & CTS_SAS_VALID_SPEED)
4798 fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4799 pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
4800 }
4801 if (cts->transport == XPORT_ATA) {
4802 struct ccb_trans_settings_pata *pata =
4803 &cts->xport_specific.ata;
4804
4805 if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
4806 fprintf(stdout, "%sATA mode: %s\n", pathstr,
4807 ata_mode2string(pata->mode));
4808 }
4809 if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
4810 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4811 pata->atapi);
4812 }
4813 if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
4814 fprintf(stdout, "%sPIO transaction length: %d\n",
4815 pathstr, pata->bytecount);
4816 }
4817 }
4818 if (cts->transport == XPORT_SATA) {
4819 struct ccb_trans_settings_sata *sata =
4820 &cts->xport_specific.sata;
4821
4822 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
4823 fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
4824 sata->revision);
4825 }
4826 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
4827 fprintf(stdout, "%sATA mode: %s\n", pathstr,
4828 ata_mode2string(sata->mode));
4829 }
4830 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
4831 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4832 sata->atapi);
4833 }
4834 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
4835 fprintf(stdout, "%sPIO transaction length: %d\n",
4836 pathstr, sata->bytecount);
4837 }
4838 if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
4839 fprintf(stdout, "%sPMP presence: %d\n", pathstr,
4840 sata->pm_present);
4841 }
4842 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
4843 fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
4844 sata->tags);
4845 }
4846 if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
4847 fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
4848 sata->caps);
4849 }
4850 }
4851 if (cts->protocol == PROTO_ATA) {
4852 struct ccb_trans_settings_ata *ata=
4853 &cts->proto_specific.ata;
4854
4855 if (ata->valid & CTS_ATA_VALID_TQ) {
4856 fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4857 (ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
4858 "enabled" : "disabled");
4859 }
4860 }
4861 if (cts->protocol == PROTO_SCSI) {
4862 struct ccb_trans_settings_scsi *scsi=
4863 &cts->proto_specific.scsi;
4864
4865 if (scsi->valid & CTS_SCSI_VALID_TQ) {
4866 fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4867 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
4868 "enabled" : "disabled");
4869 }
4870 }
4871
4872 }
4873
4874 /*
4875 * Get a path inquiry CCB for the specified device.
4876 */
4877 static int
get_cpi(struct cam_device * device,struct ccb_pathinq * cpi)4878 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
4879 {
4880 union ccb *ccb;
4881 int retval = 0;
4882
4883 ccb = cam_getccb(device);
4884 if (ccb == NULL) {
4885 warnx("get_cpi: couldn't allocate CCB");
4886 return(1);
4887 }
4888 bzero(&(&ccb->ccb_h)[1],
4889 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4890 ccb->ccb_h.func_code = XPT_PATH_INQ;
4891 if (cam_send_ccb(device, ccb) < 0) {
4892 warn("get_cpi: error sending Path Inquiry CCB");
4893 if (arglist & CAM_ARG_VERBOSE)
4894 cam_error_print(device, ccb, CAM_ESF_ALL,
4895 CAM_EPF_ALL, stderr);
4896 retval = 1;
4897 goto get_cpi_bailout;
4898 }
4899 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4900 if (arglist & CAM_ARG_VERBOSE)
4901 cam_error_print(device, ccb, CAM_ESF_ALL,
4902 CAM_EPF_ALL, stderr);
4903 retval = 1;
4904 goto get_cpi_bailout;
4905 }
4906 bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
4907
4908 get_cpi_bailout:
4909 cam_freeccb(ccb);
4910 return(retval);
4911 }
4912
4913 /*
4914 * Get a get device CCB for the specified device.
4915 */
4916 static int
get_cgd(struct cam_device * device,struct ccb_getdev * cgd)4917 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
4918 {
4919 union ccb *ccb;
4920 int retval = 0;
4921
4922 ccb = cam_getccb(device);
4923 if (ccb == NULL) {
4924 warnx("get_cgd: couldn't allocate CCB");
4925 return(1);
4926 }
4927 bzero(&(&ccb->ccb_h)[1],
4928 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4929 ccb->ccb_h.func_code = XPT_GDEV_TYPE;
4930 if (cam_send_ccb(device, ccb) < 0) {
4931 warn("get_cgd: error sending Path Inquiry CCB");
4932 if (arglist & CAM_ARG_VERBOSE)
4933 cam_error_print(device, ccb, CAM_ESF_ALL,
4934 CAM_EPF_ALL, stderr);
4935 retval = 1;
4936 goto get_cgd_bailout;
4937 }
4938 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4939 if (arglist & CAM_ARG_VERBOSE)
4940 cam_error_print(device, ccb, CAM_ESF_ALL,
4941 CAM_EPF_ALL, stderr);
4942 retval = 1;
4943 goto get_cgd_bailout;
4944 }
4945 bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
4946
4947 get_cgd_bailout:
4948 cam_freeccb(ccb);
4949 return(retval);
4950 }
4951
4952 /*
4953 * Returns 1 if the device has the VPD page, 0 if it does not, and -1 on an
4954 * error.
4955 */
4956 int
dev_has_vpd_page(struct cam_device * dev,uint8_t page_id,int retry_count,int timeout,int verbosemode)4957 dev_has_vpd_page(struct cam_device *dev, uint8_t page_id, int retry_count,
4958 int timeout, int verbosemode)
4959 {
4960 union ccb *ccb = NULL;
4961 struct scsi_vpd_supported_page_list sup_pages;
4962 int i;
4963 int retval = 0;
4964
4965 ccb = cam_getccb(dev);
4966 if (ccb == NULL) {
4967 warn("Unable to allocate CCB");
4968 retval = -1;
4969 goto bailout;
4970 }
4971
4972 /* cam_getccb cleans up the header, caller has to zero the payload */
4973 bzero(&(&ccb->ccb_h)[1],
4974 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4975
4976 bzero(&sup_pages, sizeof(sup_pages));
4977
4978 scsi_inquiry(&ccb->csio,
4979 /*retries*/ retry_count,
4980 /*cbfcnp*/ NULL,
4981 /* tag_action */ MSG_SIMPLE_Q_TAG,
4982 /* inq_buf */ (u_int8_t *)&sup_pages,
4983 /* inq_len */ sizeof(sup_pages),
4984 /* evpd */ 1,
4985 /* page_code */ SVPD_SUPPORTED_PAGE_LIST,
4986 /* sense_len */ SSD_FULL_SIZE,
4987 /* timeout */ timeout ? timeout : 5000);
4988
4989 /* Disable freezing the device queue */
4990 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4991
4992 if (retry_count != 0)
4993 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4994
4995 if (cam_send_ccb(dev, ccb) < 0) {
4996 cam_freeccb(ccb);
4997 retval = -1;
4998 goto bailout;
4999 }
5000
5001 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5002 if (verbosemode != 0)
5003 cam_error_print(dev, ccb, CAM_ESF_ALL,
5004 CAM_EPF_ALL, stderr);
5005 retval = -1;
5006 goto bailout;
5007 }
5008
5009 for (i = 0; i < sup_pages.length; i++) {
5010 if (sup_pages.list[i] == page_id) {
5011 retval = 1;
5012 goto bailout;
5013 }
5014 }
5015 bailout:
5016 if (ccb != NULL)
5017 cam_freeccb(ccb);
5018
5019 return (retval);
5020 }
5021
5022 /*
5023 * devtype is filled in with the type of device.
5024 * Returns 0 for success, non-zero for failure.
5025 */
5026 int
get_device_type(struct cam_device * dev,int retry_count,int timeout,int verbosemode,camcontrol_devtype * devtype)5027 get_device_type(struct cam_device *dev, int retry_count, int timeout,
5028 int verbosemode, camcontrol_devtype *devtype)
5029 {
5030 struct ccb_getdev cgd;
5031 int retval = 0;
5032
5033 retval = get_cgd(dev, &cgd);
5034 if (retval != 0)
5035 goto bailout;
5036
5037 switch (cgd.protocol) {
5038 case PROTO_SCSI:
5039 break;
5040 case PROTO_ATA:
5041 case PROTO_ATAPI:
5042 case PROTO_SATAPM:
5043 *devtype = CC_DT_ATA;
5044 goto bailout;
5045 break; /*NOTREACHED*/
5046 default:
5047 *devtype = CC_DT_UNKNOWN;
5048 goto bailout;
5049 break; /*NOTREACHED*/
5050 }
5051
5052 /*
5053 * Check for the ATA Information VPD page (0x89). If this is an
5054 * ATA device behind a SCSI to ATA translation layer, this VPD page
5055 * should be present.
5056 *
5057 * If that VPD page isn't present, or we get an error back from the
5058 * INQUIRY command, we'll just treat it as a normal SCSI device.
5059 */
5060 retval = dev_has_vpd_page(dev, SVPD_ATA_INFORMATION, retry_count,
5061 timeout, verbosemode);
5062 if (retval == 1)
5063 *devtype = CC_DT_ATA_BEHIND_SCSI;
5064 else
5065 *devtype = CC_DT_SCSI;
5066
5067 retval = 0;
5068
5069 bailout:
5070 return (retval);
5071 }
5072
5073 void
build_ata_cmd(union ccb * ccb,uint32_t retry_count,uint32_t flags,uint8_t tag_action,uint8_t protocol,uint8_t ata_flags,uint16_t features,uint16_t sector_count,uint64_t lba,uint8_t command,uint8_t * data_ptr,uint16_t dxfer_len,uint8_t sense_len,uint32_t timeout,int is48bit,camcontrol_devtype devtype)5074 build_ata_cmd(union ccb *ccb, uint32_t retry_count, uint32_t flags,
5075 uint8_t tag_action, uint8_t protocol, uint8_t ata_flags, uint16_t features,
5076 uint16_t sector_count, uint64_t lba, uint8_t command, uint8_t *data_ptr,
5077 uint16_t dxfer_len, uint8_t sense_len, uint32_t timeout,
5078 int is48bit, camcontrol_devtype devtype)
5079 {
5080 if (devtype == CC_DT_ATA) {
5081 cam_fill_ataio(&ccb->ataio,
5082 /*retries*/ retry_count,
5083 /*cbfcnp*/ NULL,
5084 /*flags*/ flags,
5085 /*tag_action*/ tag_action,
5086 /*data_ptr*/ data_ptr,
5087 /*dxfer_len*/ dxfer_len,
5088 /*timeout*/ timeout);
5089 if (is48bit || lba > ATA_MAX_28BIT_LBA)
5090 ata_48bit_cmd(&ccb->ataio, command, features, lba,
5091 sector_count);
5092 else
5093 ata_28bit_cmd(&ccb->ataio, command, features, lba,
5094 sector_count);
5095 } else {
5096 if (is48bit || lba > ATA_MAX_28BIT_LBA)
5097 protocol |= AP_EXTEND;
5098
5099 scsi_ata_pass_16(&ccb->csio,
5100 /*retries*/ retry_count,
5101 /*cbfcnp*/ NULL,
5102 /*flags*/ flags,
5103 /*tag_action*/ tag_action,
5104 /*protocol*/ protocol,
5105 /*ata_flags*/ ata_flags,
5106 /*features*/ features,
5107 /*sector_count*/ sector_count,
5108 /*lba*/ lba,
5109 /*command*/ command,
5110 /*control*/ 0,
5111 /*data_ptr*/ data_ptr,
5112 /*dxfer_len*/ dxfer_len,
5113 /*sense_len*/ sense_len,
5114 /*timeout*/ timeout);
5115 }
5116 }
5117
5118
5119 static void
cpi_print(struct ccb_pathinq * cpi)5120 cpi_print(struct ccb_pathinq *cpi)
5121 {
5122 char adapter_str[1024];
5123 int i;
5124
5125 snprintf(adapter_str, sizeof(adapter_str),
5126 "%s%d:", cpi->dev_name, cpi->unit_number);
5127
5128 fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
5129 cpi->version_num);
5130
5131 for (i = 1; i < 0xff; i = i << 1) {
5132 const char *str;
5133
5134 if ((i & cpi->hba_inquiry) == 0)
5135 continue;
5136
5137 fprintf(stdout, "%s supports ", adapter_str);
5138
5139 switch(i) {
5140 case PI_MDP_ABLE:
5141 str = "MDP message";
5142 break;
5143 case PI_WIDE_32:
5144 str = "32 bit wide SCSI";
5145 break;
5146 case PI_WIDE_16:
5147 str = "16 bit wide SCSI";
5148 break;
5149 case PI_SDTR_ABLE:
5150 str = "SDTR message";
5151 break;
5152 case PI_LINKED_CDB:
5153 str = "linked CDBs";
5154 break;
5155 case PI_TAG_ABLE:
5156 str = "tag queue messages";
5157 break;
5158 case PI_SOFT_RST:
5159 str = "soft reset alternative";
5160 break;
5161 case PI_SATAPM:
5162 str = "SATA Port Multiplier";
5163 break;
5164 default:
5165 str = "unknown PI bit set";
5166 break;
5167 }
5168 fprintf(stdout, "%s\n", str);
5169 }
5170
5171 for (i = 1; i < 0xff; i = i << 1) {
5172 const char *str;
5173
5174 if ((i & cpi->hba_misc) == 0)
5175 continue;
5176
5177 fprintf(stdout, "%s ", adapter_str);
5178
5179 switch(i) {
5180 case PIM_SCANHILO:
5181 str = "bus scans from high ID to low ID";
5182 break;
5183 case PIM_NOREMOVE:
5184 str = "removable devices not included in scan";
5185 break;
5186 case PIM_NOINITIATOR:
5187 str = "initiator role not supported";
5188 break;
5189 case PIM_NOBUSRESET:
5190 str = "user has disabled initial BUS RESET or"
5191 " controller is in target/mixed mode";
5192 break;
5193 case PIM_NO_6_BYTE:
5194 str = "do not send 6-byte commands";
5195 break;
5196 case PIM_SEQSCAN:
5197 str = "scan bus sequentially";
5198 break;
5199 default:
5200 str = "unknown PIM bit set";
5201 break;
5202 }
5203 fprintf(stdout, "%s\n", str);
5204 }
5205
5206 for (i = 1; i < 0xff; i = i << 1) {
5207 const char *str;
5208
5209 if ((i & cpi->target_sprt) == 0)
5210 continue;
5211
5212 fprintf(stdout, "%s supports ", adapter_str);
5213 switch(i) {
5214 case PIT_PROCESSOR:
5215 str = "target mode processor mode";
5216 break;
5217 case PIT_PHASE:
5218 str = "target mode phase cog. mode";
5219 break;
5220 case PIT_DISCONNECT:
5221 str = "disconnects in target mode";
5222 break;
5223 case PIT_TERM_IO:
5224 str = "terminate I/O message in target mode";
5225 break;
5226 case PIT_GRP_6:
5227 str = "group 6 commands in target mode";
5228 break;
5229 case PIT_GRP_7:
5230 str = "group 7 commands in target mode";
5231 break;
5232 default:
5233 str = "unknown PIT bit set";
5234 break;
5235 }
5236
5237 fprintf(stdout, "%s\n", str);
5238 }
5239 fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
5240 cpi->hba_eng_cnt);
5241 fprintf(stdout, "%s maximum target: %d\n", adapter_str,
5242 cpi->max_target);
5243 fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
5244 cpi->max_lun);
5245 fprintf(stdout, "%s highest path ID in subsystem: %d\n",
5246 adapter_str, cpi->hpath_id);
5247 fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
5248 cpi->initiator_id);
5249 fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
5250 fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
5251 fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
5252 adapter_str, cpi->hba_vendor);
5253 fprintf(stdout, "%s HBA device ID: 0x%04x\n",
5254 adapter_str, cpi->hba_device);
5255 fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
5256 adapter_str, cpi->hba_subvendor);
5257 fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
5258 adapter_str, cpi->hba_subdevice);
5259 fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
5260 fprintf(stdout, "%s base transfer speed: ", adapter_str);
5261 if (cpi->base_transfer_speed > 1000)
5262 fprintf(stdout, "%d.%03dMB/sec\n",
5263 cpi->base_transfer_speed / 1000,
5264 cpi->base_transfer_speed % 1000);
5265 else
5266 fprintf(stdout, "%dKB/sec\n",
5267 (cpi->base_transfer_speed % 1000) * 1000);
5268 fprintf(stdout, "%s maximum transfer size: %u bytes\n",
5269 adapter_str, cpi->maxio);
5270 }
5271
5272 static int
get_print_cts(struct cam_device * device,int user_settings,int quiet,struct ccb_trans_settings * cts)5273 get_print_cts(struct cam_device *device, int user_settings, int quiet,
5274 struct ccb_trans_settings *cts)
5275 {
5276 int retval;
5277 union ccb *ccb;
5278
5279 retval = 0;
5280 ccb = cam_getccb(device);
5281
5282 if (ccb == NULL) {
5283 warnx("get_print_cts: error allocating ccb");
5284 return(1);
5285 }
5286
5287 bzero(&(&ccb->ccb_h)[1],
5288 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
5289
5290 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
5291
5292 if (user_settings == 0)
5293 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
5294 else
5295 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
5296
5297 if (cam_send_ccb(device, ccb) < 0) {
5298 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
5299 if (arglist & CAM_ARG_VERBOSE)
5300 cam_error_print(device, ccb, CAM_ESF_ALL,
5301 CAM_EPF_ALL, stderr);
5302 retval = 1;
5303 goto get_print_cts_bailout;
5304 }
5305
5306 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5307 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
5308 if (arglist & CAM_ARG_VERBOSE)
5309 cam_error_print(device, ccb, CAM_ESF_ALL,
5310 CAM_EPF_ALL, stderr);
5311 retval = 1;
5312 goto get_print_cts_bailout;
5313 }
5314
5315 if (quiet == 0)
5316 cts_print(device, &ccb->cts);
5317
5318 if (cts != NULL)
5319 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
5320
5321 get_print_cts_bailout:
5322
5323 cam_freeccb(ccb);
5324
5325 return(retval);
5326 }
5327
5328 static int
ratecontrol(struct cam_device * device,int retry_count,int timeout,int argc,char ** argv,char * combinedopt)5329 ratecontrol(struct cam_device *device, int retry_count, int timeout,
5330 int argc, char **argv, char *combinedopt)
5331 {
5332 int c;
5333 union ccb *ccb;
5334 int user_settings = 0;
5335 int retval = 0;
5336 int disc_enable = -1, tag_enable = -1;
5337 int mode = -1;
5338 int offset = -1;
5339 double syncrate = -1;
5340 int bus_width = -1;
5341 int quiet = 0;
5342 int change_settings = 0, send_tur = 0;
5343 struct ccb_pathinq cpi;
5344
5345 ccb = cam_getccb(device);
5346 if (ccb == NULL) {
5347 warnx("ratecontrol: error allocating ccb");
5348 return(1);
5349 }
5350 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5351 switch(c){
5352 case 'a':
5353 send_tur = 1;
5354 break;
5355 case 'c':
5356 user_settings = 0;
5357 break;
5358 case 'D':
5359 if (strncasecmp(optarg, "enable", 6) == 0)
5360 disc_enable = 1;
5361 else if (strncasecmp(optarg, "disable", 7) == 0)
5362 disc_enable = 0;
5363 else {
5364 warnx("-D argument \"%s\" is unknown", optarg);
5365 retval = 1;
5366 goto ratecontrol_bailout;
5367 }
5368 change_settings = 1;
5369 break;
5370 case 'M':
5371 mode = ata_string2mode(optarg);
5372 if (mode < 0) {
5373 warnx("unknown mode '%s'", optarg);
5374 retval = 1;
5375 goto ratecontrol_bailout;
5376 }
5377 change_settings = 1;
5378 break;
5379 case 'O':
5380 offset = strtol(optarg, NULL, 0);
5381 if (offset < 0) {
5382 warnx("offset value %d is < 0", offset);
5383 retval = 1;
5384 goto ratecontrol_bailout;
5385 }
5386 change_settings = 1;
5387 break;
5388 case 'q':
5389 quiet++;
5390 break;
5391 case 'R':
5392 syncrate = atof(optarg);
5393 if (syncrate < 0) {
5394 warnx("sync rate %f is < 0", syncrate);
5395 retval = 1;
5396 goto ratecontrol_bailout;
5397 }
5398 change_settings = 1;
5399 break;
5400 case 'T':
5401 if (strncasecmp(optarg, "enable", 6) == 0)
5402 tag_enable = 1;
5403 else if (strncasecmp(optarg, "disable", 7) == 0)
5404 tag_enable = 0;
5405 else {
5406 warnx("-T argument \"%s\" is unknown", optarg);
5407 retval = 1;
5408 goto ratecontrol_bailout;
5409 }
5410 change_settings = 1;
5411 break;
5412 case 'U':
5413 user_settings = 1;
5414 break;
5415 case 'W':
5416 bus_width = strtol(optarg, NULL, 0);
5417 if (bus_width < 0) {
5418 warnx("bus width %d is < 0", bus_width);
5419 retval = 1;
5420 goto ratecontrol_bailout;
5421 }
5422 change_settings = 1;
5423 break;
5424 default:
5425 break;
5426 }
5427 }
5428 bzero(&(&ccb->ccb_h)[1],
5429 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
5430 /*
5431 * Grab path inquiry information, so we can determine whether
5432 * or not the initiator is capable of the things that the user
5433 * requests.
5434 */
5435 ccb->ccb_h.func_code = XPT_PATH_INQ;
5436 if (cam_send_ccb(device, ccb) < 0) {
5437 perror("error sending XPT_PATH_INQ CCB");
5438 if (arglist & CAM_ARG_VERBOSE) {
5439 cam_error_print(device, ccb, CAM_ESF_ALL,
5440 CAM_EPF_ALL, stderr);
5441 }
5442 retval = 1;
5443 goto ratecontrol_bailout;
5444 }
5445 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5446 warnx("XPT_PATH_INQ CCB failed");
5447 if (arglist & CAM_ARG_VERBOSE) {
5448 cam_error_print(device, ccb, CAM_ESF_ALL,
5449 CAM_EPF_ALL, stderr);
5450 }
5451 retval = 1;
5452 goto ratecontrol_bailout;
5453 }
5454 bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
5455 bzero(&(&ccb->ccb_h)[1],
5456 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
5457 if (quiet == 0) {
5458 fprintf(stdout, "%s parameters:\n",
5459 user_settings ? "User" : "Current");
5460 }
5461 retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
5462 if (retval != 0)
5463 goto ratecontrol_bailout;
5464
5465 if (arglist & CAM_ARG_VERBOSE)
5466 cpi_print(&cpi);
5467
5468 if (change_settings) {
5469 int didsettings = 0;
5470 struct ccb_trans_settings_spi *spi = NULL;
5471 struct ccb_trans_settings_pata *pata = NULL;
5472 struct ccb_trans_settings_sata *sata = NULL;
5473 struct ccb_trans_settings_ata *ata = NULL;
5474 struct ccb_trans_settings_scsi *scsi = NULL;
5475
5476 if (ccb->cts.transport == XPORT_SPI)
5477 spi = &ccb->cts.xport_specific.spi;
5478 if (ccb->cts.transport == XPORT_ATA)
5479 pata = &ccb->cts.xport_specific.ata;
5480 if (ccb->cts.transport == XPORT_SATA)
5481 sata = &ccb->cts.xport_specific.sata;
5482 if (ccb->cts.protocol == PROTO_ATA)
5483 ata = &ccb->cts.proto_specific.ata;
5484 if (ccb->cts.protocol == PROTO_SCSI)
5485 scsi = &ccb->cts.proto_specific.scsi;
5486 ccb->cts.xport_specific.valid = 0;
5487 ccb->cts.proto_specific.valid = 0;
5488 if (spi && disc_enable != -1) {
5489 spi->valid |= CTS_SPI_VALID_DISC;
5490 if (disc_enable == 0)
5491 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
5492 else
5493 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
5494 didsettings++;
5495 }
5496 if (tag_enable != -1) {
5497 if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
5498 warnx("HBA does not support tagged queueing, "
5499 "so you cannot modify tag settings");
5500 retval = 1;
5501 goto ratecontrol_bailout;
5502 }
5503 if (ata) {
5504 ata->valid |= CTS_SCSI_VALID_TQ;
5505 if (tag_enable == 0)
5506 ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
5507 else
5508 ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
5509 didsettings++;
5510 } else if (scsi) {
5511 scsi->valid |= CTS_SCSI_VALID_TQ;
5512 if (tag_enable == 0)
5513 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
5514 else
5515 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
5516 didsettings++;
5517 }
5518 }
5519 if (spi && offset != -1) {
5520 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5521 warnx("HBA is not capable of changing offset");
5522 retval = 1;
5523 goto ratecontrol_bailout;
5524 }
5525 spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
5526 spi->sync_offset = offset;
5527 didsettings++;
5528 }
5529 if (spi && syncrate != -1) {
5530 int prelim_sync_period;
5531
5532 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5533 warnx("HBA is not capable of changing "
5534 "transfer rates");
5535 retval = 1;
5536 goto ratecontrol_bailout;
5537 }
5538 spi->valid |= CTS_SPI_VALID_SYNC_RATE;
5539 /*
5540 * The sync rate the user gives us is in MHz.
5541 * We need to translate it into KHz for this
5542 * calculation.
5543 */
5544 syncrate *= 1000;
5545 /*
5546 * Next, we calculate a "preliminary" sync period
5547 * in tenths of a nanosecond.
5548 */
5549 if (syncrate == 0)
5550 prelim_sync_period = 0;
5551 else
5552 prelim_sync_period = 10000000 / syncrate;
5553 spi->sync_period =
5554 scsi_calc_syncparam(prelim_sync_period);
5555 didsettings++;
5556 }
5557 if (sata && syncrate != -1) {
5558 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5559 warnx("HBA is not capable of changing "
5560 "transfer rates");
5561 retval = 1;
5562 goto ratecontrol_bailout;
5563 }
5564 if (!user_settings) {
5565 warnx("You can modify only user rate "
5566 "settings for SATA");
5567 retval = 1;
5568 goto ratecontrol_bailout;
5569 }
5570 sata->revision = ata_speed2revision(syncrate * 100);
5571 if (sata->revision < 0) {
5572 warnx("Invalid rate %f", syncrate);
5573 retval = 1;
5574 goto ratecontrol_bailout;
5575 }
5576 sata->valid |= CTS_SATA_VALID_REVISION;
5577 didsettings++;
5578 }
5579 if ((pata || sata) && mode != -1) {
5580 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5581 warnx("HBA is not capable of changing "
5582 "transfer rates");
5583 retval = 1;
5584 goto ratecontrol_bailout;
5585 }
5586 if (!user_settings) {
5587 warnx("You can modify only user mode "
5588 "settings for ATA/SATA");
5589 retval = 1;
5590 goto ratecontrol_bailout;
5591 }
5592 if (pata) {
5593 pata->mode = mode;
5594 pata->valid |= CTS_ATA_VALID_MODE;
5595 } else {
5596 sata->mode = mode;
5597 sata->valid |= CTS_SATA_VALID_MODE;
5598 }
5599 didsettings++;
5600 }
5601 /*
5602 * The bus_width argument goes like this:
5603 * 0 == 8 bit
5604 * 1 == 16 bit
5605 * 2 == 32 bit
5606 * Therefore, if you shift the number of bits given on the
5607 * command line right by 4, you should get the correct
5608 * number.
5609 */
5610 if (spi && bus_width != -1) {
5611 /*
5612 * We might as well validate things here with a
5613 * decipherable error message, rather than what
5614 * will probably be an indecipherable error message
5615 * by the time it gets back to us.
5616 */
5617 if ((bus_width == 16)
5618 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
5619 warnx("HBA does not support 16 bit bus width");
5620 retval = 1;
5621 goto ratecontrol_bailout;
5622 } else if ((bus_width == 32)
5623 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
5624 warnx("HBA does not support 32 bit bus width");
5625 retval = 1;
5626 goto ratecontrol_bailout;
5627 } else if ((bus_width != 8)
5628 && (bus_width != 16)
5629 && (bus_width != 32)) {
5630 warnx("Invalid bus width %d", bus_width);
5631 retval = 1;
5632 goto ratecontrol_bailout;
5633 }
5634 spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
5635 spi->bus_width = bus_width >> 4;
5636 didsettings++;
5637 }
5638 if (didsettings == 0) {
5639 goto ratecontrol_bailout;
5640 }
5641 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
5642 if (cam_send_ccb(device, ccb) < 0) {
5643 perror("error sending XPT_SET_TRAN_SETTINGS CCB");
5644 if (arglist & CAM_ARG_VERBOSE) {
5645 cam_error_print(device, ccb, CAM_ESF_ALL,
5646 CAM_EPF_ALL, stderr);
5647 }
5648 retval = 1;
5649 goto ratecontrol_bailout;
5650 }
5651 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5652 warnx("XPT_SET_TRANS_SETTINGS CCB failed");
5653 if (arglist & CAM_ARG_VERBOSE) {
5654 cam_error_print(device, ccb, CAM_ESF_ALL,
5655 CAM_EPF_ALL, stderr);
5656 }
5657 retval = 1;
5658 goto ratecontrol_bailout;
5659 }
5660 }
5661 if (send_tur) {
5662 retval = testunitready(device, retry_count, timeout,
5663 (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
5664 /*
5665 * If the TUR didn't succeed, just bail.
5666 */
5667 if (retval != 0) {
5668 if (quiet == 0)
5669 fprintf(stderr, "Test Unit Ready failed\n");
5670 goto ratecontrol_bailout;
5671 }
5672 }
5673 if ((change_settings || send_tur) && !quiet &&
5674 (ccb->cts.transport == XPORT_ATA ||
5675 ccb->cts.transport == XPORT_SATA || send_tur)) {
5676 fprintf(stdout, "New parameters:\n");
5677 retval = get_print_cts(device, user_settings, 0, NULL);
5678 }
5679
5680 ratecontrol_bailout:
5681 cam_freeccb(ccb);
5682 return(retval);
5683 }
5684
5685 static int
scsiformat(struct cam_device * device,int argc,char ** argv,char * combinedopt,int retry_count,int timeout)5686 scsiformat(struct cam_device *device, int argc, char **argv,
5687 char *combinedopt, int retry_count, int timeout)
5688 {
5689 union ccb *ccb;
5690 int c;
5691 int ycount = 0, quiet = 0;
5692 int error = 0, retval = 0;
5693 int use_timeout = 10800 * 1000;
5694 int immediate = 1;
5695 struct format_defect_list_header fh;
5696 u_int8_t *data_ptr = NULL;
5697 u_int32_t dxfer_len = 0;
5698 u_int8_t byte2 = 0;
5699 int num_warnings = 0;
5700 int reportonly = 0;
5701
5702 ccb = cam_getccb(device);
5703
5704 if (ccb == NULL) {
5705 warnx("scsiformat: error allocating ccb");
5706 return(1);
5707 }
5708
5709 bzero(&(&ccb->ccb_h)[1],
5710 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5711
5712 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5713 switch(c) {
5714 case 'q':
5715 quiet++;
5716 break;
5717 case 'r':
5718 reportonly = 1;
5719 break;
5720 case 'w':
5721 immediate = 0;
5722 break;
5723 case 'y':
5724 ycount++;
5725 break;
5726 }
5727 }
5728
5729 if (reportonly)
5730 goto doreport;
5731
5732 if (quiet == 0) {
5733 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5734 "following device:\n");
5735
5736 error = scsidoinquiry(device, argc, argv, combinedopt,
5737 retry_count, timeout);
5738
5739 if (error != 0) {
5740 warnx("scsiformat: error sending inquiry");
5741 goto scsiformat_bailout;
5742 }
5743 }
5744
5745 if (ycount == 0) {
5746 if (!get_confirmation()) {
5747 error = 1;
5748 goto scsiformat_bailout;
5749 }
5750 }
5751
5752 if (timeout != 0)
5753 use_timeout = timeout;
5754
5755 if (quiet == 0) {
5756 fprintf(stdout, "Current format timeout is %d seconds\n",
5757 use_timeout / 1000);
5758 }
5759
5760 /*
5761 * If the user hasn't disabled questions and didn't specify a
5762 * timeout on the command line, ask them if they want the current
5763 * timeout.
5764 */
5765 if ((ycount == 0)
5766 && (timeout == 0)) {
5767 char str[1024];
5768 int new_timeout = 0;
5769
5770 fprintf(stdout, "Enter new timeout in seconds or press\n"
5771 "return to keep the current timeout [%d] ",
5772 use_timeout / 1000);
5773
5774 if (fgets(str, sizeof(str), stdin) != NULL) {
5775 if (str[0] != '\0')
5776 new_timeout = atoi(str);
5777 }
5778
5779 if (new_timeout != 0) {
5780 use_timeout = new_timeout * 1000;
5781 fprintf(stdout, "Using new timeout value %d\n",
5782 use_timeout / 1000);
5783 }
5784 }
5785
5786 /*
5787 * Keep this outside the if block below to silence any unused
5788 * variable warnings.
5789 */
5790 bzero(&fh, sizeof(fh));
5791
5792 /*
5793 * If we're in immediate mode, we've got to include the format
5794 * header
5795 */
5796 if (immediate != 0) {
5797 fh.byte2 = FU_DLH_IMMED;
5798 data_ptr = (u_int8_t *)&fh;
5799 dxfer_len = sizeof(fh);
5800 byte2 = FU_FMT_DATA;
5801 } else if (quiet == 0) {
5802 fprintf(stdout, "Formatting...");
5803 fflush(stdout);
5804 }
5805
5806 scsi_format_unit(&ccb->csio,
5807 /* retries */ retry_count,
5808 /* cbfcnp */ NULL,
5809 /* tag_action */ MSG_SIMPLE_Q_TAG,
5810 /* byte2 */ byte2,
5811 /* ileave */ 0,
5812 /* data_ptr */ data_ptr,
5813 /* dxfer_len */ dxfer_len,
5814 /* sense_len */ SSD_FULL_SIZE,
5815 /* timeout */ use_timeout);
5816
5817 /* Disable freezing the device queue */
5818 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5819
5820 if (arglist & CAM_ARG_ERR_RECOVER)
5821 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5822
5823 if (((retval = cam_send_ccb(device, ccb)) < 0)
5824 || ((immediate == 0)
5825 && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
5826 const char errstr[] = "error sending format command";
5827
5828 if (retval < 0)
5829 warn(errstr);
5830 else
5831 warnx(errstr);
5832
5833 if (arglist & CAM_ARG_VERBOSE) {
5834 cam_error_print(device, ccb, CAM_ESF_ALL,
5835 CAM_EPF_ALL, stderr);
5836 }
5837 error = 1;
5838 goto scsiformat_bailout;
5839 }
5840
5841 /*
5842 * If we ran in non-immediate mode, we already checked for errors
5843 * above and printed out any necessary information. If we're in
5844 * immediate mode, we need to loop through and get status
5845 * information periodically.
5846 */
5847 if (immediate == 0) {
5848 if (quiet == 0) {
5849 fprintf(stdout, "Format Complete\n");
5850 }
5851 goto scsiformat_bailout;
5852 }
5853
5854 doreport:
5855 do {
5856 cam_status status;
5857
5858 bzero(&(&ccb->ccb_h)[1],
5859 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5860
5861 /*
5862 * There's really no need to do error recovery or
5863 * retries here, since we're just going to sit in a
5864 * loop and wait for the device to finish formatting.
5865 */
5866 scsi_test_unit_ready(&ccb->csio,
5867 /* retries */ 0,
5868 /* cbfcnp */ NULL,
5869 /* tag_action */ MSG_SIMPLE_Q_TAG,
5870 /* sense_len */ SSD_FULL_SIZE,
5871 /* timeout */ 5000);
5872
5873 /* Disable freezing the device queue */
5874 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5875
5876 retval = cam_send_ccb(device, ccb);
5877
5878 /*
5879 * If we get an error from the ioctl, bail out. SCSI
5880 * errors are expected.
5881 */
5882 if (retval < 0) {
5883 warn("error sending CAMIOCOMMAND ioctl");
5884 if (arglist & CAM_ARG_VERBOSE) {
5885 cam_error_print(device, ccb, CAM_ESF_ALL,
5886 CAM_EPF_ALL, stderr);
5887 }
5888 error = 1;
5889 goto scsiformat_bailout;
5890 }
5891
5892 status = ccb->ccb_h.status & CAM_STATUS_MASK;
5893
5894 if ((status != CAM_REQ_CMP)
5895 && (status == CAM_SCSI_STATUS_ERROR)
5896 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
5897 struct scsi_sense_data *sense;
5898 int error_code, sense_key, asc, ascq;
5899
5900 sense = &ccb->csio.sense_data;
5901 scsi_extract_sense_len(sense, ccb->csio.sense_len -
5902 ccb->csio.sense_resid, &error_code, &sense_key,
5903 &asc, &ascq, /*show_errors*/ 1);
5904
5905 /*
5906 * According to the SCSI-2 and SCSI-3 specs, a
5907 * drive that is in the middle of a format should
5908 * return NOT READY with an ASC of "logical unit
5909 * not ready, format in progress". The sense key
5910 * specific bytes will then be a progress indicator.
5911 */
5912 if ((sense_key == SSD_KEY_NOT_READY)
5913 && (asc == 0x04) && (ascq == 0x04)) {
5914 uint8_t sks[3];
5915
5916 if ((scsi_get_sks(sense, ccb->csio.sense_len -
5917 ccb->csio.sense_resid, sks) == 0)
5918 && (quiet == 0)) {
5919 int val;
5920 u_int64_t percentage;
5921
5922 val = scsi_2btoul(&sks[1]);
5923 percentage = 10000 * val;
5924
5925 fprintf(stdout,
5926 "\rFormatting: %ju.%02u %% "
5927 "(%d/%d) done",
5928 (uintmax_t)(percentage /
5929 (0x10000 * 100)),
5930 (unsigned)((percentage /
5931 0x10000) % 100),
5932 val, 0x10000);
5933 fflush(stdout);
5934 } else if ((quiet == 0)
5935 && (++num_warnings <= 1)) {
5936 warnx("Unexpected SCSI Sense Key "
5937 "Specific value returned "
5938 "during format:");
5939 scsi_sense_print(device, &ccb->csio,
5940 stderr);
5941 warnx("Unable to print status "
5942 "information, but format will "
5943 "proceed.");
5944 warnx("will exit when format is "
5945 "complete");
5946 }
5947 sleep(1);
5948 } else {
5949 warnx("Unexpected SCSI error during format");
5950 cam_error_print(device, ccb, CAM_ESF_ALL,
5951 CAM_EPF_ALL, stderr);
5952 error = 1;
5953 goto scsiformat_bailout;
5954 }
5955
5956 } else if (status != CAM_REQ_CMP) {
5957 warnx("Unexpected CAM status %#x", status);
5958 if (arglist & CAM_ARG_VERBOSE)
5959 cam_error_print(device, ccb, CAM_ESF_ALL,
5960 CAM_EPF_ALL, stderr);
5961 error = 1;
5962 goto scsiformat_bailout;
5963 }
5964
5965 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
5966
5967 if (quiet == 0)
5968 fprintf(stdout, "\nFormat Complete\n");
5969
5970 scsiformat_bailout:
5971
5972 cam_freeccb(ccb);
5973
5974 return(error);
5975 }
5976
5977 static int
scsisanitize(struct cam_device * device,int argc,char ** argv,char * combinedopt,int retry_count,int timeout)5978 scsisanitize(struct cam_device *device, int argc, char **argv,
5979 char *combinedopt, int retry_count, int timeout)
5980 {
5981 union ccb *ccb;
5982 u_int8_t action = 0;
5983 int c;
5984 int ycount = 0, quiet = 0;
5985 int error = 0, retval = 0;
5986 int use_timeout = 10800 * 1000;
5987 int immediate = 1;
5988 int invert = 0;
5989 int passes = 0;
5990 int ause = 0;
5991 int fd = -1;
5992 const char *pattern = NULL;
5993 u_int8_t *data_ptr = NULL;
5994 u_int32_t dxfer_len = 0;
5995 u_int8_t byte2 = 0;
5996 int num_warnings = 0;
5997 int reportonly = 0;
5998
5999 ccb = cam_getccb(device);
6000
6001 if (ccb == NULL) {
6002 warnx("scsisanitize: error allocating ccb");
6003 return(1);
6004 }
6005
6006 bzero(&(&ccb->ccb_h)[1],
6007 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6008
6009 while ((c = getopt(argc, argv, combinedopt)) != -1) {
6010 switch(c) {
6011 case 'a':
6012 if (strcasecmp(optarg, "overwrite") == 0)
6013 action = SSZ_SERVICE_ACTION_OVERWRITE;
6014 else if (strcasecmp(optarg, "block") == 0)
6015 action = SSZ_SERVICE_ACTION_BLOCK_ERASE;
6016 else if (strcasecmp(optarg, "crypto") == 0)
6017 action = SSZ_SERVICE_ACTION_CRYPTO_ERASE;
6018 else if (strcasecmp(optarg, "exitfailure") == 0)
6019 action = SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE;
6020 else {
6021 warnx("invalid service operation \"%s\"",
6022 optarg);
6023 error = 1;
6024 goto scsisanitize_bailout;
6025 }
6026 break;
6027 case 'c':
6028 passes = strtol(optarg, NULL, 0);
6029 if (passes < 1 || passes > 31) {
6030 warnx("invalid passes value %d", passes);
6031 error = 1;
6032 goto scsisanitize_bailout;
6033 }
6034 break;
6035 case 'I':
6036 invert = 1;
6037 break;
6038 case 'P':
6039 pattern = optarg;
6040 break;
6041 case 'q':
6042 quiet++;
6043 break;
6044 case 'U':
6045 ause = 1;
6046 break;
6047 case 'r':
6048 reportonly = 1;
6049 break;
6050 case 'w':
6051 immediate = 0;
6052 break;
6053 case 'y':
6054 ycount++;
6055 break;
6056 }
6057 }
6058
6059 if (reportonly)
6060 goto doreport;
6061
6062 if (action == 0) {
6063 warnx("an action is required");
6064 error = 1;
6065 goto scsisanitize_bailout;
6066 } else if (action == SSZ_SERVICE_ACTION_OVERWRITE) {
6067 struct scsi_sanitize_parameter_list *pl;
6068 struct stat sb;
6069 ssize_t sz, amt;
6070
6071 if (pattern == NULL) {
6072 warnx("overwrite action requires -P argument");
6073 error = 1;
6074 goto scsisanitize_bailout;
6075 }
6076 fd = open(pattern, O_RDONLY);
6077 if (fd < 0) {
6078 warn("cannot open pattern file %s", pattern);
6079 error = 1;
6080 goto scsisanitize_bailout;
6081 }
6082 if (fstat(fd, &sb) < 0) {
6083 warn("cannot stat pattern file %s", pattern);
6084 error = 1;
6085 goto scsisanitize_bailout;
6086 }
6087 sz = sb.st_size;
6088 if (sz > SSZPL_MAX_PATTERN_LENGTH) {
6089 warnx("pattern file size exceeds maximum value %d",
6090 SSZPL_MAX_PATTERN_LENGTH);
6091 error = 1;
6092 goto scsisanitize_bailout;
6093 }
6094 dxfer_len = sizeof(*pl) + sz;
6095 data_ptr = calloc(1, dxfer_len);
6096 if (data_ptr == NULL) {
6097 warnx("cannot allocate parameter list buffer");
6098 error = 1;
6099 goto scsisanitize_bailout;
6100 }
6101
6102 amt = read(fd, data_ptr + sizeof(*pl), sz);
6103 if (amt < 0) {
6104 warn("cannot read pattern file");
6105 error = 1;
6106 goto scsisanitize_bailout;
6107 } else if (amt != sz) {
6108 warnx("short pattern file read");
6109 error = 1;
6110 goto scsisanitize_bailout;
6111 }
6112
6113 pl = (struct scsi_sanitize_parameter_list *)data_ptr;
6114 if (passes == 0)
6115 pl->byte1 = 1;
6116 else
6117 pl->byte1 = passes;
6118 if (invert != 0)
6119 pl->byte1 |= SSZPL_INVERT;
6120 scsi_ulto2b(sz, pl->length);
6121 } else {
6122 const char *arg;
6123
6124 if (passes != 0)
6125 arg = "-c";
6126 else if (invert != 0)
6127 arg = "-I";
6128 else if (pattern != NULL)
6129 arg = "-P";
6130 else
6131 arg = NULL;
6132 if (arg != NULL) {
6133 warnx("%s argument only valid with overwrite "
6134 "operation", arg);
6135 error = 1;
6136 goto scsisanitize_bailout;
6137 }
6138 }
6139
6140 if (quiet == 0) {
6141 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
6142 "following device:\n");
6143
6144 error = scsidoinquiry(device, argc, argv, combinedopt,
6145 retry_count, timeout);
6146
6147 if (error != 0) {
6148 warnx("scsisanitize: error sending inquiry");
6149 goto scsisanitize_bailout;
6150 }
6151 }
6152
6153 if (ycount == 0) {
6154 if (!get_confirmation()) {
6155 error = 1;
6156 goto scsisanitize_bailout;
6157 }
6158 }
6159
6160 if (timeout != 0)
6161 use_timeout = timeout;
6162
6163 if (quiet == 0) {
6164 fprintf(stdout, "Current sanitize timeout is %d seconds\n",
6165 use_timeout / 1000);
6166 }
6167
6168 /*
6169 * If the user hasn't disabled questions and didn't specify a
6170 * timeout on the command line, ask them if they want the current
6171 * timeout.
6172 */
6173 if ((ycount == 0)
6174 && (timeout == 0)) {
6175 char str[1024];
6176 int new_timeout = 0;
6177
6178 fprintf(stdout, "Enter new timeout in seconds or press\n"
6179 "return to keep the current timeout [%d] ",
6180 use_timeout / 1000);
6181
6182 if (fgets(str, sizeof(str), stdin) != NULL) {
6183 if (str[0] != '\0')
6184 new_timeout = atoi(str);
6185 }
6186
6187 if (new_timeout != 0) {
6188 use_timeout = new_timeout * 1000;
6189 fprintf(stdout, "Using new timeout value %d\n",
6190 use_timeout / 1000);
6191 }
6192 }
6193
6194 byte2 = action;
6195 if (ause != 0)
6196 byte2 |= SSZ_UNRESTRICTED_EXIT;
6197 if (immediate != 0)
6198 byte2 |= SSZ_IMMED;
6199
6200 scsi_sanitize(&ccb->csio,
6201 /* retries */ retry_count,
6202 /* cbfcnp */ NULL,
6203 /* tag_action */ MSG_SIMPLE_Q_TAG,
6204 /* byte2 */ byte2,
6205 /* control */ 0,
6206 /* data_ptr */ data_ptr,
6207 /* dxfer_len */ dxfer_len,
6208 /* sense_len */ SSD_FULL_SIZE,
6209 /* timeout */ use_timeout);
6210
6211 /* Disable freezing the device queue */
6212 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6213
6214 if (arglist & CAM_ARG_ERR_RECOVER)
6215 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6216
6217 if (cam_send_ccb(device, ccb) < 0) {
6218 warn("error sending sanitize command");
6219 error = 1;
6220 goto scsisanitize_bailout;
6221 }
6222
6223 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6224 struct scsi_sense_data *sense;
6225 int error_code, sense_key, asc, ascq;
6226
6227 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
6228 CAM_SCSI_STATUS_ERROR) {
6229 sense = &ccb->csio.sense_data;
6230 scsi_extract_sense_len(sense, ccb->csio.sense_len -
6231 ccb->csio.sense_resid, &error_code, &sense_key,
6232 &asc, &ascq, /*show_errors*/ 1);
6233
6234 if (sense_key == SSD_KEY_ILLEGAL_REQUEST &&
6235 asc == 0x20 && ascq == 0x00)
6236 warnx("sanitize is not supported by "
6237 "this device");
6238 else
6239 warnx("error sanitizing this device");
6240 } else
6241 warnx("error sanitizing this device");
6242
6243 if (arglist & CAM_ARG_VERBOSE) {
6244 cam_error_print(device, ccb, CAM_ESF_ALL,
6245 CAM_EPF_ALL, stderr);
6246 }
6247 error = 1;
6248 goto scsisanitize_bailout;
6249 }
6250
6251 /*
6252 * If we ran in non-immediate mode, we already checked for errors
6253 * above and printed out any necessary information. If we're in
6254 * immediate mode, we need to loop through and get status
6255 * information periodically.
6256 */
6257 if (immediate == 0) {
6258 if (quiet == 0) {
6259 fprintf(stdout, "Sanitize Complete\n");
6260 }
6261 goto scsisanitize_bailout;
6262 }
6263
6264 doreport:
6265 do {
6266 cam_status status;
6267
6268 bzero(&(&ccb->ccb_h)[1],
6269 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6270
6271 /*
6272 * There's really no need to do error recovery or
6273 * retries here, since we're just going to sit in a
6274 * loop and wait for the device to finish sanitizing.
6275 */
6276 scsi_test_unit_ready(&ccb->csio,
6277 /* retries */ 0,
6278 /* cbfcnp */ NULL,
6279 /* tag_action */ MSG_SIMPLE_Q_TAG,
6280 /* sense_len */ SSD_FULL_SIZE,
6281 /* timeout */ 5000);
6282
6283 /* Disable freezing the device queue */
6284 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6285
6286 retval = cam_send_ccb(device, ccb);
6287
6288 /*
6289 * If we get an error from the ioctl, bail out. SCSI
6290 * errors are expected.
6291 */
6292 if (retval < 0) {
6293 warn("error sending CAMIOCOMMAND ioctl");
6294 if (arglist & CAM_ARG_VERBOSE) {
6295 cam_error_print(device, ccb, CAM_ESF_ALL,
6296 CAM_EPF_ALL, stderr);
6297 }
6298 error = 1;
6299 goto scsisanitize_bailout;
6300 }
6301
6302 status = ccb->ccb_h.status & CAM_STATUS_MASK;
6303
6304 if ((status != CAM_REQ_CMP)
6305 && (status == CAM_SCSI_STATUS_ERROR)
6306 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
6307 struct scsi_sense_data *sense;
6308 int error_code, sense_key, asc, ascq;
6309
6310 sense = &ccb->csio.sense_data;
6311 scsi_extract_sense_len(sense, ccb->csio.sense_len -
6312 ccb->csio.sense_resid, &error_code, &sense_key,
6313 &asc, &ascq, /*show_errors*/ 1);
6314
6315 /*
6316 * According to the SCSI-3 spec, a drive that is in the
6317 * middle of a sanitize should return NOT READY with an
6318 * ASC of "logical unit not ready, sanitize in
6319 * progress". The sense key specific bytes will then
6320 * be a progress indicator.
6321 */
6322 if ((sense_key == SSD_KEY_NOT_READY)
6323 && (asc == 0x04) && (ascq == 0x1b)) {
6324 uint8_t sks[3];
6325
6326 if ((scsi_get_sks(sense, ccb->csio.sense_len -
6327 ccb->csio.sense_resid, sks) == 0)
6328 && (quiet == 0)) {
6329 int val;
6330 u_int64_t percentage;
6331
6332 val = scsi_2btoul(&sks[1]);
6333 percentage = 10000 * val;
6334
6335 fprintf(stdout,
6336 "\rSanitizing: %ju.%02u %% "
6337 "(%d/%d) done",
6338 (uintmax_t)(percentage /
6339 (0x10000 * 100)),
6340 (unsigned)((percentage /
6341 0x10000) % 100),
6342 val, 0x10000);
6343 fflush(stdout);
6344 } else if ((quiet == 0)
6345 && (++num_warnings <= 1)) {
6346 warnx("Unexpected SCSI Sense Key "
6347 "Specific value returned "
6348 "during sanitize:");
6349 scsi_sense_print(device, &ccb->csio,
6350 stderr);
6351 warnx("Unable to print status "
6352 "information, but sanitze will "
6353 "proceed.");
6354 warnx("will exit when sanitize is "
6355 "complete");
6356 }
6357 sleep(1);
6358 } else {
6359 warnx("Unexpected SCSI error during sanitize");
6360 cam_error_print(device, ccb, CAM_ESF_ALL,
6361 CAM_EPF_ALL, stderr);
6362 error = 1;
6363 goto scsisanitize_bailout;
6364 }
6365
6366 } else if (status != CAM_REQ_CMP) {
6367 warnx("Unexpected CAM status %#x", status);
6368 if (arglist & CAM_ARG_VERBOSE)
6369 cam_error_print(device, ccb, CAM_ESF_ALL,
6370 CAM_EPF_ALL, stderr);
6371 error = 1;
6372 goto scsisanitize_bailout;
6373 }
6374 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
6375
6376 if (quiet == 0)
6377 fprintf(stdout, "\nSanitize Complete\n");
6378
6379 scsisanitize_bailout:
6380 if (fd >= 0)
6381 close(fd);
6382 if (data_ptr != NULL)
6383 free(data_ptr);
6384 cam_freeccb(ccb);
6385
6386 return(error);
6387 }
6388
6389 static int
scsireportluns(struct cam_device * device,int argc,char ** argv,char * combinedopt,int retry_count,int timeout)6390 scsireportluns(struct cam_device *device, int argc, char **argv,
6391 char *combinedopt, int retry_count, int timeout)
6392 {
6393 union ccb *ccb;
6394 int c, countonly, lunsonly;
6395 struct scsi_report_luns_data *lundata;
6396 int alloc_len;
6397 uint8_t report_type;
6398 uint32_t list_len, i, j;
6399 int retval;
6400
6401 retval = 0;
6402 lundata = NULL;
6403 report_type = RPL_REPORT_DEFAULT;
6404 ccb = cam_getccb(device);
6405
6406 if (ccb == NULL) {
6407 warnx("%s: error allocating ccb", __func__);
6408 return (1);
6409 }
6410
6411 bzero(&(&ccb->ccb_h)[1],
6412 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6413
6414 countonly = 0;
6415 lunsonly = 0;
6416
6417 while ((c = getopt(argc, argv, combinedopt)) != -1) {
6418 switch (c) {
6419 case 'c':
6420 countonly++;
6421 break;
6422 case 'l':
6423 lunsonly++;
6424 break;
6425 case 'r':
6426 if (strcasecmp(optarg, "default") == 0)
6427 report_type = RPL_REPORT_DEFAULT;
6428 else if (strcasecmp(optarg, "wellknown") == 0)
6429 report_type = RPL_REPORT_WELLKNOWN;
6430 else if (strcasecmp(optarg, "all") == 0)
6431 report_type = RPL_REPORT_ALL;
6432 else {
6433 warnx("%s: invalid report type \"%s\"",
6434 __func__, optarg);
6435 retval = 1;
6436 goto bailout;
6437 }
6438 break;
6439 default:
6440 break;
6441 }
6442 }
6443
6444 if ((countonly != 0)
6445 && (lunsonly != 0)) {
6446 warnx("%s: you can only specify one of -c or -l", __func__);
6447 retval = 1;
6448 goto bailout;
6449 }
6450 /*
6451 * According to SPC-4, the allocation length must be at least 16
6452 * bytes -- enough for the header and one LUN.
6453 */
6454 alloc_len = sizeof(*lundata) + 8;
6455
6456 retry:
6457
6458 lundata = malloc(alloc_len);
6459
6460 if (lundata == NULL) {
6461 warn("%s: error mallocing %d bytes", __func__, alloc_len);
6462 retval = 1;
6463 goto bailout;
6464 }
6465
6466 scsi_report_luns(&ccb->csio,
6467 /*retries*/ retry_count,
6468 /*cbfcnp*/ NULL,
6469 /*tag_action*/ MSG_SIMPLE_Q_TAG,
6470 /*select_report*/ report_type,
6471 /*rpl_buf*/ lundata,
6472 /*alloc_len*/ alloc_len,
6473 /*sense_len*/ SSD_FULL_SIZE,
6474 /*timeout*/ timeout ? timeout : 5000);
6475
6476 /* Disable freezing the device queue */
6477 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6478
6479 if (arglist & CAM_ARG_ERR_RECOVER)
6480 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6481
6482 if (cam_send_ccb(device, ccb) < 0) {
6483 warn("error sending REPORT LUNS command");
6484
6485 if (arglist & CAM_ARG_VERBOSE)
6486 cam_error_print(device, ccb, CAM_ESF_ALL,
6487 CAM_EPF_ALL, stderr);
6488
6489 retval = 1;
6490 goto bailout;
6491 }
6492
6493 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6494 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6495 retval = 1;
6496 goto bailout;
6497 }
6498
6499
6500 list_len = scsi_4btoul(lundata->length);
6501
6502 /*
6503 * If we need to list the LUNs, and our allocation
6504 * length was too short, reallocate and retry.
6505 */
6506 if ((countonly == 0)
6507 && (list_len > (alloc_len - sizeof(*lundata)))) {
6508 alloc_len = list_len + sizeof(*lundata);
6509 free(lundata);
6510 goto retry;
6511 }
6512
6513 if (lunsonly == 0)
6514 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
6515 ((list_len / 8) > 1) ? "s" : "");
6516
6517 if (countonly != 0)
6518 goto bailout;
6519
6520 for (i = 0; i < (list_len / 8); i++) {
6521 int no_more;
6522
6523 no_more = 0;
6524 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
6525 if (j != 0)
6526 fprintf(stdout, ",");
6527 switch (lundata->luns[i].lundata[j] &
6528 RPL_LUNDATA_ATYP_MASK) {
6529 case RPL_LUNDATA_ATYP_PERIPH:
6530 if ((lundata->luns[i].lundata[j] &
6531 RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
6532 fprintf(stdout, "%d:",
6533 lundata->luns[i].lundata[j] &
6534 RPL_LUNDATA_PERIPH_BUS_MASK);
6535 else if ((j == 0)
6536 && ((lundata->luns[i].lundata[j+2] &
6537 RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
6538 no_more = 1;
6539
6540 fprintf(stdout, "%d",
6541 lundata->luns[i].lundata[j+1]);
6542 break;
6543 case RPL_LUNDATA_ATYP_FLAT: {
6544 uint8_t tmplun[2];
6545 tmplun[0] = lundata->luns[i].lundata[j] &
6546 RPL_LUNDATA_FLAT_LUN_MASK;
6547 tmplun[1] = lundata->luns[i].lundata[j+1];
6548
6549 fprintf(stdout, "%d", scsi_2btoul(tmplun));
6550 no_more = 1;
6551 break;
6552 }
6553 case RPL_LUNDATA_ATYP_LUN:
6554 fprintf(stdout, "%d:%d:%d",
6555 (lundata->luns[i].lundata[j+1] &
6556 RPL_LUNDATA_LUN_BUS_MASK) >> 5,
6557 lundata->luns[i].lundata[j] &
6558 RPL_LUNDATA_LUN_TARG_MASK,
6559 lundata->luns[i].lundata[j+1] &
6560 RPL_LUNDATA_LUN_LUN_MASK);
6561 break;
6562 case RPL_LUNDATA_ATYP_EXTLUN: {
6563 int field_len_code, eam_code;
6564
6565 eam_code = lundata->luns[i].lundata[j] &
6566 RPL_LUNDATA_EXT_EAM_MASK;
6567 field_len_code = (lundata->luns[i].lundata[j] &
6568 RPL_LUNDATA_EXT_LEN_MASK) >> 4;
6569
6570 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
6571 && (field_len_code == 0x00)) {
6572 fprintf(stdout, "%d",
6573 lundata->luns[i].lundata[j+1]);
6574 } else if ((eam_code ==
6575 RPL_LUNDATA_EXT_EAM_NOT_SPEC)
6576 && (field_len_code == 0x03)) {
6577 uint8_t tmp_lun[8];
6578
6579 /*
6580 * This format takes up all 8 bytes.
6581 * If we aren't starting at offset 0,
6582 * that's a bug.
6583 */
6584 if (j != 0) {
6585 fprintf(stdout, "Invalid "
6586 "offset %d for "
6587 "Extended LUN not "
6588 "specified format", j);
6589 no_more = 1;
6590 break;
6591 }
6592 bzero(tmp_lun, sizeof(tmp_lun));
6593 bcopy(&lundata->luns[i].lundata[j+1],
6594 &tmp_lun[1], sizeof(tmp_lun) - 1);
6595 fprintf(stdout, "%#jx",
6596 (intmax_t)scsi_8btou64(tmp_lun));
6597 no_more = 1;
6598 } else {
6599 fprintf(stderr, "Unknown Extended LUN"
6600 "Address method %#x, length "
6601 "code %#x", eam_code,
6602 field_len_code);
6603 no_more = 1;
6604 }
6605 break;
6606 }
6607 default:
6608 fprintf(stderr, "Unknown LUN address method "
6609 "%#x\n", lundata->luns[i].lundata[0] &
6610 RPL_LUNDATA_ATYP_MASK);
6611 break;
6612 }
6613 /*
6614 * For the flat addressing method, there are no
6615 * other levels after it.
6616 */
6617 if (no_more != 0)
6618 break;
6619 }
6620 fprintf(stdout, "\n");
6621 }
6622
6623 bailout:
6624
6625 cam_freeccb(ccb);
6626
6627 free(lundata);
6628
6629 return (retval);
6630 }
6631
6632 static int
scsireadcapacity(struct cam_device * device,int argc,char ** argv,char * combinedopt,int retry_count,int timeout)6633 scsireadcapacity(struct cam_device *device, int argc, char **argv,
6634 char *combinedopt, int retry_count, int timeout)
6635 {
6636 union ccb *ccb;
6637 int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
6638 struct scsi_read_capacity_data rcap;
6639 struct scsi_read_capacity_data_long rcaplong;
6640 uint64_t maxsector;
6641 uint32_t block_len;
6642 int retval;
6643 int c;
6644
6645 blocksizeonly = 0;
6646 humanize = 0;
6647 numblocks = 0;
6648 quiet = 0;
6649 sizeonly = 0;
6650 baseten = 0;
6651 retval = 0;
6652
6653 ccb = cam_getccb(device);
6654
6655 if (ccb == NULL) {
6656 warnx("%s: error allocating ccb", __func__);
6657 return (1);
6658 }
6659
6660 bzero(&(&ccb->ccb_h)[1],
6661 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6662
6663 while ((c = getopt(argc, argv, combinedopt)) != -1) {
6664 switch (c) {
6665 case 'b':
6666 blocksizeonly++;
6667 break;
6668 case 'h':
6669 humanize++;
6670 baseten = 0;
6671 break;
6672 case 'H':
6673 humanize++;
6674 baseten++;
6675 break;
6676 case 'N':
6677 numblocks++;
6678 break;
6679 case 'q':
6680 quiet++;
6681 break;
6682 case 's':
6683 sizeonly++;
6684 break;
6685 default:
6686 break;
6687 }
6688 }
6689
6690 if ((blocksizeonly != 0)
6691 && (numblocks != 0)) {
6692 warnx("%s: you can only specify one of -b or -N", __func__);
6693 retval = 1;
6694 goto bailout;
6695 }
6696
6697 if ((blocksizeonly != 0)
6698 && (sizeonly != 0)) {
6699 warnx("%s: you can only specify one of -b or -s", __func__);
6700 retval = 1;
6701 goto bailout;
6702 }
6703
6704 if ((humanize != 0)
6705 && (quiet != 0)) {
6706 warnx("%s: you can only specify one of -h/-H or -q", __func__);
6707 retval = 1;
6708 goto bailout;
6709 }
6710
6711 if ((humanize != 0)
6712 && (blocksizeonly != 0)) {
6713 warnx("%s: you can only specify one of -h/-H or -b", __func__);
6714 retval = 1;
6715 goto bailout;
6716 }
6717
6718 scsi_read_capacity(&ccb->csio,
6719 /*retries*/ retry_count,
6720 /*cbfcnp*/ NULL,
6721 /*tag_action*/ MSG_SIMPLE_Q_TAG,
6722 &rcap,
6723 SSD_FULL_SIZE,
6724 /*timeout*/ timeout ? timeout : 5000);
6725
6726 /* Disable freezing the device queue */
6727 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6728
6729 if (arglist & CAM_ARG_ERR_RECOVER)
6730 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6731
6732 if (cam_send_ccb(device, ccb) < 0) {
6733 warn("error sending READ CAPACITY command");
6734
6735 if (arglist & CAM_ARG_VERBOSE)
6736 cam_error_print(device, ccb, CAM_ESF_ALL,
6737 CAM_EPF_ALL, stderr);
6738
6739 retval = 1;
6740 goto bailout;
6741 }
6742
6743 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6744 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6745 retval = 1;
6746 goto bailout;
6747 }
6748
6749 maxsector = scsi_4btoul(rcap.addr);
6750 block_len = scsi_4btoul(rcap.length);
6751
6752 /*
6753 * A last block of 2^32-1 means that the true capacity is over 2TB,
6754 * and we need to issue the long READ CAPACITY to get the real
6755 * capacity. Otherwise, we're all set.
6756 */
6757 if (maxsector != 0xffffffff)
6758 goto do_print;
6759
6760 scsi_read_capacity_16(&ccb->csio,
6761 /*retries*/ retry_count,
6762 /*cbfcnp*/ NULL,
6763 /*tag_action*/ MSG_SIMPLE_Q_TAG,
6764 /*lba*/ 0,
6765 /*reladdr*/ 0,
6766 /*pmi*/ 0,
6767 /*rcap_buf*/ (uint8_t *)&rcaplong,
6768 /*rcap_buf_len*/ sizeof(rcaplong),
6769 /*sense_len*/ SSD_FULL_SIZE,
6770 /*timeout*/ timeout ? timeout : 5000);
6771
6772 /* Disable freezing the device queue */
6773 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6774
6775 if (arglist & CAM_ARG_ERR_RECOVER)
6776 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6777
6778 if (cam_send_ccb(device, ccb) < 0) {
6779 warn("error sending READ CAPACITY (16) command");
6780
6781 if (arglist & CAM_ARG_VERBOSE)
6782 cam_error_print(device, ccb, CAM_ESF_ALL,
6783 CAM_EPF_ALL, stderr);
6784
6785 retval = 1;
6786 goto bailout;
6787 }
6788
6789 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6790 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6791 retval = 1;
6792 goto bailout;
6793 }
6794
6795 maxsector = scsi_8btou64(rcaplong.addr);
6796 block_len = scsi_4btoul(rcaplong.length);
6797
6798 do_print:
6799 if (blocksizeonly == 0) {
6800 /*
6801 * Humanize implies !quiet, and also implies numblocks.
6802 */
6803 if (humanize != 0) {
6804 char tmpstr[6];
6805 int64_t tmpbytes;
6806 int ret;
6807
6808 tmpbytes = (maxsector + 1) * block_len;
6809 ret = humanize_number(tmpstr, sizeof(tmpstr),
6810 tmpbytes, "", HN_AUTOSCALE,
6811 HN_B | HN_DECIMAL |
6812 ((baseten != 0) ?
6813 HN_DIVISOR_1000 : 0));
6814 if (ret == -1) {
6815 warnx("%s: humanize_number failed!", __func__);
6816 retval = 1;
6817 goto bailout;
6818 }
6819 fprintf(stdout, "Device Size: %s%s", tmpstr,
6820 (sizeonly == 0) ? ", " : "\n");
6821 } else if (numblocks != 0) {
6822 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6823 "Blocks: " : "", (uintmax_t)maxsector + 1,
6824 (sizeonly == 0) ? ", " : "\n");
6825 } else {
6826 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6827 "Last Block: " : "", (uintmax_t)maxsector,
6828 (sizeonly == 0) ? ", " : "\n");
6829 }
6830 }
6831 if (sizeonly == 0)
6832 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
6833 "Block Length: " : "", block_len, (quiet == 0) ?
6834 " bytes" : "");
6835 bailout:
6836 cam_freeccb(ccb);
6837
6838 return (retval);
6839 }
6840
6841 static int
smpcmd(struct cam_device * device,int argc,char ** argv,char * combinedopt,int retry_count,int timeout)6842 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
6843 int retry_count, int timeout)
6844 {
6845 int c, error = 0;
6846 union ccb *ccb;
6847 uint8_t *smp_request = NULL, *smp_response = NULL;
6848 int request_size = 0, response_size = 0;
6849 int fd_request = 0, fd_response = 0;
6850 char *datastr = NULL;
6851 struct get_hook hook;
6852 int retval;
6853 int flags = 0;
6854
6855 /*
6856 * Note that at the moment we don't support sending SMP CCBs to
6857 * devices that aren't probed by CAM.
6858 */
6859 ccb = cam_getccb(device);
6860 if (ccb == NULL) {
6861 warnx("%s: error allocating CCB", __func__);
6862 return (1);
6863 }
6864
6865 bzero(&(&ccb->ccb_h)[1],
6866 sizeof(union ccb) - sizeof(struct ccb_hdr));
6867
6868 while ((c = getopt(argc, argv, combinedopt)) != -1) {
6869 switch (c) {
6870 case 'R':
6871 arglist |= CAM_ARG_CMD_IN;
6872 response_size = strtol(optarg, NULL, 0);
6873 if (response_size <= 0) {
6874 warnx("invalid number of response bytes %d",
6875 response_size);
6876 error = 1;
6877 goto smpcmd_bailout;
6878 }
6879 hook.argc = argc - optind;
6880 hook.argv = argv + optind;
6881 hook.got = 0;
6882 optind++;
6883 datastr = cget(&hook, NULL);
6884 /*
6885 * If the user supplied "-" instead of a format, he
6886 * wants the data to be written to stdout.
6887 */
6888 if ((datastr != NULL)
6889 && (datastr[0] == '-'))
6890 fd_response = 1;
6891
6892 smp_response = (u_int8_t *)malloc(response_size);
6893 if (smp_response == NULL) {
6894 warn("can't malloc memory for SMP response");
6895 error = 1;
6896 goto smpcmd_bailout;
6897 }
6898 break;
6899 case 'r':
6900 arglist |= CAM_ARG_CMD_OUT;
6901 request_size = strtol(optarg, NULL, 0);
6902 if (request_size <= 0) {
6903 warnx("invalid number of request bytes %d",
6904 request_size);
6905 error = 1;
6906 goto smpcmd_bailout;
6907 }
6908 hook.argc = argc - optind;
6909 hook.argv = argv + optind;
6910 hook.got = 0;
6911 datastr = cget(&hook, NULL);
6912 smp_request = (u_int8_t *)malloc(request_size);
6913 if (smp_request == NULL) {
6914 warn("can't malloc memory for SMP request");
6915 error = 1;
6916 goto smpcmd_bailout;
6917 }
6918 bzero(smp_request, request_size);
6919 /*
6920 * If the user supplied "-" instead of a format, he
6921 * wants the data to be read from stdin.
6922 */
6923 if ((datastr != NULL)
6924 && (datastr[0] == '-'))
6925 fd_request = 1;
6926 else
6927 buff_encode_visit(smp_request, request_size,
6928 datastr,
6929 iget, &hook);
6930 optind += hook.got;
6931 break;
6932 default:
6933 break;
6934 }
6935 }
6936
6937 /*
6938 * If fd_data is set, and we're writing to the device, we need to
6939 * read the data the user wants written from stdin.
6940 */
6941 if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
6942 ssize_t amt_read;
6943 int amt_to_read = request_size;
6944 u_int8_t *buf_ptr = smp_request;
6945
6946 for (amt_read = 0; amt_to_read > 0;
6947 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
6948 if (amt_read == -1) {
6949 warn("error reading data from stdin");
6950 error = 1;
6951 goto smpcmd_bailout;
6952 }
6953 amt_to_read -= amt_read;
6954 buf_ptr += amt_read;
6955 }
6956 }
6957
6958 if (((arglist & CAM_ARG_CMD_IN) == 0)
6959 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
6960 warnx("%s: need both the request (-r) and response (-R) "
6961 "arguments", __func__);
6962 error = 1;
6963 goto smpcmd_bailout;
6964 }
6965
6966 flags |= CAM_DEV_QFRZDIS;
6967
6968 cam_fill_smpio(&ccb->smpio,
6969 /*retries*/ retry_count,
6970 /*cbfcnp*/ NULL,
6971 /*flags*/ flags,
6972 /*smp_request*/ smp_request,
6973 /*smp_request_len*/ request_size,
6974 /*smp_response*/ smp_response,
6975 /*smp_response_len*/ response_size,
6976 /*timeout*/ timeout ? timeout : 5000);
6977
6978 ccb->smpio.flags = SMP_FLAG_NONE;
6979
6980 if (((retval = cam_send_ccb(device, ccb)) < 0)
6981 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6982 const char warnstr[] = "error sending command";
6983
6984 if (retval < 0)
6985 warn(warnstr);
6986 else
6987 warnx(warnstr);
6988
6989 if (arglist & CAM_ARG_VERBOSE) {
6990 cam_error_print(device, ccb, CAM_ESF_ALL,
6991 CAM_EPF_ALL, stderr);
6992 }
6993 }
6994
6995 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
6996 && (response_size > 0)) {
6997 if (fd_response == 0) {
6998 buff_decode_visit(smp_response, response_size,
6999 datastr, arg_put, NULL);
7000 fprintf(stdout, "\n");
7001 } else {
7002 ssize_t amt_written;
7003 int amt_to_write = response_size;
7004 u_int8_t *buf_ptr = smp_response;
7005
7006 for (amt_written = 0; (amt_to_write > 0) &&
7007 (amt_written = write(STDOUT_FILENO, buf_ptr,
7008 amt_to_write)) > 0;){
7009 amt_to_write -= amt_written;
7010 buf_ptr += amt_written;
7011 }
7012 if (amt_written == -1) {
7013 warn("error writing data to stdout");
7014 error = 1;
7015 goto smpcmd_bailout;
7016 } else if ((amt_written == 0)
7017 && (amt_to_write > 0)) {
7018 warnx("only wrote %u bytes out of %u",
7019 response_size - amt_to_write,
7020 response_size);
7021 }
7022 }
7023 }
7024 smpcmd_bailout:
7025 if (ccb != NULL)
7026 cam_freeccb(ccb);
7027
7028 if (smp_request != NULL)
7029 free(smp_request);
7030
7031 if (smp_response != NULL)
7032 free(smp_response);
7033
7034 return (error);
7035 }
7036
7037 static int
smpreportgeneral(struct cam_device * device,int argc,char ** argv,char * combinedopt,int retry_count,int timeout)7038 smpreportgeneral(struct cam_device *device, int argc, char **argv,
7039 char *combinedopt, int retry_count, int timeout)
7040 {
7041 union ccb *ccb;
7042 struct smp_report_general_request *request = NULL;
7043 struct smp_report_general_response *response = NULL;
7044 struct sbuf *sb = NULL;
7045 int error = 0;
7046 int c, long_response = 0;
7047 int retval;
7048
7049 /*
7050 * Note that at the moment we don't support sending SMP CCBs to
7051 * devices that aren't probed by CAM.
7052 */
7053 ccb = cam_getccb(device);
7054 if (ccb == NULL) {
7055 warnx("%s: error allocating CCB", __func__);
7056 return (1);
7057 }
7058
7059 bzero(&(&ccb->ccb_h)[1],
7060 sizeof(union ccb) - sizeof(struct ccb_hdr));
7061
7062 while ((c = getopt(argc, argv, combinedopt)) != -1) {
7063 switch (c) {
7064 case 'l':
7065 long_response = 1;
7066 break;
7067 default:
7068 break;
7069 }
7070 }
7071 request = malloc(sizeof(*request));
7072 if (request == NULL) {
7073 warn("%s: unable to allocate %zd bytes", __func__,
7074 sizeof(*request));
7075 error = 1;
7076 goto bailout;
7077 }
7078
7079 response = malloc(sizeof(*response));
7080 if (response == NULL) {
7081 warn("%s: unable to allocate %zd bytes", __func__,
7082 sizeof(*response));
7083 error = 1;
7084 goto bailout;
7085 }
7086
7087 try_long:
7088 smp_report_general(&ccb->smpio,
7089 retry_count,
7090 /*cbfcnp*/ NULL,
7091 request,
7092 /*request_len*/ sizeof(*request),
7093 (uint8_t *)response,
7094 /*response_len*/ sizeof(*response),
7095 /*long_response*/ long_response,
7096 timeout);
7097
7098 if (((retval = cam_send_ccb(device, ccb)) < 0)
7099 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7100 const char warnstr[] = "error sending command";
7101
7102 if (retval < 0)
7103 warn(warnstr);
7104 else
7105 warnx(warnstr);
7106
7107 if (arglist & CAM_ARG_VERBOSE) {
7108 cam_error_print(device, ccb, CAM_ESF_ALL,
7109 CAM_EPF_ALL, stderr);
7110 }
7111 error = 1;
7112 goto bailout;
7113 }
7114
7115 /*
7116 * If the device supports the long response bit, try again and see
7117 * if we can get all of the data.
7118 */
7119 if ((response->long_response & SMP_RG_LONG_RESPONSE)
7120 && (long_response == 0)) {
7121 ccb->ccb_h.status = CAM_REQ_INPROG;
7122 bzero(&(&ccb->ccb_h)[1],
7123 sizeof(union ccb) - sizeof(struct ccb_hdr));
7124 long_response = 1;
7125 goto try_long;
7126 }
7127
7128 /*
7129 * XXX KDM detect and decode SMP errors here.
7130 */
7131 sb = sbuf_new_auto();
7132 if (sb == NULL) {
7133 warnx("%s: error allocating sbuf", __func__);
7134 goto bailout;
7135 }
7136
7137 smp_report_general_sbuf(response, sizeof(*response), sb);
7138
7139 if (sbuf_finish(sb) != 0) {
7140 warnx("%s: sbuf_finish", __func__);
7141 goto bailout;
7142 }
7143
7144 printf("%s", sbuf_data(sb));
7145
7146 bailout:
7147 if (ccb != NULL)
7148 cam_freeccb(ccb);
7149
7150 if (request != NULL)
7151 free(request);
7152
7153 if (response != NULL)
7154 free(response);
7155
7156 if (sb != NULL)
7157 sbuf_delete(sb);
7158
7159 return (error);
7160 }
7161
7162 static struct camcontrol_opts phy_ops[] = {
7163 {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
7164 {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
7165 {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
7166 {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
7167 {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
7168 {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
7169 {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
7170 {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
7171 {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
7172 {NULL, 0, 0, NULL}
7173 };
7174
7175 static int
smpphycontrol(struct cam_device * device,int argc,char ** argv,char * combinedopt,int retry_count,int timeout)7176 smpphycontrol(struct cam_device *device, int argc, char **argv,
7177 char *combinedopt, int retry_count, int timeout)
7178 {
7179 union ccb *ccb;
7180 struct smp_phy_control_request *request = NULL;
7181 struct smp_phy_control_response *response = NULL;
7182 int long_response = 0;
7183 int retval = 0;
7184 int phy = -1;
7185 uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
7186 int phy_op_set = 0;
7187 uint64_t attached_dev_name = 0;
7188 int dev_name_set = 0;
7189 uint32_t min_plr = 0, max_plr = 0;
7190 uint32_t pp_timeout_val = 0;
7191 int slumber_partial = 0;
7192 int set_pp_timeout_val = 0;
7193 int c;
7194
7195 /*
7196 * Note that at the moment we don't support sending SMP CCBs to
7197 * devices that aren't probed by CAM.
7198 */
7199 ccb = cam_getccb(device);
7200 if (ccb == NULL) {
7201 warnx("%s: error allocating CCB", __func__);
7202 return (1);
7203 }
7204
7205 bzero(&(&ccb->ccb_h)[1],
7206 sizeof(union ccb) - sizeof(struct ccb_hdr));
7207
7208 while ((c = getopt(argc, argv, combinedopt)) != -1) {
7209 switch (c) {
7210 case 'a':
7211 case 'A':
7212 case 's':
7213 case 'S': {
7214 int enable = -1;
7215
7216 if (strcasecmp(optarg, "enable") == 0)
7217 enable = 1;
7218 else if (strcasecmp(optarg, "disable") == 0)
7219 enable = 2;
7220 else {
7221 warnx("%s: Invalid argument %s", __func__,
7222 optarg);
7223 retval = 1;
7224 goto bailout;
7225 }
7226 switch (c) {
7227 case 's':
7228 slumber_partial |= enable <<
7229 SMP_PC_SAS_SLUMBER_SHIFT;
7230 break;
7231 case 'S':
7232 slumber_partial |= enable <<
7233 SMP_PC_SAS_PARTIAL_SHIFT;
7234 break;
7235 case 'a':
7236 slumber_partial |= enable <<
7237 SMP_PC_SATA_SLUMBER_SHIFT;
7238 break;
7239 case 'A':
7240 slumber_partial |= enable <<
7241 SMP_PC_SATA_PARTIAL_SHIFT;
7242 break;
7243 default:
7244 warnx("%s: programmer error", __func__);
7245 retval = 1;
7246 goto bailout;
7247 break; /*NOTREACHED*/
7248 }
7249 break;
7250 }
7251 case 'd':
7252 attached_dev_name = (uintmax_t)strtoumax(optarg,
7253 NULL,0);
7254 dev_name_set = 1;
7255 break;
7256 case 'l':
7257 long_response = 1;
7258 break;
7259 case 'm':
7260 /*
7261 * We don't do extensive checking here, so this
7262 * will continue to work when new speeds come out.
7263 */
7264 min_plr = strtoul(optarg, NULL, 0);
7265 if ((min_plr == 0)
7266 || (min_plr > 0xf)) {
7267 warnx("%s: invalid link rate %x",
7268 __func__, min_plr);
7269 retval = 1;
7270 goto bailout;
7271 }
7272 break;
7273 case 'M':
7274 /*
7275 * We don't do extensive checking here, so this
7276 * will continue to work when new speeds come out.
7277 */
7278 max_plr = strtoul(optarg, NULL, 0);
7279 if ((max_plr == 0)
7280 || (max_plr > 0xf)) {
7281 warnx("%s: invalid link rate %x",
7282 __func__, max_plr);
7283 retval = 1;
7284 goto bailout;
7285 }
7286 break;
7287 case 'o': {
7288 camcontrol_optret optreturn;
7289 cam_argmask argnums;
7290 const char *subopt;
7291
7292 if (phy_op_set != 0) {
7293 warnx("%s: only one phy operation argument "
7294 "(-o) allowed", __func__);
7295 retval = 1;
7296 goto bailout;
7297 }
7298
7299 phy_op_set = 1;
7300
7301 /*
7302 * Allow the user to specify the phy operation
7303 * numerically, as well as with a name. This will
7304 * future-proof it a bit, so options that are added
7305 * in future specs can be used.
7306 */
7307 if (isdigit(optarg[0])) {
7308 phy_operation = strtoul(optarg, NULL, 0);
7309 if ((phy_operation == 0)
7310 || (phy_operation > 0xff)) {
7311 warnx("%s: invalid phy operation %#x",
7312 __func__, phy_operation);
7313 retval = 1;
7314 goto bailout;
7315 }
7316 break;
7317 }
7318 optreturn = getoption(phy_ops, optarg, &phy_operation,
7319 &argnums, &subopt);
7320
7321 if (optreturn == CC_OR_AMBIGUOUS) {
7322 warnx("%s: ambiguous option %s", __func__,
7323 optarg);
7324 usage(0);
7325 retval = 1;
7326 goto bailout;
7327 } else if (optreturn == CC_OR_NOT_FOUND) {
7328 warnx("%s: option %s not found", __func__,
7329 optarg);
7330 usage(0);
7331 retval = 1;
7332 goto bailout;
7333 }
7334 break;
7335 }
7336 case 'p':
7337 phy = atoi(optarg);
7338 break;
7339 case 'T':
7340 pp_timeout_val = strtoul(optarg, NULL, 0);
7341 if (pp_timeout_val > 15) {
7342 warnx("%s: invalid partial pathway timeout "
7343 "value %u, need a value less than 16",
7344 __func__, pp_timeout_val);
7345 retval = 1;
7346 goto bailout;
7347 }
7348 set_pp_timeout_val = 1;
7349 break;
7350 default:
7351 break;
7352 }
7353 }
7354
7355 if (phy == -1) {
7356 warnx("%s: a PHY (-p phy) argument is required",__func__);
7357 retval = 1;
7358 goto bailout;
7359 }
7360
7361 if (((dev_name_set != 0)
7362 && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
7363 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
7364 && (dev_name_set == 0))) {
7365 warnx("%s: -d name and -o setdevname arguments both "
7366 "required to set device name", __func__);
7367 retval = 1;
7368 goto bailout;
7369 }
7370
7371 request = malloc(sizeof(*request));
7372 if (request == NULL) {
7373 warn("%s: unable to allocate %zd bytes", __func__,
7374 sizeof(*request));
7375 retval = 1;
7376 goto bailout;
7377 }
7378
7379 response = malloc(sizeof(*response));
7380 if (response == NULL) {
7381 warn("%s: unable to allocate %zd bytes", __func__,
7382 sizeof(*request));
7383 retval = 1;
7384 goto bailout;
7385 }
7386
7387 smp_phy_control(&ccb->smpio,
7388 retry_count,
7389 /*cbfcnp*/ NULL,
7390 request,
7391 sizeof(*request),
7392 (uint8_t *)response,
7393 sizeof(*response),
7394 long_response,
7395 /*expected_exp_change_count*/ 0,
7396 phy,
7397 phy_operation,
7398 (set_pp_timeout_val != 0) ? 1 : 0,
7399 attached_dev_name,
7400 min_plr,
7401 max_plr,
7402 slumber_partial,
7403 pp_timeout_val,
7404 timeout);
7405
7406 if (((retval = cam_send_ccb(device, ccb)) < 0)
7407 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7408 const char warnstr[] = "error sending command";
7409
7410 if (retval < 0)
7411 warn(warnstr);
7412 else
7413 warnx(warnstr);
7414
7415 if (arglist & CAM_ARG_VERBOSE) {
7416 /*
7417 * Use CAM_EPF_NORMAL so we only get one line of
7418 * SMP command decoding.
7419 */
7420 cam_error_print(device, ccb, CAM_ESF_ALL,
7421 CAM_EPF_NORMAL, stderr);
7422 }
7423 retval = 1;
7424 goto bailout;
7425 }
7426
7427 /* XXX KDM print out something here for success? */
7428 bailout:
7429 if (ccb != NULL)
7430 cam_freeccb(ccb);
7431
7432 if (request != NULL)
7433 free(request);
7434
7435 if (response != NULL)
7436 free(response);
7437
7438 return (retval);
7439 }
7440
7441 static int
smpmaninfo(struct cam_device * device,int argc,char ** argv,char * combinedopt,int retry_count,int timeout)7442 smpmaninfo(struct cam_device *device, int argc, char **argv,
7443 char *combinedopt, int retry_count, int timeout)
7444 {
7445 union ccb *ccb;
7446 struct smp_report_manuf_info_request request;
7447 struct smp_report_manuf_info_response response;
7448 struct sbuf *sb = NULL;
7449 int long_response = 0;
7450 int retval = 0;
7451 int c;
7452
7453 /*
7454 * Note that at the moment we don't support sending SMP CCBs to
7455 * devices that aren't probed by CAM.
7456 */
7457 ccb = cam_getccb(device);
7458 if (ccb == NULL) {
7459 warnx("%s: error allocating CCB", __func__);
7460 return (1);
7461 }
7462
7463 bzero(&(&ccb->ccb_h)[1],
7464 sizeof(union ccb) - sizeof(struct ccb_hdr));
7465
7466 while ((c = getopt(argc, argv, combinedopt)) != -1) {
7467 switch (c) {
7468 case 'l':
7469 long_response = 1;
7470 break;
7471 default:
7472 break;
7473 }
7474 }
7475 bzero(&request, sizeof(request));
7476 bzero(&response, sizeof(response));
7477
7478 smp_report_manuf_info(&ccb->smpio,
7479 retry_count,
7480 /*cbfcnp*/ NULL,
7481 &request,
7482 sizeof(request),
7483 (uint8_t *)&response,
7484 sizeof(response),
7485 long_response,
7486 timeout);
7487
7488 if (((retval = cam_send_ccb(device, ccb)) < 0)
7489 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7490 const char warnstr[] = "error sending command";
7491
7492 if (retval < 0)
7493 warn(warnstr);
7494 else
7495 warnx(warnstr);
7496
7497 if (arglist & CAM_ARG_VERBOSE) {
7498 cam_error_print(device, ccb, CAM_ESF_ALL,
7499 CAM_EPF_ALL, stderr);
7500 }
7501 retval = 1;
7502 goto bailout;
7503 }
7504
7505 sb = sbuf_new_auto();
7506 if (sb == NULL) {
7507 warnx("%s: error allocating sbuf", __func__);
7508 goto bailout;
7509 }
7510
7511 smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
7512
7513 if (sbuf_finish(sb) != 0) {
7514 warnx("%s: sbuf_finish", __func__);
7515 goto bailout;
7516 }
7517
7518 printf("%s", sbuf_data(sb));
7519
7520 bailout:
7521
7522 if (ccb != NULL)
7523 cam_freeccb(ccb);
7524
7525 if (sb != NULL)
7526 sbuf_delete(sb);
7527
7528 return (retval);
7529 }
7530
7531 static int
getdevid(struct cam_devitem * item)7532 getdevid(struct cam_devitem *item)
7533 {
7534 int retval = 0;
7535 union ccb *ccb = NULL;
7536
7537 struct cam_device *dev;
7538
7539 dev = cam_open_btl(item->dev_match.path_id,
7540 item->dev_match.target_id,
7541 item->dev_match.target_lun, O_RDWR, NULL);
7542
7543 if (dev == NULL) {
7544 warnx("%s", cam_errbuf);
7545 retval = 1;
7546 goto bailout;
7547 }
7548
7549 item->device_id_len = 0;
7550
7551 ccb = cam_getccb(dev);
7552 if (ccb == NULL) {
7553 warnx("%s: error allocating CCB", __func__);
7554 retval = 1;
7555 goto bailout;
7556 }
7557
7558 bzero(&(&ccb->ccb_h)[1],
7559 sizeof(union ccb) - sizeof(struct ccb_hdr));
7560
7561 /*
7562 * On the first try, we just probe for the size of the data, and
7563 * then allocate that much memory and try again.
7564 */
7565 retry:
7566 ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
7567 ccb->ccb_h.flags = CAM_DIR_IN;
7568 ccb->cdai.flags = CDAI_FLAG_NONE;
7569 ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
7570 ccb->cdai.bufsiz = item->device_id_len;
7571 if (item->device_id_len != 0)
7572 ccb->cdai.buf = (uint8_t *)item->device_id;
7573
7574 if (cam_send_ccb(dev, ccb) < 0) {
7575 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
7576 retval = 1;
7577 goto bailout;
7578 }
7579
7580 if (ccb->ccb_h.status != CAM_REQ_CMP) {
7581 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
7582 retval = 1;
7583 goto bailout;
7584 }
7585
7586 if (item->device_id_len == 0) {
7587 /*
7588 * This is our first time through. Allocate the buffer,
7589 * and then go back to get the data.
7590 */
7591 if (ccb->cdai.provsiz == 0) {
7592 warnx("%s: invalid .provsiz field returned with "
7593 "XPT_GDEV_ADVINFO CCB", __func__);
7594 retval = 1;
7595 goto bailout;
7596 }
7597 item->device_id_len = ccb->cdai.provsiz;
7598 item->device_id = malloc(item->device_id_len);
7599 if (item->device_id == NULL) {
7600 warn("%s: unable to allocate %d bytes", __func__,
7601 item->device_id_len);
7602 retval = 1;
7603 goto bailout;
7604 }
7605 ccb->ccb_h.status = CAM_REQ_INPROG;
7606 goto retry;
7607 }
7608
7609 bailout:
7610 if (dev != NULL)
7611 cam_close_device(dev);
7612
7613 if (ccb != NULL)
7614 cam_freeccb(ccb);
7615
7616 return (retval);
7617 }
7618
7619 /*
7620 * XXX KDM merge this code with getdevtree()?
7621 */
7622 static int
buildbusdevlist(struct cam_devlist * devlist)7623 buildbusdevlist(struct cam_devlist *devlist)
7624 {
7625 union ccb ccb;
7626 int bufsize, fd = -1;
7627 struct dev_match_pattern *patterns;
7628 struct cam_devitem *item = NULL;
7629 int skip_device = 0;
7630 int retval = 0;
7631
7632 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
7633 warn("couldn't open %s", XPT_DEVICE);
7634 return(1);
7635 }
7636
7637 bzero(&ccb, sizeof(union ccb));
7638
7639 ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
7640 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
7641 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
7642
7643 ccb.ccb_h.func_code = XPT_DEV_MATCH;
7644 bufsize = sizeof(struct dev_match_result) * 100;
7645 ccb.cdm.match_buf_len = bufsize;
7646 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
7647 if (ccb.cdm.matches == NULL) {
7648 warnx("can't malloc memory for matches");
7649 close(fd);
7650 return(1);
7651 }
7652 ccb.cdm.num_matches = 0;
7653 ccb.cdm.num_patterns = 2;
7654 ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
7655 ccb.cdm.num_patterns;
7656
7657 patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
7658 if (patterns == NULL) {
7659 warnx("can't malloc memory for patterns");
7660 retval = 1;
7661 goto bailout;
7662 }
7663
7664 ccb.cdm.patterns = patterns;
7665 bzero(patterns, ccb.cdm.pattern_buf_len);
7666
7667 patterns[0].type = DEV_MATCH_DEVICE;
7668 patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
7669 patterns[0].pattern.device_pattern.path_id = devlist->path_id;
7670 patterns[1].type = DEV_MATCH_PERIPH;
7671 patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
7672 patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
7673
7674 /*
7675 * We do the ioctl multiple times if necessary, in case there are
7676 * more than 100 nodes in the EDT.
7677 */
7678 do {
7679 unsigned int i;
7680
7681 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
7682 warn("error sending CAMIOCOMMAND ioctl");
7683 retval = 1;
7684 goto bailout;
7685 }
7686
7687 if ((ccb.ccb_h.status != CAM_REQ_CMP)
7688 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
7689 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
7690 warnx("got CAM error %#x, CDM error %d\n",
7691 ccb.ccb_h.status, ccb.cdm.status);
7692 retval = 1;
7693 goto bailout;
7694 }
7695
7696 for (i = 0; i < ccb.cdm.num_matches; i++) {
7697 switch (ccb.cdm.matches[i].type) {
7698 case DEV_MATCH_DEVICE: {
7699 struct device_match_result *dev_result;
7700
7701 dev_result =
7702 &ccb.cdm.matches[i].result.device_result;
7703
7704 if (dev_result->flags &
7705 DEV_RESULT_UNCONFIGURED) {
7706 skip_device = 1;
7707 break;
7708 } else
7709 skip_device = 0;
7710
7711 item = malloc(sizeof(*item));
7712 if (item == NULL) {
7713 warn("%s: unable to allocate %zd bytes",
7714 __func__, sizeof(*item));
7715 retval = 1;
7716 goto bailout;
7717 }
7718 bzero(item, sizeof(*item));
7719 bcopy(dev_result, &item->dev_match,
7720 sizeof(*dev_result));
7721 STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
7722 links);
7723
7724 if (getdevid(item) != 0) {
7725 retval = 1;
7726 goto bailout;
7727 }
7728 break;
7729 }
7730 case DEV_MATCH_PERIPH: {
7731 struct periph_match_result *periph_result;
7732
7733 periph_result =
7734 &ccb.cdm.matches[i].result.periph_result;
7735
7736 if (skip_device != 0)
7737 break;
7738 item->num_periphs++;
7739 item->periph_matches = realloc(
7740 item->periph_matches,
7741 item->num_periphs *
7742 sizeof(struct periph_match_result));
7743 if (item->periph_matches == NULL) {
7744 warn("%s: error allocating periph "
7745 "list", __func__);
7746 retval = 1;
7747 goto bailout;
7748 }
7749 bcopy(periph_result, &item->periph_matches[
7750 item->num_periphs - 1],
7751 sizeof(*periph_result));
7752 break;
7753 }
7754 default:
7755 fprintf(stderr, "%s: unexpected match "
7756 "type %d\n", __func__,
7757 ccb.cdm.matches[i].type);
7758 retval = 1;
7759 goto bailout;
7760 break; /*NOTREACHED*/
7761 }
7762 }
7763 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
7764 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
7765 bailout:
7766
7767 if (fd != -1)
7768 close(fd);
7769
7770 free(patterns);
7771
7772 free(ccb.cdm.matches);
7773
7774 if (retval != 0)
7775 freebusdevlist(devlist);
7776
7777 return (retval);
7778 }
7779
7780 static void
freebusdevlist(struct cam_devlist * devlist)7781 freebusdevlist(struct cam_devlist *devlist)
7782 {
7783 struct cam_devitem *item, *item2;
7784
7785 STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
7786 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
7787 links);
7788 free(item->device_id);
7789 free(item->periph_matches);
7790 free(item);
7791 }
7792 }
7793
7794 static struct cam_devitem *
findsasdevice(struct cam_devlist * devlist,uint64_t sasaddr)7795 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
7796 {
7797 struct cam_devitem *item;
7798
7799 STAILQ_FOREACH(item, &devlist->dev_queue, links) {
7800 struct scsi_vpd_id_descriptor *idd;
7801
7802 /*
7803 * XXX KDM look for LUN IDs as well?
7804 */
7805 idd = scsi_get_devid(item->device_id,
7806 item->device_id_len,
7807 scsi_devid_is_sas_target);
7808 if (idd == NULL)
7809 continue;
7810
7811 if (scsi_8btou64(idd->identifier) == sasaddr)
7812 return (item);
7813 }
7814
7815 return (NULL);
7816 }
7817
7818 static int
smpphylist(struct cam_device * device,int argc,char ** argv,char * combinedopt,int retry_count,int timeout)7819 smpphylist(struct cam_device *device, int argc, char **argv,
7820 char *combinedopt, int retry_count, int timeout)
7821 {
7822 struct smp_report_general_request *rgrequest = NULL;
7823 struct smp_report_general_response *rgresponse = NULL;
7824 struct smp_discover_request *disrequest = NULL;
7825 struct smp_discover_response *disresponse = NULL;
7826 struct cam_devlist devlist;
7827 union ccb *ccb;
7828 int long_response = 0;
7829 int num_phys = 0;
7830 int quiet = 0;
7831 int retval;
7832 int i, c;
7833
7834 /*
7835 * Note that at the moment we don't support sending SMP CCBs to
7836 * devices that aren't probed by CAM.
7837 */
7838 ccb = cam_getccb(device);
7839 if (ccb == NULL) {
7840 warnx("%s: error allocating CCB", __func__);
7841 return (1);
7842 }
7843
7844 bzero(&(&ccb->ccb_h)[1],
7845 sizeof(union ccb) - sizeof(struct ccb_hdr));
7846 STAILQ_INIT(&devlist.dev_queue);
7847
7848 rgrequest = malloc(sizeof(*rgrequest));
7849 if (rgrequest == NULL) {
7850 warn("%s: unable to allocate %zd bytes", __func__,
7851 sizeof(*rgrequest));
7852 retval = 1;
7853 goto bailout;
7854 }
7855
7856 rgresponse = malloc(sizeof(*rgresponse));
7857 if (rgresponse == NULL) {
7858 warn("%s: unable to allocate %zd bytes", __func__,
7859 sizeof(*rgresponse));
7860 retval = 1;
7861 goto bailout;
7862 }
7863
7864 while ((c = getopt(argc, argv, combinedopt)) != -1) {
7865 switch (c) {
7866 case 'l':
7867 long_response = 1;
7868 break;
7869 case 'q':
7870 quiet = 1;
7871 break;
7872 default:
7873 break;
7874 }
7875 }
7876
7877 smp_report_general(&ccb->smpio,
7878 retry_count,
7879 /*cbfcnp*/ NULL,
7880 rgrequest,
7881 /*request_len*/ sizeof(*rgrequest),
7882 (uint8_t *)rgresponse,
7883 /*response_len*/ sizeof(*rgresponse),
7884 /*long_response*/ long_response,
7885 timeout);
7886
7887 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7888
7889 if (((retval = cam_send_ccb(device, ccb)) < 0)
7890 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7891 const char warnstr[] = "error sending command";
7892
7893 if (retval < 0)
7894 warn(warnstr);
7895 else
7896 warnx(warnstr);
7897
7898 if (arglist & CAM_ARG_VERBOSE) {
7899 cam_error_print(device, ccb, CAM_ESF_ALL,
7900 CAM_EPF_ALL, stderr);
7901 }
7902 retval = 1;
7903 goto bailout;
7904 }
7905
7906 num_phys = rgresponse->num_phys;
7907
7908 if (num_phys == 0) {
7909 if (quiet == 0)
7910 fprintf(stdout, "%s: No Phys reported\n", __func__);
7911 retval = 1;
7912 goto bailout;
7913 }
7914
7915 devlist.path_id = device->path_id;
7916
7917 retval = buildbusdevlist(&devlist);
7918 if (retval != 0)
7919 goto bailout;
7920
7921 if (quiet == 0) {
7922 fprintf(stdout, "%d PHYs:\n", num_phys);
7923 fprintf(stdout, "PHY Attached SAS Address\n");
7924 }
7925
7926 disrequest = malloc(sizeof(*disrequest));
7927 if (disrequest == NULL) {
7928 warn("%s: unable to allocate %zd bytes", __func__,
7929 sizeof(*disrequest));
7930 retval = 1;
7931 goto bailout;
7932 }
7933
7934 disresponse = malloc(sizeof(*disresponse));
7935 if (disresponse == NULL) {
7936 warn("%s: unable to allocate %zd bytes", __func__,
7937 sizeof(*disresponse));
7938 retval = 1;
7939 goto bailout;
7940 }
7941
7942 for (i = 0; i < num_phys; i++) {
7943 struct cam_devitem *item;
7944 struct device_match_result *dev_match;
7945 char vendor[16], product[48], revision[16];
7946 char tmpstr[256];
7947 int j;
7948
7949 bzero(&(&ccb->ccb_h)[1],
7950 sizeof(union ccb) - sizeof(struct ccb_hdr));
7951
7952 ccb->ccb_h.status = CAM_REQ_INPROG;
7953 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7954
7955 smp_discover(&ccb->smpio,
7956 retry_count,
7957 /*cbfcnp*/ NULL,
7958 disrequest,
7959 sizeof(*disrequest),
7960 (uint8_t *)disresponse,
7961 sizeof(*disresponse),
7962 long_response,
7963 /*ignore_zone_group*/ 0,
7964 /*phy*/ i,
7965 timeout);
7966
7967 if (((retval = cam_send_ccb(device, ccb)) < 0)
7968 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
7969 && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
7970 const char warnstr[] = "error sending command";
7971
7972 if (retval < 0)
7973 warn(warnstr);
7974 else
7975 warnx(warnstr);
7976
7977 if (arglist & CAM_ARG_VERBOSE) {
7978 cam_error_print(device, ccb, CAM_ESF_ALL,
7979 CAM_EPF_ALL, stderr);
7980 }
7981 retval = 1;
7982 goto bailout;
7983 }
7984
7985 if (disresponse->function_result == SMP_FR_PHY_VACANT) {
7986 if (quiet == 0)
7987 fprintf(stdout, "%3d <vacant>\n", i);
7988 continue;
7989 }
7990
7991 if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) {
7992 item = NULL;
7993 } else {
7994 item = findsasdevice(&devlist,
7995 scsi_8btou64(disresponse->attached_sas_address));
7996 }
7997
7998 if ((quiet == 0)
7999 || (item != NULL)) {
8000 fprintf(stdout, "%3d 0x%016jx", i,
8001 (uintmax_t)scsi_8btou64(
8002 disresponse->attached_sas_address));
8003 if (item == NULL) {
8004 fprintf(stdout, "\n");
8005 continue;
8006 }
8007 } else if (quiet != 0)
8008 continue;
8009
8010 dev_match = &item->dev_match;
8011
8012 if (dev_match->protocol == PROTO_SCSI) {
8013 cam_strvis(vendor, dev_match->inq_data.vendor,
8014 sizeof(dev_match->inq_data.vendor),
8015 sizeof(vendor));
8016 cam_strvis(product, dev_match->inq_data.product,
8017 sizeof(dev_match->inq_data.product),
8018 sizeof(product));
8019 cam_strvis(revision, dev_match->inq_data.revision,
8020 sizeof(dev_match->inq_data.revision),
8021 sizeof(revision));
8022 sprintf(tmpstr, "<%s %s %s>", vendor, product,
8023 revision);
8024 } else if ((dev_match->protocol == PROTO_ATA)
8025 || (dev_match->protocol == PROTO_SATAPM)) {
8026 cam_strvis(product, dev_match->ident_data.model,
8027 sizeof(dev_match->ident_data.model),
8028 sizeof(product));
8029 cam_strvis(revision, dev_match->ident_data.revision,
8030 sizeof(dev_match->ident_data.revision),
8031 sizeof(revision));
8032 sprintf(tmpstr, "<%s %s>", product, revision);
8033 } else {
8034 sprintf(tmpstr, "<>");
8035 }
8036 fprintf(stdout, " %-33s ", tmpstr);
8037
8038 /*
8039 * If we have 0 periphs, that's a bug...
8040 */
8041 if (item->num_periphs == 0) {
8042 fprintf(stdout, "\n");
8043 continue;
8044 }
8045
8046 fprintf(stdout, "(");
8047 for (j = 0; j < item->num_periphs; j++) {
8048 if (j > 0)
8049 fprintf(stdout, ",");
8050
8051 fprintf(stdout, "%s%d",
8052 item->periph_matches[j].periph_name,
8053 item->periph_matches[j].unit_number);
8054
8055 }
8056 fprintf(stdout, ")\n");
8057 }
8058 bailout:
8059 if (ccb != NULL)
8060 cam_freeccb(ccb);
8061
8062 free(rgrequest);
8063
8064 free(rgresponse);
8065
8066 free(disrequest);
8067
8068 free(disresponse);
8069
8070 freebusdevlist(&devlist);
8071
8072 return (retval);
8073 }
8074
8075 static int
atapm(struct cam_device * device,int argc,char ** argv,char * combinedopt,int retry_count,int timeout)8076 atapm(struct cam_device *device, int argc, char **argv,
8077 char *combinedopt, int retry_count, int timeout)
8078 {
8079 union ccb *ccb;
8080 int retval = 0;
8081 int t = -1;
8082 int c;
8083 u_char cmd, sc;
8084
8085 ccb = cam_getccb(device);
8086
8087 if (ccb == NULL) {
8088 warnx("%s: error allocating ccb", __func__);
8089 return (1);
8090 }
8091
8092 while ((c = getopt(argc, argv, combinedopt)) != -1) {
8093 switch (c) {
8094 case 't':
8095 t = atoi(optarg);
8096 break;
8097 default:
8098 break;
8099 }
8100 }
8101 if (strcmp(argv[1], "idle") == 0) {
8102 if (t == -1)
8103 cmd = ATA_IDLE_IMMEDIATE;
8104 else
8105 cmd = ATA_IDLE_CMD;
8106 } else if (strcmp(argv[1], "standby") == 0) {
8107 if (t == -1)
8108 cmd = ATA_STANDBY_IMMEDIATE;
8109 else
8110 cmd = ATA_STANDBY_CMD;
8111 } else {
8112 cmd = ATA_SLEEP;
8113 t = -1;
8114 }
8115
8116 if (t < 0)
8117 sc = 0;
8118 else if (t <= (240 * 5))
8119 sc = (t + 4) / 5;
8120 else if (t <= (252 * 5))
8121 /* special encoding for 21 minutes */
8122 sc = 252;
8123 else if (t <= (11 * 30 * 60))
8124 sc = (t - 1) / (30 * 60) + 241;
8125 else
8126 sc = 253;
8127
8128 retval = ata_do_28bit_cmd(device,
8129 ccb,
8130 /*retries*/retry_count,
8131 /*flags*/CAM_DIR_NONE,
8132 /*protocol*/AP_PROTO_NON_DATA,
8133 /*tag_action*/MSG_SIMPLE_Q_TAG,
8134 /*command*/cmd,
8135 /*features*/0,
8136 /*lba*/0,
8137 /*sector_count*/sc,
8138 /*data_ptr*/NULL,
8139 /*dxfer_len*/0,
8140 /*timeout*/timeout ? timeout : 30 * 1000,
8141 /*quiet*/1);
8142
8143 cam_freeccb(ccb);
8144 return (retval);
8145 }
8146
8147 static int
ataaxm(struct cam_device * device,int argc,char ** argv,char * combinedopt,int retry_count,int timeout)8148 ataaxm(struct cam_device *device, int argc, char **argv,
8149 char *combinedopt, int retry_count, int timeout)
8150 {
8151 union ccb *ccb;
8152 int retval = 0;
8153 int l = -1;
8154 int c;
8155 u_char cmd, sc;
8156
8157 ccb = cam_getccb(device);
8158
8159 if (ccb == NULL) {
8160 warnx("%s: error allocating ccb", __func__);
8161 return (1);
8162 }
8163
8164 while ((c = getopt(argc, argv, combinedopt)) != -1) {
8165 switch (c) {
8166 case 'l':
8167 l = atoi(optarg);
8168 break;
8169 default:
8170 break;
8171 }
8172 }
8173 sc = 0;
8174 if (strcmp(argv[1], "apm") == 0) {
8175 if (l == -1)
8176 cmd = 0x85;
8177 else {
8178 cmd = 0x05;
8179 sc = l;
8180 }
8181 } else /* aam */ {
8182 if (l == -1)
8183 cmd = 0xC2;
8184 else {
8185 cmd = 0x42;
8186 sc = l;
8187 }
8188 }
8189
8190 retval = ata_do_28bit_cmd(device,
8191 ccb,
8192 /*retries*/retry_count,
8193 /*flags*/CAM_DIR_NONE,
8194 /*protocol*/AP_PROTO_NON_DATA,
8195 /*tag_action*/MSG_SIMPLE_Q_TAG,
8196 /*command*/ATA_SETFEATURES,
8197 /*features*/cmd,
8198 /*lba*/0,
8199 /*sector_count*/sc,
8200 /*data_ptr*/NULL,
8201 /*dxfer_len*/0,
8202 /*timeout*/timeout ? timeout : 30 * 1000,
8203 /*quiet*/1);
8204
8205 cam_freeccb(ccb);
8206 return (retval);
8207 }
8208
8209 int
scsigetopcodes(struct cam_device * device,int opcode_set,int opcode,int show_sa_errors,int sa_set,int service_action,int timeout_desc,int retry_count,int timeout,int verbosemode,uint32_t * fill_len,uint8_t ** data_ptr)8210 scsigetopcodes(struct cam_device *device, int opcode_set, int opcode,
8211 int show_sa_errors, int sa_set, int service_action,
8212 int timeout_desc, int retry_count, int timeout, int verbosemode,
8213 uint32_t *fill_len, uint8_t **data_ptr)
8214 {
8215 union ccb *ccb = NULL;
8216 uint8_t *buf = NULL;
8217 uint32_t alloc_len = 0, num_opcodes;
8218 uint32_t valid_len = 0;
8219 uint32_t avail_len = 0;
8220 struct scsi_report_supported_opcodes_all *all_hdr;
8221 struct scsi_report_supported_opcodes_one *one;
8222 int options = 0;
8223 int retval = 0;
8224
8225 /*
8226 * Make it clear that we haven't yet allocated or filled anything.
8227 */
8228 *fill_len = 0;
8229 *data_ptr = NULL;
8230
8231 ccb = cam_getccb(device);
8232 if (ccb == NULL) {
8233 warnx("couldn't allocate CCB");
8234 retval = 1;
8235 goto bailout;
8236 }
8237
8238 /* cam_getccb cleans up the header, caller has to zero the payload */
8239 bzero(&(&ccb->ccb_h)[1],
8240 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
8241
8242 if (opcode_set != 0) {
8243 options |= RSO_OPTIONS_OC;
8244 num_opcodes = 1;
8245 alloc_len = sizeof(*one) + CAM_MAX_CDBLEN;
8246 } else {
8247 num_opcodes = 256;
8248 alloc_len = sizeof(*all_hdr) + (num_opcodes *
8249 sizeof(struct scsi_report_supported_opcodes_descr));
8250 }
8251
8252 if (timeout_desc != 0) {
8253 options |= RSO_RCTD;
8254 alloc_len += num_opcodes *
8255 sizeof(struct scsi_report_supported_opcodes_timeout);
8256 }
8257
8258 if (sa_set != 0) {
8259 options |= RSO_OPTIONS_OC_SA;
8260 if (show_sa_errors != 0)
8261 options &= ~RSO_OPTIONS_OC;
8262 }
8263
8264 retry_alloc:
8265 if (buf != NULL) {
8266 free(buf);
8267 buf = NULL;
8268 }
8269
8270 buf = malloc(alloc_len);
8271 if (buf == NULL) {
8272 warn("Unable to allocate %u bytes", alloc_len);
8273 retval = 1;
8274 goto bailout;
8275 }
8276 bzero(buf, alloc_len);
8277
8278 scsi_report_supported_opcodes(&ccb->csio,
8279 /*retries*/ retry_count,
8280 /*cbfcnp*/ NULL,
8281 /*tag_action*/ MSG_SIMPLE_Q_TAG,
8282 /*options*/ options,
8283 /*req_opcode*/ opcode,
8284 /*req_service_action*/ service_action,
8285 /*data_ptr*/ buf,
8286 /*dxfer_len*/ alloc_len,
8287 /*sense_len*/ SSD_FULL_SIZE,
8288 /*timeout*/ timeout ? timeout : 10000);
8289
8290 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8291
8292 if (retry_count != 0)
8293 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
8294
8295 if (cam_send_ccb(device, ccb) < 0) {
8296 perror("error sending REPORT SUPPORTED OPERATION CODES");
8297 retval = 1;
8298 goto bailout;
8299 }
8300
8301 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
8302 if (verbosemode != 0)
8303 cam_error_print(device, ccb, CAM_ESF_ALL,
8304 CAM_EPF_ALL, stderr);
8305
8306 retval = 1;
8307 goto bailout;
8308 }
8309
8310 valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
8311
8312 if (((options & RSO_OPTIONS_MASK) == RSO_OPTIONS_ALL)
8313 && (valid_len >= sizeof(*all_hdr))) {
8314 all_hdr = (struct scsi_report_supported_opcodes_all *)buf;
8315 avail_len = scsi_4btoul(all_hdr->length) + sizeof(*all_hdr);
8316 } else if (((options & RSO_OPTIONS_MASK) != RSO_OPTIONS_ALL)
8317 && (valid_len >= sizeof(*one))) {
8318 uint32_t cdb_length;
8319
8320 one = (struct scsi_report_supported_opcodes_one *)buf;
8321 cdb_length = scsi_2btoul(one->cdb_length);
8322 avail_len = sizeof(*one) + cdb_length;
8323 if (one->support & RSO_ONE_CTDP) {
8324 struct scsi_report_supported_opcodes_timeout *td;
8325
8326 td = (struct scsi_report_supported_opcodes_timeout *)
8327 &buf[avail_len];
8328 if (valid_len >= (avail_len + sizeof(td->length))) {
8329 avail_len += scsi_2btoul(td->length) +
8330 sizeof(td->length);
8331 } else {
8332 avail_len += sizeof(*td);
8333 }
8334 }
8335 }
8336
8337 /*
8338 * avail_len could be zero if we didn't get enough data back from
8339 * thet target to determine
8340 */
8341 if ((avail_len != 0)
8342 && (avail_len > valid_len)) {
8343 alloc_len = avail_len;
8344 goto retry_alloc;
8345 }
8346
8347 *fill_len = valid_len;
8348 *data_ptr = buf;
8349 bailout:
8350 if (retval != 0)
8351 free(buf);
8352
8353 cam_freeccb(ccb);
8354
8355 return (retval);
8356 }
8357
8358 static int
scsiprintoneopcode(struct cam_device * device,int req_opcode,int sa_set,int req_sa,uint8_t * buf,uint32_t valid_len)8359 scsiprintoneopcode(struct cam_device *device, int req_opcode, int sa_set,
8360 int req_sa, uint8_t *buf, uint32_t valid_len)
8361 {
8362 struct scsi_report_supported_opcodes_one *one;
8363 struct scsi_report_supported_opcodes_timeout *td;
8364 uint32_t cdb_len = 0, td_len = 0;
8365 const char *op_desc = NULL;
8366 unsigned int i;
8367 int retval = 0;
8368
8369 one = (struct scsi_report_supported_opcodes_one *)buf;
8370
8371 /*
8372 * If we don't have the full single opcode descriptor, no point in
8373 * continuing.
8374 */
8375 if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
8376 cdb_length)) {
8377 warnx("Only %u bytes returned, not enough to verify support",
8378 valid_len);
8379 retval = 1;
8380 goto bailout;
8381 }
8382
8383 op_desc = scsi_op_desc(req_opcode, &device->inq_data);
8384
8385 printf("%s (0x%02x)", op_desc != NULL ? op_desc : "UNKNOWN",
8386 req_opcode);
8387 if (sa_set != 0)
8388 printf(", SA 0x%x", req_sa);
8389 printf(": ");
8390
8391 switch (one->support & RSO_ONE_SUP_MASK) {
8392 case RSO_ONE_SUP_UNAVAIL:
8393 printf("No command support information currently available\n");
8394 break;
8395 case RSO_ONE_SUP_NOT_SUP:
8396 printf("Command not supported\n");
8397 retval = 1;
8398 goto bailout;
8399 break; /*NOTREACHED*/
8400 case RSO_ONE_SUP_AVAIL:
8401 printf("Command is supported, complies with a SCSI standard\n");
8402 break;
8403 case RSO_ONE_SUP_VENDOR:
8404 printf("Command is supported, vendor-specific "
8405 "implementation\n");
8406 break;
8407 default:
8408 printf("Unknown command support flags 0x%#x\n",
8409 one->support & RSO_ONE_SUP_MASK);
8410 break;
8411 }
8412
8413 /*
8414 * If we don't have the CDB length, it isn't exactly an error, the
8415 * command probably isn't supported.
8416 */
8417 if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
8418 cdb_usage))
8419 goto bailout;
8420
8421 cdb_len = scsi_2btoul(one->cdb_length);
8422
8423 /*
8424 * If our valid data doesn't include the full reported length,
8425 * return. The caller should have detected this and adjusted his
8426 * allocation length to get all of the available data.
8427 */
8428 if (valid_len < sizeof(*one) + cdb_len) {
8429 retval = 1;
8430 goto bailout;
8431 }
8432
8433 /*
8434 * If all we have is the opcode, there is no point in printing out
8435 * the usage bitmap.
8436 */
8437 if (cdb_len <= 1) {
8438 retval = 1;
8439 goto bailout;
8440 }
8441
8442 printf("CDB usage bitmap:");
8443 for (i = 0; i < cdb_len; i++) {
8444 printf(" %02x", one->cdb_usage[i]);
8445 }
8446 printf("\n");
8447
8448 /*
8449 * If we don't have a timeout descriptor, we're done.
8450 */
8451 if ((one->support & RSO_ONE_CTDP) == 0)
8452 goto bailout;
8453
8454 /*
8455 * If we don't have enough valid length to include the timeout
8456 * descriptor length, we're done.
8457 */
8458 if (valid_len < (sizeof(*one) + cdb_len + sizeof(td->length)))
8459 goto bailout;
8460
8461 td = (struct scsi_report_supported_opcodes_timeout *)
8462 &buf[sizeof(*one) + cdb_len];
8463 td_len = scsi_2btoul(td->length);
8464 td_len += sizeof(td->length);
8465
8466 /*
8467 * If we don't have the full timeout descriptor, we're done.
8468 */
8469 if (td_len < sizeof(*td))
8470 goto bailout;
8471
8472 /*
8473 * If we don't have enough valid length to contain the full timeout
8474 * descriptor, we're done.
8475 */
8476 if (valid_len < (sizeof(*one) + cdb_len + td_len))
8477 goto bailout;
8478
8479 printf("Timeout information:\n");
8480 printf("Command-specific: 0x%02x\n", td->cmd_specific);
8481 printf("Nominal timeout: %u seconds\n",
8482 scsi_4btoul(td->nominal_time));
8483 printf("Recommended timeout: %u seconds\n",
8484 scsi_4btoul(td->recommended_time));
8485
8486 bailout:
8487 return (retval);
8488 }
8489
8490 static int
scsiprintopcodes(struct cam_device * device,int td_req,uint8_t * buf,uint32_t valid_len)8491 scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf,
8492 uint32_t valid_len)
8493 {
8494 struct scsi_report_supported_opcodes_all *hdr;
8495 struct scsi_report_supported_opcodes_descr *desc;
8496 uint32_t avail_len = 0, used_len = 0;
8497 uint8_t *cur_ptr;
8498 int retval = 0;
8499
8500 if (valid_len < sizeof(*hdr)) {
8501 warnx("%s: not enough returned data (%u bytes) opcode list",
8502 __func__, valid_len);
8503 retval = 1;
8504 goto bailout;
8505 }
8506 hdr = (struct scsi_report_supported_opcodes_all *)buf;
8507 avail_len = scsi_4btoul(hdr->length);
8508 avail_len += sizeof(hdr->length);
8509 /*
8510 * Take the lesser of the amount of data the drive claims is
8511 * available, and the amount of data the HBA says was returned.
8512 */
8513 avail_len = MIN(avail_len, valid_len);
8514
8515 used_len = sizeof(hdr->length);
8516
8517 printf("%-6s %4s %8s ",
8518 "Opcode", "SA", "CDB len" );
8519
8520 if (td_req != 0)
8521 printf("%5s %6s %6s ", "CS", "Nom", "Rec");
8522 printf(" Description\n");
8523
8524 while ((avail_len - used_len) > sizeof(*desc)) {
8525 struct scsi_report_supported_opcodes_timeout *td;
8526 uint32_t td_len;
8527 const char *op_desc = NULL;
8528
8529 cur_ptr = &buf[used_len];
8530 desc = (struct scsi_report_supported_opcodes_descr *)cur_ptr;
8531
8532 op_desc = scsi_op_desc(desc->opcode, &device->inq_data);
8533 if (op_desc == NULL)
8534 op_desc = "UNKNOWN";
8535
8536 printf("0x%02x %#4x %8u ", desc->opcode,
8537 scsi_2btoul(desc->service_action),
8538 scsi_2btoul(desc->cdb_length));
8539
8540 used_len += sizeof(*desc);
8541
8542 if ((desc->flags & RSO_CTDP) == 0) {
8543 printf(" %s\n", op_desc);
8544 continue;
8545 }
8546
8547 /*
8548 * If we don't have enough space to fit a timeout
8549 * descriptor, then we're done.
8550 */
8551 if (avail_len - used_len < sizeof(*td)) {
8552 used_len = avail_len;
8553 printf(" %s\n", op_desc);
8554 continue;
8555 }
8556 cur_ptr = &buf[used_len];
8557 td = (struct scsi_report_supported_opcodes_timeout *)cur_ptr;
8558 td_len = scsi_2btoul(td->length);
8559 td_len += sizeof(td->length);
8560
8561 used_len += td_len;
8562 /*
8563 * If the given timeout descriptor length is less than what
8564 * we understand, skip it.
8565 */
8566 if (td_len < sizeof(*td)) {
8567 printf(" %s\n", op_desc);
8568 continue;
8569 }
8570
8571 printf(" 0x%02x %6u %6u %s\n", td->cmd_specific,
8572 scsi_4btoul(td->nominal_time),
8573 scsi_4btoul(td->recommended_time), op_desc);
8574 }
8575 bailout:
8576 return (retval);
8577 }
8578
8579 static int
scsiopcodes(struct cam_device * device,int argc,char ** argv,char * combinedopt,int retry_count,int timeout,int verbosemode)8580 scsiopcodes(struct cam_device *device, int argc, char **argv,
8581 char *combinedopt, int retry_count, int timeout, int verbosemode)
8582 {
8583 int c;
8584 uint32_t opcode = 0, service_action = 0;
8585 int td_set = 0, opcode_set = 0, sa_set = 0;
8586 int show_sa_errors = 1;
8587 uint32_t valid_len = 0;
8588 uint8_t *buf = NULL;
8589 char *endptr;
8590 int retval = 0;
8591
8592 while ((c = getopt(argc, argv, combinedopt)) != -1) {
8593 switch (c) {
8594 case 'N':
8595 show_sa_errors = 0;
8596 break;
8597 case 'o':
8598 opcode = strtoul(optarg, &endptr, 0);
8599 if (*endptr != '\0') {
8600 warnx("Invalid opcode \"%s\", must be a number",
8601 optarg);
8602 retval = 1;
8603 goto bailout;
8604 }
8605 if (opcode > 0xff) {
8606 warnx("Invalid opcode 0x%#x, must be between"
8607 "0 and 0xff inclusive", opcode);
8608 retval = 1;
8609 goto bailout;
8610 }
8611 opcode_set = 1;
8612 break;
8613 case 's':
8614 service_action = strtoul(optarg, &endptr, 0);
8615 if (*endptr != '\0') {
8616 warnx("Invalid service action \"%s\", must "
8617 "be a number", optarg);
8618 retval = 1;
8619 goto bailout;
8620 }
8621 if (service_action > 0xffff) {
8622 warnx("Invalid service action 0x%#x, must "
8623 "be between 0 and 0xffff inclusive",
8624 service_action);
8625 retval = 1;
8626 }
8627 sa_set = 1;
8628 break;
8629 case 'T':
8630 td_set = 1;
8631 break;
8632 default:
8633 break;
8634 }
8635 }
8636
8637 if ((sa_set != 0)
8638 && (opcode_set == 0)) {
8639 warnx("You must specify an opcode with -o if a service "
8640 "action is given");
8641 retval = 1;
8642 goto bailout;
8643 }
8644 retval = scsigetopcodes(device, opcode_set, opcode, show_sa_errors,
8645 sa_set, service_action, td_set, retry_count,
8646 timeout, verbosemode, &valid_len, &buf);
8647 if (retval != 0)
8648 goto bailout;
8649
8650 if ((opcode_set != 0)
8651 || (sa_set != 0)) {
8652 retval = scsiprintoneopcode(device, opcode, sa_set,
8653 service_action, buf, valid_len);
8654 } else {
8655 retval = scsiprintopcodes(device, td_set, buf, valid_len);
8656 }
8657
8658 bailout:
8659 free(buf);
8660
8661 return (retval);
8662 }
8663
8664 #endif /* MINIMALISTIC */
8665
8666 void
usage(int printlong)8667 usage(int printlong)
8668 {
8669
8670 fprintf(printlong ? stdout : stderr,
8671 "usage: camcontrol <command> [device id][generic args][command args]\n"
8672 " camcontrol devlist [-b] [-v]\n"
8673 #ifndef MINIMALISTIC
8674 " camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
8675 " camcontrol tur [dev_id][generic args]\n"
8676 " camcontrol inquiry [dev_id][generic args] [-D] [-S] [-R]\n"
8677 " camcontrol identify [dev_id][generic args] [-v]\n"
8678 " camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
8679 " camcontrol readcap [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
8680 " [-q] [-s]\n"
8681 " camcontrol start [dev_id][generic args]\n"
8682 " camcontrol stop [dev_id][generic args]\n"
8683 " camcontrol load [dev_id][generic args]\n"
8684 " camcontrol eject [dev_id][generic args]\n"
8685 #endif /* MINIMALISTIC */
8686 " camcontrol rescan <all | bus[:target:lun]>\n"
8687 " camcontrol reset <all | bus[:target:lun]>\n"
8688 #ifndef MINIMALISTIC
8689 " camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n"
8690 " [-q][-s][-S offset][-X]\n"
8691 " camcontrol modepage [dev_id][generic args] <-m page | -l>\n"
8692 " [-P pagectl][-e | -b][-d]\n"
8693 " camcontrol cmd [dev_id][generic args]\n"
8694 " <-a cmd [args] | -c cmd [args]>\n"
8695 " [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
8696 " camcontrol smpcmd [dev_id][generic args]\n"
8697 " <-r len fmt [args]> <-R len fmt [args]>\n"
8698 " camcontrol smprg [dev_id][generic args][-l]\n"
8699 " camcontrol smppc [dev_id][generic args] <-p phy> [-l]\n"
8700 " [-o operation][-d name][-m rate][-M rate]\n"
8701 " [-T pp_timeout][-a enable|disable]\n"
8702 " [-A enable|disable][-s enable|disable]\n"
8703 " [-S enable|disable]\n"
8704 " camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
8705 " camcontrol smpmaninfo [dev_id][generic args][-l]\n"
8706 " camcontrol debug [-I][-P][-T][-S][-X][-c]\n"
8707 " <all|bus[:target[:lun]]|off>\n"
8708 " camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n"
8709 " camcontrol negotiate [dev_id][generic args] [-a][-c]\n"
8710 " [-D <enable|disable>][-M mode][-O offset]\n"
8711 " [-q][-R syncrate][-v][-T <enable|disable>]\n"
8712 " [-U][-W bus_width]\n"
8713 " camcontrol format [dev_id][generic args][-q][-r][-w][-y]\n"
8714 " camcontrol sanitize [dev_id][generic args]\n"
8715 " [-a overwrite|block|crypto|exitfailure]\n"
8716 " [-c passes][-I][-P pattern][-q][-U][-r][-w]\n"
8717 " [-y]\n"
8718 " camcontrol idle [dev_id][generic args][-t time]\n"
8719 " camcontrol standby [dev_id][generic args][-t time]\n"
8720 " camcontrol sleep [dev_id][generic args]\n"
8721 " camcontrol apm [dev_id][generic args][-l level]\n"
8722 " camcontrol aam [dev_id][generic args][-l level]\n"
8723 " camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-q]\n"
8724 " [-s][-y]\n"
8725 " camcontrol security [dev_id][generic args]\n"
8726 " <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
8727 " [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
8728 " [-U <user|master>] [-y]\n"
8729 " camcontrol hpa [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n"
8730 " [-q] [-s max_sectors] [-U pwd] [-y]\n"
8731 " camcontrol persist [dev_id][generic args] <-i action|-o action>\n"
8732 " [-a][-I tid][-k key][-K sa_key][-p][-R rtp]\n"
8733 " [-s scope][-S][-T type][-U]\n"
8734 " camcontrol attrib [dev_id][generic args] <-r action|-w attr>\n"
8735 " [-a attr_num][-c][-e elem][-F form1,form1]\n"
8736 " [-p part][-s start][-T type][-V vol]\n"
8737 " camcontrol opcodes [dev_id][generic args][-o opcode][-s SA]\n"
8738 " [-N][-T]\n"
8739 #endif /* MINIMALISTIC */
8740 " camcontrol help\n");
8741 if (!printlong)
8742 return;
8743 #ifndef MINIMALISTIC
8744 fprintf(stdout,
8745 "Specify one of the following options:\n"
8746 "devlist list all CAM devices\n"
8747 "periphlist list all CAM peripheral drivers attached to a device\n"
8748 "tur send a test unit ready to the named device\n"
8749 "inquiry send a SCSI inquiry command to the named device\n"
8750 "identify send a ATA identify command to the named device\n"
8751 "reportluns send a SCSI report luns command to the device\n"
8752 "readcap send a SCSI read capacity command to the device\n"
8753 "start send a Start Unit command to the device\n"
8754 "stop send a Stop Unit command to the device\n"
8755 "load send a Start Unit command to the device with the load bit set\n"
8756 "eject send a Stop Unit command to the device with the eject bit set\n"
8757 "rescan rescan all busses, the given bus, or bus:target:lun\n"
8758 "reset reset all busses, the given bus, or bus:target:lun\n"
8759 "defects read the defect list of the specified device\n"
8760 "modepage display or edit (-e) the given mode page\n"
8761 "cmd send the given SCSI command, may need -i or -o as well\n"
8762 "smpcmd send the given SMP command, requires -o and -i\n"
8763 "smprg send the SMP Report General command\n"
8764 "smppc send the SMP PHY Control command, requires -p\n"
8765 "smpphylist display phys attached to a SAS expander\n"
8766 "smpmaninfo send the SMP Report Manufacturer Info command\n"
8767 "debug turn debugging on/off for a bus, target, or lun, or all devices\n"
8768 "tags report or set the number of transaction slots for a device\n"
8769 "negotiate report or set device negotiation parameters\n"
8770 "format send the SCSI FORMAT UNIT command to the named device\n"
8771 "sanitize send the SCSI SANITIZE command to the named device\n"
8772 "idle send the ATA IDLE command to the named device\n"
8773 "standby send the ATA STANDBY command to the named device\n"
8774 "sleep send the ATA SLEEP command to the named device\n"
8775 "fwdownload program firmware of the named device with the given image\n"
8776 "security report or send ATA security commands to the named device\n"
8777 "persist send the SCSI PERSISTENT RESERVE IN or OUT commands\n"
8778 "attrib send the SCSI READ or WRITE ATTRIBUTE commands\n"
8779 "opcodes send the SCSI REPORT SUPPORTED OPCODES command\n"
8780 "help this message\n"
8781 "Device Identifiers:\n"
8782 "bus:target specify the bus and target, lun defaults to 0\n"
8783 "bus:target:lun specify the bus, target and lun\n"
8784 "deviceUNIT specify the device name, like \"da4\" or \"cd2\"\n"
8785 "Generic arguments:\n"
8786 "-v be verbose, print out sense information\n"
8787 "-t timeout command timeout in seconds, overrides default timeout\n"
8788 "-n dev_name specify device name, e.g. \"da\", \"cd\"\n"
8789 "-u unit specify unit number, e.g. \"0\", \"5\"\n"
8790 "-E have the kernel attempt to perform SCSI error recovery\n"
8791 "-C count specify the SCSI command retry count (needs -E to work)\n"
8792 "modepage arguments:\n"
8793 "-l list all available mode pages\n"
8794 "-m page specify the mode page to view or edit\n"
8795 "-e edit the specified mode page\n"
8796 "-b force view to binary mode\n"
8797 "-d disable block descriptors for mode sense\n"
8798 "-P pgctl page control field 0-3\n"
8799 "defects arguments:\n"
8800 "-f format specify defect list format (block, bfi or phys)\n"
8801 "-G get the grown defect list\n"
8802 "-P get the permanent defect list\n"
8803 "inquiry arguments:\n"
8804 "-D get the standard inquiry data\n"
8805 "-S get the serial number\n"
8806 "-R get the transfer rate, etc.\n"
8807 "reportluns arguments:\n"
8808 "-c only report a count of available LUNs\n"
8809 "-l only print out luns, and not a count\n"
8810 "-r <reporttype> specify \"default\", \"wellknown\" or \"all\"\n"
8811 "readcap arguments\n"
8812 "-b only report the blocksize\n"
8813 "-h human readable device size, base 2\n"
8814 "-H human readable device size, base 10\n"
8815 "-N print the number of blocks instead of last block\n"
8816 "-q quiet, print numbers only\n"
8817 "-s only report the last block/device size\n"
8818 "cmd arguments:\n"
8819 "-c cdb [args] specify the SCSI CDB\n"
8820 "-i len fmt specify input data and input data format\n"
8821 "-o len fmt [args] specify output data and output data fmt\n"
8822 "smpcmd arguments:\n"
8823 "-r len fmt [args] specify the SMP command to be sent\n"
8824 "-R len fmt [args] specify SMP response format\n"
8825 "smprg arguments:\n"
8826 "-l specify the long response format\n"
8827 "smppc arguments:\n"
8828 "-p phy specify the PHY to operate on\n"
8829 "-l specify the long request/response format\n"
8830 "-o operation specify the phy control operation\n"
8831 "-d name set the attached device name\n"
8832 "-m rate set the minimum physical link rate\n"
8833 "-M rate set the maximum physical link rate\n"
8834 "-T pp_timeout set the partial pathway timeout value\n"
8835 "-a enable|disable enable or disable SATA slumber\n"
8836 "-A enable|disable enable or disable SATA partial phy power\n"
8837 "-s enable|disable enable or disable SAS slumber\n"
8838 "-S enable|disable enable or disable SAS partial phy power\n"
8839 "smpphylist arguments:\n"
8840 "-l specify the long response format\n"
8841 "-q only print phys with attached devices\n"
8842 "smpmaninfo arguments:\n"
8843 "-l specify the long response format\n"
8844 "debug arguments:\n"
8845 "-I CAM_DEBUG_INFO -- scsi commands, errors, data\n"
8846 "-T CAM_DEBUG_TRACE -- routine flow tracking\n"
8847 "-S CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
8848 "-c CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
8849 "tags arguments:\n"
8850 "-N tags specify the number of tags to use for this device\n"
8851 "-q be quiet, don't report the number of tags\n"
8852 "-v report a number of tag-related parameters\n"
8853 "negotiate arguments:\n"
8854 "-a send a test unit ready after negotiation\n"
8855 "-c report/set current negotiation settings\n"
8856 "-D <arg> \"enable\" or \"disable\" disconnection\n"
8857 "-M mode set ATA mode\n"
8858 "-O offset set command delay offset\n"
8859 "-q be quiet, don't report anything\n"
8860 "-R syncrate synchronization rate in MHz\n"
8861 "-T <arg> \"enable\" or \"disable\" tagged queueing\n"
8862 "-U report/set user negotiation settings\n"
8863 "-W bus_width set the bus width in bits (8, 16 or 32)\n"
8864 "-v also print a Path Inquiry CCB for the controller\n"
8865 "format arguments:\n"
8866 "-q be quiet, don't print status messages\n"
8867 "-r run in report only mode\n"
8868 "-w don't send immediate format command\n"
8869 "-y don't ask any questions\n"
8870 "sanitize arguments:\n"
8871 "-a operation operation mode: overwrite, block, crypto or exitfailure\n"
8872 "-c passes overwrite passes to perform (1 to 31)\n"
8873 "-I invert overwrite pattern after each pass\n"
8874 "-P pattern path to overwrite pattern file\n"
8875 "-q be quiet, don't print status messages\n"
8876 "-r run in report only mode\n"
8877 "-U run operation in unrestricted completion exit mode\n"
8878 "-w don't send immediate sanitize command\n"
8879 "-y don't ask any questions\n"
8880 "idle/standby arguments:\n"
8881 "-t <arg> number of seconds before respective state.\n"
8882 "fwdownload arguments:\n"
8883 "-f fw_image path to firmware image file\n"
8884 "-q don't print informational messages, only errors\n"
8885 "-s run in simulation mode\n"
8886 "-v print info for every firmware segment sent to device\n"
8887 "-y don't ask any questions\n"
8888 "security arguments:\n"
8889 "-d pwd disable security using the given password for the selected\n"
8890 " user\n"
8891 "-e pwd erase the device using the given pwd for the selected user\n"
8892 "-f freeze the security configuration of the specified device\n"
8893 "-h pwd enhanced erase the device using the given pwd for the\n"
8894 " selected user\n"
8895 "-k pwd unlock the device using the given pwd for the selected\n"
8896 " user\n"
8897 "-l <high|maximum> specifies which security level to set: high or maximum\n"
8898 "-q be quiet, do not print any status messages\n"
8899 "-s pwd password the device (enable security) using the given\n"
8900 " pwd for the selected user\n"
8901 "-T timeout overrides the timeout (seconds) used for erase operation\n"
8902 "-U <user|master> specifies which user to set: user or master\n"
8903 "-y don't ask any questions\n"
8904 "hpa arguments:\n"
8905 "-f freeze the HPA configuration of the device\n"
8906 "-l lock the HPA configuration of the device\n"
8907 "-P make the HPA max sectors persist\n"
8908 "-p pwd Set the HPA configuration password required for unlock\n"
8909 " calls\n"
8910 "-q be quiet, do not print any status messages\n"
8911 "-s sectors configures the maximum user accessible sectors of the\n"
8912 " device\n"
8913 "-U pwd unlock the HPA configuration of the device\n"
8914 "-y don't ask any questions\n"
8915 "persist arguments:\n"
8916 "-i action specify read_keys, read_reservation, report_cap, or\n"
8917 " read_full_status\n"
8918 "-o action specify register, register_ignore, reserve, release,\n"
8919 " clear, preempt, preempt_abort, register_move, replace_lost\n"
8920 "-a set the All Target Ports (ALL_TG_PT) bit\n"
8921 "-I tid specify a Transport ID, e.g.: sas,0x1234567812345678\n"
8922 "-k key specify the Reservation Key\n"
8923 "-K sa_key specify the Service Action Reservation Key\n"
8924 "-p set the Activate Persist Through Power Loss bit\n"
8925 "-R rtp specify the Relative Target Port\n"
8926 "-s scope specify the scope: lun, extent, element or a number\n"
8927 "-S specify Transport ID for register, requires -I\n"
8928 "-T res_type specify the reservation type: read_shared, wr_ex, rd_ex,\n"
8929 " ex_ac, wr_ex_ro, ex_ac_ro, wr_ex_ar, ex_ac_ar\n"
8930 "-U unregister the current initiator for register_move\n"
8931 "attrib arguments:\n"
8932 "-r action specify attr_values, attr_list, lv_list, part_list, or\n"
8933 " supp_attr\n"
8934 "-w attr specify an attribute to write, one -w argument per attr\n"
8935 "-a attr_num only display this attribute number\n"
8936 "-c get cached attributes\n"
8937 "-e elem_addr request attributes for the given element in a changer\n"
8938 "-F form1,form2 output format, comma separated list: text_esc, text_raw,\n"
8939 " nonascii_esc, nonascii_trim, nonascii_raw, field_all,\n"
8940 " field_none, field_desc, field_num, field_size, field_rw\n"
8941 "-p partition request attributes for the given partition\n"
8942 "-s start_attr request attributes starting at the given number\n"
8943 "-T elem_type specify the element type (used with -e)\n"
8944 "-V logical_vol specify the logical volume ID\n"
8945 "opcodes arguments:\n"
8946 "-o opcode specify the individual opcode to list\n"
8947 "-s service_action specify the service action for the opcode\n"
8948 "-N do not return SCSI error for unsupported SA\n"
8949 "-T request nominal and recommended timeout values\n"
8950 );
8951 #endif /* MINIMALISTIC */
8952 }
8953
8954 int
main(int argc,char ** argv)8955 main(int argc, char **argv)
8956 {
8957 int c;
8958 char *device = NULL;
8959 int unit = 0;
8960 struct cam_device *cam_dev = NULL;
8961 int timeout = 0, retry_count = 1;
8962 camcontrol_optret optreturn;
8963 char *tstr;
8964 const char *mainopt = "C:En:t:u:v";
8965 const char *subopt = NULL;
8966 char combinedopt[256];
8967 int error = 0, optstart = 2;
8968 int devopen = 1;
8969 #ifndef MINIMALISTIC
8970 path_id_t bus;
8971 target_id_t target;
8972 lun_id_t lun;
8973 #endif /* MINIMALISTIC */
8974
8975 cmdlist = CAM_CMD_NONE;
8976 arglist = CAM_ARG_NONE;
8977
8978 if (argc < 2) {
8979 usage(0);
8980 exit(1);
8981 }
8982
8983 /*
8984 * Get the base option.
8985 */
8986 optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
8987
8988 if (optreturn == CC_OR_AMBIGUOUS) {
8989 warnx("ambiguous option %s", argv[1]);
8990 usage(0);
8991 exit(1);
8992 } else if (optreturn == CC_OR_NOT_FOUND) {
8993 warnx("option %s not found", argv[1]);
8994 usage(0);
8995 exit(1);
8996 }
8997
8998 /*
8999 * Ahh, getopt(3) is a pain.
9000 *
9001 * This is a gross hack. There really aren't many other good
9002 * options (excuse the pun) for parsing options in a situation like
9003 * this. getopt is kinda braindead, so you end up having to run
9004 * through the options twice, and give each invocation of getopt
9005 * the option string for the other invocation.
9006 *
9007 * You would think that you could just have two groups of options.
9008 * The first group would get parsed by the first invocation of
9009 * getopt, and the second group would get parsed by the second
9010 * invocation of getopt. It doesn't quite work out that way. When
9011 * the first invocation of getopt finishes, it leaves optind pointing
9012 * to the argument _after_ the first argument in the second group.
9013 * So when the second invocation of getopt comes around, it doesn't
9014 * recognize the first argument it gets and then bails out.
9015 *
9016 * A nice alternative would be to have a flag for getopt that says
9017 * "just keep parsing arguments even when you encounter an unknown
9018 * argument", but there isn't one. So there's no real clean way to
9019 * easily parse two sets of arguments without having one invocation
9020 * of getopt know about the other.
9021 *
9022 * Without this hack, the first invocation of getopt would work as
9023 * long as the generic arguments are first, but the second invocation
9024 * (in the subfunction) would fail in one of two ways. In the case
9025 * where you don't set optreset, it would fail because optind may be
9026 * pointing to the argument after the one it should be pointing at.
9027 * In the case where you do set optreset, and reset optind, it would
9028 * fail because getopt would run into the first set of options, which
9029 * it doesn't understand.
9030 *
9031 * All of this would "sort of" work if you could somehow figure out
9032 * whether optind had been incremented one option too far. The
9033 * mechanics of that, however, are more daunting than just giving
9034 * both invocations all of the expect options for either invocation.
9035 *
9036 * Needless to say, I wouldn't mind if someone invented a better
9037 * (non-GPL!) command line parsing interface than getopt. I
9038 * wouldn't mind if someone added more knobs to getopt to make it
9039 * work better. Who knows, I may talk myself into doing it someday,
9040 * if the standards weenies let me. As it is, it just leads to
9041 * hackery like this and causes people to avoid it in some cases.
9042 *
9043 * KDM, September 8th, 1998
9044 */
9045 if (subopt != NULL)
9046 sprintf(combinedopt, "%s%s", mainopt, subopt);
9047 else
9048 sprintf(combinedopt, "%s", mainopt);
9049
9050 /*
9051 * For these options we do not parse optional device arguments and
9052 * we do not open a passthrough device.
9053 */
9054 if ((cmdlist == CAM_CMD_RESCAN)
9055 || (cmdlist == CAM_CMD_RESET)
9056 || (cmdlist == CAM_CMD_DEVTREE)
9057 || (cmdlist == CAM_CMD_USAGE)
9058 || (cmdlist == CAM_CMD_DEBUG))
9059 devopen = 0;
9060
9061 #ifndef MINIMALISTIC
9062 if ((devopen == 1)
9063 && (argc > 2 && argv[2][0] != '-')) {
9064 char name[30];
9065 int rv;
9066
9067 if (isdigit(argv[2][0])) {
9068 /* device specified as bus:target[:lun] */
9069 rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
9070 if (rv < 2)
9071 errx(1, "numeric device specification must "
9072 "be either bus:target, or "
9073 "bus:target:lun");
9074 /* default to 0 if lun was not specified */
9075 if ((arglist & CAM_ARG_LUN) == 0) {
9076 lun = 0;
9077 arglist |= CAM_ARG_LUN;
9078 }
9079 optstart++;
9080 } else {
9081 if (cam_get_device(argv[2], name, sizeof name, &unit)
9082 == -1)
9083 errx(1, "%s", cam_errbuf);
9084 device = strdup(name);
9085 arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
9086 optstart++;
9087 }
9088 }
9089 #endif /* MINIMALISTIC */
9090 /*
9091 * Start getopt processing at argv[2/3], since we've already
9092 * accepted argv[1..2] as the command name, and as a possible
9093 * device name.
9094 */
9095 optind = optstart;
9096
9097 /*
9098 * Now we run through the argument list looking for generic
9099 * options, and ignoring options that possibly belong to
9100 * subfunctions.
9101 */
9102 while ((c = getopt(argc, argv, combinedopt))!= -1){
9103 switch(c) {
9104 case 'C':
9105 retry_count = strtol(optarg, NULL, 0);
9106 if (retry_count < 0)
9107 errx(1, "retry count %d is < 0",
9108 retry_count);
9109 arglist |= CAM_ARG_RETRIES;
9110 break;
9111 case 'E':
9112 arglist |= CAM_ARG_ERR_RECOVER;
9113 break;
9114 case 'n':
9115 arglist |= CAM_ARG_DEVICE;
9116 tstr = optarg;
9117 while (isspace(*tstr) && (*tstr != '\0'))
9118 tstr++;
9119 device = (char *)strdup(tstr);
9120 break;
9121 case 't':
9122 timeout = strtol(optarg, NULL, 0);
9123 if (timeout < 0)
9124 errx(1, "invalid timeout %d", timeout);
9125 /* Convert the timeout from seconds to ms */
9126 timeout *= 1000;
9127 arglist |= CAM_ARG_TIMEOUT;
9128 break;
9129 case 'u':
9130 arglist |= CAM_ARG_UNIT;
9131 unit = strtol(optarg, NULL, 0);
9132 break;
9133 case 'v':
9134 arglist |= CAM_ARG_VERBOSE;
9135 break;
9136 default:
9137 break;
9138 }
9139 }
9140
9141 #ifndef MINIMALISTIC
9142 /*
9143 * For most commands we'll want to open the passthrough device
9144 * associated with the specified device. In the case of the rescan
9145 * commands, we don't use a passthrough device at all, just the
9146 * transport layer device.
9147 */
9148 if (devopen == 1) {
9149 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
9150 && (((arglist & CAM_ARG_DEVICE) == 0)
9151 || ((arglist & CAM_ARG_UNIT) == 0))) {
9152 errx(1, "subcommand \"%s\" requires a valid device "
9153 "identifier", argv[1]);
9154 }
9155
9156 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
9157 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
9158 cam_open_spec_device(device,unit,O_RDWR,NULL)))
9159 == NULL)
9160 errx(1,"%s", cam_errbuf);
9161 }
9162 #endif /* MINIMALISTIC */
9163
9164 /*
9165 * Reset optind to 2, and reset getopt, so these routines can parse
9166 * the arguments again.
9167 */
9168 optind = optstart;
9169 optreset = 1;
9170
9171 switch(cmdlist) {
9172 #ifndef MINIMALISTIC
9173 case CAM_CMD_DEVLIST:
9174 error = getdevlist(cam_dev);
9175 break;
9176 case CAM_CMD_HPA:
9177 error = atahpa(cam_dev, retry_count, timeout,
9178 argc, argv, combinedopt);
9179 break;
9180 #endif /* MINIMALISTIC */
9181 case CAM_CMD_DEVTREE:
9182 error = getdevtree(argc, argv, combinedopt);
9183 break;
9184 #ifndef MINIMALISTIC
9185 case CAM_CMD_TUR:
9186 error = testunitready(cam_dev, retry_count, timeout, 0);
9187 break;
9188 case CAM_CMD_INQUIRY:
9189 error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
9190 retry_count, timeout);
9191 break;
9192 case CAM_CMD_IDENTIFY:
9193 error = ataidentify(cam_dev, retry_count, timeout);
9194 break;
9195 case CAM_CMD_STARTSTOP:
9196 error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
9197 arglist & CAM_ARG_EJECT, retry_count,
9198 timeout);
9199 break;
9200 #endif /* MINIMALISTIC */
9201 case CAM_CMD_RESCAN:
9202 error = dorescan_or_reset(argc, argv, 1);
9203 break;
9204 case CAM_CMD_RESET:
9205 error = dorescan_or_reset(argc, argv, 0);
9206 break;
9207 #ifndef MINIMALISTIC
9208 case CAM_CMD_READ_DEFECTS:
9209 error = readdefects(cam_dev, argc, argv, combinedopt,
9210 retry_count, timeout);
9211 break;
9212 case CAM_CMD_MODE_PAGE:
9213 modepage(cam_dev, argc, argv, combinedopt,
9214 retry_count, timeout);
9215 break;
9216 case CAM_CMD_SCSI_CMD:
9217 error = scsicmd(cam_dev, argc, argv, combinedopt,
9218 retry_count, timeout);
9219 break;
9220 case CAM_CMD_SMP_CMD:
9221 error = smpcmd(cam_dev, argc, argv, combinedopt,
9222 retry_count, timeout);
9223 break;
9224 case CAM_CMD_SMP_RG:
9225 error = smpreportgeneral(cam_dev, argc, argv,
9226 combinedopt, retry_count,
9227 timeout);
9228 break;
9229 case CAM_CMD_SMP_PC:
9230 error = smpphycontrol(cam_dev, argc, argv, combinedopt,
9231 retry_count, timeout);
9232 break;
9233 case CAM_CMD_SMP_PHYLIST:
9234 error = smpphylist(cam_dev, argc, argv, combinedopt,
9235 retry_count, timeout);
9236 break;
9237 case CAM_CMD_SMP_MANINFO:
9238 error = smpmaninfo(cam_dev, argc, argv, combinedopt,
9239 retry_count, timeout);
9240 break;
9241 case CAM_CMD_DEBUG:
9242 error = camdebug(argc, argv, combinedopt);
9243 break;
9244 case CAM_CMD_TAG:
9245 error = tagcontrol(cam_dev, argc, argv, combinedopt);
9246 break;
9247 case CAM_CMD_RATE:
9248 error = ratecontrol(cam_dev, retry_count, timeout,
9249 argc, argv, combinedopt);
9250 break;
9251 case CAM_CMD_FORMAT:
9252 error = scsiformat(cam_dev, argc, argv,
9253 combinedopt, retry_count, timeout);
9254 break;
9255 case CAM_CMD_REPORTLUNS:
9256 error = scsireportluns(cam_dev, argc, argv,
9257 combinedopt, retry_count,
9258 timeout);
9259 break;
9260 case CAM_CMD_READCAP:
9261 error = scsireadcapacity(cam_dev, argc, argv,
9262 combinedopt, retry_count,
9263 timeout);
9264 break;
9265 case CAM_CMD_IDLE:
9266 case CAM_CMD_STANDBY:
9267 case CAM_CMD_SLEEP:
9268 error = atapm(cam_dev, argc, argv,
9269 combinedopt, retry_count, timeout);
9270 break;
9271 case CAM_CMD_APM:
9272 case CAM_CMD_AAM:
9273 error = ataaxm(cam_dev, argc, argv,
9274 combinedopt, retry_count, timeout);
9275 break;
9276 case CAM_CMD_SECURITY:
9277 error = atasecurity(cam_dev, retry_count, timeout,
9278 argc, argv, combinedopt);
9279 break;
9280 case CAM_CMD_DOWNLOAD_FW:
9281 error = fwdownload(cam_dev, argc, argv, combinedopt,
9282 arglist & CAM_ARG_VERBOSE, retry_count, timeout);
9283 break;
9284 case CAM_CMD_SANITIZE:
9285 error = scsisanitize(cam_dev, argc, argv,
9286 combinedopt, retry_count, timeout);
9287 break;
9288 case CAM_CMD_PERSIST:
9289 error = scsipersist(cam_dev, argc, argv, combinedopt,
9290 retry_count, timeout, arglist & CAM_ARG_VERBOSE,
9291 arglist & CAM_ARG_ERR_RECOVER);
9292 break;
9293 case CAM_CMD_ATTRIB:
9294 error = scsiattrib(cam_dev, argc, argv, combinedopt,
9295 retry_count, timeout, arglist & CAM_ARG_VERBOSE,
9296 arglist & CAM_ARG_ERR_RECOVER);
9297 break;
9298 case CAM_CMD_OPCODES:
9299 error = scsiopcodes(cam_dev, argc, argv, combinedopt,
9300 retry_count, timeout, arglist & CAM_ARG_VERBOSE);
9301 break;
9302 #endif /* MINIMALISTIC */
9303 case CAM_CMD_USAGE:
9304 usage(1);
9305 break;
9306 default:
9307 usage(0);
9308 error = 1;
9309 break;
9310 }
9311
9312 if (cam_dev != NULL)
9313 cam_close_device(cam_dev);
9314
9315 exit(error);
9316 }
9317