2 * Copyright (c) 1997-2007 Kenneth D. Merry
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/ioctl.h>
33 #include <sys/stdint.h>
34 #include <sys/types.h>
36 #include <sys/endian.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>
64 #include "camcontrol.h"
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
106 CAM_ARG_NONE = 0x00000000,
107 CAM_ARG_VERBOSE = 0x00000001,
108 CAM_ARG_DEVICE = 0x00000002,
109 CAM_ARG_BUS = 0x00000004,
110 CAM_ARG_TARGET = 0x00000008,
111 CAM_ARG_LUN = 0x00000010,
112 CAM_ARG_EJECT = 0x00000020,
113 CAM_ARG_UNIT = 0x00000040,
114 CAM_ARG_FORMAT_BLOCK = 0x00000080,
115 CAM_ARG_FORMAT_BFI = 0x00000100,
116 CAM_ARG_FORMAT_PHYS = 0x00000200,
117 CAM_ARG_PLIST = 0x00000400,
118 CAM_ARG_GLIST = 0x00000800,
119 CAM_ARG_GET_SERIAL = 0x00001000,
120 CAM_ARG_GET_STDINQ = 0x00002000,
121 CAM_ARG_GET_XFERRATE = 0x00004000,
122 CAM_ARG_INQ_MASK = 0x00007000,
123 CAM_ARG_MODE_EDIT = 0x00008000,
124 CAM_ARG_PAGE_CNTL = 0x00010000,
125 CAM_ARG_TIMEOUT = 0x00020000,
126 CAM_ARG_CMD_IN = 0x00040000,
127 CAM_ARG_CMD_OUT = 0x00080000,
128 CAM_ARG_DBD = 0x00100000,
129 CAM_ARG_ERR_RECOVER = 0x00200000,
130 CAM_ARG_RETRIES = 0x00400000,
131 CAM_ARG_START_UNIT = 0x00800000,
132 CAM_ARG_DEBUG_INFO = 0x01000000,
133 CAM_ARG_DEBUG_TRACE = 0x02000000,
134 CAM_ARG_DEBUG_SUBTRACE = 0x04000000,
135 CAM_ARG_DEBUG_CDB = 0x08000000,
136 CAM_ARG_DEBUG_XPT = 0x10000000,
137 CAM_ARG_DEBUG_PERIPH = 0x20000000,
138 CAM_ARG_DEBUG_PROBE = 0x40000000,
141 struct camcontrol_opts {
149 struct ata_res_pass16 {
150 u_int16_t reserved[5];
153 u_int8_t sector_count_exp;
154 u_int8_t sector_count;
155 u_int8_t lba_low_exp;
157 u_int8_t lba_mid_exp;
159 u_int8_t lba_high_exp;
165 struct ata_set_max_pwd
168 u_int8_t password[32];
169 u_int16_t reserved2[239];
172 static const char scsicmd_opts[] = "a:c:dfi:o:r";
173 static const char readdefect_opts[] = "f:GPqsS:X";
174 static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
175 static const char smprg_opts[] = "l";
176 static const char smppc_opts[] = "a:A:d:lm:M:o:p:s:S:T:";
177 static const char smpphylist_opts[] = "lq";
181 static struct camcontrol_opts option_table[] = {
183 {"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
184 {"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
185 {"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
186 {"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
187 {"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
188 {"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
189 {"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
190 {"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
191 {"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"},
192 #endif /* MINIMALISTIC */
193 {"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
194 {"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
196 {"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
197 {"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
198 {"smpcmd", CAM_CMD_SMP_CMD, CAM_ARG_NONE, "r:R:"},
199 {"smprg", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
200 {"smpreportgeneral", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
201 {"smppc", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
202 {"smpphycontrol", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
203 {"smpplist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
204 {"smpphylist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
205 {"smpmaninfo", CAM_CMD_SMP_MANINFO, CAM_ARG_NONE, "l"},
206 {"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
207 {"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
208 #endif /* MINIMALISTIC */
209 {"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, "-b"},
211 {"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
212 {"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
213 {"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
214 {"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
215 {"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
216 {"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXcp"},
217 {"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
218 {"sanitize", CAM_CMD_SANITIZE, CAM_ARG_NONE, "a:c:IP:qrUwy"},
219 {"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"},
220 {"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"},
221 {"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""},
222 {"apm", CAM_CMD_APM, CAM_ARG_NONE, "l:"},
223 {"aam", CAM_CMD_AAM, CAM_ARG_NONE, "l:"},
224 {"fwdownload", CAM_CMD_DOWNLOAD_FW, CAM_ARG_NONE, "f:ys"},
225 {"security", CAM_CMD_SECURITY, CAM_ARG_NONE, "d:e:fh:k:l:qs:T:U:y"},
226 {"hpa", CAM_CMD_HPA, CAM_ARG_NONE, "Pflp:qs:U:y"},
227 {"persist", CAM_CMD_PERSIST, CAM_ARG_NONE, "ai:I:k:K:o:ps:ST:U"},
228 {"attrib", CAM_CMD_ATTRIB, CAM_ARG_NONE, "a:ce:F:p:r:s:T:w:V:"},
229 #endif /* MINIMALISTIC */
230 {"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
231 {"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
232 {"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
237 struct device_match_result dev_match;
239 struct periph_match_result *periph_matches;
240 struct scsi_vpd_device_id *device_id;
242 STAILQ_ENTRY(cam_devitem) links;
246 STAILQ_HEAD(, cam_devitem) dev_queue;
250 static cam_cmdmask cmdlist;
251 static cam_argmask arglist;
253 camcontrol_optret getoption(struct camcontrol_opts *table, char *arg,
254 uint32_t *cmdnum, cam_argmask *argnum,
255 const char **subopt);
257 static int getdevlist(struct cam_device *device);
258 #endif /* MINIMALISTIC */
259 static int getdevtree(int argc, char **argv, char *combinedopt);
261 static int testunitready(struct cam_device *device, int retry_count,
262 int timeout, int quiet);
263 static int scsistart(struct cam_device *device, int startstop, int loadeject,
264 int retry_count, int timeout);
265 static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
266 static int scsiserial(struct cam_device *device, int retry_count, int timeout);
267 static int camxferrate(struct cam_device *device);
268 #endif /* MINIMALISTIC */
269 static int parse_btl(char *tstr, path_id_t *bus, target_id_t *target,
270 lun_id_t *lun, cam_argmask *arglst);
271 static int dorescan_or_reset(int argc, char **argv, int rescan);
272 static int rescan_or_reset_bus(path_id_t bus, int rescan);
273 static int scanlun_or_reset_dev(path_id_t bus, target_id_t target,
274 lun_id_t lun, int scan);
276 static int readdefects(struct cam_device *device, int argc, char **argv,
277 char *combinedopt, int retry_count, int timeout);
278 static void modepage(struct cam_device *device, int argc, char **argv,
279 char *combinedopt, int retry_count, int timeout);
280 static int scsicmd(struct cam_device *device, int argc, char **argv,
281 char *combinedopt, int retry_count, int timeout);
282 static int smpcmd(struct cam_device *device, int argc, char **argv,
283 char *combinedopt, int retry_count, int timeout);
284 static int smpreportgeneral(struct cam_device *device, int argc, char **argv,
285 char *combinedopt, int retry_count, int timeout);
286 static int smpphycontrol(struct cam_device *device, int argc, char **argv,
287 char *combinedopt, int retry_count, int timeout);
288 static int smpmaninfo(struct cam_device *device, int argc, char **argv,
289 char *combinedopt, int retry_count, int timeout);
290 static int getdevid(struct cam_devitem *item);
291 static int buildbusdevlist(struct cam_devlist *devlist);
292 static void freebusdevlist(struct cam_devlist *devlist);
293 static struct cam_devitem *findsasdevice(struct cam_devlist *devlist,
295 static int smpphylist(struct cam_device *device, int argc, char **argv,
296 char *combinedopt, int retry_count, int timeout);
297 static int tagcontrol(struct cam_device *device, int argc, char **argv,
299 static void cts_print(struct cam_device *device,
300 struct ccb_trans_settings *cts);
301 static void cpi_print(struct ccb_pathinq *cpi);
302 static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
303 static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd);
304 static int get_print_cts(struct cam_device *device, int user_settings,
305 int quiet, struct ccb_trans_settings *cts);
306 static int ratecontrol(struct cam_device *device, int retry_count,
307 int timeout, int argc, char **argv, char *combinedopt);
308 static int scsiformat(struct cam_device *device, int argc, char **argv,
309 char *combinedopt, int retry_count, int timeout);
310 static int scsisanitize(struct cam_device *device, int argc, char **argv,
311 char *combinedopt, int retry_count, int timeout);
312 static int scsireportluns(struct cam_device *device, int argc, char **argv,
313 char *combinedopt, int retry_count, int timeout);
314 static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
315 char *combinedopt, int retry_count, int timeout);
316 static int atapm(struct cam_device *device, int argc, char **argv,
317 char *combinedopt, int retry_count, int timeout);
318 static int atasecurity(struct cam_device *device, int retry_count, int timeout,
319 int argc, char **argv, char *combinedopt);
320 static int atahpa(struct cam_device *device, int retry_count, int timeout,
321 int argc, char **argv, char *combinedopt);
323 #endif /* MINIMALISTIC */
325 #define min(a,b) (((a)<(b))?(a):(b))
328 #define max(a,b) (((a)>(b))?(a):(b))
332 getoption(struct camcontrol_opts *table, char *arg, uint32_t *cmdnum,
333 cam_argmask *argnum, const char **subopt)
335 struct camcontrol_opts *opts;
338 for (opts = table; (opts != NULL) && (opts->optname != NULL);
340 if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
341 *cmdnum = opts->cmdnum;
342 *argnum = opts->argnum;
343 *subopt = opts->subopt;
344 if (++num_matches > 1)
345 return(CC_OR_AMBIGUOUS);
352 return(CC_OR_NOT_FOUND);
357 getdevlist(struct cam_device *device)
363 ccb = cam_getccb(device);
365 ccb->ccb_h.func_code = XPT_GDEVLIST;
366 ccb->ccb_h.flags = CAM_DIR_NONE;
367 ccb->ccb_h.retry_count = 1;
369 ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
370 while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
371 if (cam_send_ccb(device, ccb) < 0) {
372 perror("error getting device list");
379 switch (ccb->cgdl.status) {
380 case CAM_GDEVLIST_MORE_DEVS:
381 strcpy(status, "MORE");
383 case CAM_GDEVLIST_LAST_DEVICE:
384 strcpy(status, "LAST");
386 case CAM_GDEVLIST_LIST_CHANGED:
387 strcpy(status, "CHANGED");
389 case CAM_GDEVLIST_ERROR:
390 strcpy(status, "ERROR");
395 fprintf(stdout, "%s%d: generation: %d index: %d status: %s\n",
396 ccb->cgdl.periph_name,
397 ccb->cgdl.unit_number,
398 ccb->cgdl.generation,
403 * If the list has changed, we need to start over from the
406 if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
414 #endif /* MINIMALISTIC */
417 getdevtree(int argc, char **argv, char *combinedopt)
428 while ((c = getopt(argc, argv, combinedopt)) != -1) {
431 if ((arglist & CAM_ARG_VERBOSE) == 0)
439 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
440 warn("couldn't open %s", XPT_DEVICE);
444 bzero(&ccb, sizeof(union ccb));
446 ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
447 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
448 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
450 ccb.ccb_h.func_code = XPT_DEV_MATCH;
451 bufsize = sizeof(struct dev_match_result) * 100;
452 ccb.cdm.match_buf_len = bufsize;
453 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
454 if (ccb.cdm.matches == NULL) {
455 warnx("can't malloc memory for matches");
459 ccb.cdm.num_matches = 0;
462 * We fetch all nodes, since we display most of them in the default
463 * case, and all in the verbose case.
465 ccb.cdm.num_patterns = 0;
466 ccb.cdm.pattern_buf_len = 0;
469 * We do the ioctl multiple times if necessary, in case there are
470 * more than 100 nodes in the EDT.
473 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
474 warn("error sending CAMIOCOMMAND ioctl");
479 if ((ccb.ccb_h.status != CAM_REQ_CMP)
480 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
481 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
482 warnx("got CAM error %#x, CDM error %d\n",
483 ccb.ccb_h.status, ccb.cdm.status);
488 for (i = 0; i < ccb.cdm.num_matches; i++) {
489 switch (ccb.cdm.matches[i].type) {
490 case DEV_MATCH_BUS: {
491 struct bus_match_result *bus_result;
494 * Only print the bus information if the
495 * user turns on the verbose flag.
497 if ((busonly == 0) &&
498 (arglist & CAM_ARG_VERBOSE) == 0)
502 &ccb.cdm.matches[i].result.bus_result;
505 fprintf(stdout, ")\n");
509 fprintf(stdout, "scbus%d on %s%d bus %d%s\n",
511 bus_result->dev_name,
512 bus_result->unit_number,
514 (busonly ? "" : ":"));
517 case DEV_MATCH_DEVICE: {
518 struct device_match_result *dev_result;
519 char vendor[16], product[48], revision[16];
520 char fw[5], tmpstr[256];
526 &ccb.cdm.matches[i].result.device_result;
528 if ((dev_result->flags
529 & DEV_RESULT_UNCONFIGURED)
530 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
536 if (dev_result->protocol == PROTO_SCSI) {
537 cam_strvis(vendor, dev_result->inq_data.vendor,
538 sizeof(dev_result->inq_data.vendor),
541 dev_result->inq_data.product,
542 sizeof(dev_result->inq_data.product),
545 dev_result->inq_data.revision,
546 sizeof(dev_result->inq_data.revision),
548 sprintf(tmpstr, "<%s %s %s>", vendor, product,
550 } else if (dev_result->protocol == PROTO_ATA ||
551 dev_result->protocol == PROTO_SATAPM) {
553 dev_result->ident_data.model,
554 sizeof(dev_result->ident_data.model),
557 dev_result->ident_data.revision,
558 sizeof(dev_result->ident_data.revision),
560 sprintf(tmpstr, "<%s %s>", product,
562 } else if (dev_result->protocol == PROTO_SEMB) {
563 struct sep_identify_data *sid;
565 sid = (struct sep_identify_data *)
566 &dev_result->ident_data;
567 cam_strvis(vendor, sid->vendor_id,
568 sizeof(sid->vendor_id),
570 cam_strvis(product, sid->product_id,
571 sizeof(sid->product_id),
573 cam_strvis(revision, sid->product_rev,
574 sizeof(sid->product_rev),
576 cam_strvis(fw, sid->firmware_rev,
577 sizeof(sid->firmware_rev),
579 sprintf(tmpstr, "<%s %s %s %s>",
580 vendor, product, revision, fw);
582 sprintf(tmpstr, "<>");
585 fprintf(stdout, ")\n");
589 fprintf(stdout, "%-33s at scbus%d "
590 "target %d lun %jx (",
593 dev_result->target_id,
594 (uintmax_t)dev_result->target_lun);
600 case DEV_MATCH_PERIPH: {
601 struct periph_match_result *periph_result;
604 &ccb.cdm.matches[i].result.periph_result;
606 if (busonly || skip_device != 0)
610 fprintf(stdout, ",");
612 fprintf(stdout, "%s%d",
613 periph_result->periph_name,
614 periph_result->unit_number);
620 fprintf(stdout, "unknown match type\n");
625 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
626 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
629 fprintf(stdout, ")\n");
638 testunitready(struct cam_device *device, int retry_count, int timeout,
644 ccb = cam_getccb(device);
646 scsi_test_unit_ready(&ccb->csio,
647 /* retries */ retry_count,
649 /* tag_action */ MSG_SIMPLE_Q_TAG,
650 /* sense_len */ SSD_FULL_SIZE,
651 /* timeout */ timeout ? timeout : 5000);
653 /* Disable freezing the device queue */
654 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
656 if (arglist & CAM_ARG_ERR_RECOVER)
657 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
659 if (cam_send_ccb(device, ccb) < 0) {
661 perror("error sending test unit ready");
663 if (arglist & CAM_ARG_VERBOSE) {
664 cam_error_print(device, ccb, CAM_ESF_ALL,
665 CAM_EPF_ALL, stderr);
672 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
674 fprintf(stdout, "Unit is ready\n");
677 fprintf(stdout, "Unit is not ready\n");
680 if (arglist & CAM_ARG_VERBOSE) {
681 cam_error_print(device, ccb, CAM_ESF_ALL,
682 CAM_EPF_ALL, stderr);
692 scsistart(struct cam_device *device, int startstop, int loadeject,
693 int retry_count, int timeout)
698 ccb = cam_getccb(device);
701 * If we're stopping, send an ordered tag so the drive in question
702 * will finish any previously queued writes before stopping. If
703 * the device isn't capable of tagged queueing, or if tagged
704 * queueing is turned off, the tag action is a no-op.
706 scsi_start_stop(&ccb->csio,
707 /* retries */ retry_count,
709 /* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
711 /* start/stop */ startstop,
712 /* load_eject */ loadeject,
714 /* sense_len */ SSD_FULL_SIZE,
715 /* timeout */ timeout ? timeout : 120000);
717 /* Disable freezing the device queue */
718 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
720 if (arglist & CAM_ARG_ERR_RECOVER)
721 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
723 if (cam_send_ccb(device, ccb) < 0) {
724 perror("error sending start unit");
726 if (arglist & CAM_ARG_VERBOSE) {
727 cam_error_print(device, ccb, CAM_ESF_ALL,
728 CAM_EPF_ALL, stderr);
735 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
737 fprintf(stdout, "Unit started successfully");
739 fprintf(stdout,", Media loaded\n");
741 fprintf(stdout,"\n");
743 fprintf(stdout, "Unit stopped successfully");
745 fprintf(stdout, ", Media ejected\n");
747 fprintf(stdout, "\n");
753 "Error received from start unit command\n");
756 "Error received from stop unit command\n");
758 if (arglist & CAM_ARG_VERBOSE) {
759 cam_error_print(device, ccb, CAM_ESF_ALL,
760 CAM_EPF_ALL, stderr);
770 scsidoinquiry(struct cam_device *device, int argc, char **argv,
771 char *combinedopt, int retry_count, int timeout)
776 while ((c = getopt(argc, argv, combinedopt)) != -1) {
779 arglist |= CAM_ARG_GET_STDINQ;
782 arglist |= CAM_ARG_GET_XFERRATE;
785 arglist |= CAM_ARG_GET_SERIAL;
793 * If the user didn't specify any inquiry options, he wants all of
796 if ((arglist & CAM_ARG_INQ_MASK) == 0)
797 arglist |= CAM_ARG_INQ_MASK;
799 if (arglist & CAM_ARG_GET_STDINQ)
800 error = scsiinquiry(device, retry_count, timeout);
805 if (arglist & CAM_ARG_GET_SERIAL)
806 scsiserial(device, retry_count, timeout);
811 if (arglist & CAM_ARG_GET_XFERRATE)
812 error = camxferrate(device);
818 scsiinquiry(struct cam_device *device, int retry_count, int timeout)
821 struct scsi_inquiry_data *inq_buf;
824 ccb = cam_getccb(device);
827 warnx("couldn't allocate CCB");
831 /* cam_getccb cleans up the header, caller has to zero the payload */
832 bzero(&(&ccb->ccb_h)[1],
833 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
835 inq_buf = (struct scsi_inquiry_data *)malloc(
836 sizeof(struct scsi_inquiry_data));
838 if (inq_buf == NULL) {
840 warnx("can't malloc memory for inquiry\n");
843 bzero(inq_buf, sizeof(*inq_buf));
846 * Note that although the size of the inquiry buffer is the full
847 * 256 bytes specified in the SCSI spec, we only tell the device
848 * that we have allocated SHORT_INQUIRY_LENGTH bytes. There are
849 * two reasons for this:
851 * - The SCSI spec says that when a length field is only 1 byte,
852 * a value of 0 will be interpreted as 256. Therefore
853 * scsi_inquiry() will convert an inq_len (which is passed in as
854 * a u_int32_t, but the field in the CDB is only 1 byte) of 256
855 * to 0. Evidently, very few devices meet the spec in that
856 * regard. Some devices, like many Seagate disks, take the 0 as
857 * 0, and don't return any data. One Pioneer DVD-R drive
858 * returns more data than the command asked for.
860 * So, since there are numerous devices that just don't work
861 * right with the full inquiry size, we don't send the full size.
863 * - The second reason not to use the full inquiry data length is
864 * that we don't need it here. The only reason we issue a
865 * standard inquiry is to get the vendor name, device name,
866 * and revision so scsi_print_inquiry() can print them.
868 * If, at some point in the future, more inquiry data is needed for
869 * some reason, this code should use a procedure similar to the
870 * probe code. i.e., issue a short inquiry, and determine from
871 * the additional length passed back from the device how much
872 * inquiry data the device supports. Once the amount the device
873 * supports is determined, issue an inquiry for that amount and no
878 scsi_inquiry(&ccb->csio,
879 /* retries */ retry_count,
881 /* tag_action */ MSG_SIMPLE_Q_TAG,
882 /* inq_buf */ (u_int8_t *)inq_buf,
883 /* inq_len */ SHORT_INQUIRY_LENGTH,
886 /* sense_len */ SSD_FULL_SIZE,
887 /* timeout */ timeout ? timeout : 5000);
889 /* Disable freezing the device queue */
890 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
892 if (arglist & CAM_ARG_ERR_RECOVER)
893 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
895 if (cam_send_ccb(device, ccb) < 0) {
896 perror("error sending SCSI inquiry");
898 if (arglist & CAM_ARG_VERBOSE) {
899 cam_error_print(device, ccb, CAM_ESF_ALL,
900 CAM_EPF_ALL, stderr);
907 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
910 if (arglist & CAM_ARG_VERBOSE) {
911 cam_error_print(device, ccb, CAM_ESF_ALL,
912 CAM_EPF_ALL, stderr);
923 fprintf(stdout, "%s%d: ", device->device_name,
924 device->dev_unit_num);
925 scsi_print_inquiry(inq_buf);
933 scsiserial(struct cam_device *device, int retry_count, int timeout)
936 struct scsi_vpd_unit_serial_number *serial_buf;
937 char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
940 ccb = cam_getccb(device);
943 warnx("couldn't allocate CCB");
947 /* cam_getccb cleans up the header, caller has to zero the payload */
948 bzero(&(&ccb->ccb_h)[1],
949 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
951 serial_buf = (struct scsi_vpd_unit_serial_number *)
952 malloc(sizeof(*serial_buf));
954 if (serial_buf == NULL) {
956 warnx("can't malloc memory for serial number");
960 scsi_inquiry(&ccb->csio,
961 /*retries*/ retry_count,
963 /* tag_action */ MSG_SIMPLE_Q_TAG,
964 /* inq_buf */ (u_int8_t *)serial_buf,
965 /* inq_len */ sizeof(*serial_buf),
967 /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
968 /* sense_len */ SSD_FULL_SIZE,
969 /* timeout */ timeout ? timeout : 5000);
971 /* Disable freezing the device queue */
972 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
974 if (arglist & CAM_ARG_ERR_RECOVER)
975 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
977 if (cam_send_ccb(device, ccb) < 0) {
978 warn("error getting serial number");
980 if (arglist & CAM_ARG_VERBOSE) {
981 cam_error_print(device, ccb, CAM_ESF_ALL,
982 CAM_EPF_ALL, stderr);
990 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
993 if (arglist & CAM_ARG_VERBOSE) {
994 cam_error_print(device, ccb, CAM_ESF_ALL,
995 CAM_EPF_ALL, stderr);
1006 bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
1007 serial_num[serial_buf->length] = '\0';
1009 if ((arglist & CAM_ARG_GET_STDINQ)
1010 || (arglist & CAM_ARG_GET_XFERRATE))
1011 fprintf(stdout, "%s%d: Serial Number ",
1012 device->device_name, device->dev_unit_num);
1014 fprintf(stdout, "%.60s\n", serial_num);
1022 camxferrate(struct cam_device *device)
1024 struct ccb_pathinq cpi;
1026 u_int32_t speed = 0;
1031 if ((retval = get_cpi(device, &cpi)) != 0)
1034 ccb = cam_getccb(device);
1037 warnx("couldn't allocate CCB");
1041 bzero(&(&ccb->ccb_h)[1],
1042 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
1044 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
1045 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
1047 if (((retval = cam_send_ccb(device, ccb)) < 0)
1048 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1049 const char error_string[] = "error getting transfer settings";
1054 warnx(error_string);
1056 if (arglist & CAM_ARG_VERBOSE)
1057 cam_error_print(device, ccb, CAM_ESF_ALL,
1058 CAM_EPF_ALL, stderr);
1062 goto xferrate_bailout;
1066 speed = cpi.base_transfer_speed;
1068 if (ccb->cts.transport == XPORT_SPI) {
1069 struct ccb_trans_settings_spi *spi =
1070 &ccb->cts.xport_specific.spi;
1072 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
1073 freq = scsi_calc_syncsrate(spi->sync_period);
1076 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
1077 speed *= (0x01 << spi->bus_width);
1079 } else if (ccb->cts.transport == XPORT_FC) {
1080 struct ccb_trans_settings_fc *fc =
1081 &ccb->cts.xport_specific.fc;
1083 if (fc->valid & CTS_FC_VALID_SPEED)
1084 speed = fc->bitrate;
1085 } else if (ccb->cts.transport == XPORT_SAS) {
1086 struct ccb_trans_settings_sas *sas =
1087 &ccb->cts.xport_specific.sas;
1089 if (sas->valid & CTS_SAS_VALID_SPEED)
1090 speed = sas->bitrate;
1091 } else if (ccb->cts.transport == XPORT_ATA) {
1092 struct ccb_trans_settings_pata *pata =
1093 &ccb->cts.xport_specific.ata;
1095 if (pata->valid & CTS_ATA_VALID_MODE)
1096 speed = ata_mode2speed(pata->mode);
1097 } else if (ccb->cts.transport == XPORT_SATA) {
1098 struct ccb_trans_settings_sata *sata =
1099 &ccb->cts.xport_specific.sata;
1101 if (sata->valid & CTS_SATA_VALID_REVISION)
1102 speed = ata_revision2speed(sata->revision);
1107 fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
1108 device->device_name, device->dev_unit_num,
1111 fprintf(stdout, "%s%d: %dKB/s transfers",
1112 device->device_name, device->dev_unit_num,
1116 if (ccb->cts.transport == XPORT_SPI) {
1117 struct ccb_trans_settings_spi *spi =
1118 &ccb->cts.xport_specific.spi;
1120 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1121 && (spi->sync_offset != 0))
1122 fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
1123 freq % 1000, spi->sync_offset);
1125 if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
1126 && (spi->bus_width > 0)) {
1127 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1128 && (spi->sync_offset != 0)) {
1129 fprintf(stdout, ", ");
1131 fprintf(stdout, " (");
1133 fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
1134 } else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1135 && (spi->sync_offset != 0)) {
1136 fprintf(stdout, ")");
1138 } else if (ccb->cts.transport == XPORT_ATA) {
1139 struct ccb_trans_settings_pata *pata =
1140 &ccb->cts.xport_specific.ata;
1143 if (pata->valid & CTS_ATA_VALID_MODE)
1144 printf("%s, ", ata_mode2string(pata->mode));
1145 if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0)
1146 printf("ATAPI %dbytes, ", pata->atapi);
1147 if (pata->valid & CTS_ATA_VALID_BYTECOUNT)
1148 printf("PIO %dbytes", pata->bytecount);
1150 } else if (ccb->cts.transport == XPORT_SATA) {
1151 struct ccb_trans_settings_sata *sata =
1152 &ccb->cts.xport_specific.sata;
1155 if (sata->valid & CTS_SATA_VALID_REVISION)
1156 printf("SATA %d.x, ", sata->revision);
1159 if (sata->valid & CTS_SATA_VALID_MODE)
1160 printf("%s, ", ata_mode2string(sata->mode));
1161 if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
1162 printf("ATAPI %dbytes, ", sata->atapi);
1163 if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1164 printf("PIO %dbytes", sata->bytecount);
1168 if (ccb->cts.protocol == PROTO_SCSI) {
1169 struct ccb_trans_settings_scsi *scsi =
1170 &ccb->cts.proto_specific.scsi;
1171 if (scsi->valid & CTS_SCSI_VALID_TQ) {
1172 if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1173 fprintf(stdout, ", Command Queueing Enabled");
1178 fprintf(stdout, "\n");
1188 atahpa_print(struct ata_params *parm, u_int64_t hpasize, int header)
1190 u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1191 ((u_int32_t)parm->lba_size_2 << 16);
1193 u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1194 ((u_int64_t)parm->lba_size48_2 << 16) |
1195 ((u_int64_t)parm->lba_size48_3 << 32) |
1196 ((u_int64_t)parm->lba_size48_4 << 48);
1200 "Support Enabled Value\n");
1203 printf("Host Protected Area (HPA) ");
1204 if (parm->support.command1 & ATA_SUPPORT_PROTECTED) {
1205 u_int64_t lba = lbasize48 ? lbasize48 : lbasize;
1206 printf("yes %s %ju/%ju\n", (hpasize > lba) ? "yes" : "no ",
1209 printf("HPA - Security ");
1210 if (parm->support.command1 & ATA_SUPPORT_MAXSECURITY)
1220 atasata(struct ata_params *parm)
1224 if (parm->satacapabilities != 0xffff &&
1225 parm->satacapabilities != 0x0000)
1232 atacapprint(struct ata_params *parm)
1234 u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1235 ((u_int32_t)parm->lba_size_2 << 16);
1237 u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1238 ((u_int64_t)parm->lba_size48_2 << 16) |
1239 ((u_int64_t)parm->lba_size48_3 << 32) |
1240 ((u_int64_t)parm->lba_size48_4 << 48);
1243 printf("protocol ");
1244 printf("ATA/ATAPI-%d", ata_version(parm->version_major));
1245 if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1246 if (parm->satacapabilities & ATA_SATA_GEN3)
1247 printf(" SATA 3.x\n");
1248 else if (parm->satacapabilities & ATA_SATA_GEN2)
1249 printf(" SATA 2.x\n");
1250 else if (parm->satacapabilities & ATA_SATA_GEN1)
1251 printf(" SATA 1.x\n");
1257 printf("device model %.40s\n", parm->model);
1258 printf("firmware revision %.8s\n", parm->revision);
1259 printf("serial number %.20s\n", parm->serial);
1260 if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
1261 printf("WWN %04x%04x%04x%04x\n",
1262 parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
1264 if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
1265 printf("media serial number %.30s\n",
1266 parm->media_serial);
1269 printf("cylinders %d\n", parm->cylinders);
1270 printf("heads %d\n", parm->heads);
1271 printf("sectors/track %d\n", parm->sectors);
1272 printf("sector size logical %u, physical %lu, offset %lu\n",
1273 ata_logical_sector_size(parm),
1274 (unsigned long)ata_physical_sector_size(parm),
1275 (unsigned long)ata_logical_sector_offset(parm));
1277 if (parm->config == ATA_PROTO_CFA ||
1278 (parm->support.command2 & ATA_SUPPORT_CFA))
1279 printf("CFA supported\n");
1281 printf("LBA%ssupported ",
1282 parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1284 printf("%d sectors\n", lbasize);
1288 printf("LBA48%ssupported ",
1289 parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1291 printf("%ju sectors\n", (uintmax_t)lbasize48);
1295 printf("PIO supported PIO");
1296 switch (ata_max_pmode(parm)) {
1312 if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0)
1313 printf(" w/o IORDY");
1316 printf("DMA%ssupported ",
1317 parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1318 if (parm->capabilities1 & ATA_SUPPORT_DMA) {
1319 if (parm->mwdmamodes & 0xff) {
1321 if (parm->mwdmamodes & 0x04)
1323 else if (parm->mwdmamodes & 0x02)
1325 else if (parm->mwdmamodes & 0x01)
1329 if ((parm->atavalid & ATA_FLAG_88) &&
1330 (parm->udmamodes & 0xff)) {
1332 if (parm->udmamodes & 0x40)
1334 else if (parm->udmamodes & 0x20)
1336 else if (parm->udmamodes & 0x10)
1338 else if (parm->udmamodes & 0x08)
1340 else if (parm->udmamodes & 0x04)
1342 else if (parm->udmamodes & 0x02)
1344 else if (parm->udmamodes & 0x01)
1351 if (parm->media_rotation_rate == 1) {
1352 printf("media RPM non-rotating\n");
1353 } else if (parm->media_rotation_rate >= 0x0401 &&
1354 parm->media_rotation_rate <= 0xFFFE) {
1355 printf("media RPM %d\n",
1356 parm->media_rotation_rate);
1360 "Support Enabled Value Vendor\n");
1361 printf("read ahead %s %s\n",
1362 parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1363 parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1364 printf("write cache %s %s\n",
1365 parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1366 parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1367 printf("flush cache %s %s\n",
1368 parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no",
1369 parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no");
1370 printf("overlap %s\n",
1371 parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no");
1372 printf("Tagged Command Queuing (TCQ) %s %s",
1373 parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1374 parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no");
1375 if (parm->support.command2 & ATA_SUPPORT_QUEUED) {
1376 printf(" %d tags\n",
1377 ATA_QUEUE_LEN(parm->queue) + 1);
1380 printf("Native Command Queuing (NCQ) ");
1381 if (parm->satacapabilities != 0xffff &&
1382 (parm->satacapabilities & ATA_SUPPORT_NCQ)) {
1383 printf("yes %d tags\n",
1384 ATA_QUEUE_LEN(parm->queue) + 1);
1388 printf("NCQ Queue Management %s\n", atasata(parm) &&
1389 parm->satacapabilities2 & ATA_SUPPORT_NCQ_QMANAGEMENT ?
1391 printf("NCQ Streaming %s\n", atasata(parm) &&
1392 parm->satacapabilities2 & ATA_SUPPORT_NCQ_STREAM ?
1394 printf("Receive & Send FPDMA Queued %s\n", atasata(parm) &&
1395 parm->satacapabilities2 & ATA_SUPPORT_RCVSND_FPDMA_QUEUED ?
1398 printf("SMART %s %s\n",
1399 parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1400 parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1401 printf("microcode download %s %s\n",
1402 parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1403 parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1404 printf("security %s %s\n",
1405 parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1406 parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1407 printf("power management %s %s\n",
1408 parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1409 parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1410 printf("advanced power management %s %s",
1411 parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1412 parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no");
1413 if (parm->support.command2 & ATA_SUPPORT_APM) {
1414 printf(" %d/0x%02X\n",
1415 parm->apm_value & 0xff, parm->apm_value & 0xff);
1418 printf("automatic acoustic management %s %s",
1419 parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1420 parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no");
1421 if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) {
1422 printf(" %d/0x%02X %d/0x%02X\n",
1423 ATA_ACOUSTIC_CURRENT(parm->acoustic),
1424 ATA_ACOUSTIC_CURRENT(parm->acoustic),
1425 ATA_ACOUSTIC_VENDOR(parm->acoustic),
1426 ATA_ACOUSTIC_VENDOR(parm->acoustic));
1429 printf("media status notification %s %s\n",
1430 parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1431 parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1432 printf("power-up in Standby %s %s\n",
1433 parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1434 parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1435 printf("write-read-verify %s %s",
1436 parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1437 parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no");
1438 if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) {
1439 printf(" %d/0x%x\n",
1440 parm->wrv_mode, parm->wrv_mode);
1443 printf("unload %s %s\n",
1444 parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1445 parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1446 printf("general purpose logging %s %s\n",
1447 parm->support.extension & ATA_SUPPORT_GENLOG ? "yes" : "no",
1448 parm->enabled.extension & ATA_SUPPORT_GENLOG ? "yes" : "no");
1449 printf("free-fall %s %s\n",
1450 parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1451 parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1452 printf("Data Set Management (DSM/TRIM) ");
1453 if (parm->support_dsm & ATA_SUPPORT_DSM_TRIM) {
1455 printf("DSM - max 512byte blocks ");
1456 if (parm->max_dsm_blocks == 0x00)
1457 printf("yes not specified\n");
1460 parm->max_dsm_blocks);
1462 printf("DSM - deterministic read ");
1463 if (parm->support3 & ATA_SUPPORT_DRAT) {
1464 if (parm->support3 & ATA_SUPPORT_RZAT)
1465 printf("yes zeroed\n");
1467 printf("yes any value\n");
1477 scsi_cam_pass_16_send(struct cam_device *device, union ccb *ccb, int quiet)
1479 struct ata_pass_16 *ata_pass_16;
1480 struct ata_cmd ata_cmd;
1482 ata_pass_16 = (struct ata_pass_16 *)ccb->csio.cdb_io.cdb_bytes;
1483 ata_cmd.command = ata_pass_16->command;
1484 ata_cmd.control = ata_pass_16->control;
1485 ata_cmd.features = ata_pass_16->features;
1487 if (arglist & CAM_ARG_VERBOSE) {
1488 warnx("sending ATA %s via pass_16 with timeout of %u msecs",
1489 ata_op_string(&ata_cmd),
1490 ccb->csio.ccb_h.timeout);
1493 /* Disable freezing the device queue */
1494 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1496 if (arglist & CAM_ARG_ERR_RECOVER)
1497 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1499 if (cam_send_ccb(device, ccb) < 0) {
1500 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1501 warn("error sending ATA %s via pass_16",
1502 ata_op_string(&ata_cmd));
1505 if (arglist & CAM_ARG_VERBOSE) {
1506 cam_error_print(device, ccb, CAM_ESF_ALL,
1507 CAM_EPF_ALL, stderr);
1513 if (!(ata_pass_16->flags & AP_FLAG_CHK_COND) &&
1514 (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1515 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1516 warnx("ATA %s via pass_16 failed",
1517 ata_op_string(&ata_cmd));
1519 if (arglist & CAM_ARG_VERBOSE) {
1520 cam_error_print(device, ccb, CAM_ESF_ALL,
1521 CAM_EPF_ALL, stderr);
1532 ata_cam_send(struct cam_device *device, union ccb *ccb, int quiet)
1534 if (arglist & CAM_ARG_VERBOSE) {
1535 warnx("sending ATA %s with timeout of %u msecs",
1536 ata_op_string(&(ccb->ataio.cmd)),
1537 ccb->ataio.ccb_h.timeout);
1540 /* Disable freezing the device queue */
1541 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1543 if (arglist & CAM_ARG_ERR_RECOVER)
1544 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1546 if (cam_send_ccb(device, ccb) < 0) {
1547 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1548 warn("error sending ATA %s",
1549 ata_op_string(&(ccb->ataio.cmd)));
1552 if (arglist & CAM_ARG_VERBOSE) {
1553 cam_error_print(device, ccb, CAM_ESF_ALL,
1554 CAM_EPF_ALL, stderr);
1560 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1561 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1562 warnx("ATA %s failed: %d",
1563 ata_op_string(&(ccb->ataio.cmd)), quiet);
1566 if (arglist & CAM_ARG_VERBOSE) {
1567 cam_error_print(device, ccb, CAM_ESF_ALL,
1568 CAM_EPF_ALL, stderr);
1578 ata_do_pass_16(struct cam_device *device, union ccb *ccb, int retries,
1579 u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
1580 u_int8_t tag_action, u_int8_t command, u_int8_t features,
1581 u_int64_t lba, u_int8_t sector_count, u_int8_t *data_ptr,
1582 u_int16_t dxfer_len, int timeout, int quiet)
1584 if (data_ptr != NULL) {
1585 ata_flags |= AP_FLAG_BYT_BLOK_BYTES |
1586 AP_FLAG_TLEN_SECT_CNT;
1587 if (flags & CAM_DIR_OUT)
1588 ata_flags |= AP_FLAG_TDIR_TO_DEV;
1590 ata_flags |= AP_FLAG_TDIR_FROM_DEV;
1592 ata_flags |= AP_FLAG_TLEN_NO_DATA;
1595 bzero(&(&ccb->ccb_h)[1],
1596 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1598 scsi_ata_pass_16(&ccb->csio,
1612 /*sense_len*/SSD_FULL_SIZE,
1615 return scsi_cam_pass_16_send(device, ccb, quiet);
1619 ata_try_pass_16(struct cam_device *device)
1621 struct ccb_pathinq cpi;
1623 if (get_cpi(device, &cpi) != 0) {
1624 warnx("couldn't get CPI");
1628 if (cpi.protocol == PROTO_SCSI) {
1629 /* possibly compatible with pass_16 */
1633 /* likely not compatible with pass_16 */
1638 ata_do_28bit_cmd(struct cam_device *device, union ccb *ccb, int retries,
1639 u_int32_t flags, u_int8_t protocol, u_int8_t tag_action,
1640 u_int8_t command, u_int8_t features, u_int32_t lba,
1641 u_int8_t sector_count, u_int8_t *data_ptr, u_int16_t dxfer_len,
1642 int timeout, int quiet)
1646 switch (ata_try_pass_16(device)) {
1650 /* Try using SCSI Passthrough */
1651 return ata_do_pass_16(device, ccb, retries, flags, protocol,
1652 0, tag_action, command, features, lba,
1653 sector_count, data_ptr, dxfer_len,
1657 bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) -
1658 sizeof(struct ccb_hdr));
1659 cam_fill_ataio(&ccb->ataio,
1668 ata_28bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1669 return ata_cam_send(device, ccb, quiet);
1673 ata_do_cmd(struct cam_device *device, union ccb *ccb, int retries,
1674 u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
1675 u_int8_t tag_action, u_int8_t command, u_int8_t features,
1676 u_int64_t lba, u_int8_t sector_count, u_int8_t *data_ptr,
1677 u_int16_t dxfer_len, int timeout, int force48bit)
1681 retval = ata_try_pass_16(device);
1688 /* Try using SCSI Passthrough */
1689 error = ata_do_pass_16(device, ccb, retries, flags, protocol,
1690 ata_flags, tag_action, command, features,
1691 lba, sector_count, data_ptr, dxfer_len,
1694 if (ata_flags & AP_FLAG_CHK_COND) {
1695 /* Decode ata_res from sense data */
1696 struct ata_res_pass16 *res_pass16;
1697 struct ata_res *res;
1701 /* sense_data is 4 byte aligned */
1702 ptr = (uint16_t*)(uintptr_t)&ccb->csio.sense_data;
1703 for (i = 0; i < sizeof(*res_pass16) / 2; i++)
1704 ptr[i] = le16toh(ptr[i]);
1706 /* sense_data is 4 byte aligned */
1707 res_pass16 = (struct ata_res_pass16 *)(uintptr_t)
1708 &ccb->csio.sense_data;
1709 res = &ccb->ataio.res;
1710 res->flags = res_pass16->flags;
1711 res->status = res_pass16->status;
1712 res->error = res_pass16->error;
1713 res->lba_low = res_pass16->lba_low;
1714 res->lba_mid = res_pass16->lba_mid;
1715 res->lba_high = res_pass16->lba_high;
1716 res->device = res_pass16->device;
1717 res->lba_low_exp = res_pass16->lba_low_exp;
1718 res->lba_mid_exp = res_pass16->lba_mid_exp;
1719 res->lba_high_exp = res_pass16->lba_high_exp;
1720 res->sector_count = res_pass16->sector_count;
1721 res->sector_count_exp = res_pass16->sector_count_exp;
1727 bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) -
1728 sizeof(struct ccb_hdr));
1729 cam_fill_ataio(&ccb->ataio,
1738 if (force48bit || lba > ATA_MAX_28BIT_LBA)
1739 ata_48bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1741 ata_28bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1743 if (ata_flags & AP_FLAG_CHK_COND)
1744 ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
1746 return ata_cam_send(device, ccb, 0);
1750 dump_data(uint16_t *ptr, uint32_t len)
1754 for (i = 0; i < len / 2; i++) {
1756 printf(" %3d: ", i);
1757 printf("%04hx ", ptr[i]);
1766 atahpa_proc_resp(struct cam_device *device, union ccb *ccb,
1767 int is48bit, u_int64_t *hpasize)
1769 struct ata_res *res;
1771 res = &ccb->ataio.res;
1772 if (res->status & ATA_STATUS_ERROR) {
1773 if (arglist & CAM_ARG_VERBOSE) {
1774 cam_error_print(device, ccb, CAM_ESF_ALL,
1775 CAM_EPF_ALL, stderr);
1776 printf("error = 0x%02x, sector_count = 0x%04x, "
1777 "device = 0x%02x, status = 0x%02x\n",
1778 res->error, res->sector_count,
1779 res->device, res->status);
1782 if (res->error & ATA_ERROR_ID_NOT_FOUND) {
1783 warnx("Max address has already been set since "
1784 "last power-on or hardware reset");
1790 if (arglist & CAM_ARG_VERBOSE) {
1791 fprintf(stdout, "%s%d: Raw native max data:\n",
1792 device->device_name, device->dev_unit_num);
1793 /* res is 4 byte aligned */
1794 dump_data((uint16_t*)(uintptr_t)res, sizeof(struct ata_res));
1796 printf("error = 0x%02x, sector_count = 0x%04x, device = 0x%02x, "
1797 "status = 0x%02x\n", res->error, res->sector_count,
1798 res->device, res->status);
1801 if (hpasize != NULL) {
1803 *hpasize = (((u_int64_t)((res->lba_high_exp << 16) |
1804 (res->lba_mid_exp << 8) | res->lba_low_exp) << 24) |
1805 ((res->lba_high << 16) | (res->lba_mid << 8) |
1808 *hpasize = (((res->device & 0x0f) << 24) |
1809 (res->lba_high << 16) | (res->lba_mid << 8) |
1818 ata_read_native_max(struct cam_device *device, int retry_count,
1819 u_int32_t timeout, union ccb *ccb,
1820 struct ata_params *parm, u_int64_t *hpasize)
1826 is48bit = parm->support.command2 & ATA_SUPPORT_ADDRESS48;
1827 protocol = AP_PROTO_NON_DATA;
1830 cmd = ATA_READ_NATIVE_MAX_ADDRESS48;
1831 protocol |= AP_EXTEND;
1833 cmd = ATA_READ_NATIVE_MAX_ADDRESS;
1836 error = ata_do_cmd(device,
1839 /*flags*/CAM_DIR_NONE,
1840 /*protocol*/protocol,
1841 /*ata_flags*/AP_FLAG_CHK_COND,
1842 /*tag_action*/MSG_SIMPLE_Q_TAG,
1849 timeout ? timeout : 1000,
1855 return atahpa_proc_resp(device, ccb, is48bit, hpasize);
1859 atahpa_set_max(struct cam_device *device, int retry_count,
1860 u_int32_t timeout, union ccb *ccb,
1861 int is48bit, u_int64_t maxsize, int persist)
1867 protocol = AP_PROTO_NON_DATA;
1870 cmd = ATA_SET_MAX_ADDRESS48;
1871 protocol |= AP_EXTEND;
1873 cmd = ATA_SET_MAX_ADDRESS;
1876 /* lba's are zero indexed so the max lba is requested max - 1 */
1880 error = ata_do_cmd(device,
1883 /*flags*/CAM_DIR_NONE,
1884 /*protocol*/protocol,
1885 /*ata_flags*/AP_FLAG_CHK_COND,
1886 /*tag_action*/MSG_SIMPLE_Q_TAG,
1888 /*features*/ATA_HPA_FEAT_MAX_ADDR,
1890 /*sector_count*/persist,
1893 timeout ? timeout : 1000,
1899 return atahpa_proc_resp(device, ccb, is48bit, NULL);
1903 atahpa_password(struct cam_device *device, int retry_count,
1904 u_int32_t timeout, union ccb *ccb,
1905 int is48bit, struct ata_set_max_pwd *pwd)
1911 protocol = AP_PROTO_PIO_OUT;
1912 cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1914 error = ata_do_cmd(device,
1917 /*flags*/CAM_DIR_OUT,
1918 /*protocol*/protocol,
1919 /*ata_flags*/AP_FLAG_CHK_COND,
1920 /*tag_action*/MSG_SIMPLE_Q_TAG,
1922 /*features*/ATA_HPA_FEAT_SET_PWD,
1925 /*data_ptr*/(u_int8_t*)pwd,
1926 /*dxfer_len*/sizeof(struct ata_set_max_pwd),
1927 timeout ? timeout : 1000,
1933 return atahpa_proc_resp(device, ccb, is48bit, NULL);
1937 atahpa_lock(struct cam_device *device, int retry_count,
1938 u_int32_t timeout, union ccb *ccb, int is48bit)
1944 protocol = AP_PROTO_NON_DATA;
1945 cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1947 error = ata_do_cmd(device,
1950 /*flags*/CAM_DIR_NONE,
1951 /*protocol*/protocol,
1952 /*ata_flags*/AP_FLAG_CHK_COND,
1953 /*tag_action*/MSG_SIMPLE_Q_TAG,
1955 /*features*/ATA_HPA_FEAT_LOCK,
1960 timeout ? timeout : 1000,
1966 return atahpa_proc_resp(device, ccb, is48bit, NULL);
1970 atahpa_unlock(struct cam_device *device, int retry_count,
1971 u_int32_t timeout, union ccb *ccb,
1972 int is48bit, struct ata_set_max_pwd *pwd)
1978 protocol = AP_PROTO_PIO_OUT;
1979 cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1981 error = ata_do_cmd(device,
1984 /*flags*/CAM_DIR_OUT,
1985 /*protocol*/protocol,
1986 /*ata_flags*/AP_FLAG_CHK_COND,
1987 /*tag_action*/MSG_SIMPLE_Q_TAG,
1989 /*features*/ATA_HPA_FEAT_UNLOCK,
1992 /*data_ptr*/(u_int8_t*)pwd,
1993 /*dxfer_len*/sizeof(struct ata_set_max_pwd),
1994 timeout ? timeout : 1000,
2000 return atahpa_proc_resp(device, ccb, is48bit, NULL);
2004 atahpa_freeze_lock(struct cam_device *device, int retry_count,
2005 u_int32_t timeout, union ccb *ccb, int is48bit)
2011 protocol = AP_PROTO_NON_DATA;
2012 cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
2014 error = ata_do_cmd(device,
2017 /*flags*/CAM_DIR_NONE,
2018 /*protocol*/protocol,
2019 /*ata_flags*/AP_FLAG_CHK_COND,
2020 /*tag_action*/MSG_SIMPLE_Q_TAG,
2022 /*features*/ATA_HPA_FEAT_FREEZE,
2027 timeout ? timeout : 1000,
2033 return atahpa_proc_resp(device, ccb, is48bit, NULL);
2038 ata_do_identify(struct cam_device *device, int retry_count, int timeout,
2039 union ccb *ccb, struct ata_params** ident_bufp)
2041 struct ata_params *ident_buf;
2042 struct ccb_pathinq cpi;
2043 struct ccb_getdev cgd;
2046 u_int8_t command, retry_command;
2048 if (get_cpi(device, &cpi) != 0) {
2049 warnx("couldn't get CPI");
2053 /* Neither PROTO_ATAPI or PROTO_SATAPM are used in cpi.protocol */
2054 if (cpi.protocol == PROTO_ATA) {
2055 if (get_cgd(device, &cgd) != 0) {
2056 warnx("couldn't get CGD");
2060 command = (cgd.protocol == PROTO_ATA) ?
2061 ATA_ATA_IDENTIFY : ATA_ATAPI_IDENTIFY;
2064 /* We don't know which for sure so try both */
2065 command = ATA_ATA_IDENTIFY;
2066 retry_command = ATA_ATAPI_IDENTIFY;
2069 ptr = (uint16_t *)calloc(1, sizeof(struct ata_params));
2071 warnx("can't calloc memory for identify\n");
2075 error = ata_do_28bit_cmd(device,
2077 /*retries*/retry_count,
2078 /*flags*/CAM_DIR_IN,
2079 /*protocol*/AP_PROTO_PIO_IN,
2080 /*tag_action*/MSG_SIMPLE_Q_TAG,
2084 /*sector_count*/(u_int8_t)sizeof(struct ata_params),
2085 /*data_ptr*/(u_int8_t *)ptr,
2086 /*dxfer_len*/sizeof(struct ata_params),
2087 /*timeout*/timeout ? timeout : 30 * 1000,
2091 if (retry_command == 0) {
2095 error = ata_do_28bit_cmd(device,
2097 /*retries*/retry_count,
2098 /*flags*/CAM_DIR_IN,
2099 /*protocol*/AP_PROTO_PIO_IN,
2100 /*tag_action*/MSG_SIMPLE_Q_TAG,
2101 /*command*/retry_command,
2104 /*sector_count*/(u_int8_t)
2105 sizeof(struct ata_params),
2106 /*data_ptr*/(u_int8_t *)ptr,
2107 /*dxfer_len*/sizeof(struct ata_params),
2108 /*timeout*/timeout ? timeout : 30 * 1000,
2118 for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
2119 ptr[i] = le16toh(ptr[i]);
2124 if (arglist & CAM_ARG_VERBOSE) {
2125 fprintf(stdout, "%s%d: Raw identify data:\n",
2126 device->device_name, device->dev_unit_num);
2127 dump_data(ptr, sizeof(struct ata_params));
2130 /* check for invalid (all zero) response */
2132 warnx("Invalid identify response detected");
2137 ident_buf = (struct ata_params *)ptr;
2138 if (strncmp(ident_buf->model, "FX", 2) &&
2139 strncmp(ident_buf->model, "NEC", 3) &&
2140 strncmp(ident_buf->model, "Pioneer", 7) &&
2141 strncmp(ident_buf->model, "SHARP", 5)) {
2142 ata_bswap(ident_buf->model, sizeof(ident_buf->model));
2143 ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
2144 ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
2145 ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
2147 ata_btrim(ident_buf->model, sizeof(ident_buf->model));
2148 ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
2149 ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
2150 ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
2151 ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
2152 ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
2153 ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
2154 ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
2155 sizeof(ident_buf->media_serial));
2157 *ident_bufp = ident_buf;
2164 ataidentify(struct cam_device *device, int retry_count, int timeout)
2167 struct ata_params *ident_buf;
2170 if ((ccb = cam_getccb(device)) == NULL) {
2171 warnx("couldn't allocate CCB");
2175 if (ata_do_identify(device, retry_count, timeout, ccb, &ident_buf) != 0) {
2180 if (ident_buf->support.command1 & ATA_SUPPORT_PROTECTED) {
2181 if (ata_read_native_max(device, retry_count, timeout, ccb,
2182 ident_buf, &hpasize) != 0) {
2190 printf("%s%d: ", device->device_name, device->dev_unit_num);
2191 ata_print_ident(ident_buf);
2192 camxferrate(device);
2193 atacapprint(ident_buf);
2194 atahpa_print(ident_buf, hpasize, 0);
2201 #endif /* MINIMALISTIC */
2204 #ifndef MINIMALISTIC
2206 ATA_SECURITY_ACTION_PRINT,
2207 ATA_SECURITY_ACTION_FREEZE,
2208 ATA_SECURITY_ACTION_UNLOCK,
2209 ATA_SECURITY_ACTION_DISABLE,
2210 ATA_SECURITY_ACTION_ERASE,
2211 ATA_SECURITY_ACTION_ERASE_ENHANCED,
2212 ATA_SECURITY_ACTION_SET_PASSWORD
2216 atasecurity_print_time(u_int16_t tw)
2220 printf("unspecified");
2222 printf("> 508 min");
2224 printf("%i min", 2 * tw);
2228 atasecurity_erase_timeout_msecs(u_int16_t timeout)
2232 return 2 * 3600 * 1000; /* default: two hours */
2233 else if (timeout > 255)
2234 return (508 + 60) * 60 * 1000; /* spec says > 508 minutes */
2236 return ((2 * timeout) + 5) * 60 * 1000; /* add a 5min margin */
2241 atasecurity_notify(u_int8_t command, struct ata_security_password *pwd)
2245 bzero(&cmd, sizeof(cmd));
2246 cmd.command = command;
2247 printf("Issuing %s", ata_op_string(&cmd));
2250 char pass[sizeof(pwd->password)+1];
2252 /* pwd->password may not be null terminated */
2253 pass[sizeof(pwd->password)] = '\0';
2254 strncpy(pass, pwd->password, sizeof(pwd->password));
2255 printf(" password='%s', user='%s'",
2257 (pwd->ctrl & ATA_SECURITY_PASSWORD_MASTER) ?
2260 if (command == ATA_SECURITY_SET_PASSWORD) {
2261 printf(", mode='%s'",
2262 (pwd->ctrl & ATA_SECURITY_LEVEL_MAXIMUM) ?
2263 "maximum" : "high");
2271 atasecurity_freeze(struct cam_device *device, union ccb *ccb,
2272 int retry_count, u_int32_t timeout, int quiet)
2276 atasecurity_notify(ATA_SECURITY_FREEZE_LOCK, NULL);
2278 return ata_do_28bit_cmd(device,
2281 /*flags*/CAM_DIR_NONE,
2282 /*protocol*/AP_PROTO_NON_DATA,
2283 /*tag_action*/MSG_SIMPLE_Q_TAG,
2284 /*command*/ATA_SECURITY_FREEZE_LOCK,
2295 atasecurity_unlock(struct cam_device *device, union ccb *ccb,
2296 int retry_count, u_int32_t timeout,
2297 struct ata_security_password *pwd, int quiet)
2301 atasecurity_notify(ATA_SECURITY_UNLOCK, pwd);
2303 return ata_do_28bit_cmd(device,
2306 /*flags*/CAM_DIR_OUT,
2307 /*protocol*/AP_PROTO_PIO_OUT,
2308 /*tag_action*/MSG_SIMPLE_Q_TAG,
2309 /*command*/ATA_SECURITY_UNLOCK,
2313 /*data_ptr*/(u_int8_t *)pwd,
2314 /*dxfer_len*/sizeof(*pwd),
2320 atasecurity_disable(struct cam_device *device, union ccb *ccb,
2321 int retry_count, u_int32_t timeout,
2322 struct ata_security_password *pwd, int quiet)
2326 atasecurity_notify(ATA_SECURITY_DISABLE_PASSWORD, pwd);
2327 return ata_do_28bit_cmd(device,
2330 /*flags*/CAM_DIR_OUT,
2331 /*protocol*/AP_PROTO_PIO_OUT,
2332 /*tag_action*/MSG_SIMPLE_Q_TAG,
2333 /*command*/ATA_SECURITY_DISABLE_PASSWORD,
2337 /*data_ptr*/(u_int8_t *)pwd,
2338 /*dxfer_len*/sizeof(*pwd),
2345 atasecurity_erase_confirm(struct cam_device *device,
2346 struct ata_params* ident_buf)
2349 printf("\nYou are about to ERASE ALL DATA from the following"
2350 " device:\n%s%d,%s%d: ", device->device_name,
2351 device->dev_unit_num, device->given_dev_name,
2352 device->given_unit_number);
2353 ata_print_ident(ident_buf);
2357 printf("\nAre you SURE you want to ERASE ALL DATA? (yes/no) ");
2359 if (fgets(str, sizeof(str), stdin) != NULL) {
2360 if (strncasecmp(str, "yes", 3) == 0) {
2362 } else if (strncasecmp(str, "no", 2) == 0) {
2365 printf("Please answer \"yes\" or "
2376 atasecurity_erase(struct cam_device *device, union ccb *ccb,
2377 int retry_count, u_int32_t timeout,
2378 u_int32_t erase_timeout,
2379 struct ata_security_password *pwd, int quiet)
2384 atasecurity_notify(ATA_SECURITY_ERASE_PREPARE, NULL);
2386 error = ata_do_28bit_cmd(device,
2389 /*flags*/CAM_DIR_NONE,
2390 /*protocol*/AP_PROTO_NON_DATA,
2391 /*tag_action*/MSG_SIMPLE_Q_TAG,
2392 /*command*/ATA_SECURITY_ERASE_PREPARE,
2405 atasecurity_notify(ATA_SECURITY_ERASE_UNIT, pwd);
2407 error = ata_do_28bit_cmd(device,
2410 /*flags*/CAM_DIR_OUT,
2411 /*protocol*/AP_PROTO_PIO_OUT,
2412 /*tag_action*/MSG_SIMPLE_Q_TAG,
2413 /*command*/ATA_SECURITY_ERASE_UNIT,
2417 /*data_ptr*/(u_int8_t *)pwd,
2418 /*dxfer_len*/sizeof(*pwd),
2419 /*timeout*/erase_timeout,
2422 if (error == 0 && quiet == 0)
2423 printf("\nErase Complete\n");
2429 atasecurity_set_password(struct cam_device *device, union ccb *ccb,
2430 int retry_count, u_int32_t timeout,
2431 struct ata_security_password *pwd, int quiet)
2435 atasecurity_notify(ATA_SECURITY_SET_PASSWORD, pwd);
2437 return ata_do_28bit_cmd(device,
2440 /*flags*/CAM_DIR_OUT,
2441 /*protocol*/AP_PROTO_PIO_OUT,
2442 /*tag_action*/MSG_SIMPLE_Q_TAG,
2443 /*command*/ATA_SECURITY_SET_PASSWORD,
2447 /*data_ptr*/(u_int8_t *)pwd,
2448 /*dxfer_len*/sizeof(*pwd),
2454 atasecurity_print(struct ata_params *parm)
2457 printf("\nSecurity Option Value\n");
2458 if (arglist & CAM_ARG_VERBOSE) {
2459 printf("status %04x\n",
2460 parm->security_status);
2462 printf("supported %s\n",
2463 parm->security_status & ATA_SECURITY_SUPPORTED ? "yes" : "no");
2464 if (!(parm->security_status & ATA_SECURITY_SUPPORTED))
2466 printf("enabled %s\n",
2467 parm->security_status & ATA_SECURITY_ENABLED ? "yes" : "no");
2468 printf("drive locked %s\n",
2469 parm->security_status & ATA_SECURITY_LOCKED ? "yes" : "no");
2470 printf("security config frozen %s\n",
2471 parm->security_status & ATA_SECURITY_FROZEN ? "yes" : "no");
2472 printf("count expired %s\n",
2473 parm->security_status & ATA_SECURITY_COUNT_EXP ? "yes" : "no");
2474 printf("security level %s\n",
2475 parm->security_status & ATA_SECURITY_LEVEL ? "maximum" : "high");
2476 printf("enhanced erase supported %s\n",
2477 parm->security_status & ATA_SECURITY_ENH_SUPP ? "yes" : "no");
2478 printf("erase time ");
2479 atasecurity_print_time(parm->erase_time);
2481 printf("enhanced erase time ");
2482 atasecurity_print_time(parm->enhanced_erase_time);
2484 printf("master password rev %04x%s\n",
2485 parm->master_passwd_revision,
2486 parm->master_passwd_revision == 0x0000 ||
2487 parm->master_passwd_revision == 0xFFFF ? " (unsupported)" : "");
2491 * Validates and copies the password in optarg to the passed buffer.
2492 * If the password in optarg is the same length as the buffer then
2493 * the data will still be copied but no null termination will occur.
2496 ata_getpwd(u_int8_t *passwd, int max, char opt)
2500 len = strlen(optarg);
2502 warnx("-%c password is too long", opt);
2504 } else if (len == 0) {
2505 warnx("-%c password is missing", opt);
2507 } else if (optarg[0] == '-'){
2508 warnx("-%c password starts with '-' (generic arg?)", opt);
2510 } else if (strlen(passwd) != 0 && strcmp(passwd, optarg) != 0) {
2511 warnx("-%c password conflicts with existing password from -%c",
2516 /* Callers pass in a buffer which does NOT need to be terminated */
2517 strncpy(passwd, optarg, max);
2524 ATA_HPA_ACTION_PRINT,
2525 ATA_HPA_ACTION_SET_MAX,
2526 ATA_HPA_ACTION_SET_PWD,
2527 ATA_HPA_ACTION_LOCK,
2528 ATA_HPA_ACTION_UNLOCK,
2529 ATA_HPA_ACTION_FREEZE_LOCK
2533 atahpa_set_confirm(struct cam_device *device, struct ata_params* ident_buf,
2534 u_int64_t maxsize, int persist)
2536 printf("\nYou are about to configure HPA to limit the user accessible\n"
2537 "sectors to %ju %s on the device:\n%s%d,%s%d: ", maxsize,
2538 persist ? "persistently" : "temporarily",
2539 device->device_name, device->dev_unit_num,
2540 device->given_dev_name, device->given_unit_number);
2541 ata_print_ident(ident_buf);
2545 printf("\nAre you SURE you want to configure HPA? (yes/no) ");
2547 if (NULL != fgets(str, sizeof(str), stdin)) {
2548 if (0 == strncasecmp(str, "yes", 3)) {
2550 } else if (0 == strncasecmp(str, "no", 2)) {
2553 printf("Please answer \"yes\" or "
2564 atahpa(struct cam_device *device, int retry_count, int timeout,
2565 int argc, char **argv, char *combinedopt)
2568 struct ata_params *ident_buf;
2569 struct ccb_getdev cgd;
2570 struct ata_set_max_pwd pwd;
2571 int error, confirm, quiet, c, action, actions, setpwd, persist;
2572 int security, is48bit, pwdsize;
2573 u_int64_t hpasize, maxsize;
2583 memset(&pwd, 0, sizeof(pwd));
2585 /* default action is to print hpa information */
2586 action = ATA_HPA_ACTION_PRINT;
2587 pwdsize = sizeof(pwd.password);
2589 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2592 action = ATA_HPA_ACTION_SET_MAX;
2593 maxsize = strtoumax(optarg, NULL, 0);
2598 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2600 action = ATA_HPA_ACTION_SET_PWD;
2606 action = ATA_HPA_ACTION_LOCK;
2612 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2614 action = ATA_HPA_ACTION_UNLOCK;
2620 action = ATA_HPA_ACTION_FREEZE_LOCK;
2640 warnx("too many hpa actions specified");
2644 if (get_cgd(device, &cgd) != 0) {
2645 warnx("couldn't get CGD");
2649 ccb = cam_getccb(device);
2651 warnx("couldn't allocate CCB");
2655 error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf);
2662 printf("%s%d: ", device->device_name, device->dev_unit_num);
2663 ata_print_ident(ident_buf);
2664 camxferrate(device);
2667 if (action == ATA_HPA_ACTION_PRINT) {
2668 error = ata_read_native_max(device, retry_count, timeout, ccb,
2669 ident_buf, &hpasize);
2671 atahpa_print(ident_buf, hpasize, 1);
2678 if (!(ident_buf->support.command1 & ATA_SUPPORT_PROTECTED)) {
2679 warnx("HPA is not supported by this device");
2685 if (security && !(ident_buf->support.command1 & ATA_SUPPORT_MAXSECURITY)) {
2686 warnx("HPA Security is not supported by this device");
2692 is48bit = ident_buf->support.command2 & ATA_SUPPORT_ADDRESS48;
2695 * The ATA spec requires:
2696 * 1. Read native max addr is called directly before set max addr
2697 * 2. Read native max addr is NOT called before any other set max call
2700 case ATA_HPA_ACTION_SET_MAX:
2702 atahpa_set_confirm(device, ident_buf, maxsize,
2709 error = ata_read_native_max(device, retry_count, timeout,
2710 ccb, ident_buf, &hpasize);
2712 error = atahpa_set_max(device, retry_count, timeout,
2713 ccb, is48bit, maxsize, persist);
2715 /* redo identify to get new lba values */
2716 error = ata_do_identify(device, retry_count,
2719 atahpa_print(ident_buf, hpasize, 1);
2724 case ATA_HPA_ACTION_SET_PWD:
2725 error = atahpa_password(device, retry_count, timeout,
2726 ccb, is48bit, &pwd);
2728 printf("HPA password has been set\n");
2731 case ATA_HPA_ACTION_LOCK:
2732 error = atahpa_lock(device, retry_count, timeout,
2735 printf("HPA has been locked\n");
2738 case ATA_HPA_ACTION_UNLOCK:
2739 error = atahpa_unlock(device, retry_count, timeout,
2740 ccb, is48bit, &pwd);
2742 printf("HPA has been unlocked\n");
2745 case ATA_HPA_ACTION_FREEZE_LOCK:
2746 error = atahpa_freeze_lock(device, retry_count, timeout,
2749 printf("HPA has been frozen\n");
2753 errx(1, "Option currently not supported");
2763 atasecurity(struct cam_device *device, int retry_count, int timeout,
2764 int argc, char **argv, char *combinedopt)
2767 struct ata_params *ident_buf;
2768 int error, confirm, quiet, c, action, actions, setpwd;
2769 int security_enabled, erase_timeout, pwdsize;
2770 struct ata_security_password pwd;
2778 memset(&pwd, 0, sizeof(pwd));
2780 /* default action is to print security information */
2781 action = ATA_SECURITY_ACTION_PRINT;
2783 /* user is master by default as its safer that way */
2784 pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER;
2785 pwdsize = sizeof(pwd.password);
2787 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2790 action = ATA_SECURITY_ACTION_FREEZE;
2795 if (strcasecmp(optarg, "user") == 0) {
2796 pwd.ctrl |= ATA_SECURITY_PASSWORD_USER;
2797 pwd.ctrl &= ~ATA_SECURITY_PASSWORD_MASTER;
2798 } else if (strcasecmp(optarg, "master") == 0) {
2799 pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER;
2800 pwd.ctrl &= ~ATA_SECURITY_PASSWORD_USER;
2802 warnx("-U argument '%s' is invalid (must be "
2803 "'user' or 'master')", optarg);
2809 if (strcasecmp(optarg, "high") == 0) {
2810 pwd.ctrl |= ATA_SECURITY_LEVEL_HIGH;
2811 pwd.ctrl &= ~ATA_SECURITY_LEVEL_MAXIMUM;
2812 } else if (strcasecmp(optarg, "maximum") == 0) {
2813 pwd.ctrl |= ATA_SECURITY_LEVEL_MAXIMUM;
2814 pwd.ctrl &= ~ATA_SECURITY_LEVEL_HIGH;
2816 warnx("-l argument '%s' is unknown (must be "
2817 "'high' or 'maximum')", optarg);
2823 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2825 action = ATA_SECURITY_ACTION_UNLOCK;
2830 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2832 action = ATA_SECURITY_ACTION_DISABLE;
2837 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2839 action = ATA_SECURITY_ACTION_ERASE;
2844 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2846 pwd.ctrl |= ATA_SECURITY_ERASE_ENHANCED;
2847 action = ATA_SECURITY_ACTION_ERASE_ENHANCED;
2852 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2855 if (action == ATA_SECURITY_ACTION_PRINT)
2856 action = ATA_SECURITY_ACTION_SET_PASSWORD;
2858 * Don't increment action as this can be combined
2859 * with other actions.
2872 erase_timeout = atoi(optarg) * 1000;
2878 warnx("too many security actions specified");
2882 if ((ccb = cam_getccb(device)) == NULL) {
2883 warnx("couldn't allocate CCB");
2887 error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf);
2894 printf("%s%d: ", device->device_name, device->dev_unit_num);
2895 ata_print_ident(ident_buf);
2896 camxferrate(device);
2899 if (action == ATA_SECURITY_ACTION_PRINT) {
2900 atasecurity_print(ident_buf);
2906 if ((ident_buf->support.command1 & ATA_SUPPORT_SECURITY) == 0) {
2907 warnx("Security not supported");
2913 /* default timeout 15 seconds the same as linux hdparm */
2914 timeout = timeout ? timeout : 15 * 1000;
2916 security_enabled = ident_buf->security_status & ATA_SECURITY_ENABLED;
2918 /* first set the password if requested */
2920 /* confirm we can erase before setting the password if erasing */
2922 (action == ATA_SECURITY_ACTION_ERASE_ENHANCED ||
2923 action == ATA_SECURITY_ACTION_ERASE) &&
2924 atasecurity_erase_confirm(device, ident_buf) == 0) {
2930 if (pwd.ctrl & ATA_SECURITY_PASSWORD_MASTER) {
2931 pwd.revision = ident_buf->master_passwd_revision;
2932 if (pwd.revision != 0 && pwd.revision != 0xfff &&
2933 --pwd.revision == 0) {
2934 pwd.revision = 0xfffe;
2937 error = atasecurity_set_password(device, ccb, retry_count,
2938 timeout, &pwd, quiet);
2944 security_enabled = 1;
2948 case ATA_SECURITY_ACTION_FREEZE:
2949 error = atasecurity_freeze(device, ccb, retry_count,
2953 case ATA_SECURITY_ACTION_UNLOCK:
2954 if (security_enabled) {
2955 if (ident_buf->security_status & ATA_SECURITY_LOCKED) {
2956 error = atasecurity_unlock(device, ccb,
2957 retry_count, timeout, &pwd, quiet);
2959 warnx("Can't unlock, drive is not locked");
2963 warnx("Can't unlock, security is disabled");
2968 case ATA_SECURITY_ACTION_DISABLE:
2969 if (security_enabled) {
2970 /* First unlock the drive if its locked */
2971 if (ident_buf->security_status & ATA_SECURITY_LOCKED) {
2972 error = atasecurity_unlock(device, ccb,
2980 error = atasecurity_disable(device,
2988 warnx("Can't disable security (already disabled)");
2993 case ATA_SECURITY_ACTION_ERASE:
2994 if (security_enabled) {
2995 if (erase_timeout == 0) {
2996 erase_timeout = atasecurity_erase_timeout_msecs(
2997 ident_buf->erase_time);
3000 error = atasecurity_erase(device, ccb, retry_count,
3001 timeout, erase_timeout, &pwd,
3004 warnx("Can't secure erase (security is disabled)");
3009 case ATA_SECURITY_ACTION_ERASE_ENHANCED:
3010 if (security_enabled) {
3011 if (ident_buf->security_status & ATA_SECURITY_ENH_SUPP) {
3012 if (erase_timeout == 0) {
3014 atasecurity_erase_timeout_msecs(
3015 ident_buf->enhanced_erase_time);
3018 error = atasecurity_erase(device, ccb,
3019 retry_count, timeout,
3020 erase_timeout, &pwd,
3023 warnx("Enhanced erase is not supported");
3027 warnx("Can't secure erase (enhanced), "
3028 "(security is disabled)");
3039 #endif /* MINIMALISTIC */
3042 * Parse out a bus, or a bus, target and lun in the following
3048 * Returns the number of parsed components, or 0.
3051 parse_btl(char *tstr, path_id_t *bus, target_id_t *target, lun_id_t *lun,
3052 cam_argmask *arglst)
3057 while (isspace(*tstr) && (*tstr != '\0'))
3060 tmpstr = (char *)strtok(tstr, ":");
3061 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3062 *bus = strtol(tmpstr, NULL, 0);
3063 *arglst |= CAM_ARG_BUS;
3065 tmpstr = (char *)strtok(NULL, ":");
3066 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3067 *target = strtol(tmpstr, NULL, 0);
3068 *arglst |= CAM_ARG_TARGET;
3070 tmpstr = (char *)strtok(NULL, ":");
3071 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3072 *lun = strtol(tmpstr, NULL, 0);
3073 *arglst |= CAM_ARG_LUN;
3083 dorescan_or_reset(int argc, char **argv, int rescan)
3085 static const char must[] =
3086 "you must specify \"all\", a bus, or a bus:target:lun to %s";
3088 path_id_t bus = CAM_BUS_WILDCARD;
3089 target_id_t target = CAM_TARGET_WILDCARD;
3090 lun_id_t lun = CAM_LUN_WILDCARD;
3094 warnx(must, rescan? "rescan" : "reset");
3098 tstr = argv[optind];
3099 while (isspace(*tstr) && (*tstr != '\0'))
3101 if (strncasecmp(tstr, "all", strlen("all")) == 0)
3102 arglist |= CAM_ARG_BUS;
3104 rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
3105 if (rv != 1 && rv != 3) {
3106 warnx(must, rescan? "rescan" : "reset");
3111 if ((arglist & CAM_ARG_BUS)
3112 && (arglist & CAM_ARG_TARGET)
3113 && (arglist & CAM_ARG_LUN))
3114 error = scanlun_or_reset_dev(bus, target, lun, rescan);
3116 error = rescan_or_reset_bus(bus, rescan);
3122 rescan_or_reset_bus(path_id_t bus, int rescan)
3124 union ccb ccb, matchccb;
3130 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3131 warnx("error opening transport layer device %s", XPT_DEVICE);
3132 warn("%s", XPT_DEVICE);
3136 if (bus != CAM_BUS_WILDCARD) {
3137 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
3138 ccb.ccb_h.path_id = bus;
3139 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
3140 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
3141 ccb.crcn.flags = CAM_FLAG_NONE;
3143 /* run this at a low priority */
3144 ccb.ccb_h.pinfo.priority = 5;
3146 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
3147 warn("CAMIOCOMMAND ioctl failed");
3152 if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
3153 fprintf(stdout, "%s of bus %d was successful\n",
3154 rescan ? "Re-scan" : "Reset", bus);
3156 fprintf(stdout, "%s of bus %d returned error %#x\n",
3157 rescan ? "Re-scan" : "Reset", bus,
3158 ccb.ccb_h.status & CAM_STATUS_MASK);
3169 * The right way to handle this is to modify the xpt so that it can
3170 * handle a wildcarded bus in a rescan or reset CCB. At the moment
3171 * that isn't implemented, so instead we enumerate the busses and
3172 * send the rescan or reset to those busses in the case where the
3173 * given bus is -1 (wildcard). We don't send a rescan or reset
3174 * to the xpt bus; sending a rescan to the xpt bus is effectively a
3175 * no-op, sending a rescan to the xpt bus would result in a status of
3178 bzero(&(&matchccb.ccb_h)[1],
3179 sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
3180 matchccb.ccb_h.func_code = XPT_DEV_MATCH;
3181 matchccb.ccb_h.path_id = CAM_BUS_WILDCARD;
3182 bufsize = sizeof(struct dev_match_result) * 20;
3183 matchccb.cdm.match_buf_len = bufsize;
3184 matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
3185 if (matchccb.cdm.matches == NULL) {
3186 warnx("can't malloc memory for matches");
3190 matchccb.cdm.num_matches = 0;
3192 matchccb.cdm.num_patterns = 1;
3193 matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
3195 matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
3196 matchccb.cdm.pattern_buf_len);
3197 if (matchccb.cdm.patterns == NULL) {
3198 warnx("can't malloc memory for patterns");
3202 matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
3203 matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
3208 if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
3209 warn("CAMIOCOMMAND ioctl failed");
3214 if ((matchccb.ccb_h.status != CAM_REQ_CMP)
3215 || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
3216 && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
3217 warnx("got CAM error %#x, CDM error %d\n",
3218 matchccb.ccb_h.status, matchccb.cdm.status);
3223 for (i = 0; i < matchccb.cdm.num_matches; i++) {
3224 struct bus_match_result *bus_result;
3226 /* This shouldn't happen. */
3227 if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
3230 bus_result = &matchccb.cdm.matches[i].result.bus_result;
3233 * We don't want to rescan or reset the xpt bus.
3236 if (bus_result->path_id == CAM_XPT_PATH_ID)
3239 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
3241 ccb.ccb_h.path_id = bus_result->path_id;
3242 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
3243 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
3244 ccb.crcn.flags = CAM_FLAG_NONE;
3246 /* run this at a low priority */
3247 ccb.ccb_h.pinfo.priority = 5;
3249 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
3250 warn("CAMIOCOMMAND ioctl failed");
3255 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
3256 fprintf(stdout, "%s of bus %d was successful\n",
3257 rescan? "Re-scan" : "Reset",
3258 bus_result->path_id);
3261 * Don't bail out just yet, maybe the other
3262 * rescan or reset commands will complete
3265 fprintf(stderr, "%s of bus %d returned error "
3266 "%#x\n", rescan? "Re-scan" : "Reset",
3267 bus_result->path_id,
3268 ccb.ccb_h.status & CAM_STATUS_MASK);
3272 } while ((matchccb.ccb_h.status == CAM_REQ_CMP)
3273 && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
3280 if (matchccb.cdm.patterns != NULL)
3281 free(matchccb.cdm.patterns);
3282 if (matchccb.cdm.matches != NULL)
3283 free(matchccb.cdm.matches);
3289 scanlun_or_reset_dev(path_id_t bus, target_id_t target, lun_id_t lun, int scan)
3292 struct cam_device *device;
3297 if (bus == CAM_BUS_WILDCARD) {
3298 warnx("invalid bus number %d", bus);
3302 if (target == CAM_TARGET_WILDCARD) {
3303 warnx("invalid target number %d", target);
3307 if (lun == CAM_LUN_WILDCARD) {
3308 warnx("invalid lun number %jx", (uintmax_t)lun);
3314 bzero(&ccb, sizeof(union ccb));
3317 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3318 warnx("error opening transport layer device %s\n",
3320 warn("%s", XPT_DEVICE);
3324 device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
3325 if (device == NULL) {
3326 warnx("%s", cam_errbuf);
3331 ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
3332 ccb.ccb_h.path_id = bus;
3333 ccb.ccb_h.target_id = target;
3334 ccb.ccb_h.target_lun = lun;
3335 ccb.ccb_h.timeout = 5000;
3336 ccb.crcn.flags = CAM_FLAG_NONE;
3338 /* run this at a low priority */
3339 ccb.ccb_h.pinfo.priority = 5;
3342 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
3343 warn("CAMIOCOMMAND ioctl failed");
3348 if (cam_send_ccb(device, &ccb) < 0) {
3349 warn("error sending XPT_RESET_DEV CCB");
3350 cam_close_device(device);
3358 cam_close_device(device);
3361 * An error code of CAM_BDR_SENT is normal for a BDR request.
3363 if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
3365 && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
3366 fprintf(stdout, "%s of %d:%d:%jx was successful\n",
3367 scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun);
3370 fprintf(stdout, "%s of %d:%d:%jx returned error %#x\n",
3371 scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun,
3372 ccb.ccb_h.status & CAM_STATUS_MASK);
3377 #ifndef MINIMALISTIC
3379 static struct scsi_nv defect_list_type_map[] = {
3380 { "block", SRDD10_BLOCK_FORMAT },
3381 { "extbfi", SRDD10_EXT_BFI_FORMAT },
3382 { "extphys", SRDD10_EXT_PHYS_FORMAT },
3383 { "longblock", SRDD10_LONG_BLOCK_FORMAT },
3384 { "bfi", SRDD10_BYTES_FROM_INDEX_FORMAT },
3385 { "phys", SRDD10_PHYSICAL_SECTOR_FORMAT }
3389 readdefects(struct cam_device *device, int argc, char **argv,
3390 char *combinedopt, int retry_count, int timeout)
3392 union ccb *ccb = NULL;
3393 struct scsi_read_defect_data_hdr_10 *hdr10 = NULL;
3394 struct scsi_read_defect_data_hdr_12 *hdr12 = NULL;
3395 size_t hdr_size = 0, entry_size = 0;
3398 u_int8_t *defect_list = NULL;
3399 u_int8_t list_format = 0;
3400 int list_type_set = 0;
3401 u_int32_t dlist_length = 0;
3402 u_int32_t returned_length = 0, valid_len = 0;
3403 u_int32_t num_returned = 0, num_valid = 0;
3404 u_int32_t max_possible_size = 0, hdr_max = 0;
3405 u_int32_t starting_offset = 0;
3406 u_int8_t returned_format, returned_type;
3408 int summary = 0, quiet = 0;
3410 int lists_specified = 0;
3411 int get_length = 1, first_pass = 1;
3414 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3418 scsi_nv_status status;
3421 status = scsi_get_nv(defect_list_type_map,
3422 sizeof(defect_list_type_map) /
3423 sizeof(defect_list_type_map[0]), optarg,
3424 &entry_num, SCSI_NV_FLAG_IG_CASE);
3426 if (status == SCSI_NV_FOUND) {
3427 list_format = defect_list_type_map[
3431 warnx("%s: %s %s option %s", __func__,
3432 (status == SCSI_NV_AMBIGUOUS) ?
3433 "ambiguous" : "invalid", "defect list type",
3436 goto defect_bailout;
3441 arglist |= CAM_ARG_GLIST;
3444 arglist |= CAM_ARG_PLIST;
3455 starting_offset = strtoul(optarg, &endptr, 0);
3456 if (*endptr != '\0') {
3458 warnx("invalid starting offset %s", optarg);
3459 goto defect_bailout;
3471 if (list_type_set == 0) {
3473 warnx("no defect list format specified");
3474 goto defect_bailout;
3477 if (arglist & CAM_ARG_PLIST) {
3478 list_format |= SRDD10_PLIST;
3482 if (arglist & CAM_ARG_GLIST) {
3483 list_format |= SRDD10_GLIST;
3488 * This implies a summary, and was the previous behavior.
3490 if (lists_specified == 0)
3493 ccb = cam_getccb(device);
3498 * We start off asking for just the header to determine how much
3499 * defect data is available. Some Hitachi drives return an error
3500 * if you ask for more data than the drive has. Once we know the
3501 * length, we retry the command with the returned length.
3503 if (use_12byte == 0)
3504 dlist_length = sizeof(*hdr10);
3506 dlist_length = sizeof(*hdr12);
3509 if (defect_list != NULL) {
3513 defect_list = malloc(dlist_length);
3514 if (defect_list == NULL) {
3515 warnx("can't malloc memory for defect list");
3517 goto defect_bailout;
3521 bzero(defect_list, dlist_length);
3524 * cam_getccb() zeros the CCB header only. So we need to zero the
3525 * payload portion of the ccb.
3527 bzero(&(&ccb->ccb_h)[1],
3528 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3530 scsi_read_defects(&ccb->csio,
3531 /*retries*/ retry_count,
3533 /*tag_action*/ MSG_SIMPLE_Q_TAG,
3534 /*list_format*/ list_format,
3535 /*addr_desc_index*/ starting_offset,
3536 /*data_ptr*/ defect_list,
3537 /*dxfer_len*/ dlist_length,
3538 /*minimum_cmd_size*/ use_12byte ? 12 : 0,
3539 /*sense_len*/ SSD_FULL_SIZE,
3540 /*timeout*/ timeout ? timeout : 5000);
3542 /* Disable freezing the device queue */
3543 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3545 if (cam_send_ccb(device, ccb) < 0) {
3546 perror("error reading defect list");
3548 if (arglist & CAM_ARG_VERBOSE) {
3549 cam_error_print(device, ccb, CAM_ESF_ALL,
3550 CAM_EPF_ALL, stderr);
3554 goto defect_bailout;
3557 valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
3559 if (use_12byte == 0) {
3560 hdr10 = (struct scsi_read_defect_data_hdr_10 *)defect_list;
3561 hdr_size = sizeof(*hdr10);
3562 hdr_max = SRDDH10_MAX_LENGTH;
3564 if (valid_len >= hdr_size) {
3565 returned_length = scsi_2btoul(hdr10->length);
3566 returned_format = hdr10->format;
3568 returned_length = 0;
3569 returned_format = 0;
3572 hdr12 = (struct scsi_read_defect_data_hdr_12 *)defect_list;
3573 hdr_size = sizeof(*hdr12);
3574 hdr_max = SRDDH12_MAX_LENGTH;
3576 if (valid_len >= hdr_size) {
3577 returned_length = scsi_4btoul(hdr12->length);
3578 returned_format = hdr12->format;
3580 returned_length = 0;
3581 returned_format = 0;
3585 returned_type = returned_format & SRDDH10_DLIST_FORMAT_MASK;
3586 switch (returned_type) {
3587 case SRDD10_BLOCK_FORMAT:
3588 entry_size = sizeof(struct scsi_defect_desc_block);
3590 case SRDD10_LONG_BLOCK_FORMAT:
3591 entry_size = sizeof(struct scsi_defect_desc_long_block);
3593 case SRDD10_EXT_PHYS_FORMAT:
3594 case SRDD10_PHYSICAL_SECTOR_FORMAT:
3595 entry_size = sizeof(struct scsi_defect_desc_phys_sector);
3597 case SRDD10_EXT_BFI_FORMAT:
3598 case SRDD10_BYTES_FROM_INDEX_FORMAT:
3599 entry_size = sizeof(struct scsi_defect_desc_bytes_from_index);
3602 warnx("Unknown defect format 0x%x\n", returned_type);
3604 goto defect_bailout;
3608 max_possible_size = (hdr_max / entry_size) * entry_size;
3609 num_returned = returned_length / entry_size;
3610 num_valid = min(returned_length, valid_len - hdr_size);
3611 num_valid /= entry_size;
3613 if (get_length != 0) {
3616 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
3617 CAM_SCSI_STATUS_ERROR) {
3618 struct scsi_sense_data *sense;
3619 int error_code, sense_key, asc, ascq;
3621 sense = &ccb->csio.sense_data;
3622 scsi_extract_sense_len(sense, ccb->csio.sense_len -
3623 ccb->csio.sense_resid, &error_code, &sense_key,
3624 &asc, &ascq, /*show_errors*/ 1);
3627 * If the drive is reporting that it just doesn't
3628 * support the defect list format, go ahead and use
3629 * the length it reported. Otherwise, the length
3630 * may not be valid, so use the maximum.
3632 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3633 && (asc == 0x1c) && (ascq == 0x00)
3634 && (returned_length > 0)) {
3635 if ((use_12byte == 0)
3636 && (returned_length >= max_possible_size)) {
3641 dlist_length = returned_length + hdr_size;
3642 } else if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3643 && (asc == 0x1f) && (ascq == 0x00)
3644 && (returned_length > 0)) {
3645 /* Partial defect list transfer */
3647 * Hitachi drives return this error
3648 * along with a partial defect list if they
3649 * have more defects than the 10 byte
3650 * command can support. Retry with the 12
3653 if (use_12byte == 0) {
3658 dlist_length = returned_length + hdr_size;
3659 } else if ((sense_key == SSD_KEY_ILLEGAL_REQUEST)
3660 && (asc == 0x24) && (ascq == 0x00)) {
3661 /* Invalid field in CDB */
3663 * SBC-3 says that if the drive has more
3664 * defects than can be reported with the
3665 * 10 byte command, it should return this
3666 * error and no data. Retry with the 12
3669 if (use_12byte == 0) {
3674 dlist_length = returned_length + hdr_size;
3677 * If we got a SCSI error and no valid length,
3678 * just use the 10 byte maximum. The 12
3679 * byte maximum is too large.
3681 if (returned_length == 0)
3682 dlist_length = SRDD10_MAX_LENGTH;
3684 if ((use_12byte == 0)
3685 && (returned_length >=
3686 max_possible_size)) {
3691 dlist_length = returned_length +
3695 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
3698 warnx("Error reading defect header");
3699 if (arglist & CAM_ARG_VERBOSE)
3700 cam_error_print(device, ccb, CAM_ESF_ALL,
3701 CAM_EPF_ALL, stderr);
3702 goto defect_bailout;
3704 if ((use_12byte == 0)
3705 && (returned_length >= max_possible_size)) {
3710 dlist_length = returned_length + hdr_size;
3713 fprintf(stdout, "%u", num_returned);
3715 fprintf(stdout, " defect%s",
3716 (num_returned != 1) ? "s" : "");
3718 fprintf(stdout, "\n");
3720 goto defect_bailout;
3724 * We always limit the list length to the 10-byte maximum
3725 * length (0xffff). The reason is that some controllers
3726 * can't handle larger I/Os, and we can transfer the entire
3727 * 10 byte list in one shot. For drives that support the 12
3728 * byte read defects command, we'll step through the list
3729 * by specifying a starting offset. For drives that don't
3730 * support the 12 byte command's starting offset, we'll
3731 * just display the first 64K.
3733 dlist_length = min(dlist_length, SRDD10_MAX_LENGTH);
3739 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
3740 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
3741 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3742 struct scsi_sense_data *sense;
3743 int error_code, sense_key, asc, ascq;
3745 sense = &ccb->csio.sense_data;
3746 scsi_extract_sense_len(sense, ccb->csio.sense_len -
3747 ccb->csio.sense_resid, &error_code, &sense_key, &asc,
3748 &ascq, /*show_errors*/ 1);
3751 * According to the SCSI spec, if the disk doesn't support
3752 * the requested format, it will generally return a sense
3753 * key of RECOVERED ERROR, and an additional sense code
3754 * of "DEFECT LIST NOT FOUND". HGST drives also return
3755 * Primary/Grown defect list not found errors. So just
3756 * check for an ASC of 0x1c.
3758 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3760 const char *format_str;
3762 format_str = scsi_nv_to_str(defect_list_type_map,
3763 sizeof(defect_list_type_map) /
3764 sizeof(defect_list_type_map[0]),
3765 list_format & SRDD10_DLIST_FORMAT_MASK);
3766 warnx("requested defect format %s not available",
3767 format_str ? format_str : "unknown");
3769 format_str = scsi_nv_to_str(defect_list_type_map,
3770 sizeof(defect_list_type_map) /
3771 sizeof(defect_list_type_map[0]), returned_type);
3772 if (format_str != NULL) {
3773 warnx("Device returned %s format",
3777 warnx("Device returned unknown defect"
3778 " data format %#x", returned_type);
3779 goto defect_bailout;
3783 warnx("Error returned from read defect data command");
3784 if (arglist & CAM_ARG_VERBOSE)
3785 cam_error_print(device, ccb, CAM_ESF_ALL,
3786 CAM_EPF_ALL, stderr);
3787 goto defect_bailout;
3789 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
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;
3798 if (first_pass != 0) {
3799 fprintf(stderr, "Got %d defect", num_returned);
3801 if ((lists_specified == 0) || (num_returned == 0)) {
3802 fprintf(stderr, "s.\n");
3803 goto defect_bailout;
3804 } else if (num_returned == 1)
3805 fprintf(stderr, ":\n");
3807 fprintf(stderr, "s:\n");
3813 * XXX KDM I should probably clean up the printout format for the
3816 switch (returned_type) {
3817 case SRDD10_PHYSICAL_SECTOR_FORMAT:
3818 case SRDD10_EXT_PHYS_FORMAT:
3820 struct scsi_defect_desc_phys_sector *dlist;
3822 dlist = (struct scsi_defect_desc_phys_sector *)
3823 (defect_list + hdr_size);
3825 for (i = 0; i < num_valid; i++) {
3828 sector = scsi_4btoul(dlist[i].sector);
3829 if (returned_type == SRDD10_EXT_PHYS_FORMAT) {
3830 mads = (sector & SDD_EXT_PHYS_MADS) ?
3832 sector &= ~SDD_EXT_PHYS_FLAG_MASK;
3834 if (hex_format == 0)
3835 fprintf(stdout, "%d:%d:%d%s",
3836 scsi_3btoul(dlist[i].cylinder),
3838 scsi_4btoul(dlist[i].sector),
3839 mads ? " - " : "\n");
3841 fprintf(stdout, "0x%x:0x%x:0x%x%s",
3842 scsi_3btoul(dlist[i].cylinder),
3844 scsi_4btoul(dlist[i].sector),
3845 mads ? " - " : "\n");
3848 if (num_valid < num_returned) {
3849 starting_offset += num_valid;
3854 case SRDD10_BYTES_FROM_INDEX_FORMAT:
3855 case SRDD10_EXT_BFI_FORMAT:
3857 struct scsi_defect_desc_bytes_from_index *dlist;
3859 dlist = (struct scsi_defect_desc_bytes_from_index *)
3860 (defect_list + hdr_size);
3862 for (i = 0; i < num_valid; i++) {
3865 bfi = scsi_4btoul(dlist[i].bytes_from_index);
3866 if (returned_type == SRDD10_EXT_BFI_FORMAT) {
3867 mads = (bfi & SDD_EXT_BFI_MADS) ? 1 : 0;
3868 bfi &= ~SDD_EXT_BFI_FLAG_MASK;
3870 if (hex_format == 0)
3871 fprintf(stdout, "%d:%d:%d%s",
3872 scsi_3btoul(dlist[i].cylinder),
3874 scsi_4btoul(dlist[i].bytes_from_index),
3875 mads ? " - " : "\n");
3877 fprintf(stdout, "0x%x:0x%x:0x%x%s",
3878 scsi_3btoul(dlist[i].cylinder),
3880 scsi_4btoul(dlist[i].bytes_from_index),
3881 mads ? " - " : "\n");
3885 if (num_valid < num_returned) {
3886 starting_offset += num_valid;
3891 case SRDDH10_BLOCK_FORMAT:
3893 struct scsi_defect_desc_block *dlist;
3895 dlist = (struct scsi_defect_desc_block *)
3896 (defect_list + hdr_size);
3898 for (i = 0; i < num_valid; i++) {
3899 if (hex_format == 0)
3900 fprintf(stdout, "%u\n",
3901 scsi_4btoul(dlist[i].address));
3903 fprintf(stdout, "0x%x\n",
3904 scsi_4btoul(dlist[i].address));
3907 if (num_valid < num_returned) {
3908 starting_offset += num_valid;
3914 case SRDD10_LONG_BLOCK_FORMAT:
3916 struct scsi_defect_desc_long_block *dlist;
3918 dlist = (struct scsi_defect_desc_long_block *)
3919 (defect_list + hdr_size);
3921 for (i = 0; i < num_valid; i++) {
3922 if (hex_format == 0)
3923 fprintf(stdout, "%ju\n",
3924 (uintmax_t)scsi_8btou64(
3927 fprintf(stdout, "0x%jx\n",
3928 (uintmax_t)scsi_8btou64(
3932 if (num_valid < num_returned) {
3933 starting_offset += num_valid;
3939 fprintf(stderr, "Unknown defect format 0x%x\n",
3946 if (defect_list != NULL)
3954 #endif /* MINIMALISTIC */
3958 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
3962 ccb = cam_getccb(device);
3968 #ifndef MINIMALISTIC
3970 mode_sense(struct cam_device *device, int mode_page, int page_control,
3971 int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
3976 ccb = cam_getccb(device);
3979 errx(1, "mode_sense: couldn't allocate CCB");
3981 bzero(&(&ccb->ccb_h)[1],
3982 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3984 scsi_mode_sense(&ccb->csio,
3985 /* retries */ retry_count,
3987 /* tag_action */ MSG_SIMPLE_Q_TAG,
3989 /* page_code */ page_control << 6,
3990 /* page */ mode_page,
3991 /* param_buf */ data,
3992 /* param_len */ datalen,
3993 /* sense_len */ SSD_FULL_SIZE,
3994 /* timeout */ timeout ? timeout : 5000);
3996 if (arglist & CAM_ARG_ERR_RECOVER)
3997 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3999 /* Disable freezing the device queue */
4000 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4002 if (((retval = cam_send_ccb(device, ccb)) < 0)
4003 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4004 if (arglist & CAM_ARG_VERBOSE) {
4005 cam_error_print(device, ccb, CAM_ESF_ALL,
4006 CAM_EPF_ALL, stderr);
4009 cam_close_device(device);
4011 err(1, "error sending mode sense command");
4013 errx(1, "error sending mode sense command");
4020 mode_select(struct cam_device *device, int save_pages, int retry_count,
4021 int timeout, u_int8_t *data, int datalen)
4026 ccb = cam_getccb(device);
4029 errx(1, "mode_select: couldn't allocate CCB");
4031 bzero(&(&ccb->ccb_h)[1],
4032 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4034 scsi_mode_select(&ccb->csio,
4035 /* retries */ retry_count,
4037 /* tag_action */ MSG_SIMPLE_Q_TAG,
4038 /* scsi_page_fmt */ 1,
4039 /* save_pages */ save_pages,
4040 /* param_buf */ data,
4041 /* param_len */ datalen,
4042 /* sense_len */ SSD_FULL_SIZE,
4043 /* timeout */ timeout ? timeout : 5000);
4045 if (arglist & CAM_ARG_ERR_RECOVER)
4046 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4048 /* Disable freezing the device queue */
4049 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4051 if (((retval = cam_send_ccb(device, ccb)) < 0)
4052 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4053 if (arglist & CAM_ARG_VERBOSE) {
4054 cam_error_print(device, ccb, CAM_ESF_ALL,
4055 CAM_EPF_ALL, stderr);
4058 cam_close_device(device);
4061 err(1, "error sending mode select command");
4063 errx(1, "error sending mode select command");
4071 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
4072 int retry_count, int timeout)
4074 int c, mode_page = -1, page_control = 0;
4075 int binary = 0, list = 0;
4077 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4083 arglist |= CAM_ARG_DBD;
4086 arglist |= CAM_ARG_MODE_EDIT;
4092 mode_page = strtol(optarg, NULL, 0);
4094 errx(1, "invalid mode page %d", mode_page);
4097 page_control = strtol(optarg, NULL, 0);
4098 if ((page_control < 0) || (page_control > 3))
4099 errx(1, "invalid page control field %d",
4101 arglist |= CAM_ARG_PAGE_CNTL;
4108 if (mode_page == -1 && list == 0)
4109 errx(1, "you must specify a mode page!");
4112 mode_list(device, page_control, arglist & CAM_ARG_DBD,
4113 retry_count, timeout);
4115 mode_edit(device, mode_page, page_control,
4116 arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
4117 retry_count, timeout);
4122 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
4123 int retry_count, int timeout)
4126 u_int32_t flags = CAM_DIR_NONE;
4127 u_int8_t *data_ptr = NULL;
4129 u_int8_t atacmd[12];
4130 struct get_hook hook;
4131 int c, data_bytes = 0;
4137 char *datastr = NULL, *tstr, *resstr = NULL;
4139 int fd_data = 0, fd_res = 0;
4142 ccb = cam_getccb(device);
4145 warnx("scsicmd: error allocating ccb");
4149 bzero(&(&ccb->ccb_h)[1],
4150 sizeof(union ccb) - sizeof(struct ccb_hdr));
4152 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4156 while (isspace(*tstr) && (*tstr != '\0'))
4158 hook.argc = argc - optind;
4159 hook.argv = argv + optind;
4161 atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
4164 * Increment optind by the number of arguments the
4165 * encoding routine processed. After each call to
4166 * getopt(3), optind points to the argument that
4167 * getopt should process _next_. In this case,
4168 * that means it points to the first command string
4169 * argument, if there is one. Once we increment
4170 * this, it should point to either the next command
4171 * line argument, or it should be past the end of
4178 while (isspace(*tstr) && (*tstr != '\0'))
4180 hook.argc = argc - optind;
4181 hook.argv = argv + optind;
4183 cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
4186 * Increment optind by the number of arguments the
4187 * encoding routine processed. After each call to
4188 * getopt(3), optind points to the argument that
4189 * getopt should process _next_. In this case,
4190 * that means it points to the first command string
4191 * argument, if there is one. Once we increment
4192 * this, it should point to either the next command
4193 * line argument, or it should be past the end of
4205 if (arglist & CAM_ARG_CMD_OUT) {
4206 warnx("command must either be "
4207 "read or write, not both");
4209 goto scsicmd_bailout;
4211 arglist |= CAM_ARG_CMD_IN;
4213 data_bytes = strtol(optarg, NULL, 0);
4214 if (data_bytes <= 0) {
4215 warnx("invalid number of input bytes %d",
4218 goto scsicmd_bailout;
4220 hook.argc = argc - optind;
4221 hook.argv = argv + optind;
4224 datastr = cget(&hook, NULL);
4226 * If the user supplied "-" instead of a format, he
4227 * wants the data to be written to stdout.
4229 if ((datastr != NULL)
4230 && (datastr[0] == '-'))
4233 data_ptr = (u_int8_t *)malloc(data_bytes);
4234 if (data_ptr == NULL) {
4235 warnx("can't malloc memory for data_ptr");
4237 goto scsicmd_bailout;
4241 if (arglist & CAM_ARG_CMD_IN) {
4242 warnx("command must either be "
4243 "read or write, not both");
4245 goto scsicmd_bailout;
4247 arglist |= CAM_ARG_CMD_OUT;
4248 flags = CAM_DIR_OUT;
4249 data_bytes = strtol(optarg, NULL, 0);
4250 if (data_bytes <= 0) {
4251 warnx("invalid number of output bytes %d",
4254 goto scsicmd_bailout;
4256 hook.argc = argc - optind;
4257 hook.argv = argv + optind;
4259 datastr = cget(&hook, NULL);
4260 data_ptr = (u_int8_t *)malloc(data_bytes);
4261 if (data_ptr == NULL) {
4262 warnx("can't malloc memory for data_ptr");
4264 goto scsicmd_bailout;
4266 bzero(data_ptr, data_bytes);
4268 * If the user supplied "-" instead of a format, he
4269 * wants the data to be read from stdin.
4271 if ((datastr != NULL)
4272 && (datastr[0] == '-'))
4275 buff_encode_visit(data_ptr, data_bytes, datastr,
4281 hook.argc = argc - optind;
4282 hook.argv = argv + optind;
4284 resstr = cget(&hook, NULL);
4285 if ((resstr != NULL) && (resstr[0] == '-'))
4295 * If fd_data is set, and we're writing to the device, we need to
4296 * read the data the user wants written from stdin.
4298 if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4300 int amt_to_read = data_bytes;
4301 u_int8_t *buf_ptr = data_ptr;
4303 for (amt_read = 0; amt_to_read > 0;
4304 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4305 if (amt_read == -1) {
4306 warn("error reading data from stdin");
4308 goto scsicmd_bailout;
4310 amt_to_read -= amt_read;
4311 buf_ptr += amt_read;
4315 if (arglist & CAM_ARG_ERR_RECOVER)
4316 flags |= CAM_PASS_ERR_RECOVER;
4318 /* Disable freezing the device queue */
4319 flags |= CAM_DEV_QFRZDIS;
4323 * This is taken from the SCSI-3 draft spec.
4324 * (T10/1157D revision 0.3)
4325 * The top 3 bits of an opcode are the group code.
4326 * The next 5 bits are the command code.
4327 * Group 0: six byte commands
4328 * Group 1: ten byte commands
4329 * Group 2: ten byte commands
4331 * Group 4: sixteen byte commands
4332 * Group 5: twelve byte commands
4333 * Group 6: vendor specific
4334 * Group 7: vendor specific
4336 switch((cdb[0] >> 5) & 0x7) {
4347 /* computed by buff_encode_visit */
4358 * We should probably use csio_build_visit or something like that
4359 * here, but it's easier to encode arguments as you go. The
4360 * alternative would be skipping the CDB argument and then encoding
4361 * it here, since we've got the data buffer argument by now.
4363 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
4365 cam_fill_csio(&ccb->csio,
4366 /*retries*/ retry_count,
4369 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4370 /*data_ptr*/ data_ptr,
4371 /*dxfer_len*/ data_bytes,
4372 /*sense_len*/ SSD_FULL_SIZE,
4373 /*cdb_len*/ cdb_len,
4374 /*timeout*/ timeout ? timeout : 5000);
4377 bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
4379 ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
4381 ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
4383 ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
4385 cam_fill_ataio(&ccb->ataio,
4386 /*retries*/ retry_count,
4390 /*data_ptr*/ data_ptr,
4391 /*dxfer_len*/ data_bytes,
4392 /*timeout*/ timeout ? timeout : 5000);
4395 if (((retval = cam_send_ccb(device, ccb)) < 0)
4396 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4397 const char warnstr[] = "error sending command";
4404 if (arglist & CAM_ARG_VERBOSE) {
4405 cam_error_print(device, ccb, CAM_ESF_ALL,
4406 CAM_EPF_ALL, stderr);
4410 goto scsicmd_bailout;
4413 if (atacmd_len && need_res) {
4415 buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
4417 fprintf(stdout, "\n");
4420 "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
4421 ccb->ataio.res.status,
4422 ccb->ataio.res.error,
4423 ccb->ataio.res.lba_low,
4424 ccb->ataio.res.lba_mid,
4425 ccb->ataio.res.lba_high,
4426 ccb->ataio.res.device,
4427 ccb->ataio.res.lba_low_exp,
4428 ccb->ataio.res.lba_mid_exp,
4429 ccb->ataio.res.lba_high_exp,
4430 ccb->ataio.res.sector_count,
4431 ccb->ataio.res.sector_count_exp);
4436 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4437 && (arglist & CAM_ARG_CMD_IN)
4438 && (data_bytes > 0)) {
4440 buff_decode_visit(data_ptr, data_bytes, datastr,
4442 fprintf(stdout, "\n");
4444 ssize_t amt_written;
4445 int amt_to_write = data_bytes;
4446 u_int8_t *buf_ptr = data_ptr;
4448 for (amt_written = 0; (amt_to_write > 0) &&
4449 (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
4450 amt_to_write -= amt_written;
4451 buf_ptr += amt_written;
4453 if (amt_written == -1) {
4454 warn("error writing data to stdout");
4456 goto scsicmd_bailout;
4457 } else if ((amt_written == 0)
4458 && (amt_to_write > 0)) {
4459 warnx("only wrote %u bytes out of %u",
4460 data_bytes - amt_to_write, data_bytes);
4467 if ((data_bytes > 0) && (data_ptr != NULL))
4476 camdebug(int argc, char **argv, char *combinedopt)
4479 path_id_t bus = CAM_BUS_WILDCARD;
4480 target_id_t target = CAM_TARGET_WILDCARD;
4481 lun_id_t lun = CAM_LUN_WILDCARD;
4482 char *tstr, *tmpstr = NULL;
4486 bzero(&ccb, sizeof(union ccb));
4488 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4491 arglist |= CAM_ARG_DEBUG_INFO;
4492 ccb.cdbg.flags |= CAM_DEBUG_INFO;
4495 arglist |= CAM_ARG_DEBUG_PERIPH;
4496 ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
4499 arglist |= CAM_ARG_DEBUG_SUBTRACE;
4500 ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
4503 arglist |= CAM_ARG_DEBUG_TRACE;
4504 ccb.cdbg.flags |= CAM_DEBUG_TRACE;
4507 arglist |= CAM_ARG_DEBUG_XPT;
4508 ccb.cdbg.flags |= CAM_DEBUG_XPT;
4511 arglist |= CAM_ARG_DEBUG_CDB;
4512 ccb.cdbg.flags |= CAM_DEBUG_CDB;
4515 arglist |= CAM_ARG_DEBUG_PROBE;
4516 ccb.cdbg.flags |= CAM_DEBUG_PROBE;
4523 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
4524 warnx("error opening transport layer device %s", XPT_DEVICE);
4525 warn("%s", XPT_DEVICE);
4532 warnx("you must specify \"off\", \"all\" or a bus,");
4533 warnx("bus:target, or bus:target:lun");
4540 while (isspace(*tstr) && (*tstr != '\0'))
4543 if (strncmp(tstr, "off", 3) == 0) {
4544 ccb.cdbg.flags = CAM_DEBUG_NONE;
4545 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
4546 CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
4547 CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE);
4548 } else if (strncmp(tstr, "all", 3) != 0) {
4549 tmpstr = (char *)strtok(tstr, ":");
4550 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4551 bus = strtol(tmpstr, NULL, 0);
4552 arglist |= CAM_ARG_BUS;
4553 tmpstr = (char *)strtok(NULL, ":");
4554 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4555 target = strtol(tmpstr, NULL, 0);
4556 arglist |= CAM_ARG_TARGET;
4557 tmpstr = (char *)strtok(NULL, ":");
4558 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4559 lun = strtol(tmpstr, NULL, 0);
4560 arglist |= CAM_ARG_LUN;
4565 warnx("you must specify \"all\", \"off\", or a bus,");
4566 warnx("bus:target, or bus:target:lun to debug");
4572 ccb.ccb_h.func_code = XPT_DEBUG;
4573 ccb.ccb_h.path_id = bus;
4574 ccb.ccb_h.target_id = target;
4575 ccb.ccb_h.target_lun = lun;
4577 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
4578 warn("CAMIOCOMMAND ioctl failed");
4583 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
4584 CAM_FUNC_NOTAVAIL) {
4585 warnx("CAM debugging not available");
4586 warnx("you need to put options CAMDEBUG in"
4587 " your kernel config file!");
4589 } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
4591 warnx("XPT_DEBUG CCB failed with status %#x",
4595 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
4597 "Debugging turned off\n");
4600 "Debugging enabled for "
4602 bus, target, (uintmax_t)lun);
4613 tagcontrol(struct cam_device *device, int argc, char **argv,
4623 ccb = cam_getccb(device);
4626 warnx("tagcontrol: error allocating ccb");
4630 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4633 numtags = strtol(optarg, NULL, 0);
4635 warnx("tag count %d is < 0", numtags);
4637 goto tagcontrol_bailout;
4648 cam_path_string(device, pathstr, sizeof(pathstr));
4651 bzero(&(&ccb->ccb_h)[1],
4652 sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
4653 ccb->ccb_h.func_code = XPT_REL_SIMQ;
4654 ccb->ccb_h.flags = CAM_DEV_QFREEZE;
4655 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
4656 ccb->crs.openings = numtags;
4659 if (cam_send_ccb(device, ccb) < 0) {
4660 perror("error sending XPT_REL_SIMQ CCB");
4662 goto tagcontrol_bailout;
4665 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4666 warnx("XPT_REL_SIMQ CCB failed");
4667 cam_error_print(device, ccb, CAM_ESF_ALL,
4668 CAM_EPF_ALL, stderr);
4670 goto tagcontrol_bailout;
4675 fprintf(stdout, "%stagged openings now %d\n",
4676 pathstr, ccb->crs.openings);
4679 bzero(&(&ccb->ccb_h)[1],
4680 sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
4682 ccb->ccb_h.func_code = XPT_GDEV_STATS;
4684 if (cam_send_ccb(device, ccb) < 0) {
4685 perror("error sending XPT_GDEV_STATS CCB");
4687 goto tagcontrol_bailout;
4690 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4691 warnx("XPT_GDEV_STATS CCB failed");
4692 cam_error_print(device, ccb, CAM_ESF_ALL,
4693 CAM_EPF_ALL, stderr);
4695 goto tagcontrol_bailout;
4698 if (arglist & CAM_ARG_VERBOSE) {
4699 fprintf(stdout, "%s", pathstr);
4700 fprintf(stdout, "dev_openings %d\n", ccb->cgds.dev_openings);
4701 fprintf(stdout, "%s", pathstr);
4702 fprintf(stdout, "dev_active %d\n", ccb->cgds.dev_active);
4703 fprintf(stdout, "%s", pathstr);
4704 fprintf(stdout, "allocated %d\n", ccb->cgds.allocated);
4705 fprintf(stdout, "%s", pathstr);
4706 fprintf(stdout, "queued %d\n", ccb->cgds.queued);
4707 fprintf(stdout, "%s", pathstr);
4708 fprintf(stdout, "held %d\n", ccb->cgds.held);
4709 fprintf(stdout, "%s", pathstr);
4710 fprintf(stdout, "mintags %d\n", ccb->cgds.mintags);
4711 fprintf(stdout, "%s", pathstr);
4712 fprintf(stdout, "maxtags %d\n", ccb->cgds.maxtags);
4715 fprintf(stdout, "%s", pathstr);
4716 fprintf(stdout, "device openings: ");
4718 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
4719 ccb->cgds.dev_active);
4729 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
4733 cam_path_string(device, pathstr, sizeof(pathstr));
4735 if (cts->transport == XPORT_SPI) {
4736 struct ccb_trans_settings_spi *spi =
4737 &cts->xport_specific.spi;
4739 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
4741 fprintf(stdout, "%ssync parameter: %d\n", pathstr,
4744 if (spi->sync_offset != 0) {
4747 freq = scsi_calc_syncsrate(spi->sync_period);
4748 fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
4749 pathstr, freq / 1000, freq % 1000);
4753 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
4754 fprintf(stdout, "%soffset: %d\n", pathstr,
4758 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
4759 fprintf(stdout, "%sbus width: %d bits\n", pathstr,
4760 (0x01 << spi->bus_width) * 8);
4763 if (spi->valid & CTS_SPI_VALID_DISC) {
4764 fprintf(stdout, "%sdisconnection is %s\n", pathstr,
4765 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
4766 "enabled" : "disabled");
4769 if (cts->transport == XPORT_FC) {
4770 struct ccb_trans_settings_fc *fc =
4771 &cts->xport_specific.fc;
4773 if (fc->valid & CTS_FC_VALID_WWNN)
4774 fprintf(stdout, "%sWWNN: 0x%llx\n", pathstr,
4775 (long long) fc->wwnn);
4776 if (fc->valid & CTS_FC_VALID_WWPN)
4777 fprintf(stdout, "%sWWPN: 0x%llx\n", pathstr,
4778 (long long) fc->wwpn);
4779 if (fc->valid & CTS_FC_VALID_PORT)
4780 fprintf(stdout, "%sPortID: 0x%x\n", pathstr, fc->port);
4781 if (fc->valid & CTS_FC_VALID_SPEED)
4782 fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4783 pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
4785 if (cts->transport == XPORT_SAS) {
4786 struct ccb_trans_settings_sas *sas =
4787 &cts->xport_specific.sas;
4789 if (sas->valid & CTS_SAS_VALID_SPEED)
4790 fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4791 pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
4793 if (cts->transport == XPORT_ATA) {
4794 struct ccb_trans_settings_pata *pata =
4795 &cts->xport_specific.ata;
4797 if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
4798 fprintf(stdout, "%sATA mode: %s\n", pathstr,
4799 ata_mode2string(pata->mode));
4801 if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
4802 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4805 if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
4806 fprintf(stdout, "%sPIO transaction length: %d\n",
4807 pathstr, pata->bytecount);
4810 if (cts->transport == XPORT_SATA) {
4811 struct ccb_trans_settings_sata *sata =
4812 &cts->xport_specific.sata;
4814 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
4815 fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
4818 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
4819 fprintf(stdout, "%sATA mode: %s\n", pathstr,
4820 ata_mode2string(sata->mode));
4822 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
4823 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4826 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
4827 fprintf(stdout, "%sPIO transaction length: %d\n",
4828 pathstr, sata->bytecount);
4830 if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
4831 fprintf(stdout, "%sPMP presence: %d\n", pathstr,
4834 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
4835 fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
4838 if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
4839 fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
4843 if (cts->protocol == PROTO_ATA) {
4844 struct ccb_trans_settings_ata *ata=
4845 &cts->proto_specific.ata;
4847 if (ata->valid & CTS_ATA_VALID_TQ) {
4848 fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4849 (ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
4850 "enabled" : "disabled");
4853 if (cts->protocol == PROTO_SCSI) {
4854 struct ccb_trans_settings_scsi *scsi=
4855 &cts->proto_specific.scsi;
4857 if (scsi->valid & CTS_SCSI_VALID_TQ) {
4858 fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4859 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
4860 "enabled" : "disabled");
4867 * Get a path inquiry CCB for the specified device.
4870 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
4875 ccb = cam_getccb(device);
4877 warnx("get_cpi: couldn't allocate CCB");
4880 bzero(&(&ccb->ccb_h)[1],
4881 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4882 ccb->ccb_h.func_code = XPT_PATH_INQ;
4883 if (cam_send_ccb(device, ccb) < 0) {
4884 warn("get_cpi: error sending Path Inquiry CCB");
4885 if (arglist & CAM_ARG_VERBOSE)
4886 cam_error_print(device, ccb, CAM_ESF_ALL,
4887 CAM_EPF_ALL, stderr);
4889 goto get_cpi_bailout;
4891 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4892 if (arglist & CAM_ARG_VERBOSE)
4893 cam_error_print(device, ccb, CAM_ESF_ALL,
4894 CAM_EPF_ALL, stderr);
4896 goto get_cpi_bailout;
4898 bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
4906 * Get a get device CCB for the specified device.
4909 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
4914 ccb = cam_getccb(device);
4916 warnx("get_cgd: couldn't allocate CCB");
4919 bzero(&(&ccb->ccb_h)[1],
4920 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4921 ccb->ccb_h.func_code = XPT_GDEV_TYPE;
4922 if (cam_send_ccb(device, ccb) < 0) {
4923 warn("get_cgd: error sending Path Inquiry CCB");
4924 if (arglist & CAM_ARG_VERBOSE)
4925 cam_error_print(device, ccb, CAM_ESF_ALL,
4926 CAM_EPF_ALL, stderr);
4928 goto get_cgd_bailout;
4930 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4931 if (arglist & CAM_ARG_VERBOSE)
4932 cam_error_print(device, ccb, CAM_ESF_ALL,
4933 CAM_EPF_ALL, stderr);
4935 goto get_cgd_bailout;
4937 bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
4944 /* return the type of disk (really the command type) */
4946 get_disk_type(struct cam_device *device)
4948 struct ccb_getdev cgd;
4950 (void) memset(&cgd, 0x0, sizeof(cgd));
4951 get_cgd(device, &cgd);
4952 switch(cgd.protocol) {
4965 cpi_print(struct ccb_pathinq *cpi)
4967 char adapter_str[1024];
4970 snprintf(adapter_str, sizeof(adapter_str),
4971 "%s%d:", cpi->dev_name, cpi->unit_number);
4973 fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
4976 for (i = 1; i < 0xff; i = i << 1) {
4979 if ((i & cpi->hba_inquiry) == 0)
4982 fprintf(stdout, "%s supports ", adapter_str);
4986 str = "MDP message";
4989 str = "32 bit wide SCSI";
4992 str = "16 bit wide SCSI";
4995 str = "SDTR message";
4998 str = "linked CDBs";
5001 str = "tag queue messages";
5004 str = "soft reset alternative";
5007 str = "SATA Port Multiplier";
5010 str = "unknown PI bit set";
5013 fprintf(stdout, "%s\n", str);
5016 for (i = 1; i < 0xff; i = i << 1) {
5019 if ((i & cpi->hba_misc) == 0)
5022 fprintf(stdout, "%s ", adapter_str);
5026 str = "bus scans from high ID to low ID";
5029 str = "removable devices not included in scan";
5031 case PIM_NOINITIATOR:
5032 str = "initiator role not supported";
5034 case PIM_NOBUSRESET:
5035 str = "user has disabled initial BUS RESET or"
5036 " controller is in target/mixed mode";
5039 str = "do not send 6-byte commands";
5042 str = "scan bus sequentially";
5045 str = "unknown PIM bit set";
5048 fprintf(stdout, "%s\n", str);
5051 for (i = 1; i < 0xff; i = i << 1) {
5054 if ((i & cpi->target_sprt) == 0)
5057 fprintf(stdout, "%s supports ", adapter_str);
5060 str = "target mode processor mode";
5063 str = "target mode phase cog. mode";
5065 case PIT_DISCONNECT:
5066 str = "disconnects in target mode";
5069 str = "terminate I/O message in target mode";
5072 str = "group 6 commands in target mode";
5075 str = "group 7 commands in target mode";
5078 str = "unknown PIT bit set";
5082 fprintf(stdout, "%s\n", str);
5084 fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
5086 fprintf(stdout, "%s maximum target: %d\n", adapter_str,
5088 fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
5090 fprintf(stdout, "%s highest path ID in subsystem: %d\n",
5091 adapter_str, cpi->hpath_id);
5092 fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
5094 fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
5095 fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
5096 fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
5097 adapter_str, cpi->hba_vendor);
5098 fprintf(stdout, "%s HBA device ID: 0x%04x\n",
5099 adapter_str, cpi->hba_device);
5100 fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
5101 adapter_str, cpi->hba_subvendor);
5102 fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
5103 adapter_str, cpi->hba_subdevice);
5104 fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
5105 fprintf(stdout, "%s base transfer speed: ", adapter_str);
5106 if (cpi->base_transfer_speed > 1000)
5107 fprintf(stdout, "%d.%03dMB/sec\n",
5108 cpi->base_transfer_speed / 1000,
5109 cpi->base_transfer_speed % 1000);
5111 fprintf(stdout, "%dKB/sec\n",
5112 (cpi->base_transfer_speed % 1000) * 1000);
5113 fprintf(stdout, "%s maximum transfer size: %u bytes\n",
5114 adapter_str, cpi->maxio);
5118 get_print_cts(struct cam_device *device, int user_settings, int quiet,
5119 struct ccb_trans_settings *cts)
5125 ccb = cam_getccb(device);
5128 warnx("get_print_cts: error allocating ccb");
5132 bzero(&(&ccb->ccb_h)[1],
5133 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
5135 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
5137 if (user_settings == 0)
5138 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
5140 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
5142 if (cam_send_ccb(device, ccb) < 0) {
5143 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
5144 if (arglist & CAM_ARG_VERBOSE)
5145 cam_error_print(device, ccb, CAM_ESF_ALL,
5146 CAM_EPF_ALL, stderr);
5148 goto get_print_cts_bailout;
5151 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5152 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
5153 if (arglist & CAM_ARG_VERBOSE)
5154 cam_error_print(device, ccb, CAM_ESF_ALL,
5155 CAM_EPF_ALL, stderr);
5157 goto get_print_cts_bailout;
5161 cts_print(device, &ccb->cts);
5164 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
5166 get_print_cts_bailout:
5174 ratecontrol(struct cam_device *device, int retry_count, int timeout,
5175 int argc, char **argv, char *combinedopt)
5179 int user_settings = 0;
5181 int disc_enable = -1, tag_enable = -1;
5184 double syncrate = -1;
5187 int change_settings = 0, send_tur = 0;
5188 struct ccb_pathinq cpi;
5190 ccb = cam_getccb(device);
5192 warnx("ratecontrol: error allocating ccb");
5195 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5204 if (strncasecmp(optarg, "enable", 6) == 0)
5206 else if (strncasecmp(optarg, "disable", 7) == 0)
5209 warnx("-D argument \"%s\" is unknown", optarg);
5211 goto ratecontrol_bailout;
5213 change_settings = 1;
5216 mode = ata_string2mode(optarg);
5218 warnx("unknown mode '%s'", optarg);
5220 goto ratecontrol_bailout;
5222 change_settings = 1;
5225 offset = strtol(optarg, NULL, 0);
5227 warnx("offset value %d is < 0", offset);
5229 goto ratecontrol_bailout;
5231 change_settings = 1;
5237 syncrate = atof(optarg);
5239 warnx("sync rate %f is < 0", syncrate);
5241 goto ratecontrol_bailout;
5243 change_settings = 1;
5246 if (strncasecmp(optarg, "enable", 6) == 0)
5248 else if (strncasecmp(optarg, "disable", 7) == 0)
5251 warnx("-T argument \"%s\" is unknown", optarg);
5253 goto ratecontrol_bailout;
5255 change_settings = 1;
5261 bus_width = strtol(optarg, NULL, 0);
5262 if (bus_width < 0) {
5263 warnx("bus width %d is < 0", bus_width);
5265 goto ratecontrol_bailout;
5267 change_settings = 1;
5273 bzero(&(&ccb->ccb_h)[1],
5274 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
5276 * Grab path inquiry information, so we can determine whether
5277 * or not the initiator is capable of the things that the user
5280 ccb->ccb_h.func_code = XPT_PATH_INQ;
5281 if (cam_send_ccb(device, ccb) < 0) {
5282 perror("error sending XPT_PATH_INQ CCB");
5283 if (arglist & CAM_ARG_VERBOSE) {
5284 cam_error_print(device, ccb, CAM_ESF_ALL,
5285 CAM_EPF_ALL, stderr);
5288 goto ratecontrol_bailout;
5290 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5291 warnx("XPT_PATH_INQ CCB failed");
5292 if (arglist & CAM_ARG_VERBOSE) {
5293 cam_error_print(device, ccb, CAM_ESF_ALL,
5294 CAM_EPF_ALL, stderr);
5297 goto ratecontrol_bailout;
5299 bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
5300 bzero(&(&ccb->ccb_h)[1],
5301 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
5303 fprintf(stdout, "%s parameters:\n",
5304 user_settings ? "User" : "Current");
5306 retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
5308 goto ratecontrol_bailout;
5310 if (arglist & CAM_ARG_VERBOSE)
5313 if (change_settings) {
5314 int didsettings = 0;
5315 struct ccb_trans_settings_spi *spi = NULL;
5316 struct ccb_trans_settings_pata *pata = NULL;
5317 struct ccb_trans_settings_sata *sata = NULL;
5318 struct ccb_trans_settings_ata *ata = NULL;
5319 struct ccb_trans_settings_scsi *scsi = NULL;
5321 if (ccb->cts.transport == XPORT_SPI)
5322 spi = &ccb->cts.xport_specific.spi;
5323 if (ccb->cts.transport == XPORT_ATA)
5324 pata = &ccb->cts.xport_specific.ata;
5325 if (ccb->cts.transport == XPORT_SATA)
5326 sata = &ccb->cts.xport_specific.sata;
5327 if (ccb->cts.protocol == PROTO_ATA)
5328 ata = &ccb->cts.proto_specific.ata;
5329 if (ccb->cts.protocol == PROTO_SCSI)
5330 scsi = &ccb->cts.proto_specific.scsi;
5331 ccb->cts.xport_specific.valid = 0;
5332 ccb->cts.proto_specific.valid = 0;
5333 if (spi && disc_enable != -1) {
5334 spi->valid |= CTS_SPI_VALID_DISC;
5335 if (disc_enable == 0)
5336 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
5338 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
5341 if (tag_enable != -1) {
5342 if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
5343 warnx("HBA does not support tagged queueing, "
5344 "so you cannot modify tag settings");
5346 goto ratecontrol_bailout;
5349 ata->valid |= CTS_SCSI_VALID_TQ;
5350 if (tag_enable == 0)
5351 ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
5353 ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
5356 scsi->valid |= CTS_SCSI_VALID_TQ;
5357 if (tag_enable == 0)
5358 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
5360 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
5364 if (spi && offset != -1) {
5365 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5366 warnx("HBA is not capable of changing offset");
5368 goto ratecontrol_bailout;
5370 spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
5371 spi->sync_offset = offset;
5374 if (spi && syncrate != -1) {
5375 int prelim_sync_period;
5377 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5378 warnx("HBA is not capable of changing "
5381 goto ratecontrol_bailout;
5383 spi->valid |= CTS_SPI_VALID_SYNC_RATE;
5385 * The sync rate the user gives us is in MHz.
5386 * We need to translate it into KHz for this
5391 * Next, we calculate a "preliminary" sync period
5392 * in tenths of a nanosecond.
5395 prelim_sync_period = 0;
5397 prelim_sync_period = 10000000 / syncrate;
5399 scsi_calc_syncparam(prelim_sync_period);
5402 if (sata && syncrate != -1) {
5403 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5404 warnx("HBA is not capable of changing "
5407 goto ratecontrol_bailout;
5409 if (!user_settings) {
5410 warnx("You can modify only user rate "
5411 "settings for SATA");
5413 goto ratecontrol_bailout;
5415 sata->revision = ata_speed2revision(syncrate * 100);
5416 if (sata->revision < 0) {
5417 warnx("Invalid rate %f", syncrate);
5419 goto ratecontrol_bailout;
5421 sata->valid |= CTS_SATA_VALID_REVISION;
5424 if ((pata || sata) && mode != -1) {
5425 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5426 warnx("HBA is not capable of changing "
5429 goto ratecontrol_bailout;
5431 if (!user_settings) {
5432 warnx("You can modify only user mode "
5433 "settings for ATA/SATA");
5435 goto ratecontrol_bailout;
5439 pata->valid |= CTS_ATA_VALID_MODE;
5442 sata->valid |= CTS_SATA_VALID_MODE;
5447 * The bus_width argument goes like this:
5451 * Therefore, if you shift the number of bits given on the
5452 * command line right by 4, you should get the correct
5455 if (spi && bus_width != -1) {
5457 * We might as well validate things here with a
5458 * decipherable error message, rather than what
5459 * will probably be an indecipherable error message
5460 * by the time it gets back to us.
5462 if ((bus_width == 16)
5463 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
5464 warnx("HBA does not support 16 bit bus width");
5466 goto ratecontrol_bailout;
5467 } else if ((bus_width == 32)
5468 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
5469 warnx("HBA does not support 32 bit bus width");
5471 goto ratecontrol_bailout;
5472 } else if ((bus_width != 8)
5473 && (bus_width != 16)
5474 && (bus_width != 32)) {
5475 warnx("Invalid bus width %d", bus_width);
5477 goto ratecontrol_bailout;
5479 spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
5480 spi->bus_width = bus_width >> 4;
5483 if (didsettings == 0) {
5484 goto ratecontrol_bailout;
5486 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
5487 if (cam_send_ccb(device, ccb) < 0) {
5488 perror("error sending XPT_SET_TRAN_SETTINGS CCB");
5489 if (arglist & CAM_ARG_VERBOSE) {
5490 cam_error_print(device, ccb, CAM_ESF_ALL,
5491 CAM_EPF_ALL, stderr);
5494 goto ratecontrol_bailout;
5496 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5497 warnx("XPT_SET_TRANS_SETTINGS CCB failed");
5498 if (arglist & CAM_ARG_VERBOSE) {
5499 cam_error_print(device, ccb, CAM_ESF_ALL,
5500 CAM_EPF_ALL, stderr);
5503 goto ratecontrol_bailout;
5507 retval = testunitready(device, retry_count, timeout,
5508 (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
5510 * If the TUR didn't succeed, just bail.
5514 fprintf(stderr, "Test Unit Ready failed\n");
5515 goto ratecontrol_bailout;
5518 if ((change_settings || send_tur) && !quiet &&
5519 (ccb->cts.transport == XPORT_ATA ||
5520 ccb->cts.transport == XPORT_SATA || send_tur)) {
5521 fprintf(stdout, "New parameters:\n");
5522 retval = get_print_cts(device, user_settings, 0, NULL);
5525 ratecontrol_bailout:
5531 scsiformat(struct cam_device *device, int argc, char **argv,
5532 char *combinedopt, int retry_count, int timeout)
5536 int ycount = 0, quiet = 0;
5537 int error = 0, retval = 0;
5538 int use_timeout = 10800 * 1000;
5540 struct format_defect_list_header fh;
5541 u_int8_t *data_ptr = NULL;
5542 u_int32_t dxfer_len = 0;
5544 int num_warnings = 0;
5547 ccb = cam_getccb(device);
5550 warnx("scsiformat: error allocating ccb");
5554 bzero(&(&ccb->ccb_h)[1],
5555 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5557 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5578 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5579 "following device:\n");
5581 error = scsidoinquiry(device, argc, argv, combinedopt,
5582 retry_count, timeout);
5585 warnx("scsiformat: error sending inquiry");
5586 goto scsiformat_bailout;
5591 if (!get_confirmation()) {
5593 goto scsiformat_bailout;
5598 use_timeout = timeout;
5601 fprintf(stdout, "Current format timeout is %d seconds\n",
5602 use_timeout / 1000);
5606 * If the user hasn't disabled questions and didn't specify a
5607 * timeout on the command line, ask them if they want the current
5611 && (timeout == 0)) {
5613 int new_timeout = 0;
5615 fprintf(stdout, "Enter new timeout in seconds or press\n"
5616 "return to keep the current timeout [%d] ",
5617 use_timeout / 1000);
5619 if (fgets(str, sizeof(str), stdin) != NULL) {
5621 new_timeout = atoi(str);
5624 if (new_timeout != 0) {
5625 use_timeout = new_timeout * 1000;
5626 fprintf(stdout, "Using new timeout value %d\n",
5627 use_timeout / 1000);
5632 * Keep this outside the if block below to silence any unused
5633 * variable warnings.
5635 bzero(&fh, sizeof(fh));
5638 * If we're in immediate mode, we've got to include the format
5641 if (immediate != 0) {
5642 fh.byte2 = FU_DLH_IMMED;
5643 data_ptr = (u_int8_t *)&fh;
5644 dxfer_len = sizeof(fh);
5645 byte2 = FU_FMT_DATA;
5646 } else if (quiet == 0) {
5647 fprintf(stdout, "Formatting...");
5651 scsi_format_unit(&ccb->csio,
5652 /* retries */ retry_count,
5654 /* tag_action */ MSG_SIMPLE_Q_TAG,
5657 /* data_ptr */ data_ptr,
5658 /* dxfer_len */ dxfer_len,
5659 /* sense_len */ SSD_FULL_SIZE,
5660 /* timeout */ use_timeout);
5662 /* Disable freezing the device queue */
5663 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5665 if (arglist & CAM_ARG_ERR_RECOVER)
5666 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5668 if (((retval = cam_send_ccb(device, ccb)) < 0)
5669 || ((immediate == 0)
5670 && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
5671 const char errstr[] = "error sending format command";
5678 if (arglist & CAM_ARG_VERBOSE) {
5679 cam_error_print(device, ccb, CAM_ESF_ALL,
5680 CAM_EPF_ALL, stderr);
5683 goto scsiformat_bailout;
5687 * If we ran in non-immediate mode, we already checked for errors
5688 * above and printed out any necessary information. If we're in
5689 * immediate mode, we need to loop through and get status
5690 * information periodically.
5692 if (immediate == 0) {
5694 fprintf(stdout, "Format Complete\n");
5696 goto scsiformat_bailout;
5703 bzero(&(&ccb->ccb_h)[1],
5704 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5707 * There's really no need to do error recovery or
5708 * retries here, since we're just going to sit in a
5709 * loop and wait for the device to finish formatting.
5711 scsi_test_unit_ready(&ccb->csio,
5714 /* tag_action */ MSG_SIMPLE_Q_TAG,
5715 /* sense_len */ SSD_FULL_SIZE,
5716 /* timeout */ 5000);
5718 /* Disable freezing the device queue */
5719 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5721 retval = cam_send_ccb(device, ccb);
5724 * If we get an error from the ioctl, bail out. SCSI
5725 * errors are expected.
5728 warn("error sending CAMIOCOMMAND ioctl");
5729 if (arglist & CAM_ARG_VERBOSE) {
5730 cam_error_print(device, ccb, CAM_ESF_ALL,
5731 CAM_EPF_ALL, stderr);
5734 goto scsiformat_bailout;
5737 status = ccb->ccb_h.status & CAM_STATUS_MASK;
5739 if ((status != CAM_REQ_CMP)
5740 && (status == CAM_SCSI_STATUS_ERROR)
5741 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
5742 struct scsi_sense_data *sense;
5743 int error_code, sense_key, asc, ascq;
5745 sense = &ccb->csio.sense_data;
5746 scsi_extract_sense_len(sense, ccb->csio.sense_len -
5747 ccb->csio.sense_resid, &error_code, &sense_key,
5748 &asc, &ascq, /*show_errors*/ 1);
5751 * According to the SCSI-2 and SCSI-3 specs, a
5752 * drive that is in the middle of a format should
5753 * return NOT READY with an ASC of "logical unit
5754 * not ready, format in progress". The sense key
5755 * specific bytes will then be a progress indicator.
5757 if ((sense_key == SSD_KEY_NOT_READY)
5758 && (asc == 0x04) && (ascq == 0x04)) {
5761 if ((scsi_get_sks(sense, ccb->csio.sense_len -
5762 ccb->csio.sense_resid, sks) == 0)
5765 u_int64_t percentage;
5767 val = scsi_2btoul(&sks[1]);
5768 percentage = 10000 * val;
5771 "\rFormatting: %ju.%02u %% "
5773 (uintmax_t)(percentage /
5775 (unsigned)((percentage /
5779 } else if ((quiet == 0)
5780 && (++num_warnings <= 1)) {
5781 warnx("Unexpected SCSI Sense Key "
5782 "Specific value returned "
5784 scsi_sense_print(device, &ccb->csio,
5786 warnx("Unable to print status "
5787 "information, but format will "
5789 warnx("will exit when format is "
5794 warnx("Unexpected SCSI error during format");
5795 cam_error_print(device, ccb, CAM_ESF_ALL,
5796 CAM_EPF_ALL, stderr);
5798 goto scsiformat_bailout;
5801 } else if (status != CAM_REQ_CMP) {
5802 warnx("Unexpected CAM status %#x", status);
5803 if (arglist & CAM_ARG_VERBOSE)
5804 cam_error_print(device, ccb, CAM_ESF_ALL,
5805 CAM_EPF_ALL, stderr);
5807 goto scsiformat_bailout;
5810 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
5813 fprintf(stdout, "\nFormat Complete\n");
5823 scsisanitize(struct cam_device *device, int argc, char **argv,
5824 char *combinedopt, int retry_count, int timeout)
5827 u_int8_t action = 0;
5829 int ycount = 0, quiet = 0;
5830 int error = 0, retval = 0;
5831 int use_timeout = 10800 * 1000;
5837 const char *pattern = NULL;
5838 u_int8_t *data_ptr = NULL;
5839 u_int32_t dxfer_len = 0;
5841 int num_warnings = 0;
5844 ccb = cam_getccb(device);
5847 warnx("scsisanitize: error allocating ccb");
5851 bzero(&(&ccb->ccb_h)[1],
5852 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5854 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5857 if (strcasecmp(optarg, "overwrite") == 0)
5858 action = SSZ_SERVICE_ACTION_OVERWRITE;
5859 else if (strcasecmp(optarg, "block") == 0)
5860 action = SSZ_SERVICE_ACTION_BLOCK_ERASE;
5861 else if (strcasecmp(optarg, "crypto") == 0)
5862 action = SSZ_SERVICE_ACTION_CRYPTO_ERASE;
5863 else if (strcasecmp(optarg, "exitfailure") == 0)
5864 action = SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE;
5866 warnx("invalid service operation \"%s\"",
5869 goto scsisanitize_bailout;
5873 passes = strtol(optarg, NULL, 0);
5874 if (passes < 1 || passes > 31) {
5875 warnx("invalid passes value %d", passes);
5877 goto scsisanitize_bailout;
5908 warnx("an action is required");
5910 goto scsisanitize_bailout;
5911 } else if (action == SSZ_SERVICE_ACTION_OVERWRITE) {
5912 struct scsi_sanitize_parameter_list *pl;
5916 if (pattern == NULL) {
5917 warnx("overwrite action requires -P argument");
5919 goto scsisanitize_bailout;
5921 fd = open(pattern, O_RDONLY);
5923 warn("cannot open pattern file %s", pattern);
5925 goto scsisanitize_bailout;
5927 if (fstat(fd, &sb) < 0) {
5928 warn("cannot stat pattern file %s", pattern);
5930 goto scsisanitize_bailout;
5933 if (sz > SSZPL_MAX_PATTERN_LENGTH) {
5934 warnx("pattern file size exceeds maximum value %d",
5935 SSZPL_MAX_PATTERN_LENGTH);
5937 goto scsisanitize_bailout;
5939 dxfer_len = sizeof(*pl) + sz;
5940 data_ptr = calloc(1, dxfer_len);
5941 if (data_ptr == NULL) {
5942 warnx("cannot allocate parameter list buffer");
5944 goto scsisanitize_bailout;
5947 amt = read(fd, data_ptr + sizeof(*pl), sz);
5949 warn("cannot read pattern file");
5951 goto scsisanitize_bailout;
5952 } else if (amt != sz) {
5953 warnx("short pattern file read");
5955 goto scsisanitize_bailout;
5958 pl = (struct scsi_sanitize_parameter_list *)data_ptr;
5964 pl->byte1 |= SSZPL_INVERT;
5965 scsi_ulto2b(sz, pl->length);
5971 else if (invert != 0)
5973 else if (pattern != NULL)
5978 warnx("%s argument only valid with overwrite "
5981 goto scsisanitize_bailout;
5986 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5987 "following device:\n");
5989 error = scsidoinquiry(device, argc, argv, combinedopt,
5990 retry_count, timeout);
5993 warnx("scsisanitize: error sending inquiry");
5994 goto scsisanitize_bailout;
5999 if (!get_confirmation()) {
6001 goto scsisanitize_bailout;
6006 use_timeout = timeout;
6009 fprintf(stdout, "Current sanitize timeout is %d seconds\n",
6010 use_timeout / 1000);
6014 * If the user hasn't disabled questions and didn't specify a
6015 * timeout on the command line, ask them if they want the current
6019 && (timeout == 0)) {
6021 int new_timeout = 0;
6023 fprintf(stdout, "Enter new timeout in seconds or press\n"
6024 "return to keep the current timeout [%d] ",
6025 use_timeout / 1000);
6027 if (fgets(str, sizeof(str), stdin) != NULL) {
6029 new_timeout = atoi(str);
6032 if (new_timeout != 0) {
6033 use_timeout = new_timeout * 1000;
6034 fprintf(stdout, "Using new timeout value %d\n",
6035 use_timeout / 1000);
6041 byte2 |= SSZ_UNRESTRICTED_EXIT;
6045 scsi_sanitize(&ccb->csio,
6046 /* retries */ retry_count,
6048 /* tag_action */ MSG_SIMPLE_Q_TAG,
6051 /* data_ptr */ data_ptr,
6052 /* dxfer_len */ dxfer_len,
6053 /* sense_len */ SSD_FULL_SIZE,
6054 /* timeout */ use_timeout);
6056 /* Disable freezing the device queue */
6057 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6059 if (arglist & CAM_ARG_ERR_RECOVER)
6060 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6062 if (cam_send_ccb(device, ccb) < 0) {
6063 warn("error sending sanitize command");
6065 goto scsisanitize_bailout;
6068 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6069 struct scsi_sense_data *sense;
6070 int error_code, sense_key, asc, ascq;
6072 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
6073 CAM_SCSI_STATUS_ERROR) {
6074 sense = &ccb->csio.sense_data;
6075 scsi_extract_sense_len(sense, ccb->csio.sense_len -
6076 ccb->csio.sense_resid, &error_code, &sense_key,
6077 &asc, &ascq, /*show_errors*/ 1);
6079 if (sense_key == SSD_KEY_ILLEGAL_REQUEST &&
6080 asc == 0x20 && ascq == 0x00)
6081 warnx("sanitize is not supported by "
6084 warnx("error sanitizing this device");
6086 warnx("error sanitizing this device");
6088 if (arglist & CAM_ARG_VERBOSE) {
6089 cam_error_print(device, ccb, CAM_ESF_ALL,
6090 CAM_EPF_ALL, stderr);
6093 goto scsisanitize_bailout;
6097 * If we ran in non-immediate mode, we already checked for errors
6098 * above and printed out any necessary information. If we're in
6099 * immediate mode, we need to loop through and get status
6100 * information periodically.
6102 if (immediate == 0) {
6104 fprintf(stdout, "Sanitize Complete\n");
6106 goto scsisanitize_bailout;
6113 bzero(&(&ccb->ccb_h)[1],
6114 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6117 * There's really no need to do error recovery or
6118 * retries here, since we're just going to sit in a
6119 * loop and wait for the device to finish sanitizing.
6121 scsi_test_unit_ready(&ccb->csio,
6124 /* tag_action */ MSG_SIMPLE_Q_TAG,
6125 /* sense_len */ SSD_FULL_SIZE,
6126 /* timeout */ 5000);
6128 /* Disable freezing the device queue */
6129 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6131 retval = cam_send_ccb(device, ccb);
6134 * If we get an error from the ioctl, bail out. SCSI
6135 * errors are expected.
6138 warn("error sending CAMIOCOMMAND ioctl");
6139 if (arglist & CAM_ARG_VERBOSE) {
6140 cam_error_print(device, ccb, CAM_ESF_ALL,
6141 CAM_EPF_ALL, stderr);
6144 goto scsisanitize_bailout;
6147 status = ccb->ccb_h.status & CAM_STATUS_MASK;
6149 if ((status != CAM_REQ_CMP)
6150 && (status == CAM_SCSI_STATUS_ERROR)
6151 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
6152 struct scsi_sense_data *sense;
6153 int error_code, sense_key, asc, ascq;
6155 sense = &ccb->csio.sense_data;
6156 scsi_extract_sense_len(sense, ccb->csio.sense_len -
6157 ccb->csio.sense_resid, &error_code, &sense_key,
6158 &asc, &ascq, /*show_errors*/ 1);
6161 * According to the SCSI-3 spec, a drive that is in the
6162 * middle of a sanitize should return NOT READY with an
6163 * ASC of "logical unit not ready, sanitize in
6164 * progress". The sense key specific bytes will then
6165 * be a progress indicator.
6167 if ((sense_key == SSD_KEY_NOT_READY)
6168 && (asc == 0x04) && (ascq == 0x1b)) {
6171 if ((scsi_get_sks(sense, ccb->csio.sense_len -
6172 ccb->csio.sense_resid, sks) == 0)
6175 u_int64_t percentage;
6177 val = scsi_2btoul(&sks[1]);
6178 percentage = 10000 * val;
6181 "\rSanitizing: %ju.%02u %% "
6183 (uintmax_t)(percentage /
6185 (unsigned)((percentage /
6189 } else if ((quiet == 0)
6190 && (++num_warnings <= 1)) {
6191 warnx("Unexpected SCSI Sense Key "
6192 "Specific value returned "
6193 "during sanitize:");
6194 scsi_sense_print(device, &ccb->csio,
6196 warnx("Unable to print status "
6197 "information, but sanitze will "
6199 warnx("will exit when sanitize is "
6204 warnx("Unexpected SCSI error during sanitize");
6205 cam_error_print(device, ccb, CAM_ESF_ALL,
6206 CAM_EPF_ALL, stderr);
6208 goto scsisanitize_bailout;
6211 } else if (status != CAM_REQ_CMP) {
6212 warnx("Unexpected CAM status %#x", status);
6213 if (arglist & CAM_ARG_VERBOSE)
6214 cam_error_print(device, ccb, CAM_ESF_ALL,
6215 CAM_EPF_ALL, stderr);
6217 goto scsisanitize_bailout;
6219 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
6222 fprintf(stdout, "\nSanitize Complete\n");
6224 scsisanitize_bailout:
6227 if (data_ptr != NULL)
6235 scsireportluns(struct cam_device *device, int argc, char **argv,
6236 char *combinedopt, int retry_count, int timeout)
6239 int c, countonly, lunsonly;
6240 struct scsi_report_luns_data *lundata;
6242 uint8_t report_type;
6243 uint32_t list_len, i, j;
6248 report_type = RPL_REPORT_DEFAULT;
6249 ccb = cam_getccb(device);
6252 warnx("%s: error allocating ccb", __func__);
6256 bzero(&(&ccb->ccb_h)[1],
6257 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6262 while ((c = getopt(argc, argv, combinedopt)) != -1) {
6271 if (strcasecmp(optarg, "default") == 0)
6272 report_type = RPL_REPORT_DEFAULT;
6273 else if (strcasecmp(optarg, "wellknown") == 0)
6274 report_type = RPL_REPORT_WELLKNOWN;
6275 else if (strcasecmp(optarg, "all") == 0)
6276 report_type = RPL_REPORT_ALL;
6278 warnx("%s: invalid report type \"%s\"",
6289 if ((countonly != 0)
6290 && (lunsonly != 0)) {
6291 warnx("%s: you can only specify one of -c or -l", __func__);
6296 * According to SPC-4, the allocation length must be at least 16
6297 * bytes -- enough for the header and one LUN.
6299 alloc_len = sizeof(*lundata) + 8;
6303 lundata = malloc(alloc_len);
6305 if (lundata == NULL) {
6306 warn("%s: error mallocing %d bytes", __func__, alloc_len);
6311 scsi_report_luns(&ccb->csio,
6312 /*retries*/ retry_count,
6314 /*tag_action*/ MSG_SIMPLE_Q_TAG,
6315 /*select_report*/ report_type,
6316 /*rpl_buf*/ lundata,
6317 /*alloc_len*/ alloc_len,
6318 /*sense_len*/ SSD_FULL_SIZE,
6319 /*timeout*/ timeout ? timeout : 5000);
6321 /* Disable freezing the device queue */
6322 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6324 if (arglist & CAM_ARG_ERR_RECOVER)
6325 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6327 if (cam_send_ccb(device, ccb) < 0) {
6328 warn("error sending REPORT LUNS command");
6330 if (arglist & CAM_ARG_VERBOSE)
6331 cam_error_print(device, ccb, CAM_ESF_ALL,
6332 CAM_EPF_ALL, stderr);
6338 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6339 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6345 list_len = scsi_4btoul(lundata->length);
6348 * If we need to list the LUNs, and our allocation
6349 * length was too short, reallocate and retry.
6351 if ((countonly == 0)
6352 && (list_len > (alloc_len - sizeof(*lundata)))) {
6353 alloc_len = list_len + sizeof(*lundata);
6359 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
6360 ((list_len / 8) > 1) ? "s" : "");
6365 for (i = 0; i < (list_len / 8); i++) {
6369 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
6371 fprintf(stdout, ",");
6372 switch (lundata->luns[i].lundata[j] &
6373 RPL_LUNDATA_ATYP_MASK) {
6374 case RPL_LUNDATA_ATYP_PERIPH:
6375 if ((lundata->luns[i].lundata[j] &
6376 RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
6377 fprintf(stdout, "%d:",
6378 lundata->luns[i].lundata[j] &
6379 RPL_LUNDATA_PERIPH_BUS_MASK);
6381 && ((lundata->luns[i].lundata[j+2] &
6382 RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
6385 fprintf(stdout, "%d",
6386 lundata->luns[i].lundata[j+1]);
6388 case RPL_LUNDATA_ATYP_FLAT: {
6390 tmplun[0] = lundata->luns[i].lundata[j] &
6391 RPL_LUNDATA_FLAT_LUN_MASK;
6392 tmplun[1] = lundata->luns[i].lundata[j+1];
6394 fprintf(stdout, "%d", scsi_2btoul(tmplun));
6398 case RPL_LUNDATA_ATYP_LUN:
6399 fprintf(stdout, "%d:%d:%d",
6400 (lundata->luns[i].lundata[j+1] &
6401 RPL_LUNDATA_LUN_BUS_MASK) >> 5,
6402 lundata->luns[i].lundata[j] &
6403 RPL_LUNDATA_LUN_TARG_MASK,
6404 lundata->luns[i].lundata[j+1] &
6405 RPL_LUNDATA_LUN_LUN_MASK);
6407 case RPL_LUNDATA_ATYP_EXTLUN: {
6408 int field_len_code, eam_code;
6410 eam_code = lundata->luns[i].lundata[j] &
6411 RPL_LUNDATA_EXT_EAM_MASK;
6412 field_len_code = (lundata->luns[i].lundata[j] &
6413 RPL_LUNDATA_EXT_LEN_MASK) >> 4;
6415 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
6416 && (field_len_code == 0x00)) {
6417 fprintf(stdout, "%d",
6418 lundata->luns[i].lundata[j+1]);
6419 } else if ((eam_code ==
6420 RPL_LUNDATA_EXT_EAM_NOT_SPEC)
6421 && (field_len_code == 0x03)) {
6425 * This format takes up all 8 bytes.
6426 * If we aren't starting at offset 0,
6430 fprintf(stdout, "Invalid "
6433 "specified format", j);
6437 bzero(tmp_lun, sizeof(tmp_lun));
6438 bcopy(&lundata->luns[i].lundata[j+1],
6439 &tmp_lun[1], sizeof(tmp_lun) - 1);
6440 fprintf(stdout, "%#jx",
6441 (intmax_t)scsi_8btou64(tmp_lun));
6444 fprintf(stderr, "Unknown Extended LUN"
6445 "Address method %#x, length "
6446 "code %#x", eam_code,
6453 fprintf(stderr, "Unknown LUN address method "
6454 "%#x\n", lundata->luns[i].lundata[0] &
6455 RPL_LUNDATA_ATYP_MASK);
6459 * For the flat addressing method, there are no
6460 * other levels after it.
6465 fprintf(stdout, "\n");
6478 scsireadcapacity(struct cam_device *device, int argc, char **argv,
6479 char *combinedopt, int retry_count, int timeout)
6482 int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
6483 struct scsi_read_capacity_data rcap;
6484 struct scsi_read_capacity_data_long rcaplong;
6498 ccb = cam_getccb(device);
6501 warnx("%s: error allocating ccb", __func__);
6505 bzero(&(&ccb->ccb_h)[1],
6506 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6508 while ((c = getopt(argc, argv, combinedopt)) != -1) {
6535 if ((blocksizeonly != 0)
6536 && (numblocks != 0)) {
6537 warnx("%s: you can only specify one of -b or -N", __func__);
6542 if ((blocksizeonly != 0)
6543 && (sizeonly != 0)) {
6544 warnx("%s: you can only specify one of -b or -s", __func__);
6551 warnx("%s: you can only specify one of -h/-H or -q", __func__);
6557 && (blocksizeonly != 0)) {
6558 warnx("%s: you can only specify one of -h/-H or -b", __func__);
6563 scsi_read_capacity(&ccb->csio,
6564 /*retries*/ retry_count,
6566 /*tag_action*/ MSG_SIMPLE_Q_TAG,
6569 /*timeout*/ timeout ? timeout : 5000);
6571 /* Disable freezing the device queue */
6572 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6574 if (arglist & CAM_ARG_ERR_RECOVER)
6575 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6577 if (cam_send_ccb(device, ccb) < 0) {
6578 warn("error sending READ CAPACITY command");
6580 if (arglist & CAM_ARG_VERBOSE)
6581 cam_error_print(device, ccb, CAM_ESF_ALL,
6582 CAM_EPF_ALL, stderr);
6588 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6589 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6594 maxsector = scsi_4btoul(rcap.addr);
6595 block_len = scsi_4btoul(rcap.length);
6598 * A last block of 2^32-1 means that the true capacity is over 2TB,
6599 * and we need to issue the long READ CAPACITY to get the real
6600 * capacity. Otherwise, we're all set.
6602 if (maxsector != 0xffffffff)
6605 scsi_read_capacity_16(&ccb->csio,
6606 /*retries*/ retry_count,
6608 /*tag_action*/ MSG_SIMPLE_Q_TAG,
6612 /*rcap_buf*/ (uint8_t *)&rcaplong,
6613 /*rcap_buf_len*/ sizeof(rcaplong),
6614 /*sense_len*/ SSD_FULL_SIZE,
6615 /*timeout*/ timeout ? timeout : 5000);
6617 /* Disable freezing the device queue */
6618 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6620 if (arglist & CAM_ARG_ERR_RECOVER)
6621 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6623 if (cam_send_ccb(device, ccb) < 0) {
6624 warn("error sending READ CAPACITY (16) command");
6626 if (arglist & CAM_ARG_VERBOSE)
6627 cam_error_print(device, ccb, CAM_ESF_ALL,
6628 CAM_EPF_ALL, stderr);
6634 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6635 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6640 maxsector = scsi_8btou64(rcaplong.addr);
6641 block_len = scsi_4btoul(rcaplong.length);
6644 if (blocksizeonly == 0) {
6646 * Humanize implies !quiet, and also implies numblocks.
6648 if (humanize != 0) {
6653 tmpbytes = (maxsector + 1) * block_len;
6654 ret = humanize_number(tmpstr, sizeof(tmpstr),
6655 tmpbytes, "", HN_AUTOSCALE,
6658 HN_DIVISOR_1000 : 0));
6660 warnx("%s: humanize_number failed!", __func__);
6664 fprintf(stdout, "Device Size: %s%s", tmpstr,
6665 (sizeonly == 0) ? ", " : "\n");
6666 } else if (numblocks != 0) {
6667 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6668 "Blocks: " : "", (uintmax_t)maxsector + 1,
6669 (sizeonly == 0) ? ", " : "\n");
6671 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6672 "Last Block: " : "", (uintmax_t)maxsector,
6673 (sizeonly == 0) ? ", " : "\n");
6677 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
6678 "Block Length: " : "", block_len, (quiet == 0) ?
6687 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
6688 int retry_count, int timeout)
6692 uint8_t *smp_request = NULL, *smp_response = NULL;
6693 int request_size = 0, response_size = 0;
6694 int fd_request = 0, fd_response = 0;
6695 char *datastr = NULL;
6696 struct get_hook hook;
6701 * Note that at the moment we don't support sending SMP CCBs to
6702 * devices that aren't probed by CAM.
6704 ccb = cam_getccb(device);
6706 warnx("%s: error allocating CCB", __func__);
6710 bzero(&(&ccb->ccb_h)[1],
6711 sizeof(union ccb) - sizeof(struct ccb_hdr));
6713 while ((c = getopt(argc, argv, combinedopt)) != -1) {
6716 arglist |= CAM_ARG_CMD_IN;
6717 response_size = strtol(optarg, NULL, 0);
6718 if (response_size <= 0) {
6719 warnx("invalid number of response bytes %d",
6722 goto smpcmd_bailout;
6724 hook.argc = argc - optind;
6725 hook.argv = argv + optind;
6728 datastr = cget(&hook, NULL);
6730 * If the user supplied "-" instead of a format, he
6731 * wants the data to be written to stdout.
6733 if ((datastr != NULL)
6734 && (datastr[0] == '-'))
6737 smp_response = (u_int8_t *)malloc(response_size);
6738 if (smp_response == NULL) {
6739 warn("can't malloc memory for SMP response");
6741 goto smpcmd_bailout;
6745 arglist |= CAM_ARG_CMD_OUT;
6746 request_size = strtol(optarg, NULL, 0);
6747 if (request_size <= 0) {
6748 warnx("invalid number of request bytes %d",
6751 goto smpcmd_bailout;
6753 hook.argc = argc - optind;
6754 hook.argv = argv + optind;
6756 datastr = cget(&hook, NULL);
6757 smp_request = (u_int8_t *)malloc(request_size);
6758 if (smp_request == NULL) {
6759 warn("can't malloc memory for SMP request");
6761 goto smpcmd_bailout;
6763 bzero(smp_request, request_size);
6765 * If the user supplied "-" instead of a format, he
6766 * wants the data to be read from stdin.
6768 if ((datastr != NULL)
6769 && (datastr[0] == '-'))
6772 buff_encode_visit(smp_request, request_size,
6783 * If fd_data is set, and we're writing to the device, we need to
6784 * read the data the user wants written from stdin.
6786 if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
6788 int amt_to_read = request_size;
6789 u_int8_t *buf_ptr = smp_request;
6791 for (amt_read = 0; amt_to_read > 0;
6792 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
6793 if (amt_read == -1) {
6794 warn("error reading data from stdin");
6796 goto smpcmd_bailout;
6798 amt_to_read -= amt_read;
6799 buf_ptr += amt_read;
6803 if (((arglist & CAM_ARG_CMD_IN) == 0)
6804 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
6805 warnx("%s: need both the request (-r) and response (-R) "
6806 "arguments", __func__);
6808 goto smpcmd_bailout;
6811 flags |= CAM_DEV_QFRZDIS;
6813 cam_fill_smpio(&ccb->smpio,
6814 /*retries*/ retry_count,
6817 /*smp_request*/ smp_request,
6818 /*smp_request_len*/ request_size,
6819 /*smp_response*/ smp_response,
6820 /*smp_response_len*/ response_size,
6821 /*timeout*/ timeout ? timeout : 5000);
6823 ccb->smpio.flags = SMP_FLAG_NONE;
6825 if (((retval = cam_send_ccb(device, ccb)) < 0)
6826 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6827 const char warnstr[] = "error sending command";
6834 if (arglist & CAM_ARG_VERBOSE) {
6835 cam_error_print(device, ccb, CAM_ESF_ALL,
6836 CAM_EPF_ALL, stderr);
6840 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
6841 && (response_size > 0)) {
6842 if (fd_response == 0) {
6843 buff_decode_visit(smp_response, response_size,
6844 datastr, arg_put, NULL);
6845 fprintf(stdout, "\n");
6847 ssize_t amt_written;
6848 int amt_to_write = response_size;
6849 u_int8_t *buf_ptr = smp_response;
6851 for (amt_written = 0; (amt_to_write > 0) &&
6852 (amt_written = write(STDOUT_FILENO, buf_ptr,
6853 amt_to_write)) > 0;){
6854 amt_to_write -= amt_written;
6855 buf_ptr += amt_written;
6857 if (amt_written == -1) {
6858 warn("error writing data to stdout");
6860 goto smpcmd_bailout;
6861 } else if ((amt_written == 0)
6862 && (amt_to_write > 0)) {
6863 warnx("only wrote %u bytes out of %u",
6864 response_size - amt_to_write,
6873 if (smp_request != NULL)
6876 if (smp_response != NULL)
6883 smpreportgeneral(struct cam_device *device, int argc, char **argv,
6884 char *combinedopt, int retry_count, int timeout)
6887 struct smp_report_general_request *request = NULL;
6888 struct smp_report_general_response *response = NULL;
6889 struct sbuf *sb = NULL;
6891 int c, long_response = 0;
6895 * Note that at the moment we don't support sending SMP CCBs to
6896 * devices that aren't probed by CAM.
6898 ccb = cam_getccb(device);
6900 warnx("%s: error allocating CCB", __func__);
6904 bzero(&(&ccb->ccb_h)[1],
6905 sizeof(union ccb) - sizeof(struct ccb_hdr));
6907 while ((c = getopt(argc, argv, combinedopt)) != -1) {
6916 request = malloc(sizeof(*request));
6917 if (request == NULL) {
6918 warn("%s: unable to allocate %zd bytes", __func__,
6924 response = malloc(sizeof(*response));
6925 if (response == NULL) {
6926 warn("%s: unable to allocate %zd bytes", __func__,
6933 smp_report_general(&ccb->smpio,
6937 /*request_len*/ sizeof(*request),
6938 (uint8_t *)response,
6939 /*response_len*/ sizeof(*response),
6940 /*long_response*/ long_response,
6943 if (((retval = cam_send_ccb(device, ccb)) < 0)
6944 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6945 const char warnstr[] = "error sending command";
6952 if (arglist & CAM_ARG_VERBOSE) {
6953 cam_error_print(device, ccb, CAM_ESF_ALL,
6954 CAM_EPF_ALL, stderr);
6961 * If the device supports the long response bit, try again and see
6962 * if we can get all of the data.
6964 if ((response->long_response & SMP_RG_LONG_RESPONSE)
6965 && (long_response == 0)) {
6966 ccb->ccb_h.status = CAM_REQ_INPROG;
6967 bzero(&(&ccb->ccb_h)[1],
6968 sizeof(union ccb) - sizeof(struct ccb_hdr));
6974 * XXX KDM detect and decode SMP errors here.
6976 sb = sbuf_new_auto();
6978 warnx("%s: error allocating sbuf", __func__);
6982 smp_report_general_sbuf(response, sizeof(*response), sb);
6984 if (sbuf_finish(sb) != 0) {
6985 warnx("%s: sbuf_finish", __func__);
6989 printf("%s", sbuf_data(sb));
6995 if (request != NULL)
6998 if (response != NULL)
7007 static struct camcontrol_opts phy_ops[] = {
7008 {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
7009 {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
7010 {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
7011 {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
7012 {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
7013 {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
7014 {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
7015 {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
7016 {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
7021 smpphycontrol(struct cam_device *device, int argc, char **argv,
7022 char *combinedopt, int retry_count, int timeout)
7025 struct smp_phy_control_request *request = NULL;
7026 struct smp_phy_control_response *response = NULL;
7027 int long_response = 0;
7030 uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
7032 uint64_t attached_dev_name = 0;
7033 int dev_name_set = 0;
7034 uint32_t min_plr = 0, max_plr = 0;
7035 uint32_t pp_timeout_val = 0;
7036 int slumber_partial = 0;
7037 int set_pp_timeout_val = 0;
7041 * Note that at the moment we don't support sending SMP CCBs to
7042 * devices that aren't probed by CAM.
7044 ccb = cam_getccb(device);
7046 warnx("%s: error allocating CCB", __func__);
7050 bzero(&(&ccb->ccb_h)[1],
7051 sizeof(union ccb) - sizeof(struct ccb_hdr));
7053 while ((c = getopt(argc, argv, combinedopt)) != -1) {
7061 if (strcasecmp(optarg, "enable") == 0)
7063 else if (strcasecmp(optarg, "disable") == 0)
7066 warnx("%s: Invalid argument %s", __func__,
7073 slumber_partial |= enable <<
7074 SMP_PC_SAS_SLUMBER_SHIFT;
7077 slumber_partial |= enable <<
7078 SMP_PC_SAS_PARTIAL_SHIFT;
7081 slumber_partial |= enable <<
7082 SMP_PC_SATA_SLUMBER_SHIFT;
7085 slumber_partial |= enable <<
7086 SMP_PC_SATA_PARTIAL_SHIFT;
7089 warnx("%s: programmer error", __func__);
7092 break; /*NOTREACHED*/
7097 attached_dev_name = (uintmax_t)strtoumax(optarg,
7106 * We don't do extensive checking here, so this
7107 * will continue to work when new speeds come out.
7109 min_plr = strtoul(optarg, NULL, 0);
7111 || (min_plr > 0xf)) {
7112 warnx("%s: invalid link rate %x",
7120 * We don't do extensive checking here, so this
7121 * will continue to work when new speeds come out.
7123 max_plr = strtoul(optarg, NULL, 0);
7125 || (max_plr > 0xf)) {
7126 warnx("%s: invalid link rate %x",
7133 camcontrol_optret optreturn;
7134 cam_argmask argnums;
7137 if (phy_op_set != 0) {
7138 warnx("%s: only one phy operation argument "
7139 "(-o) allowed", __func__);
7147 * Allow the user to specify the phy operation
7148 * numerically, as well as with a name. This will
7149 * future-proof it a bit, so options that are added
7150 * in future specs can be used.
7152 if (isdigit(optarg[0])) {
7153 phy_operation = strtoul(optarg, NULL, 0);
7154 if ((phy_operation == 0)
7155 || (phy_operation > 0xff)) {
7156 warnx("%s: invalid phy operation %#x",
7157 __func__, phy_operation);
7163 optreturn = getoption(phy_ops, optarg, &phy_operation,
7166 if (optreturn == CC_OR_AMBIGUOUS) {
7167 warnx("%s: ambiguous option %s", __func__,
7172 } else if (optreturn == CC_OR_NOT_FOUND) {
7173 warnx("%s: option %s not found", __func__,
7185 pp_timeout_val = strtoul(optarg, NULL, 0);
7186 if (pp_timeout_val > 15) {
7187 warnx("%s: invalid partial pathway timeout "
7188 "value %u, need a value less than 16",
7189 __func__, pp_timeout_val);
7193 set_pp_timeout_val = 1;
7201 warnx("%s: a PHY (-p phy) argument is required",__func__);
7206 if (((dev_name_set != 0)
7207 && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
7208 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
7209 && (dev_name_set == 0))) {
7210 warnx("%s: -d name and -o setdevname arguments both "
7211 "required to set device name", __func__);
7216 request = malloc(sizeof(*request));
7217 if (request == NULL) {
7218 warn("%s: unable to allocate %zd bytes", __func__,
7224 response = malloc(sizeof(*response));
7225 if (response == NULL) {
7226 warn("%s: unable to allocate %zd bytes", __func__,
7232 smp_phy_control(&ccb->smpio,
7237 (uint8_t *)response,
7240 /*expected_exp_change_count*/ 0,
7243 (set_pp_timeout_val != 0) ? 1 : 0,
7251 if (((retval = cam_send_ccb(device, ccb)) < 0)
7252 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7253 const char warnstr[] = "error sending command";
7260 if (arglist & CAM_ARG_VERBOSE) {
7262 * Use CAM_EPF_NORMAL so we only get one line of
7263 * SMP command decoding.
7265 cam_error_print(device, ccb, CAM_ESF_ALL,
7266 CAM_EPF_NORMAL, stderr);
7272 /* XXX KDM print out something here for success? */
7277 if (request != NULL)
7280 if (response != NULL)
7287 smpmaninfo(struct cam_device *device, int argc, char **argv,
7288 char *combinedopt, int retry_count, int timeout)
7291 struct smp_report_manuf_info_request request;
7292 struct smp_report_manuf_info_response response;
7293 struct sbuf *sb = NULL;
7294 int long_response = 0;
7299 * Note that at the moment we don't support sending SMP CCBs to
7300 * devices that aren't probed by CAM.
7302 ccb = cam_getccb(device);
7304 warnx("%s: error allocating CCB", __func__);
7308 bzero(&(&ccb->ccb_h)[1],
7309 sizeof(union ccb) - sizeof(struct ccb_hdr));
7311 while ((c = getopt(argc, argv, combinedopt)) != -1) {
7320 bzero(&request, sizeof(request));
7321 bzero(&response, sizeof(response));
7323 smp_report_manuf_info(&ccb->smpio,
7328 (uint8_t *)&response,
7333 if (((retval = cam_send_ccb(device, ccb)) < 0)
7334 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7335 const char warnstr[] = "error sending command";
7342 if (arglist & CAM_ARG_VERBOSE) {
7343 cam_error_print(device, ccb, CAM_ESF_ALL,
7344 CAM_EPF_ALL, stderr);
7350 sb = sbuf_new_auto();
7352 warnx("%s: error allocating sbuf", __func__);
7356 smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
7358 if (sbuf_finish(sb) != 0) {
7359 warnx("%s: sbuf_finish", __func__);
7363 printf("%s", sbuf_data(sb));
7377 getdevid(struct cam_devitem *item)
7380 union ccb *ccb = NULL;
7382 struct cam_device *dev;
7384 dev = cam_open_btl(item->dev_match.path_id,
7385 item->dev_match.target_id,
7386 item->dev_match.target_lun, O_RDWR, NULL);
7389 warnx("%s", cam_errbuf);
7394 item->device_id_len = 0;
7396 ccb = cam_getccb(dev);
7398 warnx("%s: error allocating CCB", __func__);
7403 bzero(&(&ccb->ccb_h)[1],
7404 sizeof(union ccb) - sizeof(struct ccb_hdr));
7407 * On the first try, we just probe for the size of the data, and
7408 * then allocate that much memory and try again.
7411 ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
7412 ccb->ccb_h.flags = CAM_DIR_IN;
7413 ccb->cdai.flags = CDAI_FLAG_NONE;
7414 ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
7415 ccb->cdai.bufsiz = item->device_id_len;
7416 if (item->device_id_len != 0)
7417 ccb->cdai.buf = (uint8_t *)item->device_id;
7419 if (cam_send_ccb(dev, ccb) < 0) {
7420 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
7425 if (ccb->ccb_h.status != CAM_REQ_CMP) {
7426 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
7431 if (item->device_id_len == 0) {
7433 * This is our first time through. Allocate the buffer,
7434 * and then go back to get the data.
7436 if (ccb->cdai.provsiz == 0) {
7437 warnx("%s: invalid .provsiz field returned with "
7438 "XPT_GDEV_ADVINFO CCB", __func__);
7442 item->device_id_len = ccb->cdai.provsiz;
7443 item->device_id = malloc(item->device_id_len);
7444 if (item->device_id == NULL) {
7445 warn("%s: unable to allocate %d bytes", __func__,
7446 item->device_id_len);
7450 ccb->ccb_h.status = CAM_REQ_INPROG;
7456 cam_close_device(dev);
7465 * XXX KDM merge this code with getdevtree()?
7468 buildbusdevlist(struct cam_devlist *devlist)
7471 int bufsize, fd = -1;
7472 struct dev_match_pattern *patterns;
7473 struct cam_devitem *item = NULL;
7474 int skip_device = 0;
7477 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
7478 warn("couldn't open %s", XPT_DEVICE);
7482 bzero(&ccb, sizeof(union ccb));
7484 ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
7485 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
7486 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
7488 ccb.ccb_h.func_code = XPT_DEV_MATCH;
7489 bufsize = sizeof(struct dev_match_result) * 100;
7490 ccb.cdm.match_buf_len = bufsize;
7491 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
7492 if (ccb.cdm.matches == NULL) {
7493 warnx("can't malloc memory for matches");
7497 ccb.cdm.num_matches = 0;
7498 ccb.cdm.num_patterns = 2;
7499 ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
7500 ccb.cdm.num_patterns;
7502 patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
7503 if (patterns == NULL) {
7504 warnx("can't malloc memory for patterns");
7509 ccb.cdm.patterns = patterns;
7510 bzero(patterns, ccb.cdm.pattern_buf_len);
7512 patterns[0].type = DEV_MATCH_DEVICE;
7513 patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
7514 patterns[0].pattern.device_pattern.path_id = devlist->path_id;
7515 patterns[1].type = DEV_MATCH_PERIPH;
7516 patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
7517 patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
7520 * We do the ioctl multiple times if necessary, in case there are
7521 * more than 100 nodes in the EDT.
7526 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
7527 warn("error sending CAMIOCOMMAND ioctl");
7532 if ((ccb.ccb_h.status != CAM_REQ_CMP)
7533 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
7534 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
7535 warnx("got CAM error %#x, CDM error %d\n",
7536 ccb.ccb_h.status, ccb.cdm.status);
7541 for (i = 0; i < ccb.cdm.num_matches; i++) {
7542 switch (ccb.cdm.matches[i].type) {
7543 case DEV_MATCH_DEVICE: {
7544 struct device_match_result *dev_result;
7547 &ccb.cdm.matches[i].result.device_result;
7549 if (dev_result->flags &
7550 DEV_RESULT_UNCONFIGURED) {
7556 item = malloc(sizeof(*item));
7558 warn("%s: unable to allocate %zd bytes",
7559 __func__, sizeof(*item));
7563 bzero(item, sizeof(*item));
7564 bcopy(dev_result, &item->dev_match,
7565 sizeof(*dev_result));
7566 STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
7569 if (getdevid(item) != 0) {
7575 case DEV_MATCH_PERIPH: {
7576 struct periph_match_result *periph_result;
7579 &ccb.cdm.matches[i].result.periph_result;
7581 if (skip_device != 0)
7583 item->num_periphs++;
7584 item->periph_matches = realloc(
7585 item->periph_matches,
7587 sizeof(struct periph_match_result));
7588 if (item->periph_matches == NULL) {
7589 warn("%s: error allocating periph "
7594 bcopy(periph_result, &item->periph_matches[
7595 item->num_periphs - 1],
7596 sizeof(*periph_result));
7600 fprintf(stderr, "%s: unexpected match "
7601 "type %d\n", __func__,
7602 ccb.cdm.matches[i].type);
7605 break; /*NOTREACHED*/
7608 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
7609 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
7617 free(ccb.cdm.matches);
7620 freebusdevlist(devlist);
7626 freebusdevlist(struct cam_devlist *devlist)
7628 struct cam_devitem *item, *item2;
7630 STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
7631 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
7633 free(item->device_id);
7634 free(item->periph_matches);
7639 static struct cam_devitem *
7640 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
7642 struct cam_devitem *item;
7644 STAILQ_FOREACH(item, &devlist->dev_queue, links) {
7645 struct scsi_vpd_id_descriptor *idd;
7648 * XXX KDM look for LUN IDs as well?
7650 idd = scsi_get_devid(item->device_id,
7651 item->device_id_len,
7652 scsi_devid_is_sas_target);
7656 if (scsi_8btou64(idd->identifier) == sasaddr)
7664 smpphylist(struct cam_device *device, int argc, char **argv,
7665 char *combinedopt, int retry_count, int timeout)
7667 struct smp_report_general_request *rgrequest = NULL;
7668 struct smp_report_general_response *rgresponse = NULL;
7669 struct smp_discover_request *disrequest = NULL;
7670 struct smp_discover_response *disresponse = NULL;
7671 struct cam_devlist devlist;
7673 int long_response = 0;
7680 * Note that at the moment we don't support sending SMP CCBs to
7681 * devices that aren't probed by CAM.
7683 ccb = cam_getccb(device);
7685 warnx("%s: error allocating CCB", __func__);
7689 bzero(&(&ccb->ccb_h)[1],
7690 sizeof(union ccb) - sizeof(struct ccb_hdr));
7691 STAILQ_INIT(&devlist.dev_queue);
7693 rgrequest = malloc(sizeof(*rgrequest));
7694 if (rgrequest == NULL) {
7695 warn("%s: unable to allocate %zd bytes", __func__,
7696 sizeof(*rgrequest));
7701 rgresponse = malloc(sizeof(*rgresponse));
7702 if (rgresponse == NULL) {
7703 warn("%s: unable to allocate %zd bytes", __func__,
7704 sizeof(*rgresponse));
7709 while ((c = getopt(argc, argv, combinedopt)) != -1) {
7722 smp_report_general(&ccb->smpio,
7726 /*request_len*/ sizeof(*rgrequest),
7727 (uint8_t *)rgresponse,
7728 /*response_len*/ sizeof(*rgresponse),
7729 /*long_response*/ long_response,
7732 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7734 if (((retval = cam_send_ccb(device, ccb)) < 0)
7735 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7736 const char warnstr[] = "error sending command";
7743 if (arglist & CAM_ARG_VERBOSE) {
7744 cam_error_print(device, ccb, CAM_ESF_ALL,
7745 CAM_EPF_ALL, stderr);
7751 num_phys = rgresponse->num_phys;
7753 if (num_phys == 0) {
7755 fprintf(stdout, "%s: No Phys reported\n", __func__);
7760 devlist.path_id = device->path_id;
7762 retval = buildbusdevlist(&devlist);
7767 fprintf(stdout, "%d PHYs:\n", num_phys);
7768 fprintf(stdout, "PHY Attached SAS Address\n");
7771 disrequest = malloc(sizeof(*disrequest));
7772 if (disrequest == NULL) {
7773 warn("%s: unable to allocate %zd bytes", __func__,
7774 sizeof(*disrequest));
7779 disresponse = malloc(sizeof(*disresponse));
7780 if (disresponse == NULL) {
7781 warn("%s: unable to allocate %zd bytes", __func__,
7782 sizeof(*disresponse));
7787 for (i = 0; i < num_phys; i++) {
7788 struct cam_devitem *item;
7789 struct device_match_result *dev_match;
7790 char vendor[16], product[48], revision[16];
7794 bzero(&(&ccb->ccb_h)[1],
7795 sizeof(union ccb) - sizeof(struct ccb_hdr));
7797 ccb->ccb_h.status = CAM_REQ_INPROG;
7798 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7800 smp_discover(&ccb->smpio,
7804 sizeof(*disrequest),
7805 (uint8_t *)disresponse,
7806 sizeof(*disresponse),
7808 /*ignore_zone_group*/ 0,
7812 if (((retval = cam_send_ccb(device, ccb)) < 0)
7813 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
7814 && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
7815 const char warnstr[] = "error sending command";
7822 if (arglist & CAM_ARG_VERBOSE) {
7823 cam_error_print(device, ccb, CAM_ESF_ALL,
7824 CAM_EPF_ALL, stderr);
7830 if (disresponse->function_result == SMP_FR_PHY_VACANT) {
7832 fprintf(stdout, "%3d <vacant>\n", i);
7836 if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) {
7839 item = findsasdevice(&devlist,
7840 scsi_8btou64(disresponse->attached_sas_address));
7844 || (item != NULL)) {
7845 fprintf(stdout, "%3d 0x%016jx", i,
7846 (uintmax_t)scsi_8btou64(
7847 disresponse->attached_sas_address));
7849 fprintf(stdout, "\n");
7852 } else if (quiet != 0)
7855 dev_match = &item->dev_match;
7857 if (dev_match->protocol == PROTO_SCSI) {
7858 cam_strvis(vendor, dev_match->inq_data.vendor,
7859 sizeof(dev_match->inq_data.vendor),
7861 cam_strvis(product, dev_match->inq_data.product,
7862 sizeof(dev_match->inq_data.product),
7864 cam_strvis(revision, dev_match->inq_data.revision,
7865 sizeof(dev_match->inq_data.revision),
7867 sprintf(tmpstr, "<%s %s %s>", vendor, product,
7869 } else if ((dev_match->protocol == PROTO_ATA)
7870 || (dev_match->protocol == PROTO_SATAPM)) {
7871 cam_strvis(product, dev_match->ident_data.model,
7872 sizeof(dev_match->ident_data.model),
7874 cam_strvis(revision, dev_match->ident_data.revision,
7875 sizeof(dev_match->ident_data.revision),
7877 sprintf(tmpstr, "<%s %s>", product, revision);
7879 sprintf(tmpstr, "<>");
7881 fprintf(stdout, " %-33s ", tmpstr);
7884 * If we have 0 periphs, that's a bug...
7886 if (item->num_periphs == 0) {
7887 fprintf(stdout, "\n");
7891 fprintf(stdout, "(");
7892 for (j = 0; j < item->num_periphs; j++) {
7894 fprintf(stdout, ",");
7896 fprintf(stdout, "%s%d",
7897 item->periph_matches[j].periph_name,
7898 item->periph_matches[j].unit_number);
7901 fprintf(stdout, ")\n");
7915 freebusdevlist(&devlist);
7921 atapm(struct cam_device *device, int argc, char **argv,
7922 char *combinedopt, int retry_count, int timeout)
7930 ccb = cam_getccb(device);
7933 warnx("%s: error allocating ccb", __func__);
7937 while ((c = getopt(argc, argv, combinedopt)) != -1) {
7946 if (strcmp(argv[1], "idle") == 0) {
7948 cmd = ATA_IDLE_IMMEDIATE;
7951 } else if (strcmp(argv[1], "standby") == 0) {
7953 cmd = ATA_STANDBY_IMMEDIATE;
7955 cmd = ATA_STANDBY_CMD;
7963 else if (t <= (240 * 5))
7965 else if (t <= (252 * 5))
7966 /* special encoding for 21 minutes */
7968 else if (t <= (11 * 30 * 60))
7969 sc = (t - 1) / (30 * 60) + 241;
7973 retval = ata_do_28bit_cmd(device,
7975 /*retries*/retry_count,
7976 /*flags*/CAM_DIR_NONE,
7977 /*protocol*/AP_PROTO_NON_DATA,
7978 /*tag_action*/MSG_SIMPLE_Q_TAG,
7985 /*timeout*/timeout ? timeout : 30 * 1000,
7993 ataaxm(struct cam_device *device, int argc, char **argv,
7994 char *combinedopt, int retry_count, int timeout)
8002 ccb = cam_getccb(device);
8005 warnx("%s: error allocating ccb", __func__);
8009 while ((c = getopt(argc, argv, combinedopt)) != -1) {
8019 if (strcmp(argv[1], "apm") == 0) {
8035 retval = ata_do_28bit_cmd(device,
8037 /*retries*/retry_count,
8038 /*flags*/CAM_DIR_NONE,
8039 /*protocol*/AP_PROTO_NON_DATA,
8040 /*tag_action*/MSG_SIMPLE_Q_TAG,
8041 /*command*/ATA_SETFEATURES,
8047 /*timeout*/timeout ? timeout : 30 * 1000,
8054 #endif /* MINIMALISTIC */
8057 usage(int printlong)
8060 fprintf(printlong ? stdout : stderr,
8061 "usage: camcontrol <command> [device id][generic args][command args]\n"
8062 " camcontrol devlist [-b] [-v]\n"
8063 #ifndef MINIMALISTIC
8064 " camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
8065 " camcontrol tur [dev_id][generic args]\n"
8066 " camcontrol inquiry [dev_id][generic args] [-D] [-S] [-R]\n"
8067 " camcontrol identify [dev_id][generic args] [-v]\n"
8068 " camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
8069 " camcontrol readcap [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
8071 " camcontrol start [dev_id][generic args]\n"
8072 " camcontrol stop [dev_id][generic args]\n"
8073 " camcontrol load [dev_id][generic args]\n"
8074 " camcontrol eject [dev_id][generic args]\n"
8075 #endif /* MINIMALISTIC */
8076 " camcontrol rescan <all | bus[:target:lun]>\n"
8077 " camcontrol reset <all | bus[:target:lun]>\n"
8078 #ifndef MINIMALISTIC
8079 " camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n"
8080 " [-q][-s][-S offset][-X]\n"
8081 " camcontrol modepage [dev_id][generic args] <-m page | -l>\n"
8082 " [-P pagectl][-e | -b][-d]\n"
8083 " camcontrol cmd [dev_id][generic args]\n"
8084 " <-a cmd [args] | -c cmd [args]>\n"
8085 " [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
8086 " camcontrol smpcmd [dev_id][generic args]\n"
8087 " <-r len fmt [args]> <-R len fmt [args]>\n"
8088 " camcontrol smprg [dev_id][generic args][-l]\n"
8089 " camcontrol smppc [dev_id][generic args] <-p phy> [-l]\n"
8090 " [-o operation][-d name][-m rate][-M rate]\n"
8091 " [-T pp_timeout][-a enable|disable]\n"
8092 " [-A enable|disable][-s enable|disable]\n"
8093 " [-S enable|disable]\n"
8094 " camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
8095 " camcontrol smpmaninfo [dev_id][generic args][-l]\n"
8096 " camcontrol debug [-I][-P][-T][-S][-X][-c]\n"
8097 " <all|bus[:target[:lun]]|off>\n"
8098 " camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n"
8099 " camcontrol negotiate [dev_id][generic args] [-a][-c]\n"
8100 " [-D <enable|disable>][-M mode][-O offset]\n"
8101 " [-q][-R syncrate][-v][-T <enable|disable>]\n"
8102 " [-U][-W bus_width]\n"
8103 " camcontrol format [dev_id][generic args][-q][-r][-w][-y]\n"
8104 " camcontrol sanitize [dev_id][generic args]\n"
8105 " [-a overwrite|block|crypto|exitfailure]\n"
8106 " [-c passes][-I][-P pattern][-q][-U][-r][-w]\n"
8108 " camcontrol idle [dev_id][generic args][-t time]\n"
8109 " camcontrol standby [dev_id][generic args][-t time]\n"
8110 " camcontrol sleep [dev_id][generic args]\n"
8111 " camcontrol apm [dev_id][generic args][-l level]\n"
8112 " camcontrol aam [dev_id][generic args][-l level]\n"
8113 " camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-y][-s]\n"
8114 " camcontrol security [dev_id][generic args]\n"
8115 " <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
8116 " [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
8117 " [-U <user|master>] [-y]\n"
8118 " camcontrol hpa [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n"
8119 " [-q] [-s max_sectors] [-U pwd] [-y]\n"
8120 " camcontrol persist [dev_id][generic args] <-i action|-o action>\n"
8121 " [-a][-I tid][-k key][-K sa_key][-p][-R rtp]\n"
8122 " [-s scope][-S][-T type][-U]\n"
8123 " camcontrol attrib [dev_id][generic args] <-r action|-w attr>\n"
8124 " [-a attr_num][-c][-e elem][-F form1,form1]\n"
8125 " [-p part][-s start][-T type][-V vol]\n"
8126 #endif /* MINIMALISTIC */
8127 " camcontrol help\n");
8130 #ifndef MINIMALISTIC
8132 "Specify one of the following options:\n"
8133 "devlist list all CAM devices\n"
8134 "periphlist list all CAM peripheral drivers attached to a device\n"
8135 "tur send a test unit ready to the named device\n"
8136 "inquiry send a SCSI inquiry command to the named device\n"
8137 "identify send a ATA identify command to the named device\n"
8138 "reportluns send a SCSI report luns command to the device\n"
8139 "readcap send a SCSI read capacity command to the device\n"
8140 "start send a Start Unit command to the device\n"
8141 "stop send a Stop Unit command to the device\n"
8142 "load send a Start Unit command to the device with the load bit set\n"
8143 "eject send a Stop Unit command to the device with the eject bit set\n"
8144 "rescan rescan all busses, the given bus, or bus:target:lun\n"
8145 "reset reset all busses, the given bus, or bus:target:lun\n"
8146 "defects read the defect list of the specified device\n"
8147 "modepage display or edit (-e) the given mode page\n"
8148 "cmd send the given SCSI command, may need -i or -o as well\n"
8149 "smpcmd send the given SMP command, requires -o and -i\n"
8150 "smprg send the SMP Report General command\n"
8151 "smppc send the SMP PHY Control command, requires -p\n"
8152 "smpphylist display phys attached to a SAS expander\n"
8153 "smpmaninfo send the SMP Report Manufacturer Info command\n"
8154 "debug turn debugging on/off for a bus, target, or lun, or all devices\n"
8155 "tags report or set the number of transaction slots for a device\n"
8156 "negotiate report or set device negotiation parameters\n"
8157 "format send the SCSI FORMAT UNIT command to the named device\n"
8158 "sanitize send the SCSI SANITIZE command to the named device\n"
8159 "idle send the ATA IDLE command to the named device\n"
8160 "standby send the ATA STANDBY command to the named device\n"
8161 "sleep send the ATA SLEEP command to the named device\n"
8162 "fwdownload program firmware of the named device with the given image\n"
8163 "security report or send ATA security commands to the named device\n"
8164 "persist send the SCSI PERSISTENT RESERVE IN or OUT commands\n"
8165 "attrib send the SCSI READ or WRITE ATTRIBUTE commands\n"
8166 "help this message\n"
8167 "Device Identifiers:\n"
8168 "bus:target specify the bus and target, lun defaults to 0\n"
8169 "bus:target:lun specify the bus, target and lun\n"
8170 "deviceUNIT specify the device name, like \"da4\" or \"cd2\"\n"
8171 "Generic arguments:\n"
8172 "-v be verbose, print out sense information\n"
8173 "-t timeout command timeout in seconds, overrides default timeout\n"
8174 "-n dev_name specify device name, e.g. \"da\", \"cd\"\n"
8175 "-u unit specify unit number, e.g. \"0\", \"5\"\n"
8176 "-E have the kernel attempt to perform SCSI error recovery\n"
8177 "-C count specify the SCSI command retry count (needs -E to work)\n"
8178 "modepage arguments:\n"
8179 "-l list all available mode pages\n"
8180 "-m page specify the mode page to view or edit\n"
8181 "-e edit the specified mode page\n"
8182 "-b force view to binary mode\n"
8183 "-d disable block descriptors for mode sense\n"
8184 "-P pgctl page control field 0-3\n"
8185 "defects arguments:\n"
8186 "-f format specify defect list format (block, bfi or phys)\n"
8187 "-G get the grown defect list\n"
8188 "-P get the permanent defect list\n"
8189 "inquiry arguments:\n"
8190 "-D get the standard inquiry data\n"
8191 "-S get the serial number\n"
8192 "-R get the transfer rate, etc.\n"
8193 "reportluns arguments:\n"
8194 "-c only report a count of available LUNs\n"
8195 "-l only print out luns, and not a count\n"
8196 "-r <reporttype> specify \"default\", \"wellknown\" or \"all\"\n"
8197 "readcap arguments\n"
8198 "-b only report the blocksize\n"
8199 "-h human readable device size, base 2\n"
8200 "-H human readable device size, base 10\n"
8201 "-N print the number of blocks instead of last block\n"
8202 "-q quiet, print numbers only\n"
8203 "-s only report the last block/device size\n"
8205 "-c cdb [args] specify the SCSI CDB\n"
8206 "-i len fmt specify input data and input data format\n"
8207 "-o len fmt [args] specify output data and output data fmt\n"
8208 "smpcmd arguments:\n"
8209 "-r len fmt [args] specify the SMP command to be sent\n"
8210 "-R len fmt [args] specify SMP response format\n"
8211 "smprg arguments:\n"
8212 "-l specify the long response format\n"
8213 "smppc arguments:\n"
8214 "-p phy specify the PHY to operate on\n"
8215 "-l specify the long request/response format\n"
8216 "-o operation specify the phy control operation\n"
8217 "-d name set the attached device name\n"
8218 "-m rate set the minimum physical link rate\n"
8219 "-M rate set the maximum physical link rate\n"
8220 "-T pp_timeout set the partial pathway timeout value\n"
8221 "-a enable|disable enable or disable SATA slumber\n"
8222 "-A enable|disable enable or disable SATA partial phy power\n"
8223 "-s enable|disable enable or disable SAS slumber\n"
8224 "-S enable|disable enable or disable SAS partial phy power\n"
8225 "smpphylist arguments:\n"
8226 "-l specify the long response format\n"
8227 "-q only print phys with attached devices\n"
8228 "smpmaninfo arguments:\n"
8229 "-l specify the long response format\n"
8230 "debug arguments:\n"
8231 "-I CAM_DEBUG_INFO -- scsi commands, errors, data\n"
8232 "-T CAM_DEBUG_TRACE -- routine flow tracking\n"
8233 "-S CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
8234 "-c CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
8236 "-N tags specify the number of tags to use for this device\n"
8237 "-q be quiet, don't report the number of tags\n"
8238 "-v report a number of tag-related parameters\n"
8239 "negotiate arguments:\n"
8240 "-a send a test unit ready after negotiation\n"
8241 "-c report/set current negotiation settings\n"
8242 "-D <arg> \"enable\" or \"disable\" disconnection\n"
8243 "-M mode set ATA mode\n"
8244 "-O offset set command delay offset\n"
8245 "-q be quiet, don't report anything\n"
8246 "-R syncrate synchronization rate in MHz\n"
8247 "-T <arg> \"enable\" or \"disable\" tagged queueing\n"
8248 "-U report/set user negotiation settings\n"
8249 "-W bus_width set the bus width in bits (8, 16 or 32)\n"
8250 "-v also print a Path Inquiry CCB for the controller\n"
8251 "format arguments:\n"
8252 "-q be quiet, don't print status messages\n"
8253 "-r run in report only mode\n"
8254 "-w don't send immediate format command\n"
8255 "-y don't ask any questions\n"
8256 "sanitize arguments:\n"
8257 "-a operation operation mode: overwrite, block, crypto or exitfailure\n"
8258 "-c passes overwrite passes to perform (1 to 31)\n"
8259 "-I invert overwrite pattern after each pass\n"
8260 "-P pattern path to overwrite pattern file\n"
8261 "-q be quiet, don't print status messages\n"
8262 "-r run in report only mode\n"
8263 "-U run operation in unrestricted completion exit mode\n"
8264 "-w don't send immediate sanitize command\n"
8265 "-y don't ask any questions\n"
8266 "idle/standby arguments:\n"
8267 "-t <arg> number of seconds before respective state.\n"
8268 "fwdownload arguments:\n"
8269 "-f fw_image path to firmware image file\n"
8270 "-y don't ask any questions\n"
8271 "-s run in simulation mode\n"
8272 "-v print info for every firmware segment sent to device\n"
8273 "security arguments:\n"
8274 "-d pwd disable security using the given password for the selected\n"
8276 "-e pwd erase the device using the given pwd for the selected user\n"
8277 "-f freeze the security configuration of the specified device\n"
8278 "-h pwd enhanced erase the device using the given pwd for the\n"
8280 "-k pwd unlock the device using the given pwd for the selected\n"
8282 "-l <high|maximum> specifies which security level to set: high or maximum\n"
8283 "-q be quiet, do not print any status messages\n"
8284 "-s pwd password the device (enable security) using the given\n"
8285 " pwd for the selected user\n"
8286 "-T timeout overrides the timeout (seconds) used for erase operation\n"
8287 "-U <user|master> specifies which user to set: user or master\n"
8288 "-y don't ask any questions\n"
8290 "-f freeze the HPA configuration of the device\n"
8291 "-l lock the HPA configuration of the device\n"
8292 "-P make the HPA max sectors persist\n"
8293 "-p pwd Set the HPA configuration password required for unlock\n"
8295 "-q be quiet, do not print any status messages\n"
8296 "-s sectors configures the maximum user accessible sectors of the\n"
8298 "-U pwd unlock the HPA configuration of the device\n"
8299 "-y don't ask any questions\n"
8300 "persist arguments:\n"
8301 "-i action specify read_keys, read_reservation, report_cap, or\n"
8302 " read_full_status\n"
8303 "-o action specify register, register_ignore, reserve, release,\n"
8304 " clear, preempt, preempt_abort, register_move, replace_lost\n"
8305 "-a set the All Target Ports (ALL_TG_PT) bit\n"
8306 "-I tid specify a Transport ID, e.g.: sas,0x1234567812345678\n"
8307 "-k key specify the Reservation Key\n"
8308 "-K sa_key specify the Service Action Reservation Key\n"
8309 "-p set the Activate Persist Through Power Loss bit\n"
8310 "-R rtp specify the Relative Target Port\n"
8311 "-s scope specify the scope: lun, extent, element or a number\n"
8312 "-S specify Transport ID for register, requires -I\n"
8313 "-T res_type specify the reservation type: read_shared, wr_ex, rd_ex,\n"
8314 " ex_ac, wr_ex_ro, ex_ac_ro, wr_ex_ar, ex_ac_ar\n"
8315 "-U unregister the current initiator for register_move\n"
8316 "attrib arguments:\n"
8317 "-r action specify attr_values, attr_list, lv_list, part_list, or\n"
8319 "-w attr specify an attribute to write, one -w argument per attr\n"
8320 "-a attr_num only display this attribute number\n"
8321 "-c get cached attributes\n"
8322 "-e elem_addr request attributes for the given element in a changer\n"
8323 "-F form1,form2 output format, comma separated list: text_esc, text_raw,\n"
8324 " nonascii_esc, nonascii_trim, nonascii_raw, field_all,\n"
8325 " field_none, field_desc, field_num, field_size, field_rw\n"
8326 "-p partition request attributes for the given partition\n"
8327 "-s start_attr request attributes starting at the given number\n"
8328 "-T elem_type specify the element type (used with -e)\n"
8329 "-V logical_vol specify the logical volume ID\n"
8331 #endif /* MINIMALISTIC */
8335 main(int argc, char **argv)
8338 char *device = NULL;
8340 struct cam_device *cam_dev = NULL;
8341 int timeout = 0, retry_count = 1;
8342 camcontrol_optret optreturn;
8344 const char *mainopt = "C:En:t:u:v";
8345 const char *subopt = NULL;
8346 char combinedopt[256];
8347 int error = 0, optstart = 2;
8349 #ifndef MINIMALISTIC
8353 #endif /* MINIMALISTIC */
8355 cmdlist = CAM_CMD_NONE;
8356 arglist = CAM_ARG_NONE;
8364 * Get the base option.
8366 optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
8368 if (optreturn == CC_OR_AMBIGUOUS) {
8369 warnx("ambiguous option %s", argv[1]);
8372 } else if (optreturn == CC_OR_NOT_FOUND) {
8373 warnx("option %s not found", argv[1]);
8379 * Ahh, getopt(3) is a pain.
8381 * This is a gross hack. There really aren't many other good
8382 * options (excuse the pun) for parsing options in a situation like
8383 * this. getopt is kinda braindead, so you end up having to run
8384 * through the options twice, and give each invocation of getopt
8385 * the option string for the other invocation.
8387 * You would think that you could just have two groups of options.
8388 * The first group would get parsed by the first invocation of
8389 * getopt, and the second group would get parsed by the second
8390 * invocation of getopt. It doesn't quite work out that way. When
8391 * the first invocation of getopt finishes, it leaves optind pointing
8392 * to the argument _after_ the first argument in the second group.
8393 * So when the second invocation of getopt comes around, it doesn't
8394 * recognize the first argument it gets and then bails out.
8396 * A nice alternative would be to have a flag for getopt that says
8397 * "just keep parsing arguments even when you encounter an unknown
8398 * argument", but there isn't one. So there's no real clean way to
8399 * easily parse two sets of arguments without having one invocation
8400 * of getopt know about the other.
8402 * Without this hack, the first invocation of getopt would work as
8403 * long as the generic arguments are first, but the second invocation
8404 * (in the subfunction) would fail in one of two ways. In the case
8405 * where you don't set optreset, it would fail because optind may be
8406 * pointing to the argument after the one it should be pointing at.
8407 * In the case where you do set optreset, and reset optind, it would
8408 * fail because getopt would run into the first set of options, which
8409 * it doesn't understand.
8411 * All of this would "sort of" work if you could somehow figure out
8412 * whether optind had been incremented one option too far. The
8413 * mechanics of that, however, are more daunting than just giving
8414 * both invocations all of the expect options for either invocation.
8416 * Needless to say, I wouldn't mind if someone invented a better
8417 * (non-GPL!) command line parsing interface than getopt. I
8418 * wouldn't mind if someone added more knobs to getopt to make it
8419 * work better. Who knows, I may talk myself into doing it someday,
8420 * if the standards weenies let me. As it is, it just leads to
8421 * hackery like this and causes people to avoid it in some cases.
8423 * KDM, September 8th, 1998
8426 sprintf(combinedopt, "%s%s", mainopt, subopt);
8428 sprintf(combinedopt, "%s", mainopt);
8431 * For these options we do not parse optional device arguments and
8432 * we do not open a passthrough device.
8434 if ((cmdlist == CAM_CMD_RESCAN)
8435 || (cmdlist == CAM_CMD_RESET)
8436 || (cmdlist == CAM_CMD_DEVTREE)
8437 || (cmdlist == CAM_CMD_USAGE)
8438 || (cmdlist == CAM_CMD_DEBUG))
8441 #ifndef MINIMALISTIC
8443 && (argc > 2 && argv[2][0] != '-')) {
8447 if (isdigit(argv[2][0])) {
8448 /* device specified as bus:target[:lun] */
8449 rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
8451 errx(1, "numeric device specification must "
8452 "be either bus:target, or "
8454 /* default to 0 if lun was not specified */
8455 if ((arglist & CAM_ARG_LUN) == 0) {
8457 arglist |= CAM_ARG_LUN;
8461 if (cam_get_device(argv[2], name, sizeof name, &unit)
8463 errx(1, "%s", cam_errbuf);
8464 device = strdup(name);
8465 arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
8469 #endif /* MINIMALISTIC */
8471 * Start getopt processing at argv[2/3], since we've already
8472 * accepted argv[1..2] as the command name, and as a possible
8478 * Now we run through the argument list looking for generic
8479 * options, and ignoring options that possibly belong to
8482 while ((c = getopt(argc, argv, combinedopt))!= -1){
8485 retry_count = strtol(optarg, NULL, 0);
8486 if (retry_count < 0)
8487 errx(1, "retry count %d is < 0",
8489 arglist |= CAM_ARG_RETRIES;
8492 arglist |= CAM_ARG_ERR_RECOVER;
8495 arglist |= CAM_ARG_DEVICE;
8497 while (isspace(*tstr) && (*tstr != '\0'))
8499 device = (char *)strdup(tstr);
8502 timeout = strtol(optarg, NULL, 0);
8504 errx(1, "invalid timeout %d", timeout);
8505 /* Convert the timeout from seconds to ms */
8507 arglist |= CAM_ARG_TIMEOUT;
8510 arglist |= CAM_ARG_UNIT;
8511 unit = strtol(optarg, NULL, 0);
8514 arglist |= CAM_ARG_VERBOSE;
8521 #ifndef MINIMALISTIC
8523 * For most commands we'll want to open the passthrough device
8524 * associated with the specified device. In the case of the rescan
8525 * commands, we don't use a passthrough device at all, just the
8526 * transport layer device.
8529 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
8530 && (((arglist & CAM_ARG_DEVICE) == 0)
8531 || ((arglist & CAM_ARG_UNIT) == 0))) {
8532 errx(1, "subcommand \"%s\" requires a valid device "
8533 "identifier", argv[1]);
8536 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
8537 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
8538 cam_open_spec_device(device,unit,O_RDWR,NULL)))
8540 errx(1,"%s", cam_errbuf);
8542 #endif /* MINIMALISTIC */
8545 * Reset optind to 2, and reset getopt, so these routines can parse
8546 * the arguments again.
8552 #ifndef MINIMALISTIC
8553 case CAM_CMD_DEVLIST:
8554 error = getdevlist(cam_dev);
8557 error = atahpa(cam_dev, retry_count, timeout,
8558 argc, argv, combinedopt);
8560 #endif /* MINIMALISTIC */
8561 case CAM_CMD_DEVTREE:
8562 error = getdevtree(argc, argv, combinedopt);
8564 #ifndef MINIMALISTIC
8566 error = testunitready(cam_dev, retry_count, timeout, 0);
8568 case CAM_CMD_INQUIRY:
8569 error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
8570 retry_count, timeout);
8572 case CAM_CMD_IDENTIFY:
8573 error = ataidentify(cam_dev, retry_count, timeout);
8575 case CAM_CMD_STARTSTOP:
8576 error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
8577 arglist & CAM_ARG_EJECT, retry_count,
8580 #endif /* MINIMALISTIC */
8581 case CAM_CMD_RESCAN:
8582 error = dorescan_or_reset(argc, argv, 1);
8585 error = dorescan_or_reset(argc, argv, 0);
8587 #ifndef MINIMALISTIC
8588 case CAM_CMD_READ_DEFECTS:
8589 error = readdefects(cam_dev, argc, argv, combinedopt,
8590 retry_count, timeout);
8592 case CAM_CMD_MODE_PAGE:
8593 modepage(cam_dev, argc, argv, combinedopt,
8594 retry_count, timeout);
8596 case CAM_CMD_SCSI_CMD:
8597 error = scsicmd(cam_dev, argc, argv, combinedopt,
8598 retry_count, timeout);
8600 case CAM_CMD_SMP_CMD:
8601 error = smpcmd(cam_dev, argc, argv, combinedopt,
8602 retry_count, timeout);
8604 case CAM_CMD_SMP_RG:
8605 error = smpreportgeneral(cam_dev, argc, argv,
8606 combinedopt, retry_count,
8609 case CAM_CMD_SMP_PC:
8610 error = smpphycontrol(cam_dev, argc, argv, combinedopt,
8611 retry_count, timeout);
8613 case CAM_CMD_SMP_PHYLIST:
8614 error = smpphylist(cam_dev, argc, argv, combinedopt,
8615 retry_count, timeout);
8617 case CAM_CMD_SMP_MANINFO:
8618 error = smpmaninfo(cam_dev, argc, argv, combinedopt,
8619 retry_count, timeout);
8622 error = camdebug(argc, argv, combinedopt);
8625 error = tagcontrol(cam_dev, argc, argv, combinedopt);
8628 error = ratecontrol(cam_dev, retry_count, timeout,
8629 argc, argv, combinedopt);
8631 case CAM_CMD_FORMAT:
8632 error = scsiformat(cam_dev, argc, argv,
8633 combinedopt, retry_count, timeout);
8635 case CAM_CMD_REPORTLUNS:
8636 error = scsireportluns(cam_dev, argc, argv,
8637 combinedopt, retry_count,
8640 case CAM_CMD_READCAP:
8641 error = scsireadcapacity(cam_dev, argc, argv,
8642 combinedopt, retry_count,
8646 case CAM_CMD_STANDBY:
8648 error = atapm(cam_dev, argc, argv,
8649 combinedopt, retry_count, timeout);
8653 error = ataaxm(cam_dev, argc, argv,
8654 combinedopt, retry_count, timeout);
8656 case CAM_CMD_SECURITY:
8657 error = atasecurity(cam_dev, retry_count, timeout,
8658 argc, argv, combinedopt);
8660 case CAM_CMD_DOWNLOAD_FW:
8661 error = fwdownload(cam_dev, argc, argv, combinedopt,
8662 arglist & CAM_ARG_VERBOSE, retry_count, timeout,
8663 get_disk_type(cam_dev));
8665 case CAM_CMD_SANITIZE:
8666 error = scsisanitize(cam_dev, argc, argv,
8667 combinedopt, retry_count, timeout);
8669 case CAM_CMD_PERSIST:
8670 error = scsipersist(cam_dev, argc, argv, combinedopt,
8671 retry_count, timeout, arglist & CAM_ARG_VERBOSE,
8672 arglist & CAM_ARG_ERR_RECOVER);
8674 case CAM_CMD_ATTRIB:
8675 error = scsiattrib(cam_dev, argc, argv, combinedopt,
8676 retry_count, timeout, arglist & CAM_ARG_VERBOSE,
8677 arglist & CAM_ARG_ERR_RECOVER);
8679 #endif /* MINIMALISTIC */
8689 if (cam_dev != NULL)
8690 cam_close_device(cam_dev);