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
103 CAM_ARG_NONE = 0x00000000,
104 CAM_ARG_VERBOSE = 0x00000001,
105 CAM_ARG_DEVICE = 0x00000002,
106 CAM_ARG_BUS = 0x00000004,
107 CAM_ARG_TARGET = 0x00000008,
108 CAM_ARG_LUN = 0x00000010,
109 CAM_ARG_EJECT = 0x00000020,
110 CAM_ARG_UNIT = 0x00000040,
111 CAM_ARG_FORMAT_BLOCK = 0x00000080,
112 CAM_ARG_FORMAT_BFI = 0x00000100,
113 CAM_ARG_FORMAT_PHYS = 0x00000200,
114 CAM_ARG_PLIST = 0x00000400,
115 CAM_ARG_GLIST = 0x00000800,
116 CAM_ARG_GET_SERIAL = 0x00001000,
117 CAM_ARG_GET_STDINQ = 0x00002000,
118 CAM_ARG_GET_XFERRATE = 0x00004000,
119 CAM_ARG_INQ_MASK = 0x00007000,
120 CAM_ARG_MODE_EDIT = 0x00008000,
121 CAM_ARG_PAGE_CNTL = 0x00010000,
122 CAM_ARG_TIMEOUT = 0x00020000,
123 CAM_ARG_CMD_IN = 0x00040000,
124 CAM_ARG_CMD_OUT = 0x00080000,
125 CAM_ARG_DBD = 0x00100000,
126 CAM_ARG_ERR_RECOVER = 0x00200000,
127 CAM_ARG_RETRIES = 0x00400000,
128 CAM_ARG_START_UNIT = 0x00800000,
129 CAM_ARG_DEBUG_INFO = 0x01000000,
130 CAM_ARG_DEBUG_TRACE = 0x02000000,
131 CAM_ARG_DEBUG_SUBTRACE = 0x04000000,
132 CAM_ARG_DEBUG_CDB = 0x08000000,
133 CAM_ARG_DEBUG_XPT = 0x10000000,
134 CAM_ARG_DEBUG_PERIPH = 0x20000000,
135 CAM_ARG_DEBUG_PROBE = 0x40000000,
138 struct camcontrol_opts {
146 struct ata_res_pass16 {
147 u_int16_t reserved[5];
150 u_int8_t sector_count_exp;
151 u_int8_t sector_count;
152 u_int8_t lba_low_exp;
154 u_int8_t lba_mid_exp;
156 u_int8_t lba_high_exp;
162 struct ata_set_max_pwd
165 u_int8_t password[32];
166 u_int16_t reserved2[239];
169 static const char scsicmd_opts[] = "a:c:dfi:o:r";
170 static const char readdefect_opts[] = "f:GPqsS:X";
171 static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
172 static const char smprg_opts[] = "l";
173 static const char smppc_opts[] = "a:A:d:lm:M:o:p:s:S:T:";
174 static const char smpphylist_opts[] = "lq";
178 static struct camcontrol_opts option_table[] = {
180 {"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
181 {"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
182 {"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
183 {"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
184 {"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
185 {"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
186 {"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
187 {"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
188 {"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"},
189 #endif /* MINIMALISTIC */
190 {"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
191 {"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
193 {"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
194 {"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
195 {"smpcmd", CAM_CMD_SMP_CMD, CAM_ARG_NONE, "r:R:"},
196 {"smprg", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
197 {"smpreportgeneral", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
198 {"smppc", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
199 {"smpphycontrol", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
200 {"smpplist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
201 {"smpphylist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
202 {"smpmaninfo", CAM_CMD_SMP_MANINFO, CAM_ARG_NONE, "l"},
203 {"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
204 {"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
205 #endif /* MINIMALISTIC */
206 {"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, "-b"},
208 {"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
209 {"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
210 {"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
211 {"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
212 {"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
213 {"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXcp"},
214 {"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
215 {"sanitize", CAM_CMD_SANITIZE, CAM_ARG_NONE, "a:c:IP:qrUwy"},
216 {"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"},
217 {"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"},
218 {"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""},
219 {"fwdownload", CAM_CMD_DOWNLOAD_FW, CAM_ARG_NONE, "f:ys"},
220 {"security", CAM_CMD_SECURITY, CAM_ARG_NONE, "d:e:fh:k:l:qs:T:U:y"},
221 {"hpa", CAM_CMD_HPA, CAM_ARG_NONE, "Pflp:qs:U:y"},
222 {"persist", CAM_CMD_PERSIST, CAM_ARG_NONE, "ai:I:k:K:o:ps:ST:U"},
223 #endif /* MINIMALISTIC */
224 {"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
225 {"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
226 {"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
231 struct device_match_result dev_match;
233 struct periph_match_result *periph_matches;
234 struct scsi_vpd_device_id *device_id;
236 STAILQ_ENTRY(cam_devitem) links;
240 STAILQ_HEAD(, cam_devitem) dev_queue;
244 static cam_cmdmask cmdlist;
245 static cam_argmask arglist;
247 camcontrol_optret getoption(struct camcontrol_opts *table, char *arg,
248 uint32_t *cmdnum, cam_argmask *argnum,
249 const char **subopt);
251 static int getdevlist(struct cam_device *device);
252 #endif /* MINIMALISTIC */
253 static int getdevtree(int argc, char **argv, char *combinedopt);
255 static int testunitready(struct cam_device *device, int retry_count,
256 int timeout, int quiet);
257 static int scsistart(struct cam_device *device, int startstop, int loadeject,
258 int retry_count, int timeout);
259 static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
260 static int scsiserial(struct cam_device *device, int retry_count, int timeout);
261 static int camxferrate(struct cam_device *device);
262 #endif /* MINIMALISTIC */
263 static int parse_btl(char *tstr, path_id_t *bus, target_id_t *target,
264 lun_id_t *lun, cam_argmask *arglst);
265 static int dorescan_or_reset(int argc, char **argv, int rescan);
266 static int rescan_or_reset_bus(path_id_t bus, int rescan);
267 static int scanlun_or_reset_dev(path_id_t bus, target_id_t target,
268 lun_id_t lun, int scan);
270 static int readdefects(struct cam_device *device, int argc, char **argv,
271 char *combinedopt, int retry_count, int timeout);
272 static void modepage(struct cam_device *device, int argc, char **argv,
273 char *combinedopt, int retry_count, int timeout);
274 static int scsicmd(struct cam_device *device, int argc, char **argv,
275 char *combinedopt, int retry_count, int timeout);
276 static int smpcmd(struct cam_device *device, int argc, char **argv,
277 char *combinedopt, int retry_count, int timeout);
278 static int smpreportgeneral(struct cam_device *device, int argc, char **argv,
279 char *combinedopt, int retry_count, int timeout);
280 static int smpphycontrol(struct cam_device *device, int argc, char **argv,
281 char *combinedopt, int retry_count, int timeout);
282 static int smpmaninfo(struct cam_device *device, int argc, char **argv,
283 char *combinedopt, int retry_count, int timeout);
284 static int getdevid(struct cam_devitem *item);
285 static int buildbusdevlist(struct cam_devlist *devlist);
286 static void freebusdevlist(struct cam_devlist *devlist);
287 static struct cam_devitem *findsasdevice(struct cam_devlist *devlist,
289 static int smpphylist(struct cam_device *device, int argc, char **argv,
290 char *combinedopt, int retry_count, int timeout);
291 static int tagcontrol(struct cam_device *device, int argc, char **argv,
293 static void cts_print(struct cam_device *device,
294 struct ccb_trans_settings *cts);
295 static void cpi_print(struct ccb_pathinq *cpi);
296 static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
297 static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd);
298 static int get_print_cts(struct cam_device *device, int user_settings,
299 int quiet, struct ccb_trans_settings *cts);
300 static int ratecontrol(struct cam_device *device, int retry_count,
301 int timeout, int argc, char **argv, char *combinedopt);
302 static int scsiformat(struct cam_device *device, int argc, char **argv,
303 char *combinedopt, int retry_count, int timeout);
304 static int scsisanitize(struct cam_device *device, int argc, char **argv,
305 char *combinedopt, int retry_count, int timeout);
306 static int scsireportluns(struct cam_device *device, int argc, char **argv,
307 char *combinedopt, int retry_count, int timeout);
308 static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
309 char *combinedopt, int retry_count, int timeout);
310 static int atapm(struct cam_device *device, int argc, char **argv,
311 char *combinedopt, int retry_count, int timeout);
312 static int atasecurity(struct cam_device *device, int retry_count, int timeout,
313 int argc, char **argv, char *combinedopt);
314 static int atahpa(struct cam_device *device, int retry_count, int timeout,
315 int argc, char **argv, char *combinedopt);
317 #endif /* MINIMALISTIC */
319 #define min(a,b) (((a)<(b))?(a):(b))
322 #define max(a,b) (((a)>(b))?(a):(b))
326 getoption(struct camcontrol_opts *table, char *arg, uint32_t *cmdnum,
327 cam_argmask *argnum, const char **subopt)
329 struct camcontrol_opts *opts;
332 for (opts = table; (opts != NULL) && (opts->optname != NULL);
334 if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
335 *cmdnum = opts->cmdnum;
336 *argnum = opts->argnum;
337 *subopt = opts->subopt;
338 if (++num_matches > 1)
339 return(CC_OR_AMBIGUOUS);
346 return(CC_OR_NOT_FOUND);
351 getdevlist(struct cam_device *device)
357 ccb = cam_getccb(device);
359 ccb->ccb_h.func_code = XPT_GDEVLIST;
360 ccb->ccb_h.flags = CAM_DIR_NONE;
361 ccb->ccb_h.retry_count = 1;
363 ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
364 while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
365 if (cam_send_ccb(device, ccb) < 0) {
366 perror("error getting device list");
373 switch (ccb->cgdl.status) {
374 case CAM_GDEVLIST_MORE_DEVS:
375 strcpy(status, "MORE");
377 case CAM_GDEVLIST_LAST_DEVICE:
378 strcpy(status, "LAST");
380 case CAM_GDEVLIST_LIST_CHANGED:
381 strcpy(status, "CHANGED");
383 case CAM_GDEVLIST_ERROR:
384 strcpy(status, "ERROR");
389 fprintf(stdout, "%s%d: generation: %d index: %d status: %s\n",
390 ccb->cgdl.periph_name,
391 ccb->cgdl.unit_number,
392 ccb->cgdl.generation,
397 * If the list has changed, we need to start over from the
400 if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
408 #endif /* MINIMALISTIC */
411 getdevtree(int argc, char **argv, char *combinedopt)
422 while ((c = getopt(argc, argv, combinedopt)) != -1) {
425 if ((arglist & CAM_ARG_VERBOSE) == 0)
433 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
434 warn("couldn't open %s", XPT_DEVICE);
438 bzero(&ccb, sizeof(union ccb));
440 ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
441 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
442 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
444 ccb.ccb_h.func_code = XPT_DEV_MATCH;
445 bufsize = sizeof(struct dev_match_result) * 100;
446 ccb.cdm.match_buf_len = bufsize;
447 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
448 if (ccb.cdm.matches == NULL) {
449 warnx("can't malloc memory for matches");
453 ccb.cdm.num_matches = 0;
456 * We fetch all nodes, since we display most of them in the default
457 * case, and all in the verbose case.
459 ccb.cdm.num_patterns = 0;
460 ccb.cdm.pattern_buf_len = 0;
463 * We do the ioctl multiple times if necessary, in case there are
464 * more than 100 nodes in the EDT.
467 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
468 warn("error sending CAMIOCOMMAND ioctl");
473 if ((ccb.ccb_h.status != CAM_REQ_CMP)
474 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
475 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
476 warnx("got CAM error %#x, CDM error %d\n",
477 ccb.ccb_h.status, ccb.cdm.status);
482 for (i = 0; i < ccb.cdm.num_matches; i++) {
483 switch (ccb.cdm.matches[i].type) {
484 case DEV_MATCH_BUS: {
485 struct bus_match_result *bus_result;
488 * Only print the bus information if the
489 * user turns on the verbose flag.
491 if ((busonly == 0) &&
492 (arglist & CAM_ARG_VERBOSE) == 0)
496 &ccb.cdm.matches[i].result.bus_result;
499 fprintf(stdout, ")\n");
503 fprintf(stdout, "scbus%d on %s%d bus %d%s\n",
505 bus_result->dev_name,
506 bus_result->unit_number,
508 (busonly ? "" : ":"));
511 case DEV_MATCH_DEVICE: {
512 struct device_match_result *dev_result;
513 char vendor[16], product[48], revision[16];
514 char fw[5], tmpstr[256];
520 &ccb.cdm.matches[i].result.device_result;
522 if ((dev_result->flags
523 & DEV_RESULT_UNCONFIGURED)
524 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
530 if (dev_result->protocol == PROTO_SCSI) {
531 cam_strvis(vendor, dev_result->inq_data.vendor,
532 sizeof(dev_result->inq_data.vendor),
535 dev_result->inq_data.product,
536 sizeof(dev_result->inq_data.product),
539 dev_result->inq_data.revision,
540 sizeof(dev_result->inq_data.revision),
542 sprintf(tmpstr, "<%s %s %s>", vendor, product,
544 } else if (dev_result->protocol == PROTO_ATA ||
545 dev_result->protocol == PROTO_SATAPM) {
547 dev_result->ident_data.model,
548 sizeof(dev_result->ident_data.model),
551 dev_result->ident_data.revision,
552 sizeof(dev_result->ident_data.revision),
554 sprintf(tmpstr, "<%s %s>", product,
556 } else if (dev_result->protocol == PROTO_SEMB) {
557 struct sep_identify_data *sid;
559 sid = (struct sep_identify_data *)
560 &dev_result->ident_data;
561 cam_strvis(vendor, sid->vendor_id,
562 sizeof(sid->vendor_id),
564 cam_strvis(product, sid->product_id,
565 sizeof(sid->product_id),
567 cam_strvis(revision, sid->product_rev,
568 sizeof(sid->product_rev),
570 cam_strvis(fw, sid->firmware_rev,
571 sizeof(sid->firmware_rev),
573 sprintf(tmpstr, "<%s %s %s %s>",
574 vendor, product, revision, fw);
576 sprintf(tmpstr, "<>");
579 fprintf(stdout, ")\n");
583 fprintf(stdout, "%-33s at scbus%d "
584 "target %d lun %jx (",
587 dev_result->target_id,
588 (uintmax_t)dev_result->target_lun);
594 case DEV_MATCH_PERIPH: {
595 struct periph_match_result *periph_result;
598 &ccb.cdm.matches[i].result.periph_result;
600 if (busonly || skip_device != 0)
604 fprintf(stdout, ",");
606 fprintf(stdout, "%s%d",
607 periph_result->periph_name,
608 periph_result->unit_number);
614 fprintf(stdout, "unknown match type\n");
619 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
620 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
623 fprintf(stdout, ")\n");
632 testunitready(struct cam_device *device, int retry_count, int timeout,
638 ccb = cam_getccb(device);
640 scsi_test_unit_ready(&ccb->csio,
641 /* retries */ retry_count,
643 /* tag_action */ MSG_SIMPLE_Q_TAG,
644 /* sense_len */ SSD_FULL_SIZE,
645 /* timeout */ timeout ? timeout : 5000);
647 /* Disable freezing the device queue */
648 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
650 if (arglist & CAM_ARG_ERR_RECOVER)
651 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
653 if (cam_send_ccb(device, ccb) < 0) {
655 perror("error sending test unit ready");
657 if (arglist & CAM_ARG_VERBOSE) {
658 cam_error_print(device, ccb, CAM_ESF_ALL,
659 CAM_EPF_ALL, stderr);
666 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
668 fprintf(stdout, "Unit is ready\n");
671 fprintf(stdout, "Unit is not ready\n");
674 if (arglist & CAM_ARG_VERBOSE) {
675 cam_error_print(device, ccb, CAM_ESF_ALL,
676 CAM_EPF_ALL, stderr);
686 scsistart(struct cam_device *device, int startstop, int loadeject,
687 int retry_count, int timeout)
692 ccb = cam_getccb(device);
695 * If we're stopping, send an ordered tag so the drive in question
696 * will finish any previously queued writes before stopping. If
697 * the device isn't capable of tagged queueing, or if tagged
698 * queueing is turned off, the tag action is a no-op.
700 scsi_start_stop(&ccb->csio,
701 /* retries */ retry_count,
703 /* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
705 /* start/stop */ startstop,
706 /* load_eject */ loadeject,
708 /* sense_len */ SSD_FULL_SIZE,
709 /* timeout */ timeout ? timeout : 120000);
711 /* Disable freezing the device queue */
712 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
714 if (arglist & CAM_ARG_ERR_RECOVER)
715 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
717 if (cam_send_ccb(device, ccb) < 0) {
718 perror("error sending start unit");
720 if (arglist & CAM_ARG_VERBOSE) {
721 cam_error_print(device, ccb, CAM_ESF_ALL,
722 CAM_EPF_ALL, stderr);
729 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
731 fprintf(stdout, "Unit started successfully");
733 fprintf(stdout,", Media loaded\n");
735 fprintf(stdout,"\n");
737 fprintf(stdout, "Unit stopped successfully");
739 fprintf(stdout, ", Media ejected\n");
741 fprintf(stdout, "\n");
747 "Error received from start unit command\n");
750 "Error received from stop unit command\n");
752 if (arglist & CAM_ARG_VERBOSE) {
753 cam_error_print(device, ccb, CAM_ESF_ALL,
754 CAM_EPF_ALL, stderr);
764 scsidoinquiry(struct cam_device *device, int argc, char **argv,
765 char *combinedopt, int retry_count, int timeout)
770 while ((c = getopt(argc, argv, combinedopt)) != -1) {
773 arglist |= CAM_ARG_GET_STDINQ;
776 arglist |= CAM_ARG_GET_XFERRATE;
779 arglist |= CAM_ARG_GET_SERIAL;
787 * If the user didn't specify any inquiry options, he wants all of
790 if ((arglist & CAM_ARG_INQ_MASK) == 0)
791 arglist |= CAM_ARG_INQ_MASK;
793 if (arglist & CAM_ARG_GET_STDINQ)
794 error = scsiinquiry(device, retry_count, timeout);
799 if (arglist & CAM_ARG_GET_SERIAL)
800 scsiserial(device, retry_count, timeout);
805 if (arglist & CAM_ARG_GET_XFERRATE)
806 error = camxferrate(device);
812 scsiinquiry(struct cam_device *device, int retry_count, int timeout)
815 struct scsi_inquiry_data *inq_buf;
818 ccb = cam_getccb(device);
821 warnx("couldn't allocate CCB");
825 /* cam_getccb cleans up the header, caller has to zero the payload */
826 bzero(&(&ccb->ccb_h)[1],
827 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
829 inq_buf = (struct scsi_inquiry_data *)malloc(
830 sizeof(struct scsi_inquiry_data));
832 if (inq_buf == NULL) {
834 warnx("can't malloc memory for inquiry\n");
837 bzero(inq_buf, sizeof(*inq_buf));
840 * Note that although the size of the inquiry buffer is the full
841 * 256 bytes specified in the SCSI spec, we only tell the device
842 * that we have allocated SHORT_INQUIRY_LENGTH bytes. There are
843 * two reasons for this:
845 * - The SCSI spec says that when a length field is only 1 byte,
846 * a value of 0 will be interpreted as 256. Therefore
847 * scsi_inquiry() will convert an inq_len (which is passed in as
848 * a u_int32_t, but the field in the CDB is only 1 byte) of 256
849 * to 0. Evidently, very few devices meet the spec in that
850 * regard. Some devices, like many Seagate disks, take the 0 as
851 * 0, and don't return any data. One Pioneer DVD-R drive
852 * returns more data than the command asked for.
854 * So, since there are numerous devices that just don't work
855 * right with the full inquiry size, we don't send the full size.
857 * - The second reason not to use the full inquiry data length is
858 * that we don't need it here. The only reason we issue a
859 * standard inquiry is to get the vendor name, device name,
860 * and revision so scsi_print_inquiry() can print them.
862 * If, at some point in the future, more inquiry data is needed for
863 * some reason, this code should use a procedure similar to the
864 * probe code. i.e., issue a short inquiry, and determine from
865 * the additional length passed back from the device how much
866 * inquiry data the device supports. Once the amount the device
867 * supports is determined, issue an inquiry for that amount and no
872 scsi_inquiry(&ccb->csio,
873 /* retries */ retry_count,
875 /* tag_action */ MSG_SIMPLE_Q_TAG,
876 /* inq_buf */ (u_int8_t *)inq_buf,
877 /* inq_len */ SHORT_INQUIRY_LENGTH,
880 /* sense_len */ SSD_FULL_SIZE,
881 /* timeout */ timeout ? timeout : 5000);
883 /* Disable freezing the device queue */
884 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
886 if (arglist & CAM_ARG_ERR_RECOVER)
887 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
889 if (cam_send_ccb(device, ccb) < 0) {
890 perror("error sending SCSI inquiry");
892 if (arglist & CAM_ARG_VERBOSE) {
893 cam_error_print(device, ccb, CAM_ESF_ALL,
894 CAM_EPF_ALL, stderr);
901 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
904 if (arglist & CAM_ARG_VERBOSE) {
905 cam_error_print(device, ccb, CAM_ESF_ALL,
906 CAM_EPF_ALL, stderr);
917 fprintf(stdout, "%s%d: ", device->device_name,
918 device->dev_unit_num);
919 scsi_print_inquiry(inq_buf);
927 scsiserial(struct cam_device *device, int retry_count, int timeout)
930 struct scsi_vpd_unit_serial_number *serial_buf;
931 char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
934 ccb = cam_getccb(device);
937 warnx("couldn't allocate CCB");
941 /* cam_getccb cleans up the header, caller has to zero the payload */
942 bzero(&(&ccb->ccb_h)[1],
943 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
945 serial_buf = (struct scsi_vpd_unit_serial_number *)
946 malloc(sizeof(*serial_buf));
948 if (serial_buf == NULL) {
950 warnx("can't malloc memory for serial number");
954 scsi_inquiry(&ccb->csio,
955 /*retries*/ retry_count,
957 /* tag_action */ MSG_SIMPLE_Q_TAG,
958 /* inq_buf */ (u_int8_t *)serial_buf,
959 /* inq_len */ sizeof(*serial_buf),
961 /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
962 /* sense_len */ SSD_FULL_SIZE,
963 /* timeout */ timeout ? timeout : 5000);
965 /* Disable freezing the device queue */
966 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
968 if (arglist & CAM_ARG_ERR_RECOVER)
969 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
971 if (cam_send_ccb(device, ccb) < 0) {
972 warn("error getting serial number");
974 if (arglist & CAM_ARG_VERBOSE) {
975 cam_error_print(device, ccb, CAM_ESF_ALL,
976 CAM_EPF_ALL, stderr);
984 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
987 if (arglist & CAM_ARG_VERBOSE) {
988 cam_error_print(device, ccb, CAM_ESF_ALL,
989 CAM_EPF_ALL, stderr);
1000 bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
1001 serial_num[serial_buf->length] = '\0';
1003 if ((arglist & CAM_ARG_GET_STDINQ)
1004 || (arglist & CAM_ARG_GET_XFERRATE))
1005 fprintf(stdout, "%s%d: Serial Number ",
1006 device->device_name, device->dev_unit_num);
1008 fprintf(stdout, "%.60s\n", serial_num);
1016 camxferrate(struct cam_device *device)
1018 struct ccb_pathinq cpi;
1020 u_int32_t speed = 0;
1025 if ((retval = get_cpi(device, &cpi)) != 0)
1028 ccb = cam_getccb(device);
1031 warnx("couldn't allocate CCB");
1035 bzero(&(&ccb->ccb_h)[1],
1036 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
1038 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
1039 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
1041 if (((retval = cam_send_ccb(device, ccb)) < 0)
1042 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1043 const char error_string[] = "error getting transfer settings";
1048 warnx(error_string);
1050 if (arglist & CAM_ARG_VERBOSE)
1051 cam_error_print(device, ccb, CAM_ESF_ALL,
1052 CAM_EPF_ALL, stderr);
1056 goto xferrate_bailout;
1060 speed = cpi.base_transfer_speed;
1062 if (ccb->cts.transport == XPORT_SPI) {
1063 struct ccb_trans_settings_spi *spi =
1064 &ccb->cts.xport_specific.spi;
1066 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
1067 freq = scsi_calc_syncsrate(spi->sync_period);
1070 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
1071 speed *= (0x01 << spi->bus_width);
1073 } else if (ccb->cts.transport == XPORT_FC) {
1074 struct ccb_trans_settings_fc *fc =
1075 &ccb->cts.xport_specific.fc;
1077 if (fc->valid & CTS_FC_VALID_SPEED)
1078 speed = fc->bitrate;
1079 } else if (ccb->cts.transport == XPORT_SAS) {
1080 struct ccb_trans_settings_sas *sas =
1081 &ccb->cts.xport_specific.sas;
1083 if (sas->valid & CTS_SAS_VALID_SPEED)
1084 speed = sas->bitrate;
1085 } else if (ccb->cts.transport == XPORT_ATA) {
1086 struct ccb_trans_settings_pata *pata =
1087 &ccb->cts.xport_specific.ata;
1089 if (pata->valid & CTS_ATA_VALID_MODE)
1090 speed = ata_mode2speed(pata->mode);
1091 } else if (ccb->cts.transport == XPORT_SATA) {
1092 struct ccb_trans_settings_sata *sata =
1093 &ccb->cts.xport_specific.sata;
1095 if (sata->valid & CTS_SATA_VALID_REVISION)
1096 speed = ata_revision2speed(sata->revision);
1101 fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
1102 device->device_name, device->dev_unit_num,
1105 fprintf(stdout, "%s%d: %dKB/s transfers",
1106 device->device_name, device->dev_unit_num,
1110 if (ccb->cts.transport == XPORT_SPI) {
1111 struct ccb_trans_settings_spi *spi =
1112 &ccb->cts.xport_specific.spi;
1114 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1115 && (spi->sync_offset != 0))
1116 fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
1117 freq % 1000, spi->sync_offset);
1119 if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
1120 && (spi->bus_width > 0)) {
1121 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1122 && (spi->sync_offset != 0)) {
1123 fprintf(stdout, ", ");
1125 fprintf(stdout, " (");
1127 fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
1128 } else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1129 && (spi->sync_offset != 0)) {
1130 fprintf(stdout, ")");
1132 } else if (ccb->cts.transport == XPORT_ATA) {
1133 struct ccb_trans_settings_pata *pata =
1134 &ccb->cts.xport_specific.ata;
1137 if (pata->valid & CTS_ATA_VALID_MODE)
1138 printf("%s, ", ata_mode2string(pata->mode));
1139 if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0)
1140 printf("ATAPI %dbytes, ", pata->atapi);
1141 if (pata->valid & CTS_ATA_VALID_BYTECOUNT)
1142 printf("PIO %dbytes", pata->bytecount);
1144 } else if (ccb->cts.transport == XPORT_SATA) {
1145 struct ccb_trans_settings_sata *sata =
1146 &ccb->cts.xport_specific.sata;
1149 if (sata->valid & CTS_SATA_VALID_REVISION)
1150 printf("SATA %d.x, ", sata->revision);
1153 if (sata->valid & CTS_SATA_VALID_MODE)
1154 printf("%s, ", ata_mode2string(sata->mode));
1155 if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
1156 printf("ATAPI %dbytes, ", sata->atapi);
1157 if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1158 printf("PIO %dbytes", sata->bytecount);
1162 if (ccb->cts.protocol == PROTO_SCSI) {
1163 struct ccb_trans_settings_scsi *scsi =
1164 &ccb->cts.proto_specific.scsi;
1165 if (scsi->valid & CTS_SCSI_VALID_TQ) {
1166 if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1167 fprintf(stdout, ", Command Queueing Enabled");
1172 fprintf(stdout, "\n");
1182 atahpa_print(struct ata_params *parm, u_int64_t hpasize, int header)
1184 u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1185 ((u_int32_t)parm->lba_size_2 << 16);
1187 u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1188 ((u_int64_t)parm->lba_size48_2 << 16) |
1189 ((u_int64_t)parm->lba_size48_3 << 32) |
1190 ((u_int64_t)parm->lba_size48_4 << 48);
1194 "Support Enabled Value\n");
1197 printf("Host Protected Area (HPA) ");
1198 if (parm->support.command1 & ATA_SUPPORT_PROTECTED) {
1199 u_int64_t lba = lbasize48 ? lbasize48 : lbasize;
1200 printf("yes %s %ju/%ju\n", (hpasize > lba) ? "yes" : "no ",
1203 printf("HPA - Security ");
1204 if (parm->support.command1 & ATA_SUPPORT_MAXSECURITY)
1214 atasata(struct ata_params *parm)
1218 if (parm->satacapabilities != 0xffff &&
1219 parm->satacapabilities != 0x0000)
1226 atacapprint(struct ata_params *parm)
1228 u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1229 ((u_int32_t)parm->lba_size_2 << 16);
1231 u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1232 ((u_int64_t)parm->lba_size48_2 << 16) |
1233 ((u_int64_t)parm->lba_size48_3 << 32) |
1234 ((u_int64_t)parm->lba_size48_4 << 48);
1237 printf("protocol ");
1238 printf("ATA/ATAPI-%d", ata_version(parm->version_major));
1239 if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1240 if (parm->satacapabilities & ATA_SATA_GEN3)
1241 printf(" SATA 3.x\n");
1242 else if (parm->satacapabilities & ATA_SATA_GEN2)
1243 printf(" SATA 2.x\n");
1244 else if (parm->satacapabilities & ATA_SATA_GEN1)
1245 printf(" SATA 1.x\n");
1251 printf("device model %.40s\n", parm->model);
1252 printf("firmware revision %.8s\n", parm->revision);
1253 printf("serial number %.20s\n", parm->serial);
1254 if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
1255 printf("WWN %04x%04x%04x%04x\n",
1256 parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
1258 if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
1259 printf("media serial number %.30s\n",
1260 parm->media_serial);
1263 printf("cylinders %d\n", parm->cylinders);
1264 printf("heads %d\n", parm->heads);
1265 printf("sectors/track %d\n", parm->sectors);
1266 printf("sector size logical %u, physical %lu, offset %lu\n",
1267 ata_logical_sector_size(parm),
1268 (unsigned long)ata_physical_sector_size(parm),
1269 (unsigned long)ata_logical_sector_offset(parm));
1271 if (parm->config == ATA_PROTO_CFA ||
1272 (parm->support.command2 & ATA_SUPPORT_CFA))
1273 printf("CFA supported\n");
1275 printf("LBA%ssupported ",
1276 parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1278 printf("%d sectors\n", lbasize);
1282 printf("LBA48%ssupported ",
1283 parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1285 printf("%ju sectors\n", (uintmax_t)lbasize48);
1289 printf("PIO supported PIO");
1290 switch (ata_max_pmode(parm)) {
1306 if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0)
1307 printf(" w/o IORDY");
1310 printf("DMA%ssupported ",
1311 parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1312 if (parm->capabilities1 & ATA_SUPPORT_DMA) {
1313 if (parm->mwdmamodes & 0xff) {
1315 if (parm->mwdmamodes & 0x04)
1317 else if (parm->mwdmamodes & 0x02)
1319 else if (parm->mwdmamodes & 0x01)
1323 if ((parm->atavalid & ATA_FLAG_88) &&
1324 (parm->udmamodes & 0xff)) {
1326 if (parm->udmamodes & 0x40)
1328 else if (parm->udmamodes & 0x20)
1330 else if (parm->udmamodes & 0x10)
1332 else if (parm->udmamodes & 0x08)
1334 else if (parm->udmamodes & 0x04)
1336 else if (parm->udmamodes & 0x02)
1338 else if (parm->udmamodes & 0x01)
1345 if (parm->media_rotation_rate == 1) {
1346 printf("media RPM non-rotating\n");
1347 } else if (parm->media_rotation_rate >= 0x0401 &&
1348 parm->media_rotation_rate <= 0xFFFE) {
1349 printf("media RPM %d\n",
1350 parm->media_rotation_rate);
1354 "Support Enabled Value Vendor\n");
1355 printf("read ahead %s %s\n",
1356 parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1357 parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1358 printf("write cache %s %s\n",
1359 parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1360 parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1361 printf("flush cache %s %s\n",
1362 parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no",
1363 parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no");
1364 printf("overlap %s\n",
1365 parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no");
1366 printf("Tagged Command Queuing (TCQ) %s %s",
1367 parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1368 parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no");
1369 if (parm->support.command2 & ATA_SUPPORT_QUEUED) {
1370 printf(" %d tags\n",
1371 ATA_QUEUE_LEN(parm->queue) + 1);
1374 printf("Native Command Queuing (NCQ) ");
1375 if (parm->satacapabilities != 0xffff &&
1376 (parm->satacapabilities & ATA_SUPPORT_NCQ)) {
1377 printf("yes %d tags\n",
1378 ATA_QUEUE_LEN(parm->queue) + 1);
1382 printf("NCQ Queue Management %s\n", atasata(parm) &&
1383 parm->satacapabilities2 & ATA_SUPPORT_NCQ_QMANAGEMENT ?
1385 printf("NCQ Streaming %s\n", atasata(parm) &&
1386 parm->satacapabilities2 & ATA_SUPPORT_NCQ_STREAM ?
1388 printf("Receive & Send FPDMA Queued %s\n", atasata(parm) &&
1389 parm->satacapabilities2 & ATA_SUPPORT_RCVSND_FPDMA_QUEUED ?
1392 printf("SMART %s %s\n",
1393 parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1394 parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1395 printf("microcode download %s %s\n",
1396 parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1397 parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1398 printf("security %s %s\n",
1399 parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1400 parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1401 printf("power management %s %s\n",
1402 parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1403 parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1404 printf("advanced power management %s %s",
1405 parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1406 parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no");
1407 if (parm->support.command2 & ATA_SUPPORT_APM) {
1408 printf(" %d/0x%02X\n",
1409 parm->apm_value, parm->apm_value);
1412 printf("automatic acoustic management %s %s",
1413 parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1414 parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no");
1415 if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) {
1416 printf(" %d/0x%02X %d/0x%02X\n",
1417 ATA_ACOUSTIC_CURRENT(parm->acoustic),
1418 ATA_ACOUSTIC_CURRENT(parm->acoustic),
1419 ATA_ACOUSTIC_VENDOR(parm->acoustic),
1420 ATA_ACOUSTIC_VENDOR(parm->acoustic));
1423 printf("media status notification %s %s\n",
1424 parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1425 parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1426 printf("power-up in Standby %s %s\n",
1427 parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1428 parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1429 printf("write-read-verify %s %s",
1430 parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1431 parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no");
1432 if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) {
1433 printf(" %d/0x%x\n",
1434 parm->wrv_mode, parm->wrv_mode);
1437 printf("unload %s %s\n",
1438 parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1439 parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1440 printf("general purpose logging %s %s\n",
1441 parm->support.extension & ATA_SUPPORT_GENLOG ? "yes" : "no",
1442 parm->enabled.extension & ATA_SUPPORT_GENLOG ? "yes" : "no");
1443 printf("free-fall %s %s\n",
1444 parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1445 parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1446 printf("Data Set Management (DSM/TRIM) ");
1447 if (parm->support_dsm & ATA_SUPPORT_DSM_TRIM) {
1449 printf("DSM - max 512byte blocks ");
1450 if (parm->max_dsm_blocks == 0x00)
1451 printf("yes not specified\n");
1454 parm->max_dsm_blocks);
1456 printf("DSM - deterministic read ");
1457 if (parm->support3 & ATA_SUPPORT_DRAT) {
1458 if (parm->support3 & ATA_SUPPORT_RZAT)
1459 printf("yes zeroed\n");
1461 printf("yes any value\n");
1471 scsi_cam_pass_16_send(struct cam_device *device, union ccb *ccb, int quiet)
1473 struct ata_pass_16 *ata_pass_16;
1474 struct ata_cmd ata_cmd;
1476 ata_pass_16 = (struct ata_pass_16 *)ccb->csio.cdb_io.cdb_bytes;
1477 ata_cmd.command = ata_pass_16->command;
1478 ata_cmd.control = ata_pass_16->control;
1479 ata_cmd.features = ata_pass_16->features;
1481 if (arglist & CAM_ARG_VERBOSE) {
1482 warnx("sending ATA %s via pass_16 with timeout of %u msecs",
1483 ata_op_string(&ata_cmd),
1484 ccb->csio.ccb_h.timeout);
1487 /* Disable freezing the device queue */
1488 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1490 if (arglist & CAM_ARG_ERR_RECOVER)
1491 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1493 if (cam_send_ccb(device, ccb) < 0) {
1494 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1495 warn("error sending ATA %s via pass_16",
1496 ata_op_string(&ata_cmd));
1499 if (arglist & CAM_ARG_VERBOSE) {
1500 cam_error_print(device, ccb, CAM_ESF_ALL,
1501 CAM_EPF_ALL, stderr);
1507 if (!(ata_pass_16->flags & AP_FLAG_CHK_COND) &&
1508 (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1509 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1510 warnx("ATA %s via pass_16 failed",
1511 ata_op_string(&ata_cmd));
1513 if (arglist & CAM_ARG_VERBOSE) {
1514 cam_error_print(device, ccb, CAM_ESF_ALL,
1515 CAM_EPF_ALL, stderr);
1526 ata_cam_send(struct cam_device *device, union ccb *ccb, int quiet)
1528 if (arglist & CAM_ARG_VERBOSE) {
1529 warnx("sending ATA %s with timeout of %u msecs",
1530 ata_op_string(&(ccb->ataio.cmd)),
1531 ccb->ataio.ccb_h.timeout);
1534 /* Disable freezing the device queue */
1535 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1537 if (arglist & CAM_ARG_ERR_RECOVER)
1538 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1540 if (cam_send_ccb(device, ccb) < 0) {
1541 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1542 warn("error sending ATA %s",
1543 ata_op_string(&(ccb->ataio.cmd)));
1546 if (arglist & CAM_ARG_VERBOSE) {
1547 cam_error_print(device, ccb, CAM_ESF_ALL,
1548 CAM_EPF_ALL, stderr);
1554 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1555 if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1556 warnx("ATA %s failed: %d",
1557 ata_op_string(&(ccb->ataio.cmd)), quiet);
1560 if (arglist & CAM_ARG_VERBOSE) {
1561 cam_error_print(device, ccb, CAM_ESF_ALL,
1562 CAM_EPF_ALL, stderr);
1572 ata_do_pass_16(struct cam_device *device, union ccb *ccb, int retries,
1573 u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
1574 u_int8_t tag_action, u_int8_t command, u_int8_t features,
1575 u_int64_t lba, u_int8_t sector_count, u_int8_t *data_ptr,
1576 u_int16_t dxfer_len, int timeout, int quiet)
1578 if (data_ptr != NULL) {
1579 ata_flags |= AP_FLAG_BYT_BLOK_BYTES |
1580 AP_FLAG_TLEN_SECT_CNT;
1581 if (flags & CAM_DIR_OUT)
1582 ata_flags |= AP_FLAG_TDIR_TO_DEV;
1584 ata_flags |= AP_FLAG_TDIR_FROM_DEV;
1586 ata_flags |= AP_FLAG_TLEN_NO_DATA;
1589 bzero(&(&ccb->ccb_h)[1],
1590 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1592 scsi_ata_pass_16(&ccb->csio,
1606 /*sense_len*/SSD_FULL_SIZE,
1609 return scsi_cam_pass_16_send(device, ccb, quiet);
1613 ata_try_pass_16(struct cam_device *device)
1615 struct ccb_pathinq cpi;
1617 if (get_cpi(device, &cpi) != 0) {
1618 warnx("couldn't get CPI");
1622 if (cpi.protocol == PROTO_SCSI) {
1623 /* possibly compatible with pass_16 */
1627 /* likely not compatible with pass_16 */
1632 ata_do_28bit_cmd(struct cam_device *device, union ccb *ccb, int retries,
1633 u_int32_t flags, u_int8_t protocol, u_int8_t tag_action,
1634 u_int8_t command, u_int8_t features, u_int32_t lba,
1635 u_int8_t sector_count, u_int8_t *data_ptr, u_int16_t dxfer_len,
1636 int timeout, int quiet)
1640 switch (ata_try_pass_16(device)) {
1644 /* Try using SCSI Passthrough */
1645 return ata_do_pass_16(device, ccb, retries, flags, protocol,
1646 0, tag_action, command, features, lba,
1647 sector_count, data_ptr, dxfer_len,
1651 bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) -
1652 sizeof(struct ccb_hdr));
1653 cam_fill_ataio(&ccb->ataio,
1662 ata_28bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1663 return ata_cam_send(device, ccb, quiet);
1667 ata_do_cmd(struct cam_device *device, union ccb *ccb, int retries,
1668 u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
1669 u_int8_t tag_action, u_int8_t command, u_int8_t features,
1670 u_int64_t lba, u_int8_t sector_count, u_int8_t *data_ptr,
1671 u_int16_t dxfer_len, int timeout, int force48bit)
1675 retval = ata_try_pass_16(device);
1682 /* Try using SCSI Passthrough */
1683 error = ata_do_pass_16(device, ccb, retries, flags, protocol,
1684 ata_flags, tag_action, command, features,
1685 lba, sector_count, data_ptr, dxfer_len,
1688 if (ata_flags & AP_FLAG_CHK_COND) {
1689 /* Decode ata_res from sense data */
1690 struct ata_res_pass16 *res_pass16;
1691 struct ata_res *res;
1695 /* sense_data is 4 byte aligned */
1696 ptr = (uint16_t*)(uintptr_t)&ccb->csio.sense_data;
1697 for (i = 0; i < sizeof(*res_pass16) / 2; i++)
1698 ptr[i] = le16toh(ptr[i]);
1700 /* sense_data is 4 byte aligned */
1701 res_pass16 = (struct ata_res_pass16 *)(uintptr_t)
1702 &ccb->csio.sense_data;
1703 res = &ccb->ataio.res;
1704 res->flags = res_pass16->flags;
1705 res->status = res_pass16->status;
1706 res->error = res_pass16->error;
1707 res->lba_low = res_pass16->lba_low;
1708 res->lba_mid = res_pass16->lba_mid;
1709 res->lba_high = res_pass16->lba_high;
1710 res->device = res_pass16->device;
1711 res->lba_low_exp = res_pass16->lba_low_exp;
1712 res->lba_mid_exp = res_pass16->lba_mid_exp;
1713 res->lba_high_exp = res_pass16->lba_high_exp;
1714 res->sector_count = res_pass16->sector_count;
1715 res->sector_count_exp = res_pass16->sector_count_exp;
1721 bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) -
1722 sizeof(struct ccb_hdr));
1723 cam_fill_ataio(&ccb->ataio,
1732 if (force48bit || lba > ATA_MAX_28BIT_LBA)
1733 ata_48bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1735 ata_28bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1737 if (ata_flags & AP_FLAG_CHK_COND)
1738 ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
1740 return ata_cam_send(device, ccb, 0);
1744 dump_data(uint16_t *ptr, uint32_t len)
1748 for (i = 0; i < len / 2; i++) {
1750 printf(" %3d: ", i);
1751 printf("%04hx ", ptr[i]);
1760 atahpa_proc_resp(struct cam_device *device, union ccb *ccb,
1761 int is48bit, u_int64_t *hpasize)
1763 struct ata_res *res;
1765 res = &ccb->ataio.res;
1766 if (res->status & ATA_STATUS_ERROR) {
1767 if (arglist & CAM_ARG_VERBOSE) {
1768 cam_error_print(device, ccb, CAM_ESF_ALL,
1769 CAM_EPF_ALL, stderr);
1770 printf("error = 0x%02x, sector_count = 0x%04x, "
1771 "device = 0x%02x, status = 0x%02x\n",
1772 res->error, res->sector_count,
1773 res->device, res->status);
1776 if (res->error & ATA_ERROR_ID_NOT_FOUND) {
1777 warnx("Max address has already been set since "
1778 "last power-on or hardware reset");
1784 if (arglist & CAM_ARG_VERBOSE) {
1785 fprintf(stdout, "%s%d: Raw native max data:\n",
1786 device->device_name, device->dev_unit_num);
1787 /* res is 4 byte aligned */
1788 dump_data((uint16_t*)(uintptr_t)res, sizeof(struct ata_res));
1790 printf("error = 0x%02x, sector_count = 0x%04x, device = 0x%02x, "
1791 "status = 0x%02x\n", res->error, res->sector_count,
1792 res->device, res->status);
1795 if (hpasize != NULL) {
1797 *hpasize = (((u_int64_t)((res->lba_high_exp << 16) |
1798 (res->lba_mid_exp << 8) | res->lba_low_exp) << 24) |
1799 ((res->lba_high << 16) | (res->lba_mid << 8) |
1802 *hpasize = (((res->device & 0x0f) << 24) |
1803 (res->lba_high << 16) | (res->lba_mid << 8) |
1812 ata_read_native_max(struct cam_device *device, int retry_count,
1813 u_int32_t timeout, union ccb *ccb,
1814 struct ata_params *parm, u_int64_t *hpasize)
1820 is48bit = parm->support.command2 & ATA_SUPPORT_ADDRESS48;
1821 protocol = AP_PROTO_NON_DATA;
1824 cmd = ATA_READ_NATIVE_MAX_ADDRESS48;
1825 protocol |= AP_EXTEND;
1827 cmd = ATA_READ_NATIVE_MAX_ADDRESS;
1830 error = ata_do_cmd(device,
1833 /*flags*/CAM_DIR_NONE,
1834 /*protocol*/protocol,
1835 /*ata_flags*/AP_FLAG_CHK_COND,
1836 /*tag_action*/MSG_SIMPLE_Q_TAG,
1843 timeout ? timeout : 1000,
1849 return atahpa_proc_resp(device, ccb, is48bit, hpasize);
1853 atahpa_set_max(struct cam_device *device, int retry_count,
1854 u_int32_t timeout, union ccb *ccb,
1855 int is48bit, u_int64_t maxsize, int persist)
1861 protocol = AP_PROTO_NON_DATA;
1864 cmd = ATA_SET_MAX_ADDRESS48;
1865 protocol |= AP_EXTEND;
1867 cmd = ATA_SET_MAX_ADDRESS;
1870 /* lba's are zero indexed so the max lba is requested max - 1 */
1874 error = ata_do_cmd(device,
1877 /*flags*/CAM_DIR_NONE,
1878 /*protocol*/protocol,
1879 /*ata_flags*/AP_FLAG_CHK_COND,
1880 /*tag_action*/MSG_SIMPLE_Q_TAG,
1882 /*features*/ATA_HPA_FEAT_MAX_ADDR,
1884 /*sector_count*/persist,
1887 timeout ? timeout : 1000,
1893 return atahpa_proc_resp(device, ccb, is48bit, NULL);
1897 atahpa_password(struct cam_device *device, int retry_count,
1898 u_int32_t timeout, union ccb *ccb,
1899 int is48bit, struct ata_set_max_pwd *pwd)
1905 protocol = AP_PROTO_PIO_OUT;
1906 cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1908 error = ata_do_cmd(device,
1911 /*flags*/CAM_DIR_OUT,
1912 /*protocol*/protocol,
1913 /*ata_flags*/AP_FLAG_CHK_COND,
1914 /*tag_action*/MSG_SIMPLE_Q_TAG,
1916 /*features*/ATA_HPA_FEAT_SET_PWD,
1919 /*data_ptr*/(u_int8_t*)pwd,
1920 /*dxfer_len*/sizeof(struct ata_set_max_pwd),
1921 timeout ? timeout : 1000,
1927 return atahpa_proc_resp(device, ccb, is48bit, NULL);
1931 atahpa_lock(struct cam_device *device, int retry_count,
1932 u_int32_t timeout, union ccb *ccb, int is48bit)
1938 protocol = AP_PROTO_NON_DATA;
1939 cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1941 error = ata_do_cmd(device,
1944 /*flags*/CAM_DIR_NONE,
1945 /*protocol*/protocol,
1946 /*ata_flags*/AP_FLAG_CHK_COND,
1947 /*tag_action*/MSG_SIMPLE_Q_TAG,
1949 /*features*/ATA_HPA_FEAT_LOCK,
1954 timeout ? timeout : 1000,
1960 return atahpa_proc_resp(device, ccb, is48bit, NULL);
1964 atahpa_unlock(struct cam_device *device, int retry_count,
1965 u_int32_t timeout, union ccb *ccb,
1966 int is48bit, struct ata_set_max_pwd *pwd)
1972 protocol = AP_PROTO_PIO_OUT;
1973 cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1975 error = ata_do_cmd(device,
1978 /*flags*/CAM_DIR_OUT,
1979 /*protocol*/protocol,
1980 /*ata_flags*/AP_FLAG_CHK_COND,
1981 /*tag_action*/MSG_SIMPLE_Q_TAG,
1983 /*features*/ATA_HPA_FEAT_UNLOCK,
1986 /*data_ptr*/(u_int8_t*)pwd,
1987 /*dxfer_len*/sizeof(struct ata_set_max_pwd),
1988 timeout ? timeout : 1000,
1994 return atahpa_proc_resp(device, ccb, is48bit, NULL);
1998 atahpa_freeze_lock(struct cam_device *device, int retry_count,
1999 u_int32_t timeout, union ccb *ccb, int is48bit)
2005 protocol = AP_PROTO_NON_DATA;
2006 cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
2008 error = ata_do_cmd(device,
2011 /*flags*/CAM_DIR_NONE,
2012 /*protocol*/protocol,
2013 /*ata_flags*/AP_FLAG_CHK_COND,
2014 /*tag_action*/MSG_SIMPLE_Q_TAG,
2016 /*features*/ATA_HPA_FEAT_FREEZE,
2021 timeout ? timeout : 1000,
2027 return atahpa_proc_resp(device, ccb, is48bit, NULL);
2032 ata_do_identify(struct cam_device *device, int retry_count, int timeout,
2033 union ccb *ccb, struct ata_params** ident_bufp)
2035 struct ata_params *ident_buf;
2036 struct ccb_pathinq cpi;
2037 struct ccb_getdev cgd;
2040 u_int8_t command, retry_command;
2042 if (get_cpi(device, &cpi) != 0) {
2043 warnx("couldn't get CPI");
2047 /* Neither PROTO_ATAPI or PROTO_SATAPM are used in cpi.protocol */
2048 if (cpi.protocol == PROTO_ATA) {
2049 if (get_cgd(device, &cgd) != 0) {
2050 warnx("couldn't get CGD");
2054 command = (cgd.protocol == PROTO_ATA) ?
2055 ATA_ATA_IDENTIFY : ATA_ATAPI_IDENTIFY;
2058 /* We don't know which for sure so try both */
2059 command = ATA_ATA_IDENTIFY;
2060 retry_command = ATA_ATAPI_IDENTIFY;
2063 ptr = (uint16_t *)calloc(1, sizeof(struct ata_params));
2065 warnx("can't calloc memory for identify\n");
2069 error = ata_do_28bit_cmd(device,
2071 /*retries*/retry_count,
2072 /*flags*/CAM_DIR_IN,
2073 /*protocol*/AP_PROTO_PIO_IN,
2074 /*tag_action*/MSG_SIMPLE_Q_TAG,
2078 /*sector_count*/(u_int8_t)sizeof(struct ata_params),
2079 /*data_ptr*/(u_int8_t *)ptr,
2080 /*dxfer_len*/sizeof(struct ata_params),
2081 /*timeout*/timeout ? timeout : 30 * 1000,
2085 if (retry_command == 0) {
2089 error = ata_do_28bit_cmd(device,
2091 /*retries*/retry_count,
2092 /*flags*/CAM_DIR_IN,
2093 /*protocol*/AP_PROTO_PIO_IN,
2094 /*tag_action*/MSG_SIMPLE_Q_TAG,
2095 /*command*/retry_command,
2098 /*sector_count*/(u_int8_t)
2099 sizeof(struct ata_params),
2100 /*data_ptr*/(u_int8_t *)ptr,
2101 /*dxfer_len*/sizeof(struct ata_params),
2102 /*timeout*/timeout ? timeout : 30 * 1000,
2112 for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
2113 ptr[i] = le16toh(ptr[i]);
2118 if (arglist & CAM_ARG_VERBOSE) {
2119 fprintf(stdout, "%s%d: Raw identify data:\n",
2120 device->device_name, device->dev_unit_num);
2121 dump_data(ptr, sizeof(struct ata_params));
2124 /* check for invalid (all zero) response */
2126 warnx("Invalid identify response detected");
2131 ident_buf = (struct ata_params *)ptr;
2132 if (strncmp(ident_buf->model, "FX", 2) &&
2133 strncmp(ident_buf->model, "NEC", 3) &&
2134 strncmp(ident_buf->model, "Pioneer", 7) &&
2135 strncmp(ident_buf->model, "SHARP", 5)) {
2136 ata_bswap(ident_buf->model, sizeof(ident_buf->model));
2137 ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
2138 ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
2139 ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
2141 ata_btrim(ident_buf->model, sizeof(ident_buf->model));
2142 ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
2143 ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
2144 ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
2145 ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
2146 ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
2147 ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
2148 ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
2149 sizeof(ident_buf->media_serial));
2151 *ident_bufp = ident_buf;
2158 ataidentify(struct cam_device *device, int retry_count, int timeout)
2161 struct ata_params *ident_buf;
2164 if ((ccb = cam_getccb(device)) == NULL) {
2165 warnx("couldn't allocate CCB");
2169 if (ata_do_identify(device, retry_count, timeout, ccb, &ident_buf) != 0) {
2174 if (ident_buf->support.command1 & ATA_SUPPORT_PROTECTED) {
2175 if (ata_read_native_max(device, retry_count, timeout, ccb,
2176 ident_buf, &hpasize) != 0) {
2184 printf("%s%d: ", device->device_name, device->dev_unit_num);
2185 ata_print_ident(ident_buf);
2186 camxferrate(device);
2187 atacapprint(ident_buf);
2188 atahpa_print(ident_buf, hpasize, 0);
2195 #endif /* MINIMALISTIC */
2198 #ifndef MINIMALISTIC
2200 ATA_SECURITY_ACTION_PRINT,
2201 ATA_SECURITY_ACTION_FREEZE,
2202 ATA_SECURITY_ACTION_UNLOCK,
2203 ATA_SECURITY_ACTION_DISABLE,
2204 ATA_SECURITY_ACTION_ERASE,
2205 ATA_SECURITY_ACTION_ERASE_ENHANCED,
2206 ATA_SECURITY_ACTION_SET_PASSWORD
2210 atasecurity_print_time(u_int16_t tw)
2214 printf("unspecified");
2216 printf("> 508 min");
2218 printf("%i min", 2 * tw);
2222 atasecurity_erase_timeout_msecs(u_int16_t timeout)
2226 return 2 * 3600 * 1000; /* default: two hours */
2227 else if (timeout > 255)
2228 return (508 + 60) * 60 * 1000; /* spec says > 508 minutes */
2230 return ((2 * timeout) + 5) * 60 * 1000; /* add a 5min margin */
2235 atasecurity_notify(u_int8_t command, struct ata_security_password *pwd)
2239 bzero(&cmd, sizeof(cmd));
2240 cmd.command = command;
2241 printf("Issuing %s", ata_op_string(&cmd));
2244 char pass[sizeof(pwd->password)+1];
2246 /* pwd->password may not be null terminated */
2247 pass[sizeof(pwd->password)] = '\0';
2248 strncpy(pass, pwd->password, sizeof(pwd->password));
2249 printf(" password='%s', user='%s'",
2251 (pwd->ctrl & ATA_SECURITY_PASSWORD_MASTER) ?
2254 if (command == ATA_SECURITY_SET_PASSWORD) {
2255 printf(", mode='%s'",
2256 (pwd->ctrl & ATA_SECURITY_LEVEL_MAXIMUM) ?
2257 "maximum" : "high");
2265 atasecurity_freeze(struct cam_device *device, union ccb *ccb,
2266 int retry_count, u_int32_t timeout, int quiet)
2270 atasecurity_notify(ATA_SECURITY_FREEZE_LOCK, NULL);
2272 return ata_do_28bit_cmd(device,
2275 /*flags*/CAM_DIR_NONE,
2276 /*protocol*/AP_PROTO_NON_DATA,
2277 /*tag_action*/MSG_SIMPLE_Q_TAG,
2278 /*command*/ATA_SECURITY_FREEZE_LOCK,
2289 atasecurity_unlock(struct cam_device *device, union ccb *ccb,
2290 int retry_count, u_int32_t timeout,
2291 struct ata_security_password *pwd, int quiet)
2295 atasecurity_notify(ATA_SECURITY_UNLOCK, pwd);
2297 return ata_do_28bit_cmd(device,
2300 /*flags*/CAM_DIR_OUT,
2301 /*protocol*/AP_PROTO_PIO_OUT,
2302 /*tag_action*/MSG_SIMPLE_Q_TAG,
2303 /*command*/ATA_SECURITY_UNLOCK,
2307 /*data_ptr*/(u_int8_t *)pwd,
2308 /*dxfer_len*/sizeof(*pwd),
2314 atasecurity_disable(struct cam_device *device, union ccb *ccb,
2315 int retry_count, u_int32_t timeout,
2316 struct ata_security_password *pwd, int quiet)
2320 atasecurity_notify(ATA_SECURITY_DISABLE_PASSWORD, pwd);
2321 return ata_do_28bit_cmd(device,
2324 /*flags*/CAM_DIR_OUT,
2325 /*protocol*/AP_PROTO_PIO_OUT,
2326 /*tag_action*/MSG_SIMPLE_Q_TAG,
2327 /*command*/ATA_SECURITY_DISABLE_PASSWORD,
2331 /*data_ptr*/(u_int8_t *)pwd,
2332 /*dxfer_len*/sizeof(*pwd),
2339 atasecurity_erase_confirm(struct cam_device *device,
2340 struct ata_params* ident_buf)
2343 printf("\nYou are about to ERASE ALL DATA from the following"
2344 " device:\n%s%d,%s%d: ", device->device_name,
2345 device->dev_unit_num, device->given_dev_name,
2346 device->given_unit_number);
2347 ata_print_ident(ident_buf);
2351 printf("\nAre you SURE you want to ERASE ALL DATA? (yes/no) ");
2353 if (fgets(str, sizeof(str), stdin) != NULL) {
2354 if (strncasecmp(str, "yes", 3) == 0) {
2356 } else if (strncasecmp(str, "no", 2) == 0) {
2359 printf("Please answer \"yes\" or "
2370 atasecurity_erase(struct cam_device *device, union ccb *ccb,
2371 int retry_count, u_int32_t timeout,
2372 u_int32_t erase_timeout,
2373 struct ata_security_password *pwd, int quiet)
2378 atasecurity_notify(ATA_SECURITY_ERASE_PREPARE, NULL);
2380 error = ata_do_28bit_cmd(device,
2383 /*flags*/CAM_DIR_NONE,
2384 /*protocol*/AP_PROTO_NON_DATA,
2385 /*tag_action*/MSG_SIMPLE_Q_TAG,
2386 /*command*/ATA_SECURITY_ERASE_PREPARE,
2399 atasecurity_notify(ATA_SECURITY_ERASE_UNIT, pwd);
2401 error = ata_do_28bit_cmd(device,
2404 /*flags*/CAM_DIR_OUT,
2405 /*protocol*/AP_PROTO_PIO_OUT,
2406 /*tag_action*/MSG_SIMPLE_Q_TAG,
2407 /*command*/ATA_SECURITY_ERASE_UNIT,
2411 /*data_ptr*/(u_int8_t *)pwd,
2412 /*dxfer_len*/sizeof(*pwd),
2413 /*timeout*/erase_timeout,
2416 if (error == 0 && quiet == 0)
2417 printf("\nErase Complete\n");
2423 atasecurity_set_password(struct cam_device *device, union ccb *ccb,
2424 int retry_count, u_int32_t timeout,
2425 struct ata_security_password *pwd, int quiet)
2429 atasecurity_notify(ATA_SECURITY_SET_PASSWORD, pwd);
2431 return ata_do_28bit_cmd(device,
2434 /*flags*/CAM_DIR_OUT,
2435 /*protocol*/AP_PROTO_PIO_OUT,
2436 /*tag_action*/MSG_SIMPLE_Q_TAG,
2437 /*command*/ATA_SECURITY_SET_PASSWORD,
2441 /*data_ptr*/(u_int8_t *)pwd,
2442 /*dxfer_len*/sizeof(*pwd),
2448 atasecurity_print(struct ata_params *parm)
2451 printf("\nSecurity Option Value\n");
2452 if (arglist & CAM_ARG_VERBOSE) {
2453 printf("status %04x\n",
2454 parm->security_status);
2456 printf("supported %s\n",
2457 parm->security_status & ATA_SECURITY_SUPPORTED ? "yes" : "no");
2458 if (!(parm->security_status & ATA_SECURITY_SUPPORTED))
2460 printf("enabled %s\n",
2461 parm->security_status & ATA_SECURITY_ENABLED ? "yes" : "no");
2462 printf("drive locked %s\n",
2463 parm->security_status & ATA_SECURITY_LOCKED ? "yes" : "no");
2464 printf("security config frozen %s\n",
2465 parm->security_status & ATA_SECURITY_FROZEN ? "yes" : "no");
2466 printf("count expired %s\n",
2467 parm->security_status & ATA_SECURITY_COUNT_EXP ? "yes" : "no");
2468 printf("security level %s\n",
2469 parm->security_status & ATA_SECURITY_LEVEL ? "maximum" : "high");
2470 printf("enhanced erase supported %s\n",
2471 parm->security_status & ATA_SECURITY_ENH_SUPP ? "yes" : "no");
2472 printf("erase time ");
2473 atasecurity_print_time(parm->erase_time);
2475 printf("enhanced erase time ");
2476 atasecurity_print_time(parm->enhanced_erase_time);
2478 printf("master password rev %04x%s\n",
2479 parm->master_passwd_revision,
2480 parm->master_passwd_revision == 0x0000 ||
2481 parm->master_passwd_revision == 0xFFFF ? " (unsupported)" : "");
2485 * Validates and copies the password in optarg to the passed buffer.
2486 * If the password in optarg is the same length as the buffer then
2487 * the data will still be copied but no null termination will occur.
2490 ata_getpwd(u_int8_t *passwd, int max, char opt)
2494 len = strlen(optarg);
2496 warnx("-%c password is too long", opt);
2498 } else if (len == 0) {
2499 warnx("-%c password is missing", opt);
2501 } else if (optarg[0] == '-'){
2502 warnx("-%c password starts with '-' (generic arg?)", opt);
2504 } else if (strlen(passwd) != 0 && strcmp(passwd, optarg) != 0) {
2505 warnx("-%c password conflicts with existing password from -%c",
2510 /* Callers pass in a buffer which does NOT need to be terminated */
2511 strncpy(passwd, optarg, max);
2518 ATA_HPA_ACTION_PRINT,
2519 ATA_HPA_ACTION_SET_MAX,
2520 ATA_HPA_ACTION_SET_PWD,
2521 ATA_HPA_ACTION_LOCK,
2522 ATA_HPA_ACTION_UNLOCK,
2523 ATA_HPA_ACTION_FREEZE_LOCK
2527 atahpa_set_confirm(struct cam_device *device, struct ata_params* ident_buf,
2528 u_int64_t maxsize, int persist)
2530 printf("\nYou are about to configure HPA to limit the user accessible\n"
2531 "sectors to %ju %s on the device:\n%s%d,%s%d: ", maxsize,
2532 persist ? "persistently" : "temporarily",
2533 device->device_name, device->dev_unit_num,
2534 device->given_dev_name, device->given_unit_number);
2535 ata_print_ident(ident_buf);
2539 printf("\nAre you SURE you want to configure HPA? (yes/no) ");
2541 if (NULL != fgets(str, sizeof(str), stdin)) {
2542 if (0 == strncasecmp(str, "yes", 3)) {
2544 } else if (0 == strncasecmp(str, "no", 2)) {
2547 printf("Please answer \"yes\" or "
2558 atahpa(struct cam_device *device, int retry_count, int timeout,
2559 int argc, char **argv, char *combinedopt)
2562 struct ata_params *ident_buf;
2563 struct ccb_getdev cgd;
2564 struct ata_set_max_pwd pwd;
2565 int error, confirm, quiet, c, action, actions, setpwd, persist;
2566 int security, is48bit, pwdsize;
2567 u_int64_t hpasize, maxsize;
2577 memset(&pwd, 0, sizeof(pwd));
2579 /* default action is to print hpa information */
2580 action = ATA_HPA_ACTION_PRINT;
2581 pwdsize = sizeof(pwd.password);
2583 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2586 action = ATA_HPA_ACTION_SET_MAX;
2587 maxsize = strtoumax(optarg, NULL, 0);
2592 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2594 action = ATA_HPA_ACTION_SET_PWD;
2600 action = ATA_HPA_ACTION_LOCK;
2606 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2608 action = ATA_HPA_ACTION_UNLOCK;
2614 action = ATA_HPA_ACTION_FREEZE_LOCK;
2634 warnx("too many hpa actions specified");
2638 if (get_cgd(device, &cgd) != 0) {
2639 warnx("couldn't get CGD");
2643 ccb = cam_getccb(device);
2645 warnx("couldn't allocate CCB");
2649 error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf);
2656 printf("%s%d: ", device->device_name, device->dev_unit_num);
2657 ata_print_ident(ident_buf);
2658 camxferrate(device);
2661 if (action == ATA_HPA_ACTION_PRINT) {
2662 error = ata_read_native_max(device, retry_count, timeout, ccb,
2663 ident_buf, &hpasize);
2665 atahpa_print(ident_buf, hpasize, 1);
2672 if (!(ident_buf->support.command1 & ATA_SUPPORT_PROTECTED)) {
2673 warnx("HPA is not supported by this device");
2679 if (security && !(ident_buf->support.command1 & ATA_SUPPORT_MAXSECURITY)) {
2680 warnx("HPA Security is not supported by this device");
2686 is48bit = ident_buf->support.command2 & ATA_SUPPORT_ADDRESS48;
2689 * The ATA spec requires:
2690 * 1. Read native max addr is called directly before set max addr
2691 * 2. Read native max addr is NOT called before any other set max call
2694 case ATA_HPA_ACTION_SET_MAX:
2696 atahpa_set_confirm(device, ident_buf, maxsize,
2703 error = ata_read_native_max(device, retry_count, timeout,
2704 ccb, ident_buf, &hpasize);
2706 error = atahpa_set_max(device, retry_count, timeout,
2707 ccb, is48bit, maxsize, persist);
2709 /* redo identify to get new lba values */
2710 error = ata_do_identify(device, retry_count,
2713 atahpa_print(ident_buf, hpasize, 1);
2718 case ATA_HPA_ACTION_SET_PWD:
2719 error = atahpa_password(device, retry_count, timeout,
2720 ccb, is48bit, &pwd);
2722 printf("HPA password has been set\n");
2725 case ATA_HPA_ACTION_LOCK:
2726 error = atahpa_lock(device, retry_count, timeout,
2729 printf("HPA has been locked\n");
2732 case ATA_HPA_ACTION_UNLOCK:
2733 error = atahpa_unlock(device, retry_count, timeout,
2734 ccb, is48bit, &pwd);
2736 printf("HPA has been unlocked\n");
2739 case ATA_HPA_ACTION_FREEZE_LOCK:
2740 error = atahpa_freeze_lock(device, retry_count, timeout,
2743 printf("HPA has been frozen\n");
2747 errx(1, "Option currently not supported");
2757 atasecurity(struct cam_device *device, int retry_count, int timeout,
2758 int argc, char **argv, char *combinedopt)
2761 struct ata_params *ident_buf;
2762 int error, confirm, quiet, c, action, actions, setpwd;
2763 int security_enabled, erase_timeout, pwdsize;
2764 struct ata_security_password pwd;
2772 memset(&pwd, 0, sizeof(pwd));
2774 /* default action is to print security information */
2775 action = ATA_SECURITY_ACTION_PRINT;
2777 /* user is master by default as its safer that way */
2778 pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER;
2779 pwdsize = sizeof(pwd.password);
2781 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2784 action = ATA_SECURITY_ACTION_FREEZE;
2789 if (strcasecmp(optarg, "user") == 0) {
2790 pwd.ctrl |= ATA_SECURITY_PASSWORD_USER;
2791 pwd.ctrl &= ~ATA_SECURITY_PASSWORD_MASTER;
2792 } else if (strcasecmp(optarg, "master") == 0) {
2793 pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER;
2794 pwd.ctrl &= ~ATA_SECURITY_PASSWORD_USER;
2796 warnx("-U argument '%s' is invalid (must be "
2797 "'user' or 'master')", optarg);
2803 if (strcasecmp(optarg, "high") == 0) {
2804 pwd.ctrl |= ATA_SECURITY_LEVEL_HIGH;
2805 pwd.ctrl &= ~ATA_SECURITY_LEVEL_MAXIMUM;
2806 } else if (strcasecmp(optarg, "maximum") == 0) {
2807 pwd.ctrl |= ATA_SECURITY_LEVEL_MAXIMUM;
2808 pwd.ctrl &= ~ATA_SECURITY_LEVEL_HIGH;
2810 warnx("-l argument '%s' is unknown (must be "
2811 "'high' or 'maximum')", optarg);
2817 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2819 action = ATA_SECURITY_ACTION_UNLOCK;
2824 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2826 action = ATA_SECURITY_ACTION_DISABLE;
2831 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2833 action = ATA_SECURITY_ACTION_ERASE;
2838 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2840 pwd.ctrl |= ATA_SECURITY_ERASE_ENHANCED;
2841 action = ATA_SECURITY_ACTION_ERASE_ENHANCED;
2846 if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2849 if (action == ATA_SECURITY_ACTION_PRINT)
2850 action = ATA_SECURITY_ACTION_SET_PASSWORD;
2852 * Don't increment action as this can be combined
2853 * with other actions.
2866 erase_timeout = atoi(optarg) * 1000;
2872 warnx("too many security actions specified");
2876 if ((ccb = cam_getccb(device)) == NULL) {
2877 warnx("couldn't allocate CCB");
2881 error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf);
2888 printf("%s%d: ", device->device_name, device->dev_unit_num);
2889 ata_print_ident(ident_buf);
2890 camxferrate(device);
2893 if (action == ATA_SECURITY_ACTION_PRINT) {
2894 atasecurity_print(ident_buf);
2900 if ((ident_buf->support.command1 & ATA_SUPPORT_SECURITY) == 0) {
2901 warnx("Security not supported");
2907 /* default timeout 15 seconds the same as linux hdparm */
2908 timeout = timeout ? timeout : 15 * 1000;
2910 security_enabled = ident_buf->security_status & ATA_SECURITY_ENABLED;
2912 /* first set the password if requested */
2914 /* confirm we can erase before setting the password if erasing */
2916 (action == ATA_SECURITY_ACTION_ERASE_ENHANCED ||
2917 action == ATA_SECURITY_ACTION_ERASE) &&
2918 atasecurity_erase_confirm(device, ident_buf) == 0) {
2924 if (pwd.ctrl & ATA_SECURITY_PASSWORD_MASTER) {
2925 pwd.revision = ident_buf->master_passwd_revision;
2926 if (pwd.revision != 0 && pwd.revision != 0xfff &&
2927 --pwd.revision == 0) {
2928 pwd.revision = 0xfffe;
2931 error = atasecurity_set_password(device, ccb, retry_count,
2932 timeout, &pwd, quiet);
2938 security_enabled = 1;
2942 case ATA_SECURITY_ACTION_FREEZE:
2943 error = atasecurity_freeze(device, ccb, retry_count,
2947 case ATA_SECURITY_ACTION_UNLOCK:
2948 if (security_enabled) {
2949 if (ident_buf->security_status & ATA_SECURITY_LOCKED) {
2950 error = atasecurity_unlock(device, ccb,
2951 retry_count, timeout, &pwd, quiet);
2953 warnx("Can't unlock, drive is not locked");
2957 warnx("Can't unlock, security is disabled");
2962 case ATA_SECURITY_ACTION_DISABLE:
2963 if (security_enabled) {
2964 /* First unlock the drive if its locked */
2965 if (ident_buf->security_status & ATA_SECURITY_LOCKED) {
2966 error = atasecurity_unlock(device, ccb,
2974 error = atasecurity_disable(device,
2982 warnx("Can't disable security (already disabled)");
2987 case ATA_SECURITY_ACTION_ERASE:
2988 if (security_enabled) {
2989 if (erase_timeout == 0) {
2990 erase_timeout = atasecurity_erase_timeout_msecs(
2991 ident_buf->erase_time);
2994 error = atasecurity_erase(device, ccb, retry_count,
2995 timeout, erase_timeout, &pwd,
2998 warnx("Can't secure erase (security is disabled)");
3003 case ATA_SECURITY_ACTION_ERASE_ENHANCED:
3004 if (security_enabled) {
3005 if (ident_buf->security_status & ATA_SECURITY_ENH_SUPP) {
3006 if (erase_timeout == 0) {
3008 atasecurity_erase_timeout_msecs(
3009 ident_buf->enhanced_erase_time);
3012 error = atasecurity_erase(device, ccb,
3013 retry_count, timeout,
3014 erase_timeout, &pwd,
3017 warnx("Enhanced erase is not supported");
3021 warnx("Can't secure erase (enhanced), "
3022 "(security is disabled)");
3033 #endif /* MINIMALISTIC */
3036 * Parse out a bus, or a bus, target and lun in the following
3042 * Returns the number of parsed components, or 0.
3045 parse_btl(char *tstr, path_id_t *bus, target_id_t *target, lun_id_t *lun,
3046 cam_argmask *arglst)
3051 while (isspace(*tstr) && (*tstr != '\0'))
3054 tmpstr = (char *)strtok(tstr, ":");
3055 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3056 *bus = strtol(tmpstr, NULL, 0);
3057 *arglst |= CAM_ARG_BUS;
3059 tmpstr = (char *)strtok(NULL, ":");
3060 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3061 *target = strtol(tmpstr, NULL, 0);
3062 *arglst |= CAM_ARG_TARGET;
3064 tmpstr = (char *)strtok(NULL, ":");
3065 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3066 *lun = strtol(tmpstr, NULL, 0);
3067 *arglst |= CAM_ARG_LUN;
3077 dorescan_or_reset(int argc, char **argv, int rescan)
3079 static const char must[] =
3080 "you must specify \"all\", a bus, or a bus:target:lun to %s";
3082 path_id_t bus = CAM_BUS_WILDCARD;
3083 target_id_t target = CAM_TARGET_WILDCARD;
3084 lun_id_t lun = CAM_LUN_WILDCARD;
3088 warnx(must, rescan? "rescan" : "reset");
3092 tstr = argv[optind];
3093 while (isspace(*tstr) && (*tstr != '\0'))
3095 if (strncasecmp(tstr, "all", strlen("all")) == 0)
3096 arglist |= CAM_ARG_BUS;
3098 rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
3099 if (rv != 1 && rv != 3) {
3100 warnx(must, rescan? "rescan" : "reset");
3105 if ((arglist & CAM_ARG_BUS)
3106 && (arglist & CAM_ARG_TARGET)
3107 && (arglist & CAM_ARG_LUN))
3108 error = scanlun_or_reset_dev(bus, target, lun, rescan);
3110 error = rescan_or_reset_bus(bus, rescan);
3116 rescan_or_reset_bus(path_id_t bus, int rescan)
3118 union ccb ccb, matchccb;
3124 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3125 warnx("error opening transport layer device %s", XPT_DEVICE);
3126 warn("%s", XPT_DEVICE);
3130 if (bus != CAM_BUS_WILDCARD) {
3131 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
3132 ccb.ccb_h.path_id = bus;
3133 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
3134 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
3135 ccb.crcn.flags = CAM_FLAG_NONE;
3137 /* run this at a low priority */
3138 ccb.ccb_h.pinfo.priority = 5;
3140 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
3141 warn("CAMIOCOMMAND ioctl failed");
3146 if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
3147 fprintf(stdout, "%s of bus %d was successful\n",
3148 rescan ? "Re-scan" : "Reset", bus);
3150 fprintf(stdout, "%s of bus %d returned error %#x\n",
3151 rescan ? "Re-scan" : "Reset", bus,
3152 ccb.ccb_h.status & CAM_STATUS_MASK);
3163 * The right way to handle this is to modify the xpt so that it can
3164 * handle a wildcarded bus in a rescan or reset CCB. At the moment
3165 * that isn't implemented, so instead we enumerate the busses and
3166 * send the rescan or reset to those busses in the case where the
3167 * given bus is -1 (wildcard). We don't send a rescan or reset
3168 * to the xpt bus; sending a rescan to the xpt bus is effectively a
3169 * no-op, sending a rescan to the xpt bus would result in a status of
3172 bzero(&(&matchccb.ccb_h)[1],
3173 sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
3174 matchccb.ccb_h.func_code = XPT_DEV_MATCH;
3175 matchccb.ccb_h.path_id = CAM_BUS_WILDCARD;
3176 bufsize = sizeof(struct dev_match_result) * 20;
3177 matchccb.cdm.match_buf_len = bufsize;
3178 matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
3179 if (matchccb.cdm.matches == NULL) {
3180 warnx("can't malloc memory for matches");
3184 matchccb.cdm.num_matches = 0;
3186 matchccb.cdm.num_patterns = 1;
3187 matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
3189 matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
3190 matchccb.cdm.pattern_buf_len);
3191 if (matchccb.cdm.patterns == NULL) {
3192 warnx("can't malloc memory for patterns");
3196 matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
3197 matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
3202 if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
3203 warn("CAMIOCOMMAND ioctl failed");
3208 if ((matchccb.ccb_h.status != CAM_REQ_CMP)
3209 || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
3210 && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
3211 warnx("got CAM error %#x, CDM error %d\n",
3212 matchccb.ccb_h.status, matchccb.cdm.status);
3217 for (i = 0; i < matchccb.cdm.num_matches; i++) {
3218 struct bus_match_result *bus_result;
3220 /* This shouldn't happen. */
3221 if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
3224 bus_result = &matchccb.cdm.matches[i].result.bus_result;
3227 * We don't want to rescan or reset the xpt bus.
3230 if (bus_result->path_id == CAM_XPT_PATH_ID)
3233 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
3235 ccb.ccb_h.path_id = bus_result->path_id;
3236 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
3237 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
3238 ccb.crcn.flags = CAM_FLAG_NONE;
3240 /* run this at a low priority */
3241 ccb.ccb_h.pinfo.priority = 5;
3243 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
3244 warn("CAMIOCOMMAND ioctl failed");
3249 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
3250 fprintf(stdout, "%s of bus %d was successful\n",
3251 rescan? "Re-scan" : "Reset",
3252 bus_result->path_id);
3255 * Don't bail out just yet, maybe the other
3256 * rescan or reset commands will complete
3259 fprintf(stderr, "%s of bus %d returned error "
3260 "%#x\n", rescan? "Re-scan" : "Reset",
3261 bus_result->path_id,
3262 ccb.ccb_h.status & CAM_STATUS_MASK);
3266 } while ((matchccb.ccb_h.status == CAM_REQ_CMP)
3267 && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
3274 if (matchccb.cdm.patterns != NULL)
3275 free(matchccb.cdm.patterns);
3276 if (matchccb.cdm.matches != NULL)
3277 free(matchccb.cdm.matches);
3283 scanlun_or_reset_dev(path_id_t bus, target_id_t target, lun_id_t lun, int scan)
3286 struct cam_device *device;
3291 if (bus == CAM_BUS_WILDCARD) {
3292 warnx("invalid bus number %d", bus);
3296 if (target == CAM_TARGET_WILDCARD) {
3297 warnx("invalid target number %d", target);
3301 if (lun == CAM_LUN_WILDCARD) {
3302 warnx("invalid lun number %jx", (uintmax_t)lun);
3308 bzero(&ccb, sizeof(union ccb));
3311 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3312 warnx("error opening transport layer device %s\n",
3314 warn("%s", XPT_DEVICE);
3318 device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
3319 if (device == NULL) {
3320 warnx("%s", cam_errbuf);
3325 ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
3326 ccb.ccb_h.path_id = bus;
3327 ccb.ccb_h.target_id = target;
3328 ccb.ccb_h.target_lun = lun;
3329 ccb.ccb_h.timeout = 5000;
3330 ccb.crcn.flags = CAM_FLAG_NONE;
3332 /* run this at a low priority */
3333 ccb.ccb_h.pinfo.priority = 5;
3336 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
3337 warn("CAMIOCOMMAND ioctl failed");
3342 if (cam_send_ccb(device, &ccb) < 0) {
3343 warn("error sending XPT_RESET_DEV CCB");
3344 cam_close_device(device);
3352 cam_close_device(device);
3355 * An error code of CAM_BDR_SENT is normal for a BDR request.
3357 if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
3359 && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
3360 fprintf(stdout, "%s of %d:%d:%jx was successful\n",
3361 scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun);
3364 fprintf(stdout, "%s of %d:%d:%jx returned error %#x\n",
3365 scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun,
3366 ccb.ccb_h.status & CAM_STATUS_MASK);
3371 #ifndef MINIMALISTIC
3373 static struct scsi_nv defect_list_type_map[] = {
3374 { "block", SRDD10_BLOCK_FORMAT },
3375 { "extbfi", SRDD10_EXT_BFI_FORMAT },
3376 { "extphys", SRDD10_EXT_PHYS_FORMAT },
3377 { "longblock", SRDD10_LONG_BLOCK_FORMAT },
3378 { "bfi", SRDD10_BYTES_FROM_INDEX_FORMAT },
3379 { "phys", SRDD10_PHYSICAL_SECTOR_FORMAT }
3383 readdefects(struct cam_device *device, int argc, char **argv,
3384 char *combinedopt, int retry_count, int timeout)
3386 union ccb *ccb = NULL;
3387 struct scsi_read_defect_data_hdr_10 *hdr10 = NULL;
3388 struct scsi_read_defect_data_hdr_12 *hdr12 = NULL;
3389 size_t hdr_size = 0, entry_size = 0;
3392 u_int8_t *defect_list = NULL;
3393 u_int8_t list_format = 0;
3394 int list_type_set = 0;
3395 u_int32_t dlist_length = 0;
3396 u_int32_t returned_length = 0, valid_len = 0;
3397 u_int32_t num_returned = 0, num_valid = 0;
3398 u_int32_t max_possible_size = 0, hdr_max = 0;
3399 u_int32_t starting_offset = 0;
3400 u_int8_t returned_format, returned_type;
3402 int summary = 0, quiet = 0;
3404 int lists_specified = 0;
3405 int get_length = 1, first_pass = 1;
3408 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3412 scsi_nv_status status;
3415 status = scsi_get_nv(defect_list_type_map,
3416 sizeof(defect_list_type_map) /
3417 sizeof(defect_list_type_map[0]), optarg,
3418 &entry_num, SCSI_NV_FLAG_IG_CASE);
3420 if (status == SCSI_NV_FOUND) {
3421 list_format = defect_list_type_map[
3425 warnx("%s: %s %s option %s", __func__,
3426 (status == SCSI_NV_AMBIGUOUS) ?
3427 "ambiguous" : "invalid", "defect list type",
3430 goto defect_bailout;
3435 arglist |= CAM_ARG_GLIST;
3438 arglist |= CAM_ARG_PLIST;
3449 starting_offset = strtoul(optarg, &endptr, 0);
3450 if (*endptr != '\0') {
3452 warnx("invalid starting offset %s", optarg);
3453 goto defect_bailout;
3465 if (list_type_set == 0) {
3467 warnx("no defect list format specified");
3468 goto defect_bailout;
3471 if (arglist & CAM_ARG_PLIST) {
3472 list_format |= SRDD10_PLIST;
3476 if (arglist & CAM_ARG_GLIST) {
3477 list_format |= SRDD10_GLIST;
3482 * This implies a summary, and was the previous behavior.
3484 if (lists_specified == 0)
3487 ccb = cam_getccb(device);
3492 * We start off asking for just the header to determine how much
3493 * defect data is available. Some Hitachi drives return an error
3494 * if you ask for more data than the drive has. Once we know the
3495 * length, we retry the command with the returned length.
3497 if (use_12byte == 0)
3498 dlist_length = sizeof(*hdr10);
3500 dlist_length = sizeof(*hdr12);
3503 if (defect_list != NULL) {
3507 defect_list = malloc(dlist_length);
3508 if (defect_list == NULL) {
3509 warnx("can't malloc memory for defect list");
3511 goto defect_bailout;
3515 bzero(defect_list, dlist_length);
3518 * cam_getccb() zeros the CCB header only. So we need to zero the
3519 * payload portion of the ccb.
3521 bzero(&(&ccb->ccb_h)[1],
3522 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3524 scsi_read_defects(&ccb->csio,
3525 /*retries*/ retry_count,
3527 /*tag_action*/ MSG_SIMPLE_Q_TAG,
3528 /*list_format*/ list_format,
3529 /*addr_desc_index*/ starting_offset,
3530 /*data_ptr*/ defect_list,
3531 /*dxfer_len*/ dlist_length,
3532 /*minimum_cmd_size*/ use_12byte ? 12 : 0,
3533 /*sense_len*/ SSD_FULL_SIZE,
3534 /*timeout*/ timeout ? timeout : 5000);
3536 /* Disable freezing the device queue */
3537 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3539 if (cam_send_ccb(device, ccb) < 0) {
3540 perror("error reading defect list");
3542 if (arglist & CAM_ARG_VERBOSE) {
3543 cam_error_print(device, ccb, CAM_ESF_ALL,
3544 CAM_EPF_ALL, stderr);
3548 goto defect_bailout;
3551 valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
3553 if (use_12byte == 0) {
3554 hdr10 = (struct scsi_read_defect_data_hdr_10 *)defect_list;
3555 hdr_size = sizeof(*hdr10);
3556 hdr_max = SRDDH10_MAX_LENGTH;
3558 if (valid_len >= hdr_size) {
3559 returned_length = scsi_2btoul(hdr10->length);
3560 returned_format = hdr10->format;
3562 returned_length = 0;
3563 returned_format = 0;
3566 hdr12 = (struct scsi_read_defect_data_hdr_12 *)defect_list;
3567 hdr_size = sizeof(*hdr12);
3568 hdr_max = SRDDH12_MAX_LENGTH;
3570 if (valid_len >= hdr_size) {
3571 returned_length = scsi_4btoul(hdr12->length);
3572 returned_format = hdr12->format;
3574 returned_length = 0;
3575 returned_format = 0;
3579 returned_type = returned_format & SRDDH10_DLIST_FORMAT_MASK;
3580 switch (returned_type) {
3581 case SRDD10_BLOCK_FORMAT:
3582 entry_size = sizeof(struct scsi_defect_desc_block);
3584 case SRDD10_LONG_BLOCK_FORMAT:
3585 entry_size = sizeof(struct scsi_defect_desc_long_block);
3587 case SRDD10_EXT_PHYS_FORMAT:
3588 case SRDD10_PHYSICAL_SECTOR_FORMAT:
3589 entry_size = sizeof(struct scsi_defect_desc_phys_sector);
3591 case SRDD10_EXT_BFI_FORMAT:
3592 case SRDD10_BYTES_FROM_INDEX_FORMAT:
3593 entry_size = sizeof(struct scsi_defect_desc_bytes_from_index);
3596 warnx("Unknown defect format 0x%x\n", returned_type);
3598 goto defect_bailout;
3602 max_possible_size = (hdr_max / entry_size) * entry_size;
3603 num_returned = returned_length / entry_size;
3604 num_valid = min(returned_length, valid_len - hdr_size);
3605 num_valid /= entry_size;
3607 if (get_length != 0) {
3610 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
3611 CAM_SCSI_STATUS_ERROR) {
3612 struct scsi_sense_data *sense;
3613 int error_code, sense_key, asc, ascq;
3615 sense = &ccb->csio.sense_data;
3616 scsi_extract_sense_len(sense, ccb->csio.sense_len -
3617 ccb->csio.sense_resid, &error_code, &sense_key,
3618 &asc, &ascq, /*show_errors*/ 1);
3621 * If the drive is reporting that it just doesn't
3622 * support the defect list format, go ahead and use
3623 * the length it reported. Otherwise, the length
3624 * may not be valid, so use the maximum.
3626 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3627 && (asc == 0x1c) && (ascq == 0x00)
3628 && (returned_length > 0)) {
3629 if ((use_12byte == 0)
3630 && (returned_length >= max_possible_size)) {
3635 dlist_length = returned_length + hdr_size;
3636 } else if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3637 && (asc == 0x1f) && (ascq == 0x00)
3638 && (returned_length > 0)) {
3639 /* Partial defect list transfer */
3641 * Hitachi drives return this error
3642 * along with a partial defect list if they
3643 * have more defects than the 10 byte
3644 * command can support. Retry with the 12
3647 if (use_12byte == 0) {
3652 dlist_length = returned_length + hdr_size;
3653 } else if ((sense_key == SSD_KEY_ILLEGAL_REQUEST)
3654 && (asc == 0x24) && (ascq == 0x00)) {
3655 /* Invalid field in CDB */
3657 * SBC-3 says that if the drive has more
3658 * defects than can be reported with the
3659 * 10 byte command, it should return this
3660 * error and no data. Retry with the 12
3663 if (use_12byte == 0) {
3668 dlist_length = returned_length + hdr_size;
3671 * If we got a SCSI error and no valid length,
3672 * just use the 10 byte maximum. The 12
3673 * byte maximum is too large.
3675 if (returned_length == 0)
3676 dlist_length = SRDD10_MAX_LENGTH;
3678 if ((use_12byte == 0)
3679 && (returned_length >=
3680 max_possible_size)) {
3685 dlist_length = returned_length +
3689 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
3692 warnx("Error reading defect header");
3693 if (arglist & CAM_ARG_VERBOSE)
3694 cam_error_print(device, ccb, CAM_ESF_ALL,
3695 CAM_EPF_ALL, stderr);
3696 goto defect_bailout;
3698 if ((use_12byte == 0)
3699 && (returned_length >= max_possible_size)) {
3704 dlist_length = returned_length + hdr_size;
3707 fprintf(stdout, "%u", num_returned);
3709 fprintf(stdout, " defect%s",
3710 (num_returned != 1) ? "s" : "");
3712 fprintf(stdout, "\n");
3714 goto defect_bailout;
3718 * We always limit the list length to the 10-byte maximum
3719 * length (0xffff). The reason is that some controllers
3720 * can't handle larger I/Os, and we can transfer the entire
3721 * 10 byte list in one shot. For drives that support the 12
3722 * byte read defects command, we'll step through the list
3723 * by specifying a starting offset. For drives that don't
3724 * support the 12 byte command's starting offset, we'll
3725 * just display the first 64K.
3727 dlist_length = min(dlist_length, SRDD10_MAX_LENGTH);
3733 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
3734 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
3735 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3736 struct scsi_sense_data *sense;
3737 int error_code, sense_key, asc, ascq;
3739 sense = &ccb->csio.sense_data;
3740 scsi_extract_sense_len(sense, ccb->csio.sense_len -
3741 ccb->csio.sense_resid, &error_code, &sense_key, &asc,
3742 &ascq, /*show_errors*/ 1);
3745 * According to the SCSI spec, if the disk doesn't support
3746 * the requested format, it will generally return a sense
3747 * key of RECOVERED ERROR, and an additional sense code
3748 * of "DEFECT LIST NOT FOUND". HGST drives also return
3749 * Primary/Grown defect list not found errors. So just
3750 * check for an ASC of 0x1c.
3752 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3754 const char *format_str;
3756 format_str = scsi_nv_to_str(defect_list_type_map,
3757 sizeof(defect_list_type_map) /
3758 sizeof(defect_list_type_map[0]),
3759 list_format & SRDD10_DLIST_FORMAT_MASK);
3760 warnx("requested defect format %s not available",
3761 format_str ? format_str : "unknown");
3763 format_str = scsi_nv_to_str(defect_list_type_map,
3764 sizeof(defect_list_type_map) /
3765 sizeof(defect_list_type_map[0]), returned_type);
3766 if (format_str != NULL) {
3767 warnx("Device returned %s format",
3771 warnx("Device returned unknown defect"
3772 " data format %#x", returned_type);
3773 goto defect_bailout;
3777 warnx("Error returned from read defect data command");
3778 if (arglist & CAM_ARG_VERBOSE)
3779 cam_error_print(device, ccb, CAM_ESF_ALL,
3780 CAM_EPF_ALL, stderr);
3781 goto defect_bailout;
3783 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3785 warnx("Error returned from read defect data command");
3786 if (arglist & CAM_ARG_VERBOSE)
3787 cam_error_print(device, ccb, CAM_ESF_ALL,
3788 CAM_EPF_ALL, stderr);
3789 goto defect_bailout;
3792 if (first_pass != 0) {
3793 fprintf(stderr, "Got %d defect", num_returned);
3795 if ((lists_specified == 0) || (num_returned == 0)) {
3796 fprintf(stderr, "s.\n");
3797 goto defect_bailout;
3798 } else if (num_returned == 1)
3799 fprintf(stderr, ":\n");
3801 fprintf(stderr, "s:\n");
3807 * XXX KDM I should probably clean up the printout format for the
3810 switch (returned_type) {
3811 case SRDD10_PHYSICAL_SECTOR_FORMAT:
3812 case SRDD10_EXT_PHYS_FORMAT:
3814 struct scsi_defect_desc_phys_sector *dlist;
3816 dlist = (struct scsi_defect_desc_phys_sector *)
3817 (defect_list + hdr_size);
3819 for (i = 0; i < num_valid; i++) {
3822 sector = scsi_4btoul(dlist[i].sector);
3823 if (returned_type == SRDD10_EXT_PHYS_FORMAT) {
3824 mads = (sector & SDD_EXT_PHYS_MADS) ?
3826 sector &= ~SDD_EXT_PHYS_FLAG_MASK;
3828 if (hex_format == 0)
3829 fprintf(stdout, "%d:%d:%d%s",
3830 scsi_3btoul(dlist[i].cylinder),
3832 scsi_4btoul(dlist[i].sector),
3833 mads ? " - " : "\n");
3835 fprintf(stdout, "0x%x:0x%x:0x%x%s",
3836 scsi_3btoul(dlist[i].cylinder),
3838 scsi_4btoul(dlist[i].sector),
3839 mads ? " - " : "\n");
3842 if (num_valid < num_returned) {
3843 starting_offset += num_valid;
3848 case SRDD10_BYTES_FROM_INDEX_FORMAT:
3849 case SRDD10_EXT_BFI_FORMAT:
3851 struct scsi_defect_desc_bytes_from_index *dlist;
3853 dlist = (struct scsi_defect_desc_bytes_from_index *)
3854 (defect_list + hdr_size);
3856 for (i = 0; i < num_valid; i++) {
3859 bfi = scsi_4btoul(dlist[i].bytes_from_index);
3860 if (returned_type == SRDD10_EXT_BFI_FORMAT) {
3861 mads = (bfi & SDD_EXT_BFI_MADS) ? 1 : 0;
3862 bfi &= ~SDD_EXT_BFI_FLAG_MASK;
3864 if (hex_format == 0)
3865 fprintf(stdout, "%d:%d:%d%s",
3866 scsi_3btoul(dlist[i].cylinder),
3868 scsi_4btoul(dlist[i].bytes_from_index),
3869 mads ? " - " : "\n");
3871 fprintf(stdout, "0x%x:0x%x:0x%x%s",
3872 scsi_3btoul(dlist[i].cylinder),
3874 scsi_4btoul(dlist[i].bytes_from_index),
3875 mads ? " - " : "\n");
3879 if (num_valid < num_returned) {
3880 starting_offset += num_valid;
3885 case SRDDH10_BLOCK_FORMAT:
3887 struct scsi_defect_desc_block *dlist;
3889 dlist = (struct scsi_defect_desc_block *)
3890 (defect_list + hdr_size);
3892 for (i = 0; i < num_valid; i++) {
3893 if (hex_format == 0)
3894 fprintf(stdout, "%u\n",
3895 scsi_4btoul(dlist[i].address));
3897 fprintf(stdout, "0x%x\n",
3898 scsi_4btoul(dlist[i].address));
3901 if (num_valid < num_returned) {
3902 starting_offset += num_valid;
3908 case SRDD10_LONG_BLOCK_FORMAT:
3910 struct scsi_defect_desc_long_block *dlist;
3912 dlist = (struct scsi_defect_desc_long_block *)
3913 (defect_list + hdr_size);
3915 for (i = 0; i < num_valid; i++) {
3916 if (hex_format == 0)
3917 fprintf(stdout, "%ju\n",
3918 (uintmax_t)scsi_8btou64(
3921 fprintf(stdout, "0x%jx\n",
3922 (uintmax_t)scsi_8btou64(
3926 if (num_valid < num_returned) {
3927 starting_offset += num_valid;
3933 fprintf(stderr, "Unknown defect format 0x%x\n",
3940 if (defect_list != NULL)
3948 #endif /* MINIMALISTIC */
3952 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
3956 ccb = cam_getccb(device);
3962 #ifndef MINIMALISTIC
3964 mode_sense(struct cam_device *device, int mode_page, int page_control,
3965 int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
3970 ccb = cam_getccb(device);
3973 errx(1, "mode_sense: couldn't allocate CCB");
3975 bzero(&(&ccb->ccb_h)[1],
3976 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3978 scsi_mode_sense(&ccb->csio,
3979 /* retries */ retry_count,
3981 /* tag_action */ MSG_SIMPLE_Q_TAG,
3983 /* page_code */ page_control << 6,
3984 /* page */ mode_page,
3985 /* param_buf */ data,
3986 /* param_len */ datalen,
3987 /* sense_len */ SSD_FULL_SIZE,
3988 /* timeout */ timeout ? timeout : 5000);
3990 if (arglist & CAM_ARG_ERR_RECOVER)
3991 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3993 /* Disable freezing the device queue */
3994 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3996 if (((retval = cam_send_ccb(device, ccb)) < 0)
3997 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
3998 if (arglist & CAM_ARG_VERBOSE) {
3999 cam_error_print(device, ccb, CAM_ESF_ALL,
4000 CAM_EPF_ALL, stderr);
4003 cam_close_device(device);
4005 err(1, "error sending mode sense command");
4007 errx(1, "error sending mode sense command");
4014 mode_select(struct cam_device *device, int save_pages, int retry_count,
4015 int timeout, u_int8_t *data, int datalen)
4020 ccb = cam_getccb(device);
4023 errx(1, "mode_select: couldn't allocate CCB");
4025 bzero(&(&ccb->ccb_h)[1],
4026 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4028 scsi_mode_select(&ccb->csio,
4029 /* retries */ retry_count,
4031 /* tag_action */ MSG_SIMPLE_Q_TAG,
4032 /* scsi_page_fmt */ 1,
4033 /* save_pages */ save_pages,
4034 /* param_buf */ data,
4035 /* param_len */ datalen,
4036 /* sense_len */ SSD_FULL_SIZE,
4037 /* timeout */ timeout ? timeout : 5000);
4039 if (arglist & CAM_ARG_ERR_RECOVER)
4040 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4042 /* Disable freezing the device queue */
4043 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4045 if (((retval = cam_send_ccb(device, ccb)) < 0)
4046 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4047 if (arglist & CAM_ARG_VERBOSE) {
4048 cam_error_print(device, ccb, CAM_ESF_ALL,
4049 CAM_EPF_ALL, stderr);
4052 cam_close_device(device);
4055 err(1, "error sending mode select command");
4057 errx(1, "error sending mode select command");
4065 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
4066 int retry_count, int timeout)
4068 int c, mode_page = -1, page_control = 0;
4069 int binary = 0, list = 0;
4071 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4077 arglist |= CAM_ARG_DBD;
4080 arglist |= CAM_ARG_MODE_EDIT;
4086 mode_page = strtol(optarg, NULL, 0);
4088 errx(1, "invalid mode page %d", mode_page);
4091 page_control = strtol(optarg, NULL, 0);
4092 if ((page_control < 0) || (page_control > 3))
4093 errx(1, "invalid page control field %d",
4095 arglist |= CAM_ARG_PAGE_CNTL;
4102 if (mode_page == -1 && list == 0)
4103 errx(1, "you must specify a mode page!");
4106 mode_list(device, page_control, arglist & CAM_ARG_DBD,
4107 retry_count, timeout);
4109 mode_edit(device, mode_page, page_control,
4110 arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
4111 retry_count, timeout);
4116 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
4117 int retry_count, int timeout)
4120 u_int32_t flags = CAM_DIR_NONE;
4121 u_int8_t *data_ptr = NULL;
4123 u_int8_t atacmd[12];
4124 struct get_hook hook;
4125 int c, data_bytes = 0;
4131 char *datastr = NULL, *tstr, *resstr = NULL;
4133 int fd_data = 0, fd_res = 0;
4136 ccb = cam_getccb(device);
4139 warnx("scsicmd: error allocating ccb");
4143 bzero(&(&ccb->ccb_h)[1],
4144 sizeof(union ccb) - sizeof(struct ccb_hdr));
4146 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4150 while (isspace(*tstr) && (*tstr != '\0'))
4152 hook.argc = argc - optind;
4153 hook.argv = argv + optind;
4155 atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
4158 * Increment optind by the number of arguments the
4159 * encoding routine processed. After each call to
4160 * getopt(3), optind points to the argument that
4161 * getopt should process _next_. In this case,
4162 * that means it points to the first command string
4163 * argument, if there is one. Once we increment
4164 * this, it should point to either the next command
4165 * line argument, or it should be past the end of
4172 while (isspace(*tstr) && (*tstr != '\0'))
4174 hook.argc = argc - optind;
4175 hook.argv = argv + optind;
4177 cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
4180 * Increment optind by the number of arguments the
4181 * encoding routine processed. After each call to
4182 * getopt(3), optind points to the argument that
4183 * getopt should process _next_. In this case,
4184 * that means it points to the first command string
4185 * argument, if there is one. Once we increment
4186 * this, it should point to either the next command
4187 * line argument, or it should be past the end of
4199 if (arglist & CAM_ARG_CMD_OUT) {
4200 warnx("command must either be "
4201 "read or write, not both");
4203 goto scsicmd_bailout;
4205 arglist |= CAM_ARG_CMD_IN;
4207 data_bytes = strtol(optarg, NULL, 0);
4208 if (data_bytes <= 0) {
4209 warnx("invalid number of input bytes %d",
4212 goto scsicmd_bailout;
4214 hook.argc = argc - optind;
4215 hook.argv = argv + optind;
4218 datastr = cget(&hook, NULL);
4220 * If the user supplied "-" instead of a format, he
4221 * wants the data to be written to stdout.
4223 if ((datastr != NULL)
4224 && (datastr[0] == '-'))
4227 data_ptr = (u_int8_t *)malloc(data_bytes);
4228 if (data_ptr == NULL) {
4229 warnx("can't malloc memory for data_ptr");
4231 goto scsicmd_bailout;
4235 if (arglist & CAM_ARG_CMD_IN) {
4236 warnx("command must either be "
4237 "read or write, not both");
4239 goto scsicmd_bailout;
4241 arglist |= CAM_ARG_CMD_OUT;
4242 flags = CAM_DIR_OUT;
4243 data_bytes = strtol(optarg, NULL, 0);
4244 if (data_bytes <= 0) {
4245 warnx("invalid number of output bytes %d",
4248 goto scsicmd_bailout;
4250 hook.argc = argc - optind;
4251 hook.argv = argv + optind;
4253 datastr = cget(&hook, NULL);
4254 data_ptr = (u_int8_t *)malloc(data_bytes);
4255 if (data_ptr == NULL) {
4256 warnx("can't malloc memory for data_ptr");
4258 goto scsicmd_bailout;
4260 bzero(data_ptr, data_bytes);
4262 * If the user supplied "-" instead of a format, he
4263 * wants the data to be read from stdin.
4265 if ((datastr != NULL)
4266 && (datastr[0] == '-'))
4269 buff_encode_visit(data_ptr, data_bytes, datastr,
4275 hook.argc = argc - optind;
4276 hook.argv = argv + optind;
4278 resstr = cget(&hook, NULL);
4279 if ((resstr != NULL) && (resstr[0] == '-'))
4289 * If fd_data is set, and we're writing to the device, we need to
4290 * read the data the user wants written from stdin.
4292 if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4294 int amt_to_read = data_bytes;
4295 u_int8_t *buf_ptr = data_ptr;
4297 for (amt_read = 0; amt_to_read > 0;
4298 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4299 if (amt_read == -1) {
4300 warn("error reading data from stdin");
4302 goto scsicmd_bailout;
4304 amt_to_read -= amt_read;
4305 buf_ptr += amt_read;
4309 if (arglist & CAM_ARG_ERR_RECOVER)
4310 flags |= CAM_PASS_ERR_RECOVER;
4312 /* Disable freezing the device queue */
4313 flags |= CAM_DEV_QFRZDIS;
4317 * This is taken from the SCSI-3 draft spec.
4318 * (T10/1157D revision 0.3)
4319 * The top 3 bits of an opcode are the group code.
4320 * The next 5 bits are the command code.
4321 * Group 0: six byte commands
4322 * Group 1: ten byte commands
4323 * Group 2: ten byte commands
4325 * Group 4: sixteen byte commands
4326 * Group 5: twelve byte commands
4327 * Group 6: vendor specific
4328 * Group 7: vendor specific
4330 switch((cdb[0] >> 5) & 0x7) {
4341 /* computed by buff_encode_visit */
4352 * We should probably use csio_build_visit or something like that
4353 * here, but it's easier to encode arguments as you go. The
4354 * alternative would be skipping the CDB argument and then encoding
4355 * it here, since we've got the data buffer argument by now.
4357 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
4359 cam_fill_csio(&ccb->csio,
4360 /*retries*/ retry_count,
4363 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4364 /*data_ptr*/ data_ptr,
4365 /*dxfer_len*/ data_bytes,
4366 /*sense_len*/ SSD_FULL_SIZE,
4367 /*cdb_len*/ cdb_len,
4368 /*timeout*/ timeout ? timeout : 5000);
4371 bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
4373 ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
4375 ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
4377 ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
4379 cam_fill_ataio(&ccb->ataio,
4380 /*retries*/ retry_count,
4384 /*data_ptr*/ data_ptr,
4385 /*dxfer_len*/ data_bytes,
4386 /*timeout*/ timeout ? timeout : 5000);
4389 if (((retval = cam_send_ccb(device, ccb)) < 0)
4390 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4391 const char warnstr[] = "error sending command";
4398 if (arglist & CAM_ARG_VERBOSE) {
4399 cam_error_print(device, ccb, CAM_ESF_ALL,
4400 CAM_EPF_ALL, stderr);
4404 goto scsicmd_bailout;
4407 if (atacmd_len && need_res) {
4409 buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
4411 fprintf(stdout, "\n");
4414 "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
4415 ccb->ataio.res.status,
4416 ccb->ataio.res.error,
4417 ccb->ataio.res.lba_low,
4418 ccb->ataio.res.lba_mid,
4419 ccb->ataio.res.lba_high,
4420 ccb->ataio.res.device,
4421 ccb->ataio.res.lba_low_exp,
4422 ccb->ataio.res.lba_mid_exp,
4423 ccb->ataio.res.lba_high_exp,
4424 ccb->ataio.res.sector_count,
4425 ccb->ataio.res.sector_count_exp);
4430 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4431 && (arglist & CAM_ARG_CMD_IN)
4432 && (data_bytes > 0)) {
4434 buff_decode_visit(data_ptr, data_bytes, datastr,
4436 fprintf(stdout, "\n");
4438 ssize_t amt_written;
4439 int amt_to_write = data_bytes;
4440 u_int8_t *buf_ptr = data_ptr;
4442 for (amt_written = 0; (amt_to_write > 0) &&
4443 (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
4444 amt_to_write -= amt_written;
4445 buf_ptr += amt_written;
4447 if (amt_written == -1) {
4448 warn("error writing data to stdout");
4450 goto scsicmd_bailout;
4451 } else if ((amt_written == 0)
4452 && (amt_to_write > 0)) {
4453 warnx("only wrote %u bytes out of %u",
4454 data_bytes - amt_to_write, data_bytes);
4461 if ((data_bytes > 0) && (data_ptr != NULL))
4470 camdebug(int argc, char **argv, char *combinedopt)
4473 path_id_t bus = CAM_BUS_WILDCARD;
4474 target_id_t target = CAM_TARGET_WILDCARD;
4475 lun_id_t lun = CAM_LUN_WILDCARD;
4476 char *tstr, *tmpstr = NULL;
4480 bzero(&ccb, sizeof(union ccb));
4482 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4485 arglist |= CAM_ARG_DEBUG_INFO;
4486 ccb.cdbg.flags |= CAM_DEBUG_INFO;
4489 arglist |= CAM_ARG_DEBUG_PERIPH;
4490 ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
4493 arglist |= CAM_ARG_DEBUG_SUBTRACE;
4494 ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
4497 arglist |= CAM_ARG_DEBUG_TRACE;
4498 ccb.cdbg.flags |= CAM_DEBUG_TRACE;
4501 arglist |= CAM_ARG_DEBUG_XPT;
4502 ccb.cdbg.flags |= CAM_DEBUG_XPT;
4505 arglist |= CAM_ARG_DEBUG_CDB;
4506 ccb.cdbg.flags |= CAM_DEBUG_CDB;
4509 arglist |= CAM_ARG_DEBUG_PROBE;
4510 ccb.cdbg.flags |= CAM_DEBUG_PROBE;
4517 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
4518 warnx("error opening transport layer device %s", XPT_DEVICE);
4519 warn("%s", XPT_DEVICE);
4526 warnx("you must specify \"off\", \"all\" or a bus,");
4527 warnx("bus:target, or bus:target:lun");
4534 while (isspace(*tstr) && (*tstr != '\0'))
4537 if (strncmp(tstr, "off", 3) == 0) {
4538 ccb.cdbg.flags = CAM_DEBUG_NONE;
4539 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
4540 CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
4541 CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE);
4542 } else if (strncmp(tstr, "all", 3) != 0) {
4543 tmpstr = (char *)strtok(tstr, ":");
4544 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4545 bus = strtol(tmpstr, NULL, 0);
4546 arglist |= CAM_ARG_BUS;
4547 tmpstr = (char *)strtok(NULL, ":");
4548 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4549 target = strtol(tmpstr, NULL, 0);
4550 arglist |= CAM_ARG_TARGET;
4551 tmpstr = (char *)strtok(NULL, ":");
4552 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4553 lun = strtol(tmpstr, NULL, 0);
4554 arglist |= CAM_ARG_LUN;
4559 warnx("you must specify \"all\", \"off\", or a bus,");
4560 warnx("bus:target, or bus:target:lun to debug");
4566 ccb.ccb_h.func_code = XPT_DEBUG;
4567 ccb.ccb_h.path_id = bus;
4568 ccb.ccb_h.target_id = target;
4569 ccb.ccb_h.target_lun = lun;
4571 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
4572 warn("CAMIOCOMMAND ioctl failed");
4577 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
4578 CAM_FUNC_NOTAVAIL) {
4579 warnx("CAM debugging not available");
4580 warnx("you need to put options CAMDEBUG in"
4581 " your kernel config file!");
4583 } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
4585 warnx("XPT_DEBUG CCB failed with status %#x",
4589 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
4591 "Debugging turned off\n");
4594 "Debugging enabled for "
4596 bus, target, (uintmax_t)lun);
4607 tagcontrol(struct cam_device *device, int argc, char **argv,
4617 ccb = cam_getccb(device);
4620 warnx("tagcontrol: error allocating ccb");
4624 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4627 numtags = strtol(optarg, NULL, 0);
4629 warnx("tag count %d is < 0", numtags);
4631 goto tagcontrol_bailout;
4642 cam_path_string(device, pathstr, sizeof(pathstr));
4645 bzero(&(&ccb->ccb_h)[1],
4646 sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
4647 ccb->ccb_h.func_code = XPT_REL_SIMQ;
4648 ccb->ccb_h.flags = CAM_DEV_QFREEZE;
4649 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
4650 ccb->crs.openings = numtags;
4653 if (cam_send_ccb(device, ccb) < 0) {
4654 perror("error sending XPT_REL_SIMQ CCB");
4656 goto tagcontrol_bailout;
4659 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4660 warnx("XPT_REL_SIMQ CCB failed");
4661 cam_error_print(device, ccb, CAM_ESF_ALL,
4662 CAM_EPF_ALL, stderr);
4664 goto tagcontrol_bailout;
4669 fprintf(stdout, "%stagged openings now %d\n",
4670 pathstr, ccb->crs.openings);
4673 bzero(&(&ccb->ccb_h)[1],
4674 sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
4676 ccb->ccb_h.func_code = XPT_GDEV_STATS;
4678 if (cam_send_ccb(device, ccb) < 0) {
4679 perror("error sending XPT_GDEV_STATS CCB");
4681 goto tagcontrol_bailout;
4684 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4685 warnx("XPT_GDEV_STATS CCB failed");
4686 cam_error_print(device, ccb, CAM_ESF_ALL,
4687 CAM_EPF_ALL, stderr);
4689 goto tagcontrol_bailout;
4692 if (arglist & CAM_ARG_VERBOSE) {
4693 fprintf(stdout, "%s", pathstr);
4694 fprintf(stdout, "dev_openings %d\n", ccb->cgds.dev_openings);
4695 fprintf(stdout, "%s", pathstr);
4696 fprintf(stdout, "dev_active %d\n", ccb->cgds.dev_active);
4697 fprintf(stdout, "%s", pathstr);
4698 fprintf(stdout, "allocated %d\n", ccb->cgds.allocated);
4699 fprintf(stdout, "%s", pathstr);
4700 fprintf(stdout, "queued %d\n", ccb->cgds.queued);
4701 fprintf(stdout, "%s", pathstr);
4702 fprintf(stdout, "held %d\n", ccb->cgds.held);
4703 fprintf(stdout, "%s", pathstr);
4704 fprintf(stdout, "mintags %d\n", ccb->cgds.mintags);
4705 fprintf(stdout, "%s", pathstr);
4706 fprintf(stdout, "maxtags %d\n", ccb->cgds.maxtags);
4709 fprintf(stdout, "%s", pathstr);
4710 fprintf(stdout, "device openings: ");
4712 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
4713 ccb->cgds.dev_active);
4723 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
4727 cam_path_string(device, pathstr, sizeof(pathstr));
4729 if (cts->transport == XPORT_SPI) {
4730 struct ccb_trans_settings_spi *spi =
4731 &cts->xport_specific.spi;
4733 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
4735 fprintf(stdout, "%ssync parameter: %d\n", pathstr,
4738 if (spi->sync_offset != 0) {
4741 freq = scsi_calc_syncsrate(spi->sync_period);
4742 fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
4743 pathstr, freq / 1000, freq % 1000);
4747 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
4748 fprintf(stdout, "%soffset: %d\n", pathstr,
4752 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
4753 fprintf(stdout, "%sbus width: %d bits\n", pathstr,
4754 (0x01 << spi->bus_width) * 8);
4757 if (spi->valid & CTS_SPI_VALID_DISC) {
4758 fprintf(stdout, "%sdisconnection is %s\n", pathstr,
4759 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
4760 "enabled" : "disabled");
4763 if (cts->transport == XPORT_FC) {
4764 struct ccb_trans_settings_fc *fc =
4765 &cts->xport_specific.fc;
4767 if (fc->valid & CTS_FC_VALID_WWNN)
4768 fprintf(stdout, "%sWWNN: 0x%llx\n", pathstr,
4769 (long long) fc->wwnn);
4770 if (fc->valid & CTS_FC_VALID_WWPN)
4771 fprintf(stdout, "%sWWPN: 0x%llx\n", pathstr,
4772 (long long) fc->wwpn);
4773 if (fc->valid & CTS_FC_VALID_PORT)
4774 fprintf(stdout, "%sPortID: 0x%x\n", pathstr, fc->port);
4775 if (fc->valid & CTS_FC_VALID_SPEED)
4776 fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4777 pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
4779 if (cts->transport == XPORT_SAS) {
4780 struct ccb_trans_settings_sas *sas =
4781 &cts->xport_specific.sas;
4783 if (sas->valid & CTS_SAS_VALID_SPEED)
4784 fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4785 pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
4787 if (cts->transport == XPORT_ATA) {
4788 struct ccb_trans_settings_pata *pata =
4789 &cts->xport_specific.ata;
4791 if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
4792 fprintf(stdout, "%sATA mode: %s\n", pathstr,
4793 ata_mode2string(pata->mode));
4795 if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
4796 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4799 if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
4800 fprintf(stdout, "%sPIO transaction length: %d\n",
4801 pathstr, pata->bytecount);
4804 if (cts->transport == XPORT_SATA) {
4805 struct ccb_trans_settings_sata *sata =
4806 &cts->xport_specific.sata;
4808 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
4809 fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
4812 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
4813 fprintf(stdout, "%sATA mode: %s\n", pathstr,
4814 ata_mode2string(sata->mode));
4816 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
4817 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4820 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
4821 fprintf(stdout, "%sPIO transaction length: %d\n",
4822 pathstr, sata->bytecount);
4824 if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
4825 fprintf(stdout, "%sPMP presence: %d\n", pathstr,
4828 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
4829 fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
4832 if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
4833 fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
4837 if (cts->protocol == PROTO_ATA) {
4838 struct ccb_trans_settings_ata *ata=
4839 &cts->proto_specific.ata;
4841 if (ata->valid & CTS_ATA_VALID_TQ) {
4842 fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4843 (ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
4844 "enabled" : "disabled");
4847 if (cts->protocol == PROTO_SCSI) {
4848 struct ccb_trans_settings_scsi *scsi=
4849 &cts->proto_specific.scsi;
4851 if (scsi->valid & CTS_SCSI_VALID_TQ) {
4852 fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4853 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
4854 "enabled" : "disabled");
4861 * Get a path inquiry CCB for the specified device.
4864 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
4869 ccb = cam_getccb(device);
4871 warnx("get_cpi: couldn't allocate CCB");
4874 bzero(&(&ccb->ccb_h)[1],
4875 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4876 ccb->ccb_h.func_code = XPT_PATH_INQ;
4877 if (cam_send_ccb(device, ccb) < 0) {
4878 warn("get_cpi: error sending Path Inquiry CCB");
4879 if (arglist & CAM_ARG_VERBOSE)
4880 cam_error_print(device, ccb, CAM_ESF_ALL,
4881 CAM_EPF_ALL, stderr);
4883 goto get_cpi_bailout;
4885 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4886 if (arglist & CAM_ARG_VERBOSE)
4887 cam_error_print(device, ccb, CAM_ESF_ALL,
4888 CAM_EPF_ALL, stderr);
4890 goto get_cpi_bailout;
4892 bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
4900 * Get a get device CCB for the specified device.
4903 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
4908 ccb = cam_getccb(device);
4910 warnx("get_cgd: couldn't allocate CCB");
4913 bzero(&(&ccb->ccb_h)[1],
4914 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4915 ccb->ccb_h.func_code = XPT_GDEV_TYPE;
4916 if (cam_send_ccb(device, ccb) < 0) {
4917 warn("get_cgd: error sending Path Inquiry CCB");
4918 if (arglist & CAM_ARG_VERBOSE)
4919 cam_error_print(device, ccb, CAM_ESF_ALL,
4920 CAM_EPF_ALL, stderr);
4922 goto get_cgd_bailout;
4924 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4925 if (arglist & CAM_ARG_VERBOSE)
4926 cam_error_print(device, ccb, CAM_ESF_ALL,
4927 CAM_EPF_ALL, stderr);
4929 goto get_cgd_bailout;
4931 bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
4938 /* return the type of disk (really the command type) */
4940 get_disk_type(struct cam_device *device)
4942 struct ccb_getdev cgd;
4944 (void) memset(&cgd, 0x0, sizeof(cgd));
4945 get_cgd(device, &cgd);
4946 switch(cgd.protocol) {
4959 cpi_print(struct ccb_pathinq *cpi)
4961 char adapter_str[1024];
4964 snprintf(adapter_str, sizeof(adapter_str),
4965 "%s%d:", cpi->dev_name, cpi->unit_number);
4967 fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
4970 for (i = 1; i < 0xff; i = i << 1) {
4973 if ((i & cpi->hba_inquiry) == 0)
4976 fprintf(stdout, "%s supports ", adapter_str);
4980 str = "MDP message";
4983 str = "32 bit wide SCSI";
4986 str = "16 bit wide SCSI";
4989 str = "SDTR message";
4992 str = "linked CDBs";
4995 str = "tag queue messages";
4998 str = "soft reset alternative";
5001 str = "SATA Port Multiplier";
5004 str = "unknown PI bit set";
5007 fprintf(stdout, "%s\n", str);
5010 for (i = 1; i < 0xff; i = i << 1) {
5013 if ((i & cpi->hba_misc) == 0)
5016 fprintf(stdout, "%s ", adapter_str);
5020 str = "bus scans from high ID to low ID";
5023 str = "removable devices not included in scan";
5025 case PIM_NOINITIATOR:
5026 str = "initiator role not supported";
5028 case PIM_NOBUSRESET:
5029 str = "user has disabled initial BUS RESET or"
5030 " controller is in target/mixed mode";
5033 str = "do not send 6-byte commands";
5036 str = "scan bus sequentially";
5039 str = "unknown PIM bit set";
5042 fprintf(stdout, "%s\n", str);
5045 for (i = 1; i < 0xff; i = i << 1) {
5048 if ((i & cpi->target_sprt) == 0)
5051 fprintf(stdout, "%s supports ", adapter_str);
5054 str = "target mode processor mode";
5057 str = "target mode phase cog. mode";
5059 case PIT_DISCONNECT:
5060 str = "disconnects in target mode";
5063 str = "terminate I/O message in target mode";
5066 str = "group 6 commands in target mode";
5069 str = "group 7 commands in target mode";
5072 str = "unknown PIT bit set";
5076 fprintf(stdout, "%s\n", str);
5078 fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
5080 fprintf(stdout, "%s maximum target: %d\n", adapter_str,
5082 fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
5084 fprintf(stdout, "%s highest path ID in subsystem: %d\n",
5085 adapter_str, cpi->hpath_id);
5086 fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
5088 fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
5089 fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
5090 fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
5091 adapter_str, cpi->hba_vendor);
5092 fprintf(stdout, "%s HBA device ID: 0x%04x\n",
5093 adapter_str, cpi->hba_device);
5094 fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
5095 adapter_str, cpi->hba_subvendor);
5096 fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
5097 adapter_str, cpi->hba_subdevice);
5098 fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
5099 fprintf(stdout, "%s base transfer speed: ", adapter_str);
5100 if (cpi->base_transfer_speed > 1000)
5101 fprintf(stdout, "%d.%03dMB/sec\n",
5102 cpi->base_transfer_speed / 1000,
5103 cpi->base_transfer_speed % 1000);
5105 fprintf(stdout, "%dKB/sec\n",
5106 (cpi->base_transfer_speed % 1000) * 1000);
5107 fprintf(stdout, "%s maximum transfer size: %u bytes\n",
5108 adapter_str, cpi->maxio);
5112 get_print_cts(struct cam_device *device, int user_settings, int quiet,
5113 struct ccb_trans_settings *cts)
5119 ccb = cam_getccb(device);
5122 warnx("get_print_cts: error allocating ccb");
5126 bzero(&(&ccb->ccb_h)[1],
5127 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
5129 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
5131 if (user_settings == 0)
5132 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
5134 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
5136 if (cam_send_ccb(device, ccb) < 0) {
5137 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
5138 if (arglist & CAM_ARG_VERBOSE)
5139 cam_error_print(device, ccb, CAM_ESF_ALL,
5140 CAM_EPF_ALL, stderr);
5142 goto get_print_cts_bailout;
5145 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5146 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
5147 if (arglist & CAM_ARG_VERBOSE)
5148 cam_error_print(device, ccb, CAM_ESF_ALL,
5149 CAM_EPF_ALL, stderr);
5151 goto get_print_cts_bailout;
5155 cts_print(device, &ccb->cts);
5158 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
5160 get_print_cts_bailout:
5168 ratecontrol(struct cam_device *device, int retry_count, int timeout,
5169 int argc, char **argv, char *combinedopt)
5173 int user_settings = 0;
5175 int disc_enable = -1, tag_enable = -1;
5178 double syncrate = -1;
5181 int change_settings = 0, send_tur = 0;
5182 struct ccb_pathinq cpi;
5184 ccb = cam_getccb(device);
5186 warnx("ratecontrol: error allocating ccb");
5189 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5198 if (strncasecmp(optarg, "enable", 6) == 0)
5200 else if (strncasecmp(optarg, "disable", 7) == 0)
5203 warnx("-D argument \"%s\" is unknown", optarg);
5205 goto ratecontrol_bailout;
5207 change_settings = 1;
5210 mode = ata_string2mode(optarg);
5212 warnx("unknown mode '%s'", optarg);
5214 goto ratecontrol_bailout;
5216 change_settings = 1;
5219 offset = strtol(optarg, NULL, 0);
5221 warnx("offset value %d is < 0", offset);
5223 goto ratecontrol_bailout;
5225 change_settings = 1;
5231 syncrate = atof(optarg);
5233 warnx("sync rate %f is < 0", syncrate);
5235 goto ratecontrol_bailout;
5237 change_settings = 1;
5240 if (strncasecmp(optarg, "enable", 6) == 0)
5242 else if (strncasecmp(optarg, "disable", 7) == 0)
5245 warnx("-T argument \"%s\" is unknown", optarg);
5247 goto ratecontrol_bailout;
5249 change_settings = 1;
5255 bus_width = strtol(optarg, NULL, 0);
5256 if (bus_width < 0) {
5257 warnx("bus width %d is < 0", bus_width);
5259 goto ratecontrol_bailout;
5261 change_settings = 1;
5267 bzero(&(&ccb->ccb_h)[1],
5268 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
5270 * Grab path inquiry information, so we can determine whether
5271 * or not the initiator is capable of the things that the user
5274 ccb->ccb_h.func_code = XPT_PATH_INQ;
5275 if (cam_send_ccb(device, ccb) < 0) {
5276 perror("error sending XPT_PATH_INQ CCB");
5277 if (arglist & CAM_ARG_VERBOSE) {
5278 cam_error_print(device, ccb, CAM_ESF_ALL,
5279 CAM_EPF_ALL, stderr);
5282 goto ratecontrol_bailout;
5284 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5285 warnx("XPT_PATH_INQ CCB failed");
5286 if (arglist & CAM_ARG_VERBOSE) {
5287 cam_error_print(device, ccb, CAM_ESF_ALL,
5288 CAM_EPF_ALL, stderr);
5291 goto ratecontrol_bailout;
5293 bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
5294 bzero(&(&ccb->ccb_h)[1],
5295 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
5297 fprintf(stdout, "%s parameters:\n",
5298 user_settings ? "User" : "Current");
5300 retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
5302 goto ratecontrol_bailout;
5304 if (arglist & CAM_ARG_VERBOSE)
5307 if (change_settings) {
5308 int didsettings = 0;
5309 struct ccb_trans_settings_spi *spi = NULL;
5310 struct ccb_trans_settings_pata *pata = NULL;
5311 struct ccb_trans_settings_sata *sata = NULL;
5312 struct ccb_trans_settings_ata *ata = NULL;
5313 struct ccb_trans_settings_scsi *scsi = NULL;
5315 if (ccb->cts.transport == XPORT_SPI)
5316 spi = &ccb->cts.xport_specific.spi;
5317 if (ccb->cts.transport == XPORT_ATA)
5318 pata = &ccb->cts.xport_specific.ata;
5319 if (ccb->cts.transport == XPORT_SATA)
5320 sata = &ccb->cts.xport_specific.sata;
5321 if (ccb->cts.protocol == PROTO_ATA)
5322 ata = &ccb->cts.proto_specific.ata;
5323 if (ccb->cts.protocol == PROTO_SCSI)
5324 scsi = &ccb->cts.proto_specific.scsi;
5325 ccb->cts.xport_specific.valid = 0;
5326 ccb->cts.proto_specific.valid = 0;
5327 if (spi && disc_enable != -1) {
5328 spi->valid |= CTS_SPI_VALID_DISC;
5329 if (disc_enable == 0)
5330 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
5332 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
5335 if (tag_enable != -1) {
5336 if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
5337 warnx("HBA does not support tagged queueing, "
5338 "so you cannot modify tag settings");
5340 goto ratecontrol_bailout;
5343 ata->valid |= CTS_SCSI_VALID_TQ;
5344 if (tag_enable == 0)
5345 ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
5347 ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
5350 scsi->valid |= CTS_SCSI_VALID_TQ;
5351 if (tag_enable == 0)
5352 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
5354 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
5358 if (spi && offset != -1) {
5359 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5360 warnx("HBA is not capable of changing offset");
5362 goto ratecontrol_bailout;
5364 spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
5365 spi->sync_offset = offset;
5368 if (spi && syncrate != -1) {
5369 int prelim_sync_period;
5371 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5372 warnx("HBA is not capable of changing "
5375 goto ratecontrol_bailout;
5377 spi->valid |= CTS_SPI_VALID_SYNC_RATE;
5379 * The sync rate the user gives us is in MHz.
5380 * We need to translate it into KHz for this
5385 * Next, we calculate a "preliminary" sync period
5386 * in tenths of a nanosecond.
5389 prelim_sync_period = 0;
5391 prelim_sync_period = 10000000 / syncrate;
5393 scsi_calc_syncparam(prelim_sync_period);
5396 if (sata && syncrate != -1) {
5397 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5398 warnx("HBA is not capable of changing "
5401 goto ratecontrol_bailout;
5403 if (!user_settings) {
5404 warnx("You can modify only user rate "
5405 "settings for SATA");
5407 goto ratecontrol_bailout;
5409 sata->revision = ata_speed2revision(syncrate * 100);
5410 if (sata->revision < 0) {
5411 warnx("Invalid rate %f", syncrate);
5413 goto ratecontrol_bailout;
5415 sata->valid |= CTS_SATA_VALID_REVISION;
5418 if ((pata || sata) && mode != -1) {
5419 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5420 warnx("HBA is not capable of changing "
5423 goto ratecontrol_bailout;
5425 if (!user_settings) {
5426 warnx("You can modify only user mode "
5427 "settings for ATA/SATA");
5429 goto ratecontrol_bailout;
5433 pata->valid |= CTS_ATA_VALID_MODE;
5436 sata->valid |= CTS_SATA_VALID_MODE;
5441 * The bus_width argument goes like this:
5445 * Therefore, if you shift the number of bits given on the
5446 * command line right by 4, you should get the correct
5449 if (spi && bus_width != -1) {
5451 * We might as well validate things here with a
5452 * decipherable error message, rather than what
5453 * will probably be an indecipherable error message
5454 * by the time it gets back to us.
5456 if ((bus_width == 16)
5457 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
5458 warnx("HBA does not support 16 bit bus width");
5460 goto ratecontrol_bailout;
5461 } else if ((bus_width == 32)
5462 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
5463 warnx("HBA does not support 32 bit bus width");
5465 goto ratecontrol_bailout;
5466 } else if ((bus_width != 8)
5467 && (bus_width != 16)
5468 && (bus_width != 32)) {
5469 warnx("Invalid bus width %d", bus_width);
5471 goto ratecontrol_bailout;
5473 spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
5474 spi->bus_width = bus_width >> 4;
5477 if (didsettings == 0) {
5478 goto ratecontrol_bailout;
5480 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
5481 if (cam_send_ccb(device, ccb) < 0) {
5482 perror("error sending XPT_SET_TRAN_SETTINGS CCB");
5483 if (arglist & CAM_ARG_VERBOSE) {
5484 cam_error_print(device, ccb, CAM_ESF_ALL,
5485 CAM_EPF_ALL, stderr);
5488 goto ratecontrol_bailout;
5490 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5491 warnx("XPT_SET_TRANS_SETTINGS CCB failed");
5492 if (arglist & CAM_ARG_VERBOSE) {
5493 cam_error_print(device, ccb, CAM_ESF_ALL,
5494 CAM_EPF_ALL, stderr);
5497 goto ratecontrol_bailout;
5501 retval = testunitready(device, retry_count, timeout,
5502 (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
5504 * If the TUR didn't succeed, just bail.
5508 fprintf(stderr, "Test Unit Ready failed\n");
5509 goto ratecontrol_bailout;
5512 if ((change_settings || send_tur) && !quiet &&
5513 (ccb->cts.transport == XPORT_ATA ||
5514 ccb->cts.transport == XPORT_SATA || send_tur)) {
5515 fprintf(stdout, "New parameters:\n");
5516 retval = get_print_cts(device, user_settings, 0, NULL);
5519 ratecontrol_bailout:
5525 scsiformat(struct cam_device *device, int argc, char **argv,
5526 char *combinedopt, int retry_count, int timeout)
5530 int ycount = 0, quiet = 0;
5531 int error = 0, retval = 0;
5532 int use_timeout = 10800 * 1000;
5534 struct format_defect_list_header fh;
5535 u_int8_t *data_ptr = NULL;
5536 u_int32_t dxfer_len = 0;
5538 int num_warnings = 0;
5541 ccb = cam_getccb(device);
5544 warnx("scsiformat: error allocating ccb");
5548 bzero(&(&ccb->ccb_h)[1],
5549 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5551 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5572 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5573 "following device:\n");
5575 error = scsidoinquiry(device, argc, argv, combinedopt,
5576 retry_count, timeout);
5579 warnx("scsiformat: error sending inquiry");
5580 goto scsiformat_bailout;
5585 if (!get_confirmation()) {
5587 goto scsiformat_bailout;
5592 use_timeout = timeout;
5595 fprintf(stdout, "Current format timeout is %d seconds\n",
5596 use_timeout / 1000);
5600 * If the user hasn't disabled questions and didn't specify a
5601 * timeout on the command line, ask them if they want the current
5605 && (timeout == 0)) {
5607 int new_timeout = 0;
5609 fprintf(stdout, "Enter new timeout in seconds or press\n"
5610 "return to keep the current timeout [%d] ",
5611 use_timeout / 1000);
5613 if (fgets(str, sizeof(str), stdin) != NULL) {
5615 new_timeout = atoi(str);
5618 if (new_timeout != 0) {
5619 use_timeout = new_timeout * 1000;
5620 fprintf(stdout, "Using new timeout value %d\n",
5621 use_timeout / 1000);
5626 * Keep this outside the if block below to silence any unused
5627 * variable warnings.
5629 bzero(&fh, sizeof(fh));
5632 * If we're in immediate mode, we've got to include the format
5635 if (immediate != 0) {
5636 fh.byte2 = FU_DLH_IMMED;
5637 data_ptr = (u_int8_t *)&fh;
5638 dxfer_len = sizeof(fh);
5639 byte2 = FU_FMT_DATA;
5640 } else if (quiet == 0) {
5641 fprintf(stdout, "Formatting...");
5645 scsi_format_unit(&ccb->csio,
5646 /* retries */ retry_count,
5648 /* tag_action */ MSG_SIMPLE_Q_TAG,
5651 /* data_ptr */ data_ptr,
5652 /* dxfer_len */ dxfer_len,
5653 /* sense_len */ SSD_FULL_SIZE,
5654 /* timeout */ use_timeout);
5656 /* Disable freezing the device queue */
5657 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5659 if (arglist & CAM_ARG_ERR_RECOVER)
5660 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5662 if (((retval = cam_send_ccb(device, ccb)) < 0)
5663 || ((immediate == 0)
5664 && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
5665 const char errstr[] = "error sending format command";
5672 if (arglist & CAM_ARG_VERBOSE) {
5673 cam_error_print(device, ccb, CAM_ESF_ALL,
5674 CAM_EPF_ALL, stderr);
5677 goto scsiformat_bailout;
5681 * If we ran in non-immediate mode, we already checked for errors
5682 * above and printed out any necessary information. If we're in
5683 * immediate mode, we need to loop through and get status
5684 * information periodically.
5686 if (immediate == 0) {
5688 fprintf(stdout, "Format Complete\n");
5690 goto scsiformat_bailout;
5697 bzero(&(&ccb->ccb_h)[1],
5698 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5701 * There's really no need to do error recovery or
5702 * retries here, since we're just going to sit in a
5703 * loop and wait for the device to finish formatting.
5705 scsi_test_unit_ready(&ccb->csio,
5708 /* tag_action */ MSG_SIMPLE_Q_TAG,
5709 /* sense_len */ SSD_FULL_SIZE,
5710 /* timeout */ 5000);
5712 /* Disable freezing the device queue */
5713 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5715 retval = cam_send_ccb(device, ccb);
5718 * If we get an error from the ioctl, bail out. SCSI
5719 * errors are expected.
5722 warn("error sending CAMIOCOMMAND ioctl");
5723 if (arglist & CAM_ARG_VERBOSE) {
5724 cam_error_print(device, ccb, CAM_ESF_ALL,
5725 CAM_EPF_ALL, stderr);
5728 goto scsiformat_bailout;
5731 status = ccb->ccb_h.status & CAM_STATUS_MASK;
5733 if ((status != CAM_REQ_CMP)
5734 && (status == CAM_SCSI_STATUS_ERROR)
5735 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
5736 struct scsi_sense_data *sense;
5737 int error_code, sense_key, asc, ascq;
5739 sense = &ccb->csio.sense_data;
5740 scsi_extract_sense_len(sense, ccb->csio.sense_len -
5741 ccb->csio.sense_resid, &error_code, &sense_key,
5742 &asc, &ascq, /*show_errors*/ 1);
5745 * According to the SCSI-2 and SCSI-3 specs, a
5746 * drive that is in the middle of a format should
5747 * return NOT READY with an ASC of "logical unit
5748 * not ready, format in progress". The sense key
5749 * specific bytes will then be a progress indicator.
5751 if ((sense_key == SSD_KEY_NOT_READY)
5752 && (asc == 0x04) && (ascq == 0x04)) {
5755 if ((scsi_get_sks(sense, ccb->csio.sense_len -
5756 ccb->csio.sense_resid, sks) == 0)
5759 u_int64_t percentage;
5761 val = scsi_2btoul(&sks[1]);
5762 percentage = 10000 * val;
5765 "\rFormatting: %ju.%02u %% "
5767 (uintmax_t)(percentage /
5769 (unsigned)((percentage /
5773 } else if ((quiet == 0)
5774 && (++num_warnings <= 1)) {
5775 warnx("Unexpected SCSI Sense Key "
5776 "Specific value returned "
5778 scsi_sense_print(device, &ccb->csio,
5780 warnx("Unable to print status "
5781 "information, but format will "
5783 warnx("will exit when format is "
5788 warnx("Unexpected SCSI error during format");
5789 cam_error_print(device, ccb, CAM_ESF_ALL,
5790 CAM_EPF_ALL, stderr);
5792 goto scsiformat_bailout;
5795 } else if (status != CAM_REQ_CMP) {
5796 warnx("Unexpected CAM status %#x", status);
5797 if (arglist & CAM_ARG_VERBOSE)
5798 cam_error_print(device, ccb, CAM_ESF_ALL,
5799 CAM_EPF_ALL, stderr);
5801 goto scsiformat_bailout;
5804 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
5807 fprintf(stdout, "\nFormat Complete\n");
5817 scsisanitize(struct cam_device *device, int argc, char **argv,
5818 char *combinedopt, int retry_count, int timeout)
5821 u_int8_t action = 0;
5823 int ycount = 0, quiet = 0;
5824 int error = 0, retval = 0;
5825 int use_timeout = 10800 * 1000;
5831 const char *pattern = NULL;
5832 u_int8_t *data_ptr = NULL;
5833 u_int32_t dxfer_len = 0;
5835 int num_warnings = 0;
5838 ccb = cam_getccb(device);
5841 warnx("scsisanitize: error allocating ccb");
5845 bzero(&(&ccb->ccb_h)[1],
5846 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5848 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5851 if (strcasecmp(optarg, "overwrite") == 0)
5852 action = SSZ_SERVICE_ACTION_OVERWRITE;
5853 else if (strcasecmp(optarg, "block") == 0)
5854 action = SSZ_SERVICE_ACTION_BLOCK_ERASE;
5855 else if (strcasecmp(optarg, "crypto") == 0)
5856 action = SSZ_SERVICE_ACTION_CRYPTO_ERASE;
5857 else if (strcasecmp(optarg, "exitfailure") == 0)
5858 action = SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE;
5860 warnx("invalid service operation \"%s\"",
5863 goto scsisanitize_bailout;
5867 passes = strtol(optarg, NULL, 0);
5868 if (passes < 1 || passes > 31) {
5869 warnx("invalid passes value %d", passes);
5871 goto scsisanitize_bailout;
5902 warnx("an action is required");
5904 goto scsisanitize_bailout;
5905 } else if (action == SSZ_SERVICE_ACTION_OVERWRITE) {
5906 struct scsi_sanitize_parameter_list *pl;
5910 if (pattern == NULL) {
5911 warnx("overwrite action requires -P argument");
5913 goto scsisanitize_bailout;
5915 fd = open(pattern, O_RDONLY);
5917 warn("cannot open pattern file %s", pattern);
5919 goto scsisanitize_bailout;
5921 if (fstat(fd, &sb) < 0) {
5922 warn("cannot stat pattern file %s", pattern);
5924 goto scsisanitize_bailout;
5927 if (sz > SSZPL_MAX_PATTERN_LENGTH) {
5928 warnx("pattern file size exceeds maximum value %d",
5929 SSZPL_MAX_PATTERN_LENGTH);
5931 goto scsisanitize_bailout;
5933 dxfer_len = sizeof(*pl) + sz;
5934 data_ptr = calloc(1, dxfer_len);
5935 if (data_ptr == NULL) {
5936 warnx("cannot allocate parameter list buffer");
5938 goto scsisanitize_bailout;
5941 amt = read(fd, data_ptr + sizeof(*pl), sz);
5943 warn("cannot read pattern file");
5945 goto scsisanitize_bailout;
5946 } else if (amt != sz) {
5947 warnx("short pattern file read");
5949 goto scsisanitize_bailout;
5952 pl = (struct scsi_sanitize_parameter_list *)data_ptr;
5958 pl->byte1 |= SSZPL_INVERT;
5959 scsi_ulto2b(sz, pl->length);
5965 else if (invert != 0)
5967 else if (pattern != NULL)
5972 warnx("%s argument only valid with overwrite "
5975 goto scsisanitize_bailout;
5980 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5981 "following device:\n");
5983 error = scsidoinquiry(device, argc, argv, combinedopt,
5984 retry_count, timeout);
5987 warnx("scsisanitize: error sending inquiry");
5988 goto scsisanitize_bailout;
5993 if (!get_confirmation()) {
5995 goto scsisanitize_bailout;
6000 use_timeout = timeout;
6003 fprintf(stdout, "Current sanitize timeout is %d seconds\n",
6004 use_timeout / 1000);
6008 * If the user hasn't disabled questions and didn't specify a
6009 * timeout on the command line, ask them if they want the current
6013 && (timeout == 0)) {
6015 int new_timeout = 0;
6017 fprintf(stdout, "Enter new timeout in seconds or press\n"
6018 "return to keep the current timeout [%d] ",
6019 use_timeout / 1000);
6021 if (fgets(str, sizeof(str), stdin) != NULL) {
6023 new_timeout = atoi(str);
6026 if (new_timeout != 0) {
6027 use_timeout = new_timeout * 1000;
6028 fprintf(stdout, "Using new timeout value %d\n",
6029 use_timeout / 1000);
6035 byte2 |= SSZ_UNRESTRICTED_EXIT;
6039 scsi_sanitize(&ccb->csio,
6040 /* retries */ retry_count,
6042 /* tag_action */ MSG_SIMPLE_Q_TAG,
6045 /* data_ptr */ data_ptr,
6046 /* dxfer_len */ dxfer_len,
6047 /* sense_len */ SSD_FULL_SIZE,
6048 /* timeout */ use_timeout);
6050 /* Disable freezing the device queue */
6051 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6053 if (arglist & CAM_ARG_ERR_RECOVER)
6054 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6056 if (cam_send_ccb(device, ccb) < 0) {
6057 warn("error sending sanitize command");
6059 goto scsisanitize_bailout;
6062 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6063 struct scsi_sense_data *sense;
6064 int error_code, sense_key, asc, ascq;
6066 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
6067 CAM_SCSI_STATUS_ERROR) {
6068 sense = &ccb->csio.sense_data;
6069 scsi_extract_sense_len(sense, ccb->csio.sense_len -
6070 ccb->csio.sense_resid, &error_code, &sense_key,
6071 &asc, &ascq, /*show_errors*/ 1);
6073 if (sense_key == SSD_KEY_ILLEGAL_REQUEST &&
6074 asc == 0x20 && ascq == 0x00)
6075 warnx("sanitize is not supported by "
6078 warnx("error sanitizing this device");
6080 warnx("error sanitizing this device");
6082 if (arglist & CAM_ARG_VERBOSE) {
6083 cam_error_print(device, ccb, CAM_ESF_ALL,
6084 CAM_EPF_ALL, stderr);
6087 goto scsisanitize_bailout;
6091 * If we ran in non-immediate mode, we already checked for errors
6092 * above and printed out any necessary information. If we're in
6093 * immediate mode, we need to loop through and get status
6094 * information periodically.
6096 if (immediate == 0) {
6098 fprintf(stdout, "Sanitize Complete\n");
6100 goto scsisanitize_bailout;
6107 bzero(&(&ccb->ccb_h)[1],
6108 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6111 * There's really no need to do error recovery or
6112 * retries here, since we're just going to sit in a
6113 * loop and wait for the device to finish sanitizing.
6115 scsi_test_unit_ready(&ccb->csio,
6118 /* tag_action */ MSG_SIMPLE_Q_TAG,
6119 /* sense_len */ SSD_FULL_SIZE,
6120 /* timeout */ 5000);
6122 /* Disable freezing the device queue */
6123 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6125 retval = cam_send_ccb(device, ccb);
6128 * If we get an error from the ioctl, bail out. SCSI
6129 * errors are expected.
6132 warn("error sending CAMIOCOMMAND ioctl");
6133 if (arglist & CAM_ARG_VERBOSE) {
6134 cam_error_print(device, ccb, CAM_ESF_ALL,
6135 CAM_EPF_ALL, stderr);
6138 goto scsisanitize_bailout;
6141 status = ccb->ccb_h.status & CAM_STATUS_MASK;
6143 if ((status != CAM_REQ_CMP)
6144 && (status == CAM_SCSI_STATUS_ERROR)
6145 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
6146 struct scsi_sense_data *sense;
6147 int error_code, sense_key, asc, ascq;
6149 sense = &ccb->csio.sense_data;
6150 scsi_extract_sense_len(sense, ccb->csio.sense_len -
6151 ccb->csio.sense_resid, &error_code, &sense_key,
6152 &asc, &ascq, /*show_errors*/ 1);
6155 * According to the SCSI-3 spec, a drive that is in the
6156 * middle of a sanitize should return NOT READY with an
6157 * ASC of "logical unit not ready, sanitize in
6158 * progress". The sense key specific bytes will then
6159 * be a progress indicator.
6161 if ((sense_key == SSD_KEY_NOT_READY)
6162 && (asc == 0x04) && (ascq == 0x1b)) {
6165 if ((scsi_get_sks(sense, ccb->csio.sense_len -
6166 ccb->csio.sense_resid, sks) == 0)
6169 u_int64_t percentage;
6171 val = scsi_2btoul(&sks[1]);
6172 percentage = 10000 * val;
6175 "\rSanitizing: %ju.%02u %% "
6177 (uintmax_t)(percentage /
6179 (unsigned)((percentage /
6183 } else if ((quiet == 0)
6184 && (++num_warnings <= 1)) {
6185 warnx("Unexpected SCSI Sense Key "
6186 "Specific value returned "
6187 "during sanitize:");
6188 scsi_sense_print(device, &ccb->csio,
6190 warnx("Unable to print status "
6191 "information, but sanitze will "
6193 warnx("will exit when sanitize is "
6198 warnx("Unexpected SCSI error during sanitize");
6199 cam_error_print(device, ccb, CAM_ESF_ALL,
6200 CAM_EPF_ALL, stderr);
6202 goto scsisanitize_bailout;
6205 } else if (status != CAM_REQ_CMP) {
6206 warnx("Unexpected CAM status %#x", status);
6207 if (arglist & CAM_ARG_VERBOSE)
6208 cam_error_print(device, ccb, CAM_ESF_ALL,
6209 CAM_EPF_ALL, stderr);
6211 goto scsisanitize_bailout;
6213 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
6216 fprintf(stdout, "\nSanitize Complete\n");
6218 scsisanitize_bailout:
6221 if (data_ptr != NULL)
6229 scsireportluns(struct cam_device *device, int argc, char **argv,
6230 char *combinedopt, int retry_count, int timeout)
6233 int c, countonly, lunsonly;
6234 struct scsi_report_luns_data *lundata;
6236 uint8_t report_type;
6237 uint32_t list_len, i, j;
6242 report_type = RPL_REPORT_DEFAULT;
6243 ccb = cam_getccb(device);
6246 warnx("%s: error allocating ccb", __func__);
6250 bzero(&(&ccb->ccb_h)[1],
6251 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6256 while ((c = getopt(argc, argv, combinedopt)) != -1) {
6265 if (strcasecmp(optarg, "default") == 0)
6266 report_type = RPL_REPORT_DEFAULT;
6267 else if (strcasecmp(optarg, "wellknown") == 0)
6268 report_type = RPL_REPORT_WELLKNOWN;
6269 else if (strcasecmp(optarg, "all") == 0)
6270 report_type = RPL_REPORT_ALL;
6272 warnx("%s: invalid report type \"%s\"",
6283 if ((countonly != 0)
6284 && (lunsonly != 0)) {
6285 warnx("%s: you can only specify one of -c or -l", __func__);
6290 * According to SPC-4, the allocation length must be at least 16
6291 * bytes -- enough for the header and one LUN.
6293 alloc_len = sizeof(*lundata) + 8;
6297 lundata = malloc(alloc_len);
6299 if (lundata == NULL) {
6300 warn("%s: error mallocing %d bytes", __func__, alloc_len);
6305 scsi_report_luns(&ccb->csio,
6306 /*retries*/ retry_count,
6308 /*tag_action*/ MSG_SIMPLE_Q_TAG,
6309 /*select_report*/ report_type,
6310 /*rpl_buf*/ lundata,
6311 /*alloc_len*/ alloc_len,
6312 /*sense_len*/ SSD_FULL_SIZE,
6313 /*timeout*/ timeout ? timeout : 5000);
6315 /* Disable freezing the device queue */
6316 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6318 if (arglist & CAM_ARG_ERR_RECOVER)
6319 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6321 if (cam_send_ccb(device, ccb) < 0) {
6322 warn("error sending REPORT LUNS command");
6324 if (arglist & CAM_ARG_VERBOSE)
6325 cam_error_print(device, ccb, CAM_ESF_ALL,
6326 CAM_EPF_ALL, stderr);
6332 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6333 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6339 list_len = scsi_4btoul(lundata->length);
6342 * If we need to list the LUNs, and our allocation
6343 * length was too short, reallocate and retry.
6345 if ((countonly == 0)
6346 && (list_len > (alloc_len - sizeof(*lundata)))) {
6347 alloc_len = list_len + sizeof(*lundata);
6353 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
6354 ((list_len / 8) > 1) ? "s" : "");
6359 for (i = 0; i < (list_len / 8); i++) {
6363 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
6365 fprintf(stdout, ",");
6366 switch (lundata->luns[i].lundata[j] &
6367 RPL_LUNDATA_ATYP_MASK) {
6368 case RPL_LUNDATA_ATYP_PERIPH:
6369 if ((lundata->luns[i].lundata[j] &
6370 RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
6371 fprintf(stdout, "%d:",
6372 lundata->luns[i].lundata[j] &
6373 RPL_LUNDATA_PERIPH_BUS_MASK);
6375 && ((lundata->luns[i].lundata[j+2] &
6376 RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
6379 fprintf(stdout, "%d",
6380 lundata->luns[i].lundata[j+1]);
6382 case RPL_LUNDATA_ATYP_FLAT: {
6384 tmplun[0] = lundata->luns[i].lundata[j] &
6385 RPL_LUNDATA_FLAT_LUN_MASK;
6386 tmplun[1] = lundata->luns[i].lundata[j+1];
6388 fprintf(stdout, "%d", scsi_2btoul(tmplun));
6392 case RPL_LUNDATA_ATYP_LUN:
6393 fprintf(stdout, "%d:%d:%d",
6394 (lundata->luns[i].lundata[j+1] &
6395 RPL_LUNDATA_LUN_BUS_MASK) >> 5,
6396 lundata->luns[i].lundata[j] &
6397 RPL_LUNDATA_LUN_TARG_MASK,
6398 lundata->luns[i].lundata[j+1] &
6399 RPL_LUNDATA_LUN_LUN_MASK);
6401 case RPL_LUNDATA_ATYP_EXTLUN: {
6402 int field_len_code, eam_code;
6404 eam_code = lundata->luns[i].lundata[j] &
6405 RPL_LUNDATA_EXT_EAM_MASK;
6406 field_len_code = (lundata->luns[i].lundata[j] &
6407 RPL_LUNDATA_EXT_LEN_MASK) >> 4;
6409 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
6410 && (field_len_code == 0x00)) {
6411 fprintf(stdout, "%d",
6412 lundata->luns[i].lundata[j+1]);
6413 } else if ((eam_code ==
6414 RPL_LUNDATA_EXT_EAM_NOT_SPEC)
6415 && (field_len_code == 0x03)) {
6419 * This format takes up all 8 bytes.
6420 * If we aren't starting at offset 0,
6424 fprintf(stdout, "Invalid "
6427 "specified format", j);
6431 bzero(tmp_lun, sizeof(tmp_lun));
6432 bcopy(&lundata->luns[i].lundata[j+1],
6433 &tmp_lun[1], sizeof(tmp_lun) - 1);
6434 fprintf(stdout, "%#jx",
6435 (intmax_t)scsi_8btou64(tmp_lun));
6438 fprintf(stderr, "Unknown Extended LUN"
6439 "Address method %#x, length "
6440 "code %#x", eam_code,
6447 fprintf(stderr, "Unknown LUN address method "
6448 "%#x\n", lundata->luns[i].lundata[0] &
6449 RPL_LUNDATA_ATYP_MASK);
6453 * For the flat addressing method, there are no
6454 * other levels after it.
6459 fprintf(stdout, "\n");
6472 scsireadcapacity(struct cam_device *device, int argc, char **argv,
6473 char *combinedopt, int retry_count, int timeout)
6476 int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
6477 struct scsi_read_capacity_data rcap;
6478 struct scsi_read_capacity_data_long rcaplong;
6492 ccb = cam_getccb(device);
6495 warnx("%s: error allocating ccb", __func__);
6499 bzero(&(&ccb->ccb_h)[1],
6500 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6502 while ((c = getopt(argc, argv, combinedopt)) != -1) {
6529 if ((blocksizeonly != 0)
6530 && (numblocks != 0)) {
6531 warnx("%s: you can only specify one of -b or -N", __func__);
6536 if ((blocksizeonly != 0)
6537 && (sizeonly != 0)) {
6538 warnx("%s: you can only specify one of -b or -s", __func__);
6545 warnx("%s: you can only specify one of -h/-H or -q", __func__);
6551 && (blocksizeonly != 0)) {
6552 warnx("%s: you can only specify one of -h/-H or -b", __func__);
6557 scsi_read_capacity(&ccb->csio,
6558 /*retries*/ retry_count,
6560 /*tag_action*/ MSG_SIMPLE_Q_TAG,
6563 /*timeout*/ timeout ? timeout : 5000);
6565 /* Disable freezing the device queue */
6566 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6568 if (arglist & CAM_ARG_ERR_RECOVER)
6569 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6571 if (cam_send_ccb(device, ccb) < 0) {
6572 warn("error sending READ CAPACITY command");
6574 if (arglist & CAM_ARG_VERBOSE)
6575 cam_error_print(device, ccb, CAM_ESF_ALL,
6576 CAM_EPF_ALL, stderr);
6582 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6583 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6588 maxsector = scsi_4btoul(rcap.addr);
6589 block_len = scsi_4btoul(rcap.length);
6592 * A last block of 2^32-1 means that the true capacity is over 2TB,
6593 * and we need to issue the long READ CAPACITY to get the real
6594 * capacity. Otherwise, we're all set.
6596 if (maxsector != 0xffffffff)
6599 scsi_read_capacity_16(&ccb->csio,
6600 /*retries*/ retry_count,
6602 /*tag_action*/ MSG_SIMPLE_Q_TAG,
6606 /*rcap_buf*/ (uint8_t *)&rcaplong,
6607 /*rcap_buf_len*/ sizeof(rcaplong),
6608 /*sense_len*/ SSD_FULL_SIZE,
6609 /*timeout*/ timeout ? timeout : 5000);
6611 /* Disable freezing the device queue */
6612 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6614 if (arglist & CAM_ARG_ERR_RECOVER)
6615 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6617 if (cam_send_ccb(device, ccb) < 0) {
6618 warn("error sending READ CAPACITY (16) command");
6620 if (arglist & CAM_ARG_VERBOSE)
6621 cam_error_print(device, ccb, CAM_ESF_ALL,
6622 CAM_EPF_ALL, stderr);
6628 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6629 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6634 maxsector = scsi_8btou64(rcaplong.addr);
6635 block_len = scsi_4btoul(rcaplong.length);
6638 if (blocksizeonly == 0) {
6640 * Humanize implies !quiet, and also implies numblocks.
6642 if (humanize != 0) {
6647 tmpbytes = (maxsector + 1) * block_len;
6648 ret = humanize_number(tmpstr, sizeof(tmpstr),
6649 tmpbytes, "", HN_AUTOSCALE,
6652 HN_DIVISOR_1000 : 0));
6654 warnx("%s: humanize_number failed!", __func__);
6658 fprintf(stdout, "Device Size: %s%s", tmpstr,
6659 (sizeonly == 0) ? ", " : "\n");
6660 } else if (numblocks != 0) {
6661 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6662 "Blocks: " : "", (uintmax_t)maxsector + 1,
6663 (sizeonly == 0) ? ", " : "\n");
6665 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6666 "Last Block: " : "", (uintmax_t)maxsector,
6667 (sizeonly == 0) ? ", " : "\n");
6671 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
6672 "Block Length: " : "", block_len, (quiet == 0) ?
6681 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
6682 int retry_count, int timeout)
6686 uint8_t *smp_request = NULL, *smp_response = NULL;
6687 int request_size = 0, response_size = 0;
6688 int fd_request = 0, fd_response = 0;
6689 char *datastr = NULL;
6690 struct get_hook hook;
6695 * Note that at the moment we don't support sending SMP CCBs to
6696 * devices that aren't probed by CAM.
6698 ccb = cam_getccb(device);
6700 warnx("%s: error allocating CCB", __func__);
6704 bzero(&(&ccb->ccb_h)[1],
6705 sizeof(union ccb) - sizeof(struct ccb_hdr));
6707 while ((c = getopt(argc, argv, combinedopt)) != -1) {
6710 arglist |= CAM_ARG_CMD_IN;
6711 response_size = strtol(optarg, NULL, 0);
6712 if (response_size <= 0) {
6713 warnx("invalid number of response bytes %d",
6716 goto smpcmd_bailout;
6718 hook.argc = argc - optind;
6719 hook.argv = argv + optind;
6722 datastr = cget(&hook, NULL);
6724 * If the user supplied "-" instead of a format, he
6725 * wants the data to be written to stdout.
6727 if ((datastr != NULL)
6728 && (datastr[0] == '-'))
6731 smp_response = (u_int8_t *)malloc(response_size);
6732 if (smp_response == NULL) {
6733 warn("can't malloc memory for SMP response");
6735 goto smpcmd_bailout;
6739 arglist |= CAM_ARG_CMD_OUT;
6740 request_size = strtol(optarg, NULL, 0);
6741 if (request_size <= 0) {
6742 warnx("invalid number of request bytes %d",
6745 goto smpcmd_bailout;
6747 hook.argc = argc - optind;
6748 hook.argv = argv + optind;
6750 datastr = cget(&hook, NULL);
6751 smp_request = (u_int8_t *)malloc(request_size);
6752 if (smp_request == NULL) {
6753 warn("can't malloc memory for SMP request");
6755 goto smpcmd_bailout;
6757 bzero(smp_request, request_size);
6759 * If the user supplied "-" instead of a format, he
6760 * wants the data to be read from stdin.
6762 if ((datastr != NULL)
6763 && (datastr[0] == '-'))
6766 buff_encode_visit(smp_request, request_size,
6777 * If fd_data is set, and we're writing to the device, we need to
6778 * read the data the user wants written from stdin.
6780 if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
6782 int amt_to_read = request_size;
6783 u_int8_t *buf_ptr = smp_request;
6785 for (amt_read = 0; amt_to_read > 0;
6786 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
6787 if (amt_read == -1) {
6788 warn("error reading data from stdin");
6790 goto smpcmd_bailout;
6792 amt_to_read -= amt_read;
6793 buf_ptr += amt_read;
6797 if (((arglist & CAM_ARG_CMD_IN) == 0)
6798 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
6799 warnx("%s: need both the request (-r) and response (-R) "
6800 "arguments", __func__);
6802 goto smpcmd_bailout;
6805 flags |= CAM_DEV_QFRZDIS;
6807 cam_fill_smpio(&ccb->smpio,
6808 /*retries*/ retry_count,
6811 /*smp_request*/ smp_request,
6812 /*smp_request_len*/ request_size,
6813 /*smp_response*/ smp_response,
6814 /*smp_response_len*/ response_size,
6815 /*timeout*/ timeout ? timeout : 5000);
6817 ccb->smpio.flags = SMP_FLAG_NONE;
6819 if (((retval = cam_send_ccb(device, ccb)) < 0)
6820 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6821 const char warnstr[] = "error sending command";
6828 if (arglist & CAM_ARG_VERBOSE) {
6829 cam_error_print(device, ccb, CAM_ESF_ALL,
6830 CAM_EPF_ALL, stderr);
6834 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
6835 && (response_size > 0)) {
6836 if (fd_response == 0) {
6837 buff_decode_visit(smp_response, response_size,
6838 datastr, arg_put, NULL);
6839 fprintf(stdout, "\n");
6841 ssize_t amt_written;
6842 int amt_to_write = response_size;
6843 u_int8_t *buf_ptr = smp_response;
6845 for (amt_written = 0; (amt_to_write > 0) &&
6846 (amt_written = write(STDOUT_FILENO, buf_ptr,
6847 amt_to_write)) > 0;){
6848 amt_to_write -= amt_written;
6849 buf_ptr += amt_written;
6851 if (amt_written == -1) {
6852 warn("error writing data to stdout");
6854 goto smpcmd_bailout;
6855 } else if ((amt_written == 0)
6856 && (amt_to_write > 0)) {
6857 warnx("only wrote %u bytes out of %u",
6858 response_size - amt_to_write,
6867 if (smp_request != NULL)
6870 if (smp_response != NULL)
6877 smpreportgeneral(struct cam_device *device, int argc, char **argv,
6878 char *combinedopt, int retry_count, int timeout)
6881 struct smp_report_general_request *request = NULL;
6882 struct smp_report_general_response *response = NULL;
6883 struct sbuf *sb = NULL;
6885 int c, long_response = 0;
6889 * Note that at the moment we don't support sending SMP CCBs to
6890 * devices that aren't probed by CAM.
6892 ccb = cam_getccb(device);
6894 warnx("%s: error allocating CCB", __func__);
6898 bzero(&(&ccb->ccb_h)[1],
6899 sizeof(union ccb) - sizeof(struct ccb_hdr));
6901 while ((c = getopt(argc, argv, combinedopt)) != -1) {
6910 request = malloc(sizeof(*request));
6911 if (request == NULL) {
6912 warn("%s: unable to allocate %zd bytes", __func__,
6918 response = malloc(sizeof(*response));
6919 if (response == NULL) {
6920 warn("%s: unable to allocate %zd bytes", __func__,
6927 smp_report_general(&ccb->smpio,
6931 /*request_len*/ sizeof(*request),
6932 (uint8_t *)response,
6933 /*response_len*/ sizeof(*response),
6934 /*long_response*/ long_response,
6937 if (((retval = cam_send_ccb(device, ccb)) < 0)
6938 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6939 const char warnstr[] = "error sending command";
6946 if (arglist & CAM_ARG_VERBOSE) {
6947 cam_error_print(device, ccb, CAM_ESF_ALL,
6948 CAM_EPF_ALL, stderr);
6955 * If the device supports the long response bit, try again and see
6956 * if we can get all of the data.
6958 if ((response->long_response & SMP_RG_LONG_RESPONSE)
6959 && (long_response == 0)) {
6960 ccb->ccb_h.status = CAM_REQ_INPROG;
6961 bzero(&(&ccb->ccb_h)[1],
6962 sizeof(union ccb) - sizeof(struct ccb_hdr));
6968 * XXX KDM detect and decode SMP errors here.
6970 sb = sbuf_new_auto();
6972 warnx("%s: error allocating sbuf", __func__);
6976 smp_report_general_sbuf(response, sizeof(*response), sb);
6978 if (sbuf_finish(sb) != 0) {
6979 warnx("%s: sbuf_finish", __func__);
6983 printf("%s", sbuf_data(sb));
6989 if (request != NULL)
6992 if (response != NULL)
7001 static struct camcontrol_opts phy_ops[] = {
7002 {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
7003 {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
7004 {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
7005 {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
7006 {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
7007 {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
7008 {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
7009 {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
7010 {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
7015 smpphycontrol(struct cam_device *device, int argc, char **argv,
7016 char *combinedopt, int retry_count, int timeout)
7019 struct smp_phy_control_request *request = NULL;
7020 struct smp_phy_control_response *response = NULL;
7021 int long_response = 0;
7024 uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
7026 uint64_t attached_dev_name = 0;
7027 int dev_name_set = 0;
7028 uint32_t min_plr = 0, max_plr = 0;
7029 uint32_t pp_timeout_val = 0;
7030 int slumber_partial = 0;
7031 int set_pp_timeout_val = 0;
7035 * Note that at the moment we don't support sending SMP CCBs to
7036 * devices that aren't probed by CAM.
7038 ccb = cam_getccb(device);
7040 warnx("%s: error allocating CCB", __func__);
7044 bzero(&(&ccb->ccb_h)[1],
7045 sizeof(union ccb) - sizeof(struct ccb_hdr));
7047 while ((c = getopt(argc, argv, combinedopt)) != -1) {
7055 if (strcasecmp(optarg, "enable") == 0)
7057 else if (strcasecmp(optarg, "disable") == 0)
7060 warnx("%s: Invalid argument %s", __func__,
7067 slumber_partial |= enable <<
7068 SMP_PC_SAS_SLUMBER_SHIFT;
7071 slumber_partial |= enable <<
7072 SMP_PC_SAS_PARTIAL_SHIFT;
7075 slumber_partial |= enable <<
7076 SMP_PC_SATA_SLUMBER_SHIFT;
7079 slumber_partial |= enable <<
7080 SMP_PC_SATA_PARTIAL_SHIFT;
7083 warnx("%s: programmer error", __func__);
7086 break; /*NOTREACHED*/
7091 attached_dev_name = (uintmax_t)strtoumax(optarg,
7100 * We don't do extensive checking here, so this
7101 * will continue to work when new speeds come out.
7103 min_plr = strtoul(optarg, NULL, 0);
7105 || (min_plr > 0xf)) {
7106 warnx("%s: invalid link rate %x",
7114 * We don't do extensive checking here, so this
7115 * will continue to work when new speeds come out.
7117 max_plr = strtoul(optarg, NULL, 0);
7119 || (max_plr > 0xf)) {
7120 warnx("%s: invalid link rate %x",
7127 camcontrol_optret optreturn;
7128 cam_argmask argnums;
7131 if (phy_op_set != 0) {
7132 warnx("%s: only one phy operation argument "
7133 "(-o) allowed", __func__);
7141 * Allow the user to specify the phy operation
7142 * numerically, as well as with a name. This will
7143 * future-proof it a bit, so options that are added
7144 * in future specs can be used.
7146 if (isdigit(optarg[0])) {
7147 phy_operation = strtoul(optarg, NULL, 0);
7148 if ((phy_operation == 0)
7149 || (phy_operation > 0xff)) {
7150 warnx("%s: invalid phy operation %#x",
7151 __func__, phy_operation);
7157 optreturn = getoption(phy_ops, optarg, &phy_operation,
7160 if (optreturn == CC_OR_AMBIGUOUS) {
7161 warnx("%s: ambiguous option %s", __func__,
7166 } else if (optreturn == CC_OR_NOT_FOUND) {
7167 warnx("%s: option %s not found", __func__,
7179 pp_timeout_val = strtoul(optarg, NULL, 0);
7180 if (pp_timeout_val > 15) {
7181 warnx("%s: invalid partial pathway timeout "
7182 "value %u, need a value less than 16",
7183 __func__, pp_timeout_val);
7187 set_pp_timeout_val = 1;
7195 warnx("%s: a PHY (-p phy) argument is required",__func__);
7200 if (((dev_name_set != 0)
7201 && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
7202 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
7203 && (dev_name_set == 0))) {
7204 warnx("%s: -d name and -o setdevname arguments both "
7205 "required to set device name", __func__);
7210 request = malloc(sizeof(*request));
7211 if (request == NULL) {
7212 warn("%s: unable to allocate %zd bytes", __func__,
7218 response = malloc(sizeof(*response));
7219 if (response == NULL) {
7220 warn("%s: unable to allocate %zd bytes", __func__,
7226 smp_phy_control(&ccb->smpio,
7231 (uint8_t *)response,
7234 /*expected_exp_change_count*/ 0,
7237 (set_pp_timeout_val != 0) ? 1 : 0,
7245 if (((retval = cam_send_ccb(device, ccb)) < 0)
7246 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7247 const char warnstr[] = "error sending command";
7254 if (arglist & CAM_ARG_VERBOSE) {
7256 * Use CAM_EPF_NORMAL so we only get one line of
7257 * SMP command decoding.
7259 cam_error_print(device, ccb, CAM_ESF_ALL,
7260 CAM_EPF_NORMAL, stderr);
7266 /* XXX KDM print out something here for success? */
7271 if (request != NULL)
7274 if (response != NULL)
7281 smpmaninfo(struct cam_device *device, int argc, char **argv,
7282 char *combinedopt, int retry_count, int timeout)
7285 struct smp_report_manuf_info_request request;
7286 struct smp_report_manuf_info_response response;
7287 struct sbuf *sb = NULL;
7288 int long_response = 0;
7293 * Note that at the moment we don't support sending SMP CCBs to
7294 * devices that aren't probed by CAM.
7296 ccb = cam_getccb(device);
7298 warnx("%s: error allocating CCB", __func__);
7302 bzero(&(&ccb->ccb_h)[1],
7303 sizeof(union ccb) - sizeof(struct ccb_hdr));
7305 while ((c = getopt(argc, argv, combinedopt)) != -1) {
7314 bzero(&request, sizeof(request));
7315 bzero(&response, sizeof(response));
7317 smp_report_manuf_info(&ccb->smpio,
7322 (uint8_t *)&response,
7327 if (((retval = cam_send_ccb(device, ccb)) < 0)
7328 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7329 const char warnstr[] = "error sending command";
7336 if (arglist & CAM_ARG_VERBOSE) {
7337 cam_error_print(device, ccb, CAM_ESF_ALL,
7338 CAM_EPF_ALL, stderr);
7344 sb = sbuf_new_auto();
7346 warnx("%s: error allocating sbuf", __func__);
7350 smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
7352 if (sbuf_finish(sb) != 0) {
7353 warnx("%s: sbuf_finish", __func__);
7357 printf("%s", sbuf_data(sb));
7371 getdevid(struct cam_devitem *item)
7374 union ccb *ccb = NULL;
7376 struct cam_device *dev;
7378 dev = cam_open_btl(item->dev_match.path_id,
7379 item->dev_match.target_id,
7380 item->dev_match.target_lun, O_RDWR, NULL);
7383 warnx("%s", cam_errbuf);
7388 item->device_id_len = 0;
7390 ccb = cam_getccb(dev);
7392 warnx("%s: error allocating CCB", __func__);
7397 bzero(&(&ccb->ccb_h)[1],
7398 sizeof(union ccb) - sizeof(struct ccb_hdr));
7401 * On the first try, we just probe for the size of the data, and
7402 * then allocate that much memory and try again.
7405 ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
7406 ccb->ccb_h.flags = CAM_DIR_IN;
7407 ccb->cdai.flags = CDAI_FLAG_NONE;
7408 ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
7409 ccb->cdai.bufsiz = item->device_id_len;
7410 if (item->device_id_len != 0)
7411 ccb->cdai.buf = (uint8_t *)item->device_id;
7413 if (cam_send_ccb(dev, ccb) < 0) {
7414 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
7419 if (ccb->ccb_h.status != CAM_REQ_CMP) {
7420 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
7425 if (item->device_id_len == 0) {
7427 * This is our first time through. Allocate the buffer,
7428 * and then go back to get the data.
7430 if (ccb->cdai.provsiz == 0) {
7431 warnx("%s: invalid .provsiz field returned with "
7432 "XPT_GDEV_ADVINFO CCB", __func__);
7436 item->device_id_len = ccb->cdai.provsiz;
7437 item->device_id = malloc(item->device_id_len);
7438 if (item->device_id == NULL) {
7439 warn("%s: unable to allocate %d bytes", __func__,
7440 item->device_id_len);
7444 ccb->ccb_h.status = CAM_REQ_INPROG;
7450 cam_close_device(dev);
7459 * XXX KDM merge this code with getdevtree()?
7462 buildbusdevlist(struct cam_devlist *devlist)
7465 int bufsize, fd = -1;
7466 struct dev_match_pattern *patterns;
7467 struct cam_devitem *item = NULL;
7468 int skip_device = 0;
7471 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
7472 warn("couldn't open %s", XPT_DEVICE);
7476 bzero(&ccb, sizeof(union ccb));
7478 ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
7479 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
7480 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
7482 ccb.ccb_h.func_code = XPT_DEV_MATCH;
7483 bufsize = sizeof(struct dev_match_result) * 100;
7484 ccb.cdm.match_buf_len = bufsize;
7485 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
7486 if (ccb.cdm.matches == NULL) {
7487 warnx("can't malloc memory for matches");
7491 ccb.cdm.num_matches = 0;
7492 ccb.cdm.num_patterns = 2;
7493 ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
7494 ccb.cdm.num_patterns;
7496 patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
7497 if (patterns == NULL) {
7498 warnx("can't malloc memory for patterns");
7503 ccb.cdm.patterns = patterns;
7504 bzero(patterns, ccb.cdm.pattern_buf_len);
7506 patterns[0].type = DEV_MATCH_DEVICE;
7507 patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
7508 patterns[0].pattern.device_pattern.path_id = devlist->path_id;
7509 patterns[1].type = DEV_MATCH_PERIPH;
7510 patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
7511 patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
7514 * We do the ioctl multiple times if necessary, in case there are
7515 * more than 100 nodes in the EDT.
7520 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
7521 warn("error sending CAMIOCOMMAND ioctl");
7526 if ((ccb.ccb_h.status != CAM_REQ_CMP)
7527 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
7528 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
7529 warnx("got CAM error %#x, CDM error %d\n",
7530 ccb.ccb_h.status, ccb.cdm.status);
7535 for (i = 0; i < ccb.cdm.num_matches; i++) {
7536 switch (ccb.cdm.matches[i].type) {
7537 case DEV_MATCH_DEVICE: {
7538 struct device_match_result *dev_result;
7541 &ccb.cdm.matches[i].result.device_result;
7543 if (dev_result->flags &
7544 DEV_RESULT_UNCONFIGURED) {
7550 item = malloc(sizeof(*item));
7552 warn("%s: unable to allocate %zd bytes",
7553 __func__, sizeof(*item));
7557 bzero(item, sizeof(*item));
7558 bcopy(dev_result, &item->dev_match,
7559 sizeof(*dev_result));
7560 STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
7563 if (getdevid(item) != 0) {
7569 case DEV_MATCH_PERIPH: {
7570 struct periph_match_result *periph_result;
7573 &ccb.cdm.matches[i].result.periph_result;
7575 if (skip_device != 0)
7577 item->num_periphs++;
7578 item->periph_matches = realloc(
7579 item->periph_matches,
7581 sizeof(struct periph_match_result));
7582 if (item->periph_matches == NULL) {
7583 warn("%s: error allocating periph "
7588 bcopy(periph_result, &item->periph_matches[
7589 item->num_periphs - 1],
7590 sizeof(*periph_result));
7594 fprintf(stderr, "%s: unexpected match "
7595 "type %d\n", __func__,
7596 ccb.cdm.matches[i].type);
7599 break; /*NOTREACHED*/
7602 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
7603 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
7611 free(ccb.cdm.matches);
7614 freebusdevlist(devlist);
7620 freebusdevlist(struct cam_devlist *devlist)
7622 struct cam_devitem *item, *item2;
7624 STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
7625 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
7627 free(item->device_id);
7628 free(item->periph_matches);
7633 static struct cam_devitem *
7634 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
7636 struct cam_devitem *item;
7638 STAILQ_FOREACH(item, &devlist->dev_queue, links) {
7639 struct scsi_vpd_id_descriptor *idd;
7642 * XXX KDM look for LUN IDs as well?
7644 idd = scsi_get_devid(item->device_id,
7645 item->device_id_len,
7646 scsi_devid_is_sas_target);
7650 if (scsi_8btou64(idd->identifier) == sasaddr)
7658 smpphylist(struct cam_device *device, int argc, char **argv,
7659 char *combinedopt, int retry_count, int timeout)
7661 struct smp_report_general_request *rgrequest = NULL;
7662 struct smp_report_general_response *rgresponse = NULL;
7663 struct smp_discover_request *disrequest = NULL;
7664 struct smp_discover_response *disresponse = NULL;
7665 struct cam_devlist devlist;
7667 int long_response = 0;
7674 * Note that at the moment we don't support sending SMP CCBs to
7675 * devices that aren't probed by CAM.
7677 ccb = cam_getccb(device);
7679 warnx("%s: error allocating CCB", __func__);
7683 bzero(&(&ccb->ccb_h)[1],
7684 sizeof(union ccb) - sizeof(struct ccb_hdr));
7685 STAILQ_INIT(&devlist.dev_queue);
7687 rgrequest = malloc(sizeof(*rgrequest));
7688 if (rgrequest == NULL) {
7689 warn("%s: unable to allocate %zd bytes", __func__,
7690 sizeof(*rgrequest));
7695 rgresponse = malloc(sizeof(*rgresponse));
7696 if (rgresponse == NULL) {
7697 warn("%s: unable to allocate %zd bytes", __func__,
7698 sizeof(*rgresponse));
7703 while ((c = getopt(argc, argv, combinedopt)) != -1) {
7716 smp_report_general(&ccb->smpio,
7720 /*request_len*/ sizeof(*rgrequest),
7721 (uint8_t *)rgresponse,
7722 /*response_len*/ sizeof(*rgresponse),
7723 /*long_response*/ long_response,
7726 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7728 if (((retval = cam_send_ccb(device, ccb)) < 0)
7729 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7730 const char warnstr[] = "error sending command";
7737 if (arglist & CAM_ARG_VERBOSE) {
7738 cam_error_print(device, ccb, CAM_ESF_ALL,
7739 CAM_EPF_ALL, stderr);
7745 num_phys = rgresponse->num_phys;
7747 if (num_phys == 0) {
7749 fprintf(stdout, "%s: No Phys reported\n", __func__);
7754 devlist.path_id = device->path_id;
7756 retval = buildbusdevlist(&devlist);
7761 fprintf(stdout, "%d PHYs:\n", num_phys);
7762 fprintf(stdout, "PHY Attached SAS Address\n");
7765 disrequest = malloc(sizeof(*disrequest));
7766 if (disrequest == NULL) {
7767 warn("%s: unable to allocate %zd bytes", __func__,
7768 sizeof(*disrequest));
7773 disresponse = malloc(sizeof(*disresponse));
7774 if (disresponse == NULL) {
7775 warn("%s: unable to allocate %zd bytes", __func__,
7776 sizeof(*disresponse));
7781 for (i = 0; i < num_phys; i++) {
7782 struct cam_devitem *item;
7783 struct device_match_result *dev_match;
7784 char vendor[16], product[48], revision[16];
7788 bzero(&(&ccb->ccb_h)[1],
7789 sizeof(union ccb) - sizeof(struct ccb_hdr));
7791 ccb->ccb_h.status = CAM_REQ_INPROG;
7792 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7794 smp_discover(&ccb->smpio,
7798 sizeof(*disrequest),
7799 (uint8_t *)disresponse,
7800 sizeof(*disresponse),
7802 /*ignore_zone_group*/ 0,
7806 if (((retval = cam_send_ccb(device, ccb)) < 0)
7807 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
7808 && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
7809 const char warnstr[] = "error sending command";
7816 if (arglist & CAM_ARG_VERBOSE) {
7817 cam_error_print(device, ccb, CAM_ESF_ALL,
7818 CAM_EPF_ALL, stderr);
7824 if (disresponse->function_result == SMP_FR_PHY_VACANT) {
7826 fprintf(stdout, "%3d <vacant>\n", i);
7830 if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) {
7833 item = findsasdevice(&devlist,
7834 scsi_8btou64(disresponse->attached_sas_address));
7838 || (item != NULL)) {
7839 fprintf(stdout, "%3d 0x%016jx", i,
7840 (uintmax_t)scsi_8btou64(
7841 disresponse->attached_sas_address));
7843 fprintf(stdout, "\n");
7846 } else if (quiet != 0)
7849 dev_match = &item->dev_match;
7851 if (dev_match->protocol == PROTO_SCSI) {
7852 cam_strvis(vendor, dev_match->inq_data.vendor,
7853 sizeof(dev_match->inq_data.vendor),
7855 cam_strvis(product, dev_match->inq_data.product,
7856 sizeof(dev_match->inq_data.product),
7858 cam_strvis(revision, dev_match->inq_data.revision,
7859 sizeof(dev_match->inq_data.revision),
7861 sprintf(tmpstr, "<%s %s %s>", vendor, product,
7863 } else if ((dev_match->protocol == PROTO_ATA)
7864 || (dev_match->protocol == PROTO_SATAPM)) {
7865 cam_strvis(product, dev_match->ident_data.model,
7866 sizeof(dev_match->ident_data.model),
7868 cam_strvis(revision, dev_match->ident_data.revision,
7869 sizeof(dev_match->ident_data.revision),
7871 sprintf(tmpstr, "<%s %s>", product, revision);
7873 sprintf(tmpstr, "<>");
7875 fprintf(stdout, " %-33s ", tmpstr);
7878 * If we have 0 periphs, that's a bug...
7880 if (item->num_periphs == 0) {
7881 fprintf(stdout, "\n");
7885 fprintf(stdout, "(");
7886 for (j = 0; j < item->num_periphs; j++) {
7888 fprintf(stdout, ",");
7890 fprintf(stdout, "%s%d",
7891 item->periph_matches[j].periph_name,
7892 item->periph_matches[j].unit_number);
7895 fprintf(stdout, ")\n");
7909 freebusdevlist(&devlist);
7915 atapm(struct cam_device *device, int argc, char **argv,
7916 char *combinedopt, int retry_count, int timeout)
7924 ccb = cam_getccb(device);
7927 warnx("%s: error allocating ccb", __func__);
7931 while ((c = getopt(argc, argv, combinedopt)) != -1) {
7940 if (strcmp(argv[1], "idle") == 0) {
7942 cmd = ATA_IDLE_IMMEDIATE;
7945 } else if (strcmp(argv[1], "standby") == 0) {
7947 cmd = ATA_STANDBY_IMMEDIATE;
7949 cmd = ATA_STANDBY_CMD;
7957 else if (t <= (240 * 5))
7959 else if (t <= (252 * 5))
7960 /* special encoding for 21 minutes */
7962 else if (t <= (11 * 30 * 60))
7963 sc = (t - 1) / (30 * 60) + 241;
7967 cam_fill_ataio(&ccb->ataio,
7970 /*flags*/CAM_DIR_NONE,
7974 timeout ? timeout : 30 * 1000);
7975 ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
7977 /* Disable freezing the device queue */
7978 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7980 if (arglist & CAM_ARG_ERR_RECOVER)
7981 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
7983 if (cam_send_ccb(device, ccb) < 0) {
7984 warn("error sending command");
7986 if (arglist & CAM_ARG_VERBOSE)
7987 cam_error_print(device, ccb, CAM_ESF_ALL,
7988 CAM_EPF_ALL, stderr);
7994 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
7995 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
8004 #endif /* MINIMALISTIC */
8007 usage(int printlong)
8010 fprintf(printlong ? stdout : stderr,
8011 "usage: camcontrol <command> [device id][generic args][command args]\n"
8012 " camcontrol devlist [-v]\n"
8013 #ifndef MINIMALISTIC
8014 " camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
8015 " camcontrol tur [dev_id][generic args]\n"
8016 " camcontrol inquiry [dev_id][generic args] [-D] [-S] [-R]\n"
8017 " camcontrol identify [dev_id][generic args] [-v]\n"
8018 " camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
8019 " camcontrol readcap [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
8021 " camcontrol start [dev_id][generic args]\n"
8022 " camcontrol stop [dev_id][generic args]\n"
8023 " camcontrol load [dev_id][generic args]\n"
8024 " camcontrol eject [dev_id][generic args]\n"
8025 #endif /* MINIMALISTIC */
8026 " camcontrol rescan <all | bus[:target:lun]>\n"
8027 " camcontrol reset <all | bus[:target:lun]>\n"
8028 #ifndef MINIMALISTIC
8029 " camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n"
8030 " [-q][-s][-S offset][-X]\n"
8031 " camcontrol modepage [dev_id][generic args] <-m page | -l>\n"
8032 " [-P pagectl][-e | -b][-d]\n"
8033 " camcontrol cmd [dev_id][generic args]\n"
8034 " <-a cmd [args] | -c cmd [args]>\n"
8035 " [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
8036 " camcontrol smpcmd [dev_id][generic args]\n"
8037 " <-r len fmt [args]> <-R len fmt [args]>\n"
8038 " camcontrol smprg [dev_id][generic args][-l]\n"
8039 " camcontrol smppc [dev_id][generic args] <-p phy> [-l]\n"
8040 " [-o operation][-d name][-m rate][-M rate]\n"
8041 " [-T pp_timeout][-a enable|disable]\n"
8042 " [-A enable|disable][-s enable|disable]\n"
8043 " [-S enable|disable]\n"
8044 " camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
8045 " camcontrol smpmaninfo [dev_id][generic args][-l]\n"
8046 " camcontrol debug [-I][-P][-T][-S][-X][-c]\n"
8047 " <all|bus[:target[:lun]]|off>\n"
8048 " camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n"
8049 " camcontrol negotiate [dev_id][generic args] [-a][-c]\n"
8050 " [-D <enable|disable>][-M mode][-O offset]\n"
8051 " [-q][-R syncrate][-v][-T <enable|disable>]\n"
8052 " [-U][-W bus_width]\n"
8053 " camcontrol format [dev_id][generic args][-q][-r][-w][-y]\n"
8054 " camcontrol sanitize [dev_id][generic args]\n"
8055 " [-a overwrite|block|crypto|exitfailure]\n"
8056 " [-c passes][-I][-P pattern][-q][-U][-r][-w]\n"
8058 " camcontrol idle [dev_id][generic args][-t time]\n"
8059 " camcontrol standby [dev_id][generic args][-t time]\n"
8060 " camcontrol sleep [dev_id][generic args]\n"
8061 " camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-y][-s]\n"
8062 " camcontrol security [dev_id][generic args]\n"
8063 " <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
8064 " [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
8065 " [-U <user|master>] [-y]\n"
8066 " camcontrol hpa [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n"
8067 " [-q] [-s max_sectors] [-U pwd] [-y]\n"
8068 " camcontrol persist [dev_id][generic args] <-i action|-o action>\n"
8069 " [-a][-I tid][-k key][-K sa_key][-p][-R rtp]\n"
8070 " [-s scope][-S][-T type][-U]\n"
8071 #endif /* MINIMALISTIC */
8072 " camcontrol help\n");
8075 #ifndef MINIMALISTIC
8077 "Specify one of the following options:\n"
8078 "devlist list all CAM devices\n"
8079 "periphlist list all CAM peripheral drivers attached to a device\n"
8080 "tur send a test unit ready to the named device\n"
8081 "inquiry send a SCSI inquiry command to the named device\n"
8082 "identify send a ATA identify command to the named device\n"
8083 "reportluns send a SCSI report luns command to the device\n"
8084 "readcap send a SCSI read capacity command to the device\n"
8085 "start send a Start Unit command to the device\n"
8086 "stop send a Stop Unit command to the device\n"
8087 "load send a Start Unit command to the device with the load bit set\n"
8088 "eject send a Stop Unit command to the device with the eject bit set\n"
8089 "rescan rescan all busses, the given bus, or bus:target:lun\n"
8090 "reset reset all busses, the given bus, or bus:target:lun\n"
8091 "defects read the defect list of the specified device\n"
8092 "modepage display or edit (-e) the given mode page\n"
8093 "cmd send the given SCSI command, may need -i or -o as well\n"
8094 "smpcmd send the given SMP command, requires -o and -i\n"
8095 "smprg send the SMP Report General command\n"
8096 "smppc send the SMP PHY Control command, requires -p\n"
8097 "smpphylist display phys attached to a SAS expander\n"
8098 "smpmaninfo send the SMP Report Manufacturer Info command\n"
8099 "debug turn debugging on/off for a bus, target, or lun, or all devices\n"
8100 "tags report or set the number of transaction slots for a device\n"
8101 "negotiate report or set device negotiation parameters\n"
8102 "format send the SCSI FORMAT UNIT command to the named device\n"
8103 "sanitize send the SCSI SANITIZE command to the named device\n"
8104 "idle send the ATA IDLE command to the named device\n"
8105 "standby send the ATA STANDBY command to the named device\n"
8106 "sleep send the ATA SLEEP command to the named device\n"
8107 "fwdownload program firmware of the named device with the given image\n"
8108 "security report or send ATA security commands to the named device\n"
8109 "persist send the SCSI PERSISTENT RESERVE IN or OUT commands\n"
8110 "help this message\n"
8111 "Device Identifiers:\n"
8112 "bus:target specify the bus and target, lun defaults to 0\n"
8113 "bus:target:lun specify the bus, target and lun\n"
8114 "deviceUNIT specify the device name, like \"da4\" or \"cd2\"\n"
8115 "Generic arguments:\n"
8116 "-v be verbose, print out sense information\n"
8117 "-t timeout command timeout in seconds, overrides default timeout\n"
8118 "-n dev_name specify device name, e.g. \"da\", \"cd\"\n"
8119 "-u unit specify unit number, e.g. \"0\", \"5\"\n"
8120 "-E have the kernel attempt to perform SCSI error recovery\n"
8121 "-C count specify the SCSI command retry count (needs -E to work)\n"
8122 "modepage arguments:\n"
8123 "-l list all available mode pages\n"
8124 "-m page specify the mode page to view or edit\n"
8125 "-e edit the specified mode page\n"
8126 "-b force view to binary mode\n"
8127 "-d disable block descriptors for mode sense\n"
8128 "-P pgctl page control field 0-3\n"
8129 "defects arguments:\n"
8130 "-f format specify defect list format (block, bfi or phys)\n"
8131 "-G get the grown defect list\n"
8132 "-P get the permanent defect list\n"
8133 "inquiry arguments:\n"
8134 "-D get the standard inquiry data\n"
8135 "-S get the serial number\n"
8136 "-R get the transfer rate, etc.\n"
8137 "reportluns arguments:\n"
8138 "-c only report a count of available LUNs\n"
8139 "-l only print out luns, and not a count\n"
8140 "-r <reporttype> specify \"default\", \"wellknown\" or \"all\"\n"
8141 "readcap arguments\n"
8142 "-b only report the blocksize\n"
8143 "-h human readable device size, base 2\n"
8144 "-H human readable device size, base 10\n"
8145 "-N print the number of blocks instead of last block\n"
8146 "-q quiet, print numbers only\n"
8147 "-s only report the last block/device size\n"
8149 "-c cdb [args] specify the SCSI CDB\n"
8150 "-i len fmt specify input data and input data format\n"
8151 "-o len fmt [args] specify output data and output data fmt\n"
8152 "smpcmd arguments:\n"
8153 "-r len fmt [args] specify the SMP command to be sent\n"
8154 "-R len fmt [args] specify SMP response format\n"
8155 "smprg arguments:\n"
8156 "-l specify the long response format\n"
8157 "smppc arguments:\n"
8158 "-p phy specify the PHY to operate on\n"
8159 "-l specify the long request/response format\n"
8160 "-o operation specify the phy control operation\n"
8161 "-d name set the attached device name\n"
8162 "-m rate set the minimum physical link rate\n"
8163 "-M rate set the maximum physical link rate\n"
8164 "-T pp_timeout set the partial pathway timeout value\n"
8165 "-a enable|disable enable or disable SATA slumber\n"
8166 "-A enable|disable enable or disable SATA partial phy power\n"
8167 "-s enable|disable enable or disable SAS slumber\n"
8168 "-S enable|disable enable or disable SAS partial phy power\n"
8169 "smpphylist arguments:\n"
8170 "-l specify the long response format\n"
8171 "-q only print phys with attached devices\n"
8172 "smpmaninfo arguments:\n"
8173 "-l specify the long response format\n"
8174 "debug arguments:\n"
8175 "-I CAM_DEBUG_INFO -- scsi commands, errors, data\n"
8176 "-T CAM_DEBUG_TRACE -- routine flow tracking\n"
8177 "-S CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
8178 "-c CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
8180 "-N tags specify the number of tags to use for this device\n"
8181 "-q be quiet, don't report the number of tags\n"
8182 "-v report a number of tag-related parameters\n"
8183 "negotiate arguments:\n"
8184 "-a send a test unit ready after negotiation\n"
8185 "-c report/set current negotiation settings\n"
8186 "-D <arg> \"enable\" or \"disable\" disconnection\n"
8187 "-M mode set ATA mode\n"
8188 "-O offset set command delay offset\n"
8189 "-q be quiet, don't report anything\n"
8190 "-R syncrate synchronization rate in MHz\n"
8191 "-T <arg> \"enable\" or \"disable\" tagged queueing\n"
8192 "-U report/set user negotiation settings\n"
8193 "-W bus_width set the bus width in bits (8, 16 or 32)\n"
8194 "-v also print a Path Inquiry CCB for the controller\n"
8195 "format arguments:\n"
8196 "-q be quiet, don't print status messages\n"
8197 "-r run in report only mode\n"
8198 "-w don't send immediate format command\n"
8199 "-y don't ask any questions\n"
8200 "sanitize arguments:\n"
8201 "-a operation operation mode: overwrite, block, crypto or exitfailure\n"
8202 "-c passes overwrite passes to perform (1 to 31)\n"
8203 "-I invert overwrite pattern after each pass\n"
8204 "-P pattern path to overwrite pattern file\n"
8205 "-q be quiet, don't print status messages\n"
8206 "-r run in report only mode\n"
8207 "-U run operation in unrestricted completion exit mode\n"
8208 "-w don't send immediate sanitize command\n"
8209 "-y don't ask any questions\n"
8210 "idle/standby arguments:\n"
8211 "-t <arg> number of seconds before respective state.\n"
8212 "fwdownload arguments:\n"
8213 "-f fw_image path to firmware image file\n"
8214 "-y don't ask any questions\n"
8215 "-s run in simulation mode\n"
8216 "-v print info for every firmware segment sent to device\n"
8217 "security arguments:\n"
8218 "-d pwd disable security using the given password for the selected\n"
8220 "-e pwd erase the device using the given pwd for the selected user\n"
8221 "-f freeze the security configuration of the specified device\n"
8222 "-h pwd enhanced erase the device using the given pwd for the\n"
8224 "-k pwd unlock the device using the given pwd for the selected\n"
8226 "-l <high|maximum> specifies which security level to set: high or maximum\n"
8227 "-q be quiet, do not print any status messages\n"
8228 "-s pwd password the device (enable security) using the given\n"
8229 " pwd for the selected user\n"
8230 "-T timeout overrides the timeout (seconds) used for erase operation\n"
8231 "-U <user|master> specifies which user to set: user or master\n"
8232 "-y don't ask any questions\n"
8234 "-f freeze the HPA configuration of the device\n"
8235 "-l lock the HPA configuration of the device\n"
8236 "-P make the HPA max sectors persist\n"
8237 "-p pwd Set the HPA configuration password required for unlock\n"
8239 "-q be quiet, do not print any status messages\n"
8240 "-s sectors configures the maximum user accessible sectors of the\n"
8242 "-U pwd unlock the HPA configuration of the device\n"
8243 "-y don't ask any questions\n"
8244 "persist arguments:\n"
8245 "-i action specify read_keys, read_reservation, report_cap, or\n"
8246 " read_full_status\n"
8247 "-o action specify register, register_ignore, reserve, release,\n"
8248 " clear, preempt, preempt_abort, register_move, replace_lost\n"
8249 "-a set the All Target Ports (ALL_TG_PT) bit\n"
8250 "-I tid specify a Transport ID, e.g.: sas,0x1234567812345678\n"
8251 "-k key specify the Reservation Key\n"
8252 "-K sa_key specify the Service Action Reservation Key\n"
8253 "-p set the Activate Persist Through Power Loss bit\n"
8254 "-R rtp specify the Relative Target Port\n"
8255 "-s scope specify the scope: lun, extent, element or a number\n"
8256 "-S specify Transport ID for register, requires -I\n"
8257 "-T res_type specify the reservation type: read_shared, wr_ex, rd_ex,\n"
8258 " ex_ac, wr_ex_ro, ex_ac_ro, wr_ex_ar, ex_ac_ar\n"
8259 "-U unregister the current initiator for register_move\n"
8261 #endif /* MINIMALISTIC */
8265 main(int argc, char **argv)
8268 char *device = NULL;
8270 struct cam_device *cam_dev = NULL;
8271 int timeout = 0, retry_count = 1;
8272 camcontrol_optret optreturn;
8274 const char *mainopt = "C:En:t:u:v";
8275 const char *subopt = NULL;
8276 char combinedopt[256];
8277 int error = 0, optstart = 2;
8279 #ifndef MINIMALISTIC
8283 #endif /* MINIMALISTIC */
8285 cmdlist = CAM_CMD_NONE;
8286 arglist = CAM_ARG_NONE;
8294 * Get the base option.
8296 optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
8298 if (optreturn == CC_OR_AMBIGUOUS) {
8299 warnx("ambiguous option %s", argv[1]);
8302 } else if (optreturn == CC_OR_NOT_FOUND) {
8303 warnx("option %s not found", argv[1]);
8309 * Ahh, getopt(3) is a pain.
8311 * This is a gross hack. There really aren't many other good
8312 * options (excuse the pun) for parsing options in a situation like
8313 * this. getopt is kinda braindead, so you end up having to run
8314 * through the options twice, and give each invocation of getopt
8315 * the option string for the other invocation.
8317 * You would think that you could just have two groups of options.
8318 * The first group would get parsed by the first invocation of
8319 * getopt, and the second group would get parsed by the second
8320 * invocation of getopt. It doesn't quite work out that way. When
8321 * the first invocation of getopt finishes, it leaves optind pointing
8322 * to the argument _after_ the first argument in the second group.
8323 * So when the second invocation of getopt comes around, it doesn't
8324 * recognize the first argument it gets and then bails out.
8326 * A nice alternative would be to have a flag for getopt that says
8327 * "just keep parsing arguments even when you encounter an unknown
8328 * argument", but there isn't one. So there's no real clean way to
8329 * easily parse two sets of arguments without having one invocation
8330 * of getopt know about the other.
8332 * Without this hack, the first invocation of getopt would work as
8333 * long as the generic arguments are first, but the second invocation
8334 * (in the subfunction) would fail in one of two ways. In the case
8335 * where you don't set optreset, it would fail because optind may be
8336 * pointing to the argument after the one it should be pointing at.
8337 * In the case where you do set optreset, and reset optind, it would
8338 * fail because getopt would run into the first set of options, which
8339 * it doesn't understand.
8341 * All of this would "sort of" work if you could somehow figure out
8342 * whether optind had been incremented one option too far. The
8343 * mechanics of that, however, are more daunting than just giving
8344 * both invocations all of the expect options for either invocation.
8346 * Needless to say, I wouldn't mind if someone invented a better
8347 * (non-GPL!) command line parsing interface than getopt. I
8348 * wouldn't mind if someone added more knobs to getopt to make it
8349 * work better. Who knows, I may talk myself into doing it someday,
8350 * if the standards weenies let me. As it is, it just leads to
8351 * hackery like this and causes people to avoid it in some cases.
8353 * KDM, September 8th, 1998
8356 sprintf(combinedopt, "%s%s", mainopt, subopt);
8358 sprintf(combinedopt, "%s", mainopt);
8361 * For these options we do not parse optional device arguments and
8362 * we do not open a passthrough device.
8364 if ((cmdlist == CAM_CMD_RESCAN)
8365 || (cmdlist == CAM_CMD_RESET)
8366 || (cmdlist == CAM_CMD_DEVTREE)
8367 || (cmdlist == CAM_CMD_USAGE)
8368 || (cmdlist == CAM_CMD_DEBUG))
8371 #ifndef MINIMALISTIC
8373 && (argc > 2 && argv[2][0] != '-')) {
8377 if (isdigit(argv[2][0])) {
8378 /* device specified as bus:target[:lun] */
8379 rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
8381 errx(1, "numeric device specification must "
8382 "be either bus:target, or "
8384 /* default to 0 if lun was not specified */
8385 if ((arglist & CAM_ARG_LUN) == 0) {
8387 arglist |= CAM_ARG_LUN;
8391 if (cam_get_device(argv[2], name, sizeof name, &unit)
8393 errx(1, "%s", cam_errbuf);
8394 device = strdup(name);
8395 arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
8399 #endif /* MINIMALISTIC */
8401 * Start getopt processing at argv[2/3], since we've already
8402 * accepted argv[1..2] as the command name, and as a possible
8408 * Now we run through the argument list looking for generic
8409 * options, and ignoring options that possibly belong to
8412 while ((c = getopt(argc, argv, combinedopt))!= -1){
8415 retry_count = strtol(optarg, NULL, 0);
8416 if (retry_count < 0)
8417 errx(1, "retry count %d is < 0",
8419 arglist |= CAM_ARG_RETRIES;
8422 arglist |= CAM_ARG_ERR_RECOVER;
8425 arglist |= CAM_ARG_DEVICE;
8427 while (isspace(*tstr) && (*tstr != '\0'))
8429 device = (char *)strdup(tstr);
8432 timeout = strtol(optarg, NULL, 0);
8434 errx(1, "invalid timeout %d", timeout);
8435 /* Convert the timeout from seconds to ms */
8437 arglist |= CAM_ARG_TIMEOUT;
8440 arglist |= CAM_ARG_UNIT;
8441 unit = strtol(optarg, NULL, 0);
8444 arglist |= CAM_ARG_VERBOSE;
8451 #ifndef MINIMALISTIC
8453 * For most commands we'll want to open the passthrough device
8454 * associated with the specified device. In the case of the rescan
8455 * commands, we don't use a passthrough device at all, just the
8456 * transport layer device.
8459 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
8460 && (((arglist & CAM_ARG_DEVICE) == 0)
8461 || ((arglist & CAM_ARG_UNIT) == 0))) {
8462 errx(1, "subcommand \"%s\" requires a valid device "
8463 "identifier", argv[1]);
8466 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
8467 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
8468 cam_open_spec_device(device,unit,O_RDWR,NULL)))
8470 errx(1,"%s", cam_errbuf);
8472 #endif /* MINIMALISTIC */
8475 * Reset optind to 2, and reset getopt, so these routines can parse
8476 * the arguments again.
8482 #ifndef MINIMALISTIC
8483 case CAM_CMD_DEVLIST:
8484 error = getdevlist(cam_dev);
8487 error = atahpa(cam_dev, retry_count, timeout,
8488 argc, argv, combinedopt);
8490 #endif /* MINIMALISTIC */
8491 case CAM_CMD_DEVTREE:
8492 error = getdevtree(argc, argv, combinedopt);
8494 #ifndef MINIMALISTIC
8496 error = testunitready(cam_dev, retry_count, timeout, 0);
8498 case CAM_CMD_INQUIRY:
8499 error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
8500 retry_count, timeout);
8502 case CAM_CMD_IDENTIFY:
8503 error = ataidentify(cam_dev, retry_count, timeout);
8505 case CAM_CMD_STARTSTOP:
8506 error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
8507 arglist & CAM_ARG_EJECT, retry_count,
8510 #endif /* MINIMALISTIC */
8511 case CAM_CMD_RESCAN:
8512 error = dorescan_or_reset(argc, argv, 1);
8515 error = dorescan_or_reset(argc, argv, 0);
8517 #ifndef MINIMALISTIC
8518 case CAM_CMD_READ_DEFECTS:
8519 error = readdefects(cam_dev, argc, argv, combinedopt,
8520 retry_count, timeout);
8522 case CAM_CMD_MODE_PAGE:
8523 modepage(cam_dev, argc, argv, combinedopt,
8524 retry_count, timeout);
8526 case CAM_CMD_SCSI_CMD:
8527 error = scsicmd(cam_dev, argc, argv, combinedopt,
8528 retry_count, timeout);
8530 case CAM_CMD_SMP_CMD:
8531 error = smpcmd(cam_dev, argc, argv, combinedopt,
8532 retry_count, timeout);
8534 case CAM_CMD_SMP_RG:
8535 error = smpreportgeneral(cam_dev, argc, argv,
8536 combinedopt, retry_count,
8539 case CAM_CMD_SMP_PC:
8540 error = smpphycontrol(cam_dev, argc, argv, combinedopt,
8541 retry_count, timeout);
8543 case CAM_CMD_SMP_PHYLIST:
8544 error = smpphylist(cam_dev, argc, argv, combinedopt,
8545 retry_count, timeout);
8547 case CAM_CMD_SMP_MANINFO:
8548 error = smpmaninfo(cam_dev, argc, argv, combinedopt,
8549 retry_count, timeout);
8552 error = camdebug(argc, argv, combinedopt);
8555 error = tagcontrol(cam_dev, argc, argv, combinedopt);
8558 error = ratecontrol(cam_dev, retry_count, timeout,
8559 argc, argv, combinedopt);
8561 case CAM_CMD_FORMAT:
8562 error = scsiformat(cam_dev, argc, argv,
8563 combinedopt, retry_count, timeout);
8565 case CAM_CMD_REPORTLUNS:
8566 error = scsireportluns(cam_dev, argc, argv,
8567 combinedopt, retry_count,
8570 case CAM_CMD_READCAP:
8571 error = scsireadcapacity(cam_dev, argc, argv,
8572 combinedopt, retry_count,
8576 case CAM_CMD_STANDBY:
8578 error = atapm(cam_dev, argc, argv,
8579 combinedopt, retry_count, timeout);
8581 case CAM_CMD_SECURITY:
8582 error = atasecurity(cam_dev, retry_count, timeout,
8583 argc, argv, combinedopt);
8585 case CAM_CMD_DOWNLOAD_FW:
8586 error = fwdownload(cam_dev, argc, argv, combinedopt,
8587 arglist & CAM_ARG_VERBOSE, retry_count, timeout,
8588 get_disk_type(cam_dev));
8590 case CAM_CMD_SANITIZE:
8591 error = scsisanitize(cam_dev, argc, argv,
8592 combinedopt, retry_count, timeout);
8594 case CAM_CMD_PERSIST:
8595 error = scsipersist(cam_dev, argc, argv, combinedopt,
8596 retry_count, timeout, arglist & CAM_ARG_VERBOSE,
8597 arglist & CAM_ARG_ERR_RECOVER);
8599 #endif /* MINIMALISTIC */
8609 if (cam_dev != NULL)
8610 cam_close_device(cam_dev);