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:GP";
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 readdefects(struct cam_device *device, int argc, char **argv,
3374 char *combinedopt, int retry_count, int timeout)
3376 union ccb *ccb = NULL;
3377 struct scsi_read_defect_data_10 *rdd_cdb;
3378 u_int8_t *defect_list = NULL;
3379 u_int32_t max_dlist_length = SRDD10_MAX_LENGTH, dlist_length = 0;
3380 u_int32_t returned_length = 0;
3381 u_int32_t num_returned = 0;
3382 u_int8_t returned_format;
3385 int lists_specified;
3388 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3394 while (isspace(*tstr) && (*tstr != '\0'))
3396 if (strcmp(tstr, "block") == 0)
3397 arglist |= CAM_ARG_FORMAT_BLOCK;
3398 else if (strcmp(tstr, "bfi") == 0)
3399 arglist |= CAM_ARG_FORMAT_BFI;
3400 else if (strcmp(tstr, "phys") == 0)
3401 arglist |= CAM_ARG_FORMAT_PHYS;
3404 warnx("invalid defect format %s", tstr);
3405 goto defect_bailout;
3410 arglist |= CAM_ARG_GLIST;
3413 arglist |= CAM_ARG_PLIST;
3420 ccb = cam_getccb(device);
3423 * Eventually we should probably support the 12 byte READ DEFECT
3424 * DATA command. It supports a longer parameter list, which may be
3425 * necessary on newer drives with lots of defects. According to
3426 * the SBC-3 spec, drives are supposed to return an illegal request
3427 * if they have more defect data than will fit in 64K.
3429 defect_list = malloc(max_dlist_length);
3430 if (defect_list == NULL) {
3431 warnx("can't malloc memory for defect list");
3433 goto defect_bailout;
3437 * We start off asking for just the header to determine how much
3438 * defect data is available. Some Hitachi drives return an error
3439 * if you ask for more data than the drive has. Once we know the
3440 * length, we retry the command with the returned length.
3442 dlist_length = sizeof(struct scsi_read_defect_data_hdr_10);
3444 rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
3448 lists_specified = 0;
3451 * cam_getccb() zeros the CCB header only. So we need to zero the
3452 * payload portion of the ccb.
3454 bzero(&(&ccb->ccb_h)[1],
3455 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3457 cam_fill_csio(&ccb->csio,
3458 /*retries*/ retry_count,
3460 /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
3461 CAM_PASS_ERR_RECOVER : 0),
3462 /*tag_action*/ MSG_SIMPLE_Q_TAG,
3463 /*data_ptr*/ defect_list,
3464 /*dxfer_len*/ dlist_length,
3465 /*sense_len*/ SSD_FULL_SIZE,
3466 /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
3467 /*timeout*/ timeout ? timeout : 5000);
3469 rdd_cdb->opcode = READ_DEFECT_DATA_10;
3470 if (arglist & CAM_ARG_FORMAT_BLOCK)
3471 rdd_cdb->format = SRDD10_BLOCK_FORMAT;
3472 else if (arglist & CAM_ARG_FORMAT_BFI)
3473 rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
3474 else if (arglist & CAM_ARG_FORMAT_PHYS)
3475 rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
3478 warnx("no defect list format specified");
3479 goto defect_bailout;
3481 if (arglist & CAM_ARG_PLIST) {
3482 rdd_cdb->format |= SRDD10_PLIST;
3486 if (arglist & CAM_ARG_GLIST) {
3487 rdd_cdb->format |= SRDD10_GLIST;
3491 scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
3493 /* Disable freezing the device queue */
3494 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3496 if (cam_send_ccb(device, ccb) < 0) {
3497 perror("error reading defect list");
3499 if (arglist & CAM_ARG_VERBOSE) {
3500 cam_error_print(device, ccb, CAM_ESF_ALL,
3501 CAM_EPF_ALL, stderr);
3505 goto defect_bailout;
3508 returned_length = scsi_2btoul(((struct
3509 scsi_read_defect_data_hdr_10 *)defect_list)->length);
3511 if (get_length != 0) {
3514 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
3515 CAM_SCSI_STATUS_ERROR) {
3516 struct scsi_sense_data *sense;
3517 int error_code, sense_key, asc, ascq;
3519 sense = &ccb->csio.sense_data;
3520 scsi_extract_sense_len(sense, ccb->csio.sense_len -
3521 ccb->csio.sense_resid, &error_code, &sense_key,
3522 &asc, &ascq, /*show_errors*/ 1);
3525 * If the drive is reporting that it just doesn't
3526 * support the defect list format, go ahead and use
3527 * the length it reported. Otherwise, the length
3528 * may not be valid, so use the maximum.
3530 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3531 && (asc == 0x1c) && (ascq == 0x00)
3532 && (returned_length > 0)) {
3533 dlist_length = returned_length +
3534 sizeof(struct scsi_read_defect_data_hdr_10);
3535 dlist_length = min(dlist_length,
3538 dlist_length = max_dlist_length;
3539 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
3542 warnx("Error reading defect header");
3543 if (arglist & CAM_ARG_VERBOSE)
3544 cam_error_print(device, ccb, CAM_ESF_ALL,
3545 CAM_EPF_ALL, stderr);
3546 goto defect_bailout;
3548 dlist_length = returned_length +
3549 sizeof(struct scsi_read_defect_data_hdr_10);
3550 dlist_length = min(dlist_length, SRDD10_MAX_LENGTH);
3556 returned_format = ((struct scsi_read_defect_data_hdr_10 *)
3557 defect_list)->format;
3559 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
3560 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
3561 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3562 struct scsi_sense_data *sense;
3563 int error_code, sense_key, asc, ascq;
3565 sense = &ccb->csio.sense_data;
3566 scsi_extract_sense_len(sense, ccb->csio.sense_len -
3567 ccb->csio.sense_resid, &error_code, &sense_key, &asc,
3568 &ascq, /*show_errors*/ 1);
3571 * According to the SCSI spec, if the disk doesn't support
3572 * the requested format, it will generally return a sense
3573 * key of RECOVERED ERROR, and an additional sense code
3574 * of "DEFECT LIST NOT FOUND". So, we check for that, and
3575 * also check to make sure that the returned length is
3576 * greater than 0, and then print out whatever format the
3579 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3580 && (asc == 0x1c) && (ascq == 0x00)
3581 && (returned_length > 0)) {
3582 warnx("requested defect format not available");
3583 switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
3584 case SRDD10_BLOCK_FORMAT:
3585 warnx("Device returned block format");
3587 case SRDD10_BYTES_FROM_INDEX_FORMAT:
3588 warnx("Device returned bytes from index"
3591 case SRDD10_PHYSICAL_SECTOR_FORMAT:
3592 warnx("Device returned physical sector format");
3596 warnx("Device returned unknown defect"
3597 " data format %#x", returned_format);
3598 goto defect_bailout;
3599 break; /* NOTREACHED */
3603 warnx("Error returned from read defect data command");
3604 if (arglist & CAM_ARG_VERBOSE)
3605 cam_error_print(device, ccb, CAM_ESF_ALL,
3606 CAM_EPF_ALL, stderr);
3607 goto defect_bailout;
3609 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3611 warnx("Error returned from read defect data command");
3612 if (arglist & CAM_ARG_VERBOSE)
3613 cam_error_print(device, ccb, CAM_ESF_ALL,
3614 CAM_EPF_ALL, stderr);
3615 goto defect_bailout;
3619 * XXX KDM I should probably clean up the printout format for the
3622 switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
3623 case SRDDH10_PHYSICAL_SECTOR_FORMAT:
3625 struct scsi_defect_desc_phys_sector *dlist;
3627 dlist = (struct scsi_defect_desc_phys_sector *)
3629 sizeof(struct scsi_read_defect_data_hdr_10));
3631 num_returned = returned_length /
3632 sizeof(struct scsi_defect_desc_phys_sector);
3634 fprintf(stderr, "Got %d defect", num_returned);
3636 if ((lists_specified == 0) || (num_returned == 0)) {
3637 fprintf(stderr, "s.\n");
3639 } else if (num_returned == 1)
3640 fprintf(stderr, ":\n");
3642 fprintf(stderr, "s:\n");
3644 for (i = 0; i < num_returned; i++) {
3645 fprintf(stdout, "%d:%d:%d\n",
3646 scsi_3btoul(dlist[i].cylinder),
3648 scsi_4btoul(dlist[i].sector));
3652 case SRDDH10_BYTES_FROM_INDEX_FORMAT:
3654 struct scsi_defect_desc_bytes_from_index *dlist;
3656 dlist = (struct scsi_defect_desc_bytes_from_index *)
3658 sizeof(struct scsi_read_defect_data_hdr_10));
3660 num_returned = returned_length /
3661 sizeof(struct scsi_defect_desc_bytes_from_index);
3663 fprintf(stderr, "Got %d defect", num_returned);
3665 if ((lists_specified == 0) || (num_returned == 0)) {
3666 fprintf(stderr, "s.\n");
3668 } else if (num_returned == 1)
3669 fprintf(stderr, ":\n");
3671 fprintf(stderr, "s:\n");
3673 for (i = 0; i < num_returned; i++) {
3674 fprintf(stdout, "%d:%d:%d\n",
3675 scsi_3btoul(dlist[i].cylinder),
3677 scsi_4btoul(dlist[i].bytes_from_index));
3681 case SRDDH10_BLOCK_FORMAT:
3683 struct scsi_defect_desc_block *dlist;
3685 dlist = (struct scsi_defect_desc_block *)(defect_list +
3686 sizeof(struct scsi_read_defect_data_hdr_10));
3688 num_returned = returned_length /
3689 sizeof(struct scsi_defect_desc_block);
3691 fprintf(stderr, "Got %d defect", num_returned);
3693 if ((lists_specified == 0) || (num_returned == 0)) {
3694 fprintf(stderr, "s.\n");
3696 } else if (num_returned == 1)
3697 fprintf(stderr, ":\n");
3699 fprintf(stderr, "s:\n");
3701 for (i = 0; i < num_returned; i++)
3702 fprintf(stdout, "%u\n",
3703 scsi_4btoul(dlist[i].address));
3707 fprintf(stderr, "Unknown defect format %d\n",
3708 returned_format & SRDDH10_DLIST_FORMAT_MASK);
3714 if (defect_list != NULL)
3722 #endif /* MINIMALISTIC */
3726 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
3730 ccb = cam_getccb(device);
3736 #ifndef MINIMALISTIC
3738 mode_sense(struct cam_device *device, int mode_page, int page_control,
3739 int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
3744 ccb = cam_getccb(device);
3747 errx(1, "mode_sense: couldn't allocate CCB");
3749 bzero(&(&ccb->ccb_h)[1],
3750 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3752 scsi_mode_sense(&ccb->csio,
3753 /* retries */ retry_count,
3755 /* tag_action */ MSG_SIMPLE_Q_TAG,
3757 /* page_code */ page_control << 6,
3758 /* page */ mode_page,
3759 /* param_buf */ data,
3760 /* param_len */ datalen,
3761 /* sense_len */ SSD_FULL_SIZE,
3762 /* timeout */ timeout ? timeout : 5000);
3764 if (arglist & CAM_ARG_ERR_RECOVER)
3765 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3767 /* Disable freezing the device queue */
3768 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3770 if (((retval = cam_send_ccb(device, ccb)) < 0)
3771 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
3772 if (arglist & CAM_ARG_VERBOSE) {
3773 cam_error_print(device, ccb, CAM_ESF_ALL,
3774 CAM_EPF_ALL, stderr);
3777 cam_close_device(device);
3779 err(1, "error sending mode sense command");
3781 errx(1, "error sending mode sense command");
3788 mode_select(struct cam_device *device, int save_pages, int retry_count,
3789 int timeout, u_int8_t *data, int datalen)
3794 ccb = cam_getccb(device);
3797 errx(1, "mode_select: couldn't allocate CCB");
3799 bzero(&(&ccb->ccb_h)[1],
3800 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3802 scsi_mode_select(&ccb->csio,
3803 /* retries */ retry_count,
3805 /* tag_action */ MSG_SIMPLE_Q_TAG,
3806 /* scsi_page_fmt */ 1,
3807 /* save_pages */ save_pages,
3808 /* param_buf */ data,
3809 /* param_len */ datalen,
3810 /* sense_len */ SSD_FULL_SIZE,
3811 /* timeout */ timeout ? timeout : 5000);
3813 if (arglist & CAM_ARG_ERR_RECOVER)
3814 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3816 /* Disable freezing the device queue */
3817 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3819 if (((retval = cam_send_ccb(device, ccb)) < 0)
3820 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
3821 if (arglist & CAM_ARG_VERBOSE) {
3822 cam_error_print(device, ccb, CAM_ESF_ALL,
3823 CAM_EPF_ALL, stderr);
3826 cam_close_device(device);
3829 err(1, "error sending mode select command");
3831 errx(1, "error sending mode select command");
3839 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
3840 int retry_count, int timeout)
3842 int c, mode_page = -1, page_control = 0;
3843 int binary = 0, list = 0;
3845 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3851 arglist |= CAM_ARG_DBD;
3854 arglist |= CAM_ARG_MODE_EDIT;
3860 mode_page = strtol(optarg, NULL, 0);
3862 errx(1, "invalid mode page %d", mode_page);
3865 page_control = strtol(optarg, NULL, 0);
3866 if ((page_control < 0) || (page_control > 3))
3867 errx(1, "invalid page control field %d",
3869 arglist |= CAM_ARG_PAGE_CNTL;
3876 if (mode_page == -1 && list == 0)
3877 errx(1, "you must specify a mode page!");
3880 mode_list(device, page_control, arglist & CAM_ARG_DBD,
3881 retry_count, timeout);
3883 mode_edit(device, mode_page, page_control,
3884 arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
3885 retry_count, timeout);
3890 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
3891 int retry_count, int timeout)
3894 u_int32_t flags = CAM_DIR_NONE;
3895 u_int8_t *data_ptr = NULL;
3897 u_int8_t atacmd[12];
3898 struct get_hook hook;
3899 int c, data_bytes = 0;
3905 char *datastr = NULL, *tstr, *resstr = NULL;
3907 int fd_data = 0, fd_res = 0;
3910 ccb = cam_getccb(device);
3913 warnx("scsicmd: error allocating ccb");
3917 bzero(&(&ccb->ccb_h)[1],
3918 sizeof(union ccb) - sizeof(struct ccb_hdr));
3920 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3924 while (isspace(*tstr) && (*tstr != '\0'))
3926 hook.argc = argc - optind;
3927 hook.argv = argv + optind;
3929 atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
3932 * Increment optind by the number of arguments the
3933 * encoding routine processed. After each call to
3934 * getopt(3), optind points to the argument that
3935 * getopt should process _next_. In this case,
3936 * that means it points to the first command string
3937 * argument, if there is one. Once we increment
3938 * this, it should point to either the next command
3939 * line argument, or it should be past the end of
3946 while (isspace(*tstr) && (*tstr != '\0'))
3948 hook.argc = argc - optind;
3949 hook.argv = argv + optind;
3951 cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
3954 * Increment optind by the number of arguments the
3955 * encoding routine processed. After each call to
3956 * getopt(3), optind points to the argument that
3957 * getopt should process _next_. In this case,
3958 * that means it points to the first command string
3959 * argument, if there is one. Once we increment
3960 * this, it should point to either the next command
3961 * line argument, or it should be past the end of
3973 if (arglist & CAM_ARG_CMD_OUT) {
3974 warnx("command must either be "
3975 "read or write, not both");
3977 goto scsicmd_bailout;
3979 arglist |= CAM_ARG_CMD_IN;
3981 data_bytes = strtol(optarg, NULL, 0);
3982 if (data_bytes <= 0) {
3983 warnx("invalid number of input bytes %d",
3986 goto scsicmd_bailout;
3988 hook.argc = argc - optind;
3989 hook.argv = argv + optind;
3992 datastr = cget(&hook, NULL);
3994 * If the user supplied "-" instead of a format, he
3995 * wants the data to be written to stdout.
3997 if ((datastr != NULL)
3998 && (datastr[0] == '-'))
4001 data_ptr = (u_int8_t *)malloc(data_bytes);
4002 if (data_ptr == NULL) {
4003 warnx("can't malloc memory for data_ptr");
4005 goto scsicmd_bailout;
4009 if (arglist & CAM_ARG_CMD_IN) {
4010 warnx("command must either be "
4011 "read or write, not both");
4013 goto scsicmd_bailout;
4015 arglist |= CAM_ARG_CMD_OUT;
4016 flags = CAM_DIR_OUT;
4017 data_bytes = strtol(optarg, NULL, 0);
4018 if (data_bytes <= 0) {
4019 warnx("invalid number of output bytes %d",
4022 goto scsicmd_bailout;
4024 hook.argc = argc - optind;
4025 hook.argv = argv + optind;
4027 datastr = cget(&hook, NULL);
4028 data_ptr = (u_int8_t *)malloc(data_bytes);
4029 if (data_ptr == NULL) {
4030 warnx("can't malloc memory for data_ptr");
4032 goto scsicmd_bailout;
4034 bzero(data_ptr, data_bytes);
4036 * If the user supplied "-" instead of a format, he
4037 * wants the data to be read from stdin.
4039 if ((datastr != NULL)
4040 && (datastr[0] == '-'))
4043 buff_encode_visit(data_ptr, data_bytes, datastr,
4049 hook.argc = argc - optind;
4050 hook.argv = argv + optind;
4052 resstr = cget(&hook, NULL);
4053 if ((resstr != NULL) && (resstr[0] == '-'))
4063 * If fd_data is set, and we're writing to the device, we need to
4064 * read the data the user wants written from stdin.
4066 if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4068 int amt_to_read = data_bytes;
4069 u_int8_t *buf_ptr = data_ptr;
4071 for (amt_read = 0; amt_to_read > 0;
4072 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4073 if (amt_read == -1) {
4074 warn("error reading data from stdin");
4076 goto scsicmd_bailout;
4078 amt_to_read -= amt_read;
4079 buf_ptr += amt_read;
4083 if (arglist & CAM_ARG_ERR_RECOVER)
4084 flags |= CAM_PASS_ERR_RECOVER;
4086 /* Disable freezing the device queue */
4087 flags |= CAM_DEV_QFRZDIS;
4091 * This is taken from the SCSI-3 draft spec.
4092 * (T10/1157D revision 0.3)
4093 * The top 3 bits of an opcode are the group code.
4094 * The next 5 bits are the command code.
4095 * Group 0: six byte commands
4096 * Group 1: ten byte commands
4097 * Group 2: ten byte commands
4099 * Group 4: sixteen byte commands
4100 * Group 5: twelve byte commands
4101 * Group 6: vendor specific
4102 * Group 7: vendor specific
4104 switch((cdb[0] >> 5) & 0x7) {
4115 /* computed by buff_encode_visit */
4126 * We should probably use csio_build_visit or something like that
4127 * here, but it's easier to encode arguments as you go. The
4128 * alternative would be skipping the CDB argument and then encoding
4129 * it here, since we've got the data buffer argument by now.
4131 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
4133 cam_fill_csio(&ccb->csio,
4134 /*retries*/ retry_count,
4137 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4138 /*data_ptr*/ data_ptr,
4139 /*dxfer_len*/ data_bytes,
4140 /*sense_len*/ SSD_FULL_SIZE,
4141 /*cdb_len*/ cdb_len,
4142 /*timeout*/ timeout ? timeout : 5000);
4145 bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
4147 ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
4149 ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
4151 ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
4153 cam_fill_ataio(&ccb->ataio,
4154 /*retries*/ retry_count,
4158 /*data_ptr*/ data_ptr,
4159 /*dxfer_len*/ data_bytes,
4160 /*timeout*/ timeout ? timeout : 5000);
4163 if (((retval = cam_send_ccb(device, ccb)) < 0)
4164 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4165 const char warnstr[] = "error sending command";
4172 if (arglist & CAM_ARG_VERBOSE) {
4173 cam_error_print(device, ccb, CAM_ESF_ALL,
4174 CAM_EPF_ALL, stderr);
4178 goto scsicmd_bailout;
4181 if (atacmd_len && need_res) {
4183 buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
4185 fprintf(stdout, "\n");
4188 "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
4189 ccb->ataio.res.status,
4190 ccb->ataio.res.error,
4191 ccb->ataio.res.lba_low,
4192 ccb->ataio.res.lba_mid,
4193 ccb->ataio.res.lba_high,
4194 ccb->ataio.res.device,
4195 ccb->ataio.res.lba_low_exp,
4196 ccb->ataio.res.lba_mid_exp,
4197 ccb->ataio.res.lba_high_exp,
4198 ccb->ataio.res.sector_count,
4199 ccb->ataio.res.sector_count_exp);
4204 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4205 && (arglist & CAM_ARG_CMD_IN)
4206 && (data_bytes > 0)) {
4208 buff_decode_visit(data_ptr, data_bytes, datastr,
4210 fprintf(stdout, "\n");
4212 ssize_t amt_written;
4213 int amt_to_write = data_bytes;
4214 u_int8_t *buf_ptr = data_ptr;
4216 for (amt_written = 0; (amt_to_write > 0) &&
4217 (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
4218 amt_to_write -= amt_written;
4219 buf_ptr += amt_written;
4221 if (amt_written == -1) {
4222 warn("error writing data to stdout");
4224 goto scsicmd_bailout;
4225 } else if ((amt_written == 0)
4226 && (amt_to_write > 0)) {
4227 warnx("only wrote %u bytes out of %u",
4228 data_bytes - amt_to_write, data_bytes);
4235 if ((data_bytes > 0) && (data_ptr != NULL))
4244 camdebug(int argc, char **argv, char *combinedopt)
4247 path_id_t bus = CAM_BUS_WILDCARD;
4248 target_id_t target = CAM_TARGET_WILDCARD;
4249 lun_id_t lun = CAM_LUN_WILDCARD;
4250 char *tstr, *tmpstr = NULL;
4254 bzero(&ccb, sizeof(union ccb));
4256 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4259 arglist |= CAM_ARG_DEBUG_INFO;
4260 ccb.cdbg.flags |= CAM_DEBUG_INFO;
4263 arglist |= CAM_ARG_DEBUG_PERIPH;
4264 ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
4267 arglist |= CAM_ARG_DEBUG_SUBTRACE;
4268 ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
4271 arglist |= CAM_ARG_DEBUG_TRACE;
4272 ccb.cdbg.flags |= CAM_DEBUG_TRACE;
4275 arglist |= CAM_ARG_DEBUG_XPT;
4276 ccb.cdbg.flags |= CAM_DEBUG_XPT;
4279 arglist |= CAM_ARG_DEBUG_CDB;
4280 ccb.cdbg.flags |= CAM_DEBUG_CDB;
4283 arglist |= CAM_ARG_DEBUG_PROBE;
4284 ccb.cdbg.flags |= CAM_DEBUG_PROBE;
4291 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
4292 warnx("error opening transport layer device %s", XPT_DEVICE);
4293 warn("%s", XPT_DEVICE);
4300 warnx("you must specify \"off\", \"all\" or a bus,");
4301 warnx("bus:target, or bus:target:lun");
4308 while (isspace(*tstr) && (*tstr != '\0'))
4311 if (strncmp(tstr, "off", 3) == 0) {
4312 ccb.cdbg.flags = CAM_DEBUG_NONE;
4313 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
4314 CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
4315 CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE);
4316 } else if (strncmp(tstr, "all", 3) != 0) {
4317 tmpstr = (char *)strtok(tstr, ":");
4318 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4319 bus = strtol(tmpstr, NULL, 0);
4320 arglist |= CAM_ARG_BUS;
4321 tmpstr = (char *)strtok(NULL, ":");
4322 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4323 target = strtol(tmpstr, NULL, 0);
4324 arglist |= CAM_ARG_TARGET;
4325 tmpstr = (char *)strtok(NULL, ":");
4326 if ((tmpstr != NULL) && (*tmpstr != '\0')){
4327 lun = strtol(tmpstr, NULL, 0);
4328 arglist |= CAM_ARG_LUN;
4333 warnx("you must specify \"all\", \"off\", or a bus,");
4334 warnx("bus:target, or bus:target:lun to debug");
4340 ccb.ccb_h.func_code = XPT_DEBUG;
4341 ccb.ccb_h.path_id = bus;
4342 ccb.ccb_h.target_id = target;
4343 ccb.ccb_h.target_lun = lun;
4345 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
4346 warn("CAMIOCOMMAND ioctl failed");
4351 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
4352 CAM_FUNC_NOTAVAIL) {
4353 warnx("CAM debugging not available");
4354 warnx("you need to put options CAMDEBUG in"
4355 " your kernel config file!");
4357 } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
4359 warnx("XPT_DEBUG CCB failed with status %#x",
4363 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
4365 "Debugging turned off\n");
4368 "Debugging enabled for "
4370 bus, target, (uintmax_t)lun);
4381 tagcontrol(struct cam_device *device, int argc, char **argv,
4391 ccb = cam_getccb(device);
4394 warnx("tagcontrol: error allocating ccb");
4398 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4401 numtags = strtol(optarg, NULL, 0);
4403 warnx("tag count %d is < 0", numtags);
4405 goto tagcontrol_bailout;
4416 cam_path_string(device, pathstr, sizeof(pathstr));
4419 bzero(&(&ccb->ccb_h)[1],
4420 sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
4421 ccb->ccb_h.func_code = XPT_REL_SIMQ;
4422 ccb->ccb_h.flags = CAM_DEV_QFREEZE;
4423 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
4424 ccb->crs.openings = numtags;
4427 if (cam_send_ccb(device, ccb) < 0) {
4428 perror("error sending XPT_REL_SIMQ CCB");
4430 goto tagcontrol_bailout;
4433 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4434 warnx("XPT_REL_SIMQ CCB failed");
4435 cam_error_print(device, ccb, CAM_ESF_ALL,
4436 CAM_EPF_ALL, stderr);
4438 goto tagcontrol_bailout;
4443 fprintf(stdout, "%stagged openings now %d\n",
4444 pathstr, ccb->crs.openings);
4447 bzero(&(&ccb->ccb_h)[1],
4448 sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
4450 ccb->ccb_h.func_code = XPT_GDEV_STATS;
4452 if (cam_send_ccb(device, ccb) < 0) {
4453 perror("error sending XPT_GDEV_STATS CCB");
4455 goto tagcontrol_bailout;
4458 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4459 warnx("XPT_GDEV_STATS CCB failed");
4460 cam_error_print(device, ccb, CAM_ESF_ALL,
4461 CAM_EPF_ALL, stderr);
4463 goto tagcontrol_bailout;
4466 if (arglist & CAM_ARG_VERBOSE) {
4467 fprintf(stdout, "%s", pathstr);
4468 fprintf(stdout, "dev_openings %d\n", ccb->cgds.dev_openings);
4469 fprintf(stdout, "%s", pathstr);
4470 fprintf(stdout, "dev_active %d\n", ccb->cgds.dev_active);
4471 fprintf(stdout, "%s", pathstr);
4472 fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
4473 fprintf(stdout, "%s", pathstr);
4474 fprintf(stdout, "devq_queued %d\n", ccb->cgds.devq_queued);
4475 fprintf(stdout, "%s", pathstr);
4476 fprintf(stdout, "held %d\n", ccb->cgds.held);
4477 fprintf(stdout, "%s", pathstr);
4478 fprintf(stdout, "mintags %d\n", ccb->cgds.mintags);
4479 fprintf(stdout, "%s", pathstr);
4480 fprintf(stdout, "maxtags %d\n", ccb->cgds.maxtags);
4483 fprintf(stdout, "%s", pathstr);
4484 fprintf(stdout, "device openings: ");
4486 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
4487 ccb->cgds.dev_active);
4497 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
4501 cam_path_string(device, pathstr, sizeof(pathstr));
4503 if (cts->transport == XPORT_SPI) {
4504 struct ccb_trans_settings_spi *spi =
4505 &cts->xport_specific.spi;
4507 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
4509 fprintf(stdout, "%ssync parameter: %d\n", pathstr,
4512 if (spi->sync_offset != 0) {
4515 freq = scsi_calc_syncsrate(spi->sync_period);
4516 fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
4517 pathstr, freq / 1000, freq % 1000);
4521 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
4522 fprintf(stdout, "%soffset: %d\n", pathstr,
4526 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
4527 fprintf(stdout, "%sbus width: %d bits\n", pathstr,
4528 (0x01 << spi->bus_width) * 8);
4531 if (spi->valid & CTS_SPI_VALID_DISC) {
4532 fprintf(stdout, "%sdisconnection is %s\n", pathstr,
4533 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
4534 "enabled" : "disabled");
4537 if (cts->transport == XPORT_FC) {
4538 struct ccb_trans_settings_fc *fc =
4539 &cts->xport_specific.fc;
4541 if (fc->valid & CTS_FC_VALID_WWNN)
4542 fprintf(stdout, "%sWWNN: 0x%llx\n", pathstr,
4543 (long long) fc->wwnn);
4544 if (fc->valid & CTS_FC_VALID_WWPN)
4545 fprintf(stdout, "%sWWPN: 0x%llx\n", pathstr,
4546 (long long) fc->wwpn);
4547 if (fc->valid & CTS_FC_VALID_PORT)
4548 fprintf(stdout, "%sPortID: 0x%x\n", pathstr, fc->port);
4549 if (fc->valid & CTS_FC_VALID_SPEED)
4550 fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4551 pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
4553 if (cts->transport == XPORT_SAS) {
4554 struct ccb_trans_settings_sas *sas =
4555 &cts->xport_specific.sas;
4557 if (sas->valid & CTS_SAS_VALID_SPEED)
4558 fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4559 pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
4561 if (cts->transport == XPORT_ATA) {
4562 struct ccb_trans_settings_pata *pata =
4563 &cts->xport_specific.ata;
4565 if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
4566 fprintf(stdout, "%sATA mode: %s\n", pathstr,
4567 ata_mode2string(pata->mode));
4569 if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
4570 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4573 if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
4574 fprintf(stdout, "%sPIO transaction length: %d\n",
4575 pathstr, pata->bytecount);
4578 if (cts->transport == XPORT_SATA) {
4579 struct ccb_trans_settings_sata *sata =
4580 &cts->xport_specific.sata;
4582 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
4583 fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
4586 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
4587 fprintf(stdout, "%sATA mode: %s\n", pathstr,
4588 ata_mode2string(sata->mode));
4590 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
4591 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4594 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
4595 fprintf(stdout, "%sPIO transaction length: %d\n",
4596 pathstr, sata->bytecount);
4598 if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
4599 fprintf(stdout, "%sPMP presence: %d\n", pathstr,
4602 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
4603 fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
4606 if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
4607 fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
4611 if (cts->protocol == PROTO_ATA) {
4612 struct ccb_trans_settings_ata *ata=
4613 &cts->proto_specific.ata;
4615 if (ata->valid & CTS_ATA_VALID_TQ) {
4616 fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4617 (ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
4618 "enabled" : "disabled");
4621 if (cts->protocol == PROTO_SCSI) {
4622 struct ccb_trans_settings_scsi *scsi=
4623 &cts->proto_specific.scsi;
4625 if (scsi->valid & CTS_SCSI_VALID_TQ) {
4626 fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4627 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
4628 "enabled" : "disabled");
4635 * Get a path inquiry CCB for the specified device.
4638 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
4643 ccb = cam_getccb(device);
4645 warnx("get_cpi: couldn't allocate CCB");
4648 bzero(&(&ccb->ccb_h)[1],
4649 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4650 ccb->ccb_h.func_code = XPT_PATH_INQ;
4651 if (cam_send_ccb(device, ccb) < 0) {
4652 warn("get_cpi: error sending Path Inquiry CCB");
4653 if (arglist & CAM_ARG_VERBOSE)
4654 cam_error_print(device, ccb, CAM_ESF_ALL,
4655 CAM_EPF_ALL, stderr);
4657 goto get_cpi_bailout;
4659 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4660 if (arglist & CAM_ARG_VERBOSE)
4661 cam_error_print(device, ccb, CAM_ESF_ALL,
4662 CAM_EPF_ALL, stderr);
4664 goto get_cpi_bailout;
4666 bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
4674 * Get a get device CCB for the specified device.
4677 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
4682 ccb = cam_getccb(device);
4684 warnx("get_cgd: couldn't allocate CCB");
4687 bzero(&(&ccb->ccb_h)[1],
4688 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4689 ccb->ccb_h.func_code = XPT_GDEV_TYPE;
4690 if (cam_send_ccb(device, ccb) < 0) {
4691 warn("get_cgd: error sending Path Inquiry CCB");
4692 if (arglist & CAM_ARG_VERBOSE)
4693 cam_error_print(device, ccb, CAM_ESF_ALL,
4694 CAM_EPF_ALL, stderr);
4696 goto get_cgd_bailout;
4698 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4699 if (arglist & CAM_ARG_VERBOSE)
4700 cam_error_print(device, ccb, CAM_ESF_ALL,
4701 CAM_EPF_ALL, stderr);
4703 goto get_cgd_bailout;
4705 bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
4712 /* return the type of disk (really the command type) */
4714 get_disk_type(struct cam_device *device)
4716 struct ccb_getdev cgd;
4718 (void) memset(&cgd, 0x0, sizeof(cgd));
4719 get_cgd(device, &cgd);
4720 switch(cgd.protocol) {
4733 cpi_print(struct ccb_pathinq *cpi)
4735 char adapter_str[1024];
4738 snprintf(adapter_str, sizeof(adapter_str),
4739 "%s%d:", cpi->dev_name, cpi->unit_number);
4741 fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
4744 for (i = 1; i < 0xff; i = i << 1) {
4747 if ((i & cpi->hba_inquiry) == 0)
4750 fprintf(stdout, "%s supports ", adapter_str);
4754 str = "MDP message";
4757 str = "32 bit wide SCSI";
4760 str = "16 bit wide SCSI";
4763 str = "SDTR message";
4766 str = "linked CDBs";
4769 str = "tag queue messages";
4772 str = "soft reset alternative";
4775 str = "SATA Port Multiplier";
4778 str = "unknown PI bit set";
4781 fprintf(stdout, "%s\n", str);
4784 for (i = 1; i < 0xff; i = i << 1) {
4787 if ((i & cpi->hba_misc) == 0)
4790 fprintf(stdout, "%s ", adapter_str);
4794 str = "bus scans from high ID to low ID";
4797 str = "removable devices not included in scan";
4799 case PIM_NOINITIATOR:
4800 str = "initiator role not supported";
4802 case PIM_NOBUSRESET:
4803 str = "user has disabled initial BUS RESET or"
4804 " controller is in target/mixed mode";
4807 str = "do not send 6-byte commands";
4810 str = "scan bus sequentially";
4813 str = "unknown PIM bit set";
4816 fprintf(stdout, "%s\n", str);
4819 for (i = 1; i < 0xff; i = i << 1) {
4822 if ((i & cpi->target_sprt) == 0)
4825 fprintf(stdout, "%s supports ", adapter_str);
4828 str = "target mode processor mode";
4831 str = "target mode phase cog. mode";
4833 case PIT_DISCONNECT:
4834 str = "disconnects in target mode";
4837 str = "terminate I/O message in target mode";
4840 str = "group 6 commands in target mode";
4843 str = "group 7 commands in target mode";
4846 str = "unknown PIT bit set";
4850 fprintf(stdout, "%s\n", str);
4852 fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
4854 fprintf(stdout, "%s maximum target: %d\n", adapter_str,
4856 fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
4858 fprintf(stdout, "%s highest path ID in subsystem: %d\n",
4859 adapter_str, cpi->hpath_id);
4860 fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
4862 fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
4863 fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
4864 fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
4865 adapter_str, cpi->hba_vendor);
4866 fprintf(stdout, "%s HBA device ID: 0x%04x\n",
4867 adapter_str, cpi->hba_device);
4868 fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
4869 adapter_str, cpi->hba_subvendor);
4870 fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
4871 adapter_str, cpi->hba_subdevice);
4872 fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
4873 fprintf(stdout, "%s base transfer speed: ", adapter_str);
4874 if (cpi->base_transfer_speed > 1000)
4875 fprintf(stdout, "%d.%03dMB/sec\n",
4876 cpi->base_transfer_speed / 1000,
4877 cpi->base_transfer_speed % 1000);
4879 fprintf(stdout, "%dKB/sec\n",
4880 (cpi->base_transfer_speed % 1000) * 1000);
4881 fprintf(stdout, "%s maximum transfer size: %u bytes\n",
4882 adapter_str, cpi->maxio);
4886 get_print_cts(struct cam_device *device, int user_settings, int quiet,
4887 struct ccb_trans_settings *cts)
4893 ccb = cam_getccb(device);
4896 warnx("get_print_cts: error allocating ccb");
4900 bzero(&(&ccb->ccb_h)[1],
4901 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
4903 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
4905 if (user_settings == 0)
4906 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
4908 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
4910 if (cam_send_ccb(device, ccb) < 0) {
4911 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
4912 if (arglist & CAM_ARG_VERBOSE)
4913 cam_error_print(device, ccb, CAM_ESF_ALL,
4914 CAM_EPF_ALL, stderr);
4916 goto get_print_cts_bailout;
4919 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4920 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
4921 if (arglist & CAM_ARG_VERBOSE)
4922 cam_error_print(device, ccb, CAM_ESF_ALL,
4923 CAM_EPF_ALL, stderr);
4925 goto get_print_cts_bailout;
4929 cts_print(device, &ccb->cts);
4932 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
4934 get_print_cts_bailout:
4942 ratecontrol(struct cam_device *device, int retry_count, int timeout,
4943 int argc, char **argv, char *combinedopt)
4947 int user_settings = 0;
4949 int disc_enable = -1, tag_enable = -1;
4952 double syncrate = -1;
4955 int change_settings = 0, send_tur = 0;
4956 struct ccb_pathinq cpi;
4958 ccb = cam_getccb(device);
4960 warnx("ratecontrol: error allocating ccb");
4963 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4972 if (strncasecmp(optarg, "enable", 6) == 0)
4974 else if (strncasecmp(optarg, "disable", 7) == 0)
4977 warnx("-D argument \"%s\" is unknown", optarg);
4979 goto ratecontrol_bailout;
4981 change_settings = 1;
4984 mode = ata_string2mode(optarg);
4986 warnx("unknown mode '%s'", optarg);
4988 goto ratecontrol_bailout;
4990 change_settings = 1;
4993 offset = strtol(optarg, NULL, 0);
4995 warnx("offset value %d is < 0", offset);
4997 goto ratecontrol_bailout;
4999 change_settings = 1;
5005 syncrate = atof(optarg);
5007 warnx("sync rate %f is < 0", syncrate);
5009 goto ratecontrol_bailout;
5011 change_settings = 1;
5014 if (strncasecmp(optarg, "enable", 6) == 0)
5016 else if (strncasecmp(optarg, "disable", 7) == 0)
5019 warnx("-T argument \"%s\" is unknown", optarg);
5021 goto ratecontrol_bailout;
5023 change_settings = 1;
5029 bus_width = strtol(optarg, NULL, 0);
5030 if (bus_width < 0) {
5031 warnx("bus width %d is < 0", bus_width);
5033 goto ratecontrol_bailout;
5035 change_settings = 1;
5041 bzero(&(&ccb->ccb_h)[1],
5042 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
5044 * Grab path inquiry information, so we can determine whether
5045 * or not the initiator is capable of the things that the user
5048 ccb->ccb_h.func_code = XPT_PATH_INQ;
5049 if (cam_send_ccb(device, ccb) < 0) {
5050 perror("error sending XPT_PATH_INQ CCB");
5051 if (arglist & CAM_ARG_VERBOSE) {
5052 cam_error_print(device, ccb, CAM_ESF_ALL,
5053 CAM_EPF_ALL, stderr);
5056 goto ratecontrol_bailout;
5058 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5059 warnx("XPT_PATH_INQ CCB failed");
5060 if (arglist & CAM_ARG_VERBOSE) {
5061 cam_error_print(device, ccb, CAM_ESF_ALL,
5062 CAM_EPF_ALL, stderr);
5065 goto ratecontrol_bailout;
5067 bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
5068 bzero(&(&ccb->ccb_h)[1],
5069 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
5071 fprintf(stdout, "%s parameters:\n",
5072 user_settings ? "User" : "Current");
5074 retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
5076 goto ratecontrol_bailout;
5078 if (arglist & CAM_ARG_VERBOSE)
5081 if (change_settings) {
5082 int didsettings = 0;
5083 struct ccb_trans_settings_spi *spi = NULL;
5084 struct ccb_trans_settings_pata *pata = NULL;
5085 struct ccb_trans_settings_sata *sata = NULL;
5086 struct ccb_trans_settings_ata *ata = NULL;
5087 struct ccb_trans_settings_scsi *scsi = NULL;
5089 if (ccb->cts.transport == XPORT_SPI)
5090 spi = &ccb->cts.xport_specific.spi;
5091 if (ccb->cts.transport == XPORT_ATA)
5092 pata = &ccb->cts.xport_specific.ata;
5093 if (ccb->cts.transport == XPORT_SATA)
5094 sata = &ccb->cts.xport_specific.sata;
5095 if (ccb->cts.protocol == PROTO_ATA)
5096 ata = &ccb->cts.proto_specific.ata;
5097 if (ccb->cts.protocol == PROTO_SCSI)
5098 scsi = &ccb->cts.proto_specific.scsi;
5099 ccb->cts.xport_specific.valid = 0;
5100 ccb->cts.proto_specific.valid = 0;
5101 if (spi && disc_enable != -1) {
5102 spi->valid |= CTS_SPI_VALID_DISC;
5103 if (disc_enable == 0)
5104 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
5106 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
5109 if (tag_enable != -1) {
5110 if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
5111 warnx("HBA does not support tagged queueing, "
5112 "so you cannot modify tag settings");
5114 goto ratecontrol_bailout;
5117 ata->valid |= CTS_SCSI_VALID_TQ;
5118 if (tag_enable == 0)
5119 ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
5121 ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
5124 scsi->valid |= CTS_SCSI_VALID_TQ;
5125 if (tag_enable == 0)
5126 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
5128 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
5132 if (spi && offset != -1) {
5133 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5134 warnx("HBA is not capable of changing offset");
5136 goto ratecontrol_bailout;
5138 spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
5139 spi->sync_offset = offset;
5142 if (spi && syncrate != -1) {
5143 int prelim_sync_period;
5145 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5146 warnx("HBA is not capable of changing "
5149 goto ratecontrol_bailout;
5151 spi->valid |= CTS_SPI_VALID_SYNC_RATE;
5153 * The sync rate the user gives us is in MHz.
5154 * We need to translate it into KHz for this
5159 * Next, we calculate a "preliminary" sync period
5160 * in tenths of a nanosecond.
5163 prelim_sync_period = 0;
5165 prelim_sync_period = 10000000 / syncrate;
5167 scsi_calc_syncparam(prelim_sync_period);
5170 if (sata && syncrate != -1) {
5171 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5172 warnx("HBA is not capable of changing "
5175 goto ratecontrol_bailout;
5177 if (!user_settings) {
5178 warnx("You can modify only user rate "
5179 "settings for SATA");
5181 goto ratecontrol_bailout;
5183 sata->revision = ata_speed2revision(syncrate * 100);
5184 if (sata->revision < 0) {
5185 warnx("Invalid rate %f", syncrate);
5187 goto ratecontrol_bailout;
5189 sata->valid |= CTS_SATA_VALID_REVISION;
5192 if ((pata || sata) && mode != -1) {
5193 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5194 warnx("HBA is not capable of changing "
5197 goto ratecontrol_bailout;
5199 if (!user_settings) {
5200 warnx("You can modify only user mode "
5201 "settings for ATA/SATA");
5203 goto ratecontrol_bailout;
5207 pata->valid |= CTS_ATA_VALID_MODE;
5210 sata->valid |= CTS_SATA_VALID_MODE;
5215 * The bus_width argument goes like this:
5219 * Therefore, if you shift the number of bits given on the
5220 * command line right by 4, you should get the correct
5223 if (spi && bus_width != -1) {
5225 * We might as well validate things here with a
5226 * decipherable error message, rather than what
5227 * will probably be an indecipherable error message
5228 * by the time it gets back to us.
5230 if ((bus_width == 16)
5231 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
5232 warnx("HBA does not support 16 bit bus width");
5234 goto ratecontrol_bailout;
5235 } else if ((bus_width == 32)
5236 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
5237 warnx("HBA does not support 32 bit bus width");
5239 goto ratecontrol_bailout;
5240 } else if ((bus_width != 8)
5241 && (bus_width != 16)
5242 && (bus_width != 32)) {
5243 warnx("Invalid bus width %d", bus_width);
5245 goto ratecontrol_bailout;
5247 spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
5248 spi->bus_width = bus_width >> 4;
5251 if (didsettings == 0) {
5252 goto ratecontrol_bailout;
5254 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
5255 if (cam_send_ccb(device, ccb) < 0) {
5256 perror("error sending XPT_SET_TRAN_SETTINGS CCB");
5257 if (arglist & CAM_ARG_VERBOSE) {
5258 cam_error_print(device, ccb, CAM_ESF_ALL,
5259 CAM_EPF_ALL, stderr);
5262 goto ratecontrol_bailout;
5264 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5265 warnx("XPT_SET_TRANS_SETTINGS CCB failed");
5266 if (arglist & CAM_ARG_VERBOSE) {
5267 cam_error_print(device, ccb, CAM_ESF_ALL,
5268 CAM_EPF_ALL, stderr);
5271 goto ratecontrol_bailout;
5275 retval = testunitready(device, retry_count, timeout,
5276 (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
5278 * If the TUR didn't succeed, just bail.
5282 fprintf(stderr, "Test Unit Ready failed\n");
5283 goto ratecontrol_bailout;
5286 if ((change_settings || send_tur) && !quiet &&
5287 (ccb->cts.transport == XPORT_ATA ||
5288 ccb->cts.transport == XPORT_SATA || send_tur)) {
5289 fprintf(stdout, "New parameters:\n");
5290 retval = get_print_cts(device, user_settings, 0, NULL);
5293 ratecontrol_bailout:
5299 scsiformat(struct cam_device *device, int argc, char **argv,
5300 char *combinedopt, int retry_count, int timeout)
5304 int ycount = 0, quiet = 0;
5305 int error = 0, retval = 0;
5306 int use_timeout = 10800 * 1000;
5308 struct format_defect_list_header fh;
5309 u_int8_t *data_ptr = NULL;
5310 u_int32_t dxfer_len = 0;
5312 int num_warnings = 0;
5315 ccb = cam_getccb(device);
5318 warnx("scsiformat: error allocating ccb");
5322 bzero(&(&ccb->ccb_h)[1],
5323 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5325 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5346 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5347 "following device:\n");
5349 error = scsidoinquiry(device, argc, argv, combinedopt,
5350 retry_count, timeout);
5353 warnx("scsiformat: error sending inquiry");
5354 goto scsiformat_bailout;
5359 if (!get_confirmation()) {
5361 goto scsiformat_bailout;
5366 use_timeout = timeout;
5369 fprintf(stdout, "Current format timeout is %d seconds\n",
5370 use_timeout / 1000);
5374 * If the user hasn't disabled questions and didn't specify a
5375 * timeout on the command line, ask them if they want the current
5379 && (timeout == 0)) {
5381 int new_timeout = 0;
5383 fprintf(stdout, "Enter new timeout in seconds or press\n"
5384 "return to keep the current timeout [%d] ",
5385 use_timeout / 1000);
5387 if (fgets(str, sizeof(str), stdin) != NULL) {
5389 new_timeout = atoi(str);
5392 if (new_timeout != 0) {
5393 use_timeout = new_timeout * 1000;
5394 fprintf(stdout, "Using new timeout value %d\n",
5395 use_timeout / 1000);
5400 * Keep this outside the if block below to silence any unused
5401 * variable warnings.
5403 bzero(&fh, sizeof(fh));
5406 * If we're in immediate mode, we've got to include the format
5409 if (immediate != 0) {
5410 fh.byte2 = FU_DLH_IMMED;
5411 data_ptr = (u_int8_t *)&fh;
5412 dxfer_len = sizeof(fh);
5413 byte2 = FU_FMT_DATA;
5414 } else if (quiet == 0) {
5415 fprintf(stdout, "Formatting...");
5419 scsi_format_unit(&ccb->csio,
5420 /* retries */ retry_count,
5422 /* tag_action */ MSG_SIMPLE_Q_TAG,
5425 /* data_ptr */ data_ptr,
5426 /* dxfer_len */ dxfer_len,
5427 /* sense_len */ SSD_FULL_SIZE,
5428 /* timeout */ use_timeout);
5430 /* Disable freezing the device queue */
5431 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5433 if (arglist & CAM_ARG_ERR_RECOVER)
5434 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5436 if (((retval = cam_send_ccb(device, ccb)) < 0)
5437 || ((immediate == 0)
5438 && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
5439 const char errstr[] = "error sending format command";
5446 if (arglist & CAM_ARG_VERBOSE) {
5447 cam_error_print(device, ccb, CAM_ESF_ALL,
5448 CAM_EPF_ALL, stderr);
5451 goto scsiformat_bailout;
5455 * If we ran in non-immediate mode, we already checked for errors
5456 * above and printed out any necessary information. If we're in
5457 * immediate mode, we need to loop through and get status
5458 * information periodically.
5460 if (immediate == 0) {
5462 fprintf(stdout, "Format Complete\n");
5464 goto scsiformat_bailout;
5471 bzero(&(&ccb->ccb_h)[1],
5472 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5475 * There's really no need to do error recovery or
5476 * retries here, since we're just going to sit in a
5477 * loop and wait for the device to finish formatting.
5479 scsi_test_unit_ready(&ccb->csio,
5482 /* tag_action */ MSG_SIMPLE_Q_TAG,
5483 /* sense_len */ SSD_FULL_SIZE,
5484 /* timeout */ 5000);
5486 /* Disable freezing the device queue */
5487 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5489 retval = cam_send_ccb(device, ccb);
5492 * If we get an error from the ioctl, bail out. SCSI
5493 * errors are expected.
5496 warn("error sending CAMIOCOMMAND ioctl");
5497 if (arglist & CAM_ARG_VERBOSE) {
5498 cam_error_print(device, ccb, CAM_ESF_ALL,
5499 CAM_EPF_ALL, stderr);
5502 goto scsiformat_bailout;
5505 status = ccb->ccb_h.status & CAM_STATUS_MASK;
5507 if ((status != CAM_REQ_CMP)
5508 && (status == CAM_SCSI_STATUS_ERROR)
5509 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
5510 struct scsi_sense_data *sense;
5511 int error_code, sense_key, asc, ascq;
5513 sense = &ccb->csio.sense_data;
5514 scsi_extract_sense_len(sense, ccb->csio.sense_len -
5515 ccb->csio.sense_resid, &error_code, &sense_key,
5516 &asc, &ascq, /*show_errors*/ 1);
5519 * According to the SCSI-2 and SCSI-3 specs, a
5520 * drive that is in the middle of a format should
5521 * return NOT READY with an ASC of "logical unit
5522 * not ready, format in progress". The sense key
5523 * specific bytes will then be a progress indicator.
5525 if ((sense_key == SSD_KEY_NOT_READY)
5526 && (asc == 0x04) && (ascq == 0x04)) {
5529 if ((scsi_get_sks(sense, ccb->csio.sense_len -
5530 ccb->csio.sense_resid, sks) == 0)
5533 u_int64_t percentage;
5535 val = scsi_2btoul(&sks[1]);
5536 percentage = 10000 * val;
5539 "\rFormatting: %ju.%02u %% "
5541 (uintmax_t)(percentage /
5543 (unsigned)((percentage /
5547 } else if ((quiet == 0)
5548 && (++num_warnings <= 1)) {
5549 warnx("Unexpected SCSI Sense Key "
5550 "Specific value returned "
5552 scsi_sense_print(device, &ccb->csio,
5554 warnx("Unable to print status "
5555 "information, but format will "
5557 warnx("will exit when format is "
5562 warnx("Unexpected SCSI error during format");
5563 cam_error_print(device, ccb, CAM_ESF_ALL,
5564 CAM_EPF_ALL, stderr);
5566 goto scsiformat_bailout;
5569 } else if (status != CAM_REQ_CMP) {
5570 warnx("Unexpected CAM status %#x", status);
5571 if (arglist & CAM_ARG_VERBOSE)
5572 cam_error_print(device, ccb, CAM_ESF_ALL,
5573 CAM_EPF_ALL, stderr);
5575 goto scsiformat_bailout;
5578 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
5581 fprintf(stdout, "\nFormat Complete\n");
5591 scsisanitize(struct cam_device *device, int argc, char **argv,
5592 char *combinedopt, int retry_count, int timeout)
5595 u_int8_t action = 0;
5597 int ycount = 0, quiet = 0;
5598 int error = 0, retval = 0;
5599 int use_timeout = 10800 * 1000;
5605 const char *pattern = NULL;
5606 u_int8_t *data_ptr = NULL;
5607 u_int32_t dxfer_len = 0;
5609 int num_warnings = 0;
5612 ccb = cam_getccb(device);
5615 warnx("scsisanitize: error allocating ccb");
5619 bzero(&(&ccb->ccb_h)[1],
5620 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5622 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5625 if (strcasecmp(optarg, "overwrite") == 0)
5626 action = SSZ_SERVICE_ACTION_OVERWRITE;
5627 else if (strcasecmp(optarg, "block") == 0)
5628 action = SSZ_SERVICE_ACTION_BLOCK_ERASE;
5629 else if (strcasecmp(optarg, "crypto") == 0)
5630 action = SSZ_SERVICE_ACTION_CRYPTO_ERASE;
5631 else if (strcasecmp(optarg, "exitfailure") == 0)
5632 action = SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE;
5634 warnx("invalid service operation \"%s\"",
5637 goto scsisanitize_bailout;
5641 passes = strtol(optarg, NULL, 0);
5642 if (passes < 1 || passes > 31) {
5643 warnx("invalid passes value %d", passes);
5645 goto scsisanitize_bailout;
5676 warnx("an action is required");
5678 goto scsisanitize_bailout;
5679 } else if (action == SSZ_SERVICE_ACTION_OVERWRITE) {
5680 struct scsi_sanitize_parameter_list *pl;
5684 if (pattern == NULL) {
5685 warnx("overwrite action requires -P argument");
5687 goto scsisanitize_bailout;
5689 fd = open(pattern, O_RDONLY);
5691 warn("cannot open pattern file %s", pattern);
5693 goto scsisanitize_bailout;
5695 if (fstat(fd, &sb) < 0) {
5696 warn("cannot stat pattern file %s", pattern);
5698 goto scsisanitize_bailout;
5701 if (sz > SSZPL_MAX_PATTERN_LENGTH) {
5702 warnx("pattern file size exceeds maximum value %d",
5703 SSZPL_MAX_PATTERN_LENGTH);
5705 goto scsisanitize_bailout;
5707 dxfer_len = sizeof(*pl) + sz;
5708 data_ptr = calloc(1, dxfer_len);
5709 if (data_ptr == NULL) {
5710 warnx("cannot allocate parameter list buffer");
5712 goto scsisanitize_bailout;
5715 amt = read(fd, data_ptr + sizeof(*pl), sz);
5717 warn("cannot read pattern file");
5719 goto scsisanitize_bailout;
5720 } else if (amt != sz) {
5721 warnx("short pattern file read");
5723 goto scsisanitize_bailout;
5726 pl = (struct scsi_sanitize_parameter_list *)data_ptr;
5732 pl->byte1 |= SSZPL_INVERT;
5733 scsi_ulto2b(sz, pl->length);
5739 else if (invert != 0)
5741 else if (pattern != NULL)
5746 warnx("%s argument only valid with overwrite "
5749 goto scsisanitize_bailout;
5754 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5755 "following device:\n");
5757 error = scsidoinquiry(device, argc, argv, combinedopt,
5758 retry_count, timeout);
5761 warnx("scsisanitize: error sending inquiry");
5762 goto scsisanitize_bailout;
5767 if (!get_confirmation()) {
5769 goto scsisanitize_bailout;
5774 use_timeout = timeout;
5777 fprintf(stdout, "Current sanitize timeout is %d seconds\n",
5778 use_timeout / 1000);
5782 * If the user hasn't disabled questions and didn't specify a
5783 * timeout on the command line, ask them if they want the current
5787 && (timeout == 0)) {
5789 int new_timeout = 0;
5791 fprintf(stdout, "Enter new timeout in seconds or press\n"
5792 "return to keep the current timeout [%d] ",
5793 use_timeout / 1000);
5795 if (fgets(str, sizeof(str), stdin) != NULL) {
5797 new_timeout = atoi(str);
5800 if (new_timeout != 0) {
5801 use_timeout = new_timeout * 1000;
5802 fprintf(stdout, "Using new timeout value %d\n",
5803 use_timeout / 1000);
5809 byte2 |= SSZ_UNRESTRICTED_EXIT;
5813 scsi_sanitize(&ccb->csio,
5814 /* retries */ retry_count,
5816 /* tag_action */ MSG_SIMPLE_Q_TAG,
5819 /* data_ptr */ data_ptr,
5820 /* dxfer_len */ dxfer_len,
5821 /* sense_len */ SSD_FULL_SIZE,
5822 /* timeout */ use_timeout);
5824 /* Disable freezing the device queue */
5825 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5827 if (arglist & CAM_ARG_ERR_RECOVER)
5828 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5830 if (((retval = cam_send_ccb(device, ccb)) < 0)
5831 || ((immediate == 0)
5832 && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
5833 const char errstr[] = "error sending sanitize command";
5840 if (arglist & CAM_ARG_VERBOSE) {
5841 cam_error_print(device, ccb, CAM_ESF_ALL,
5842 CAM_EPF_ALL, stderr);
5845 goto scsisanitize_bailout;
5849 * If we ran in non-immediate mode, we already checked for errors
5850 * above and printed out any necessary information. If we're in
5851 * immediate mode, we need to loop through and get status
5852 * information periodically.
5854 if (immediate == 0) {
5856 fprintf(stdout, "Sanitize Complete\n");
5858 goto scsisanitize_bailout;
5865 bzero(&(&ccb->ccb_h)[1],
5866 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5869 * There's really no need to do error recovery or
5870 * retries here, since we're just going to sit in a
5871 * loop and wait for the device to finish sanitizing.
5873 scsi_test_unit_ready(&ccb->csio,
5876 /* tag_action */ MSG_SIMPLE_Q_TAG,
5877 /* sense_len */ SSD_FULL_SIZE,
5878 /* timeout */ 5000);
5880 /* Disable freezing the device queue */
5881 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5883 retval = cam_send_ccb(device, ccb);
5886 * If we get an error from the ioctl, bail out. SCSI
5887 * errors are expected.
5890 warn("error sending CAMIOCOMMAND ioctl");
5891 if (arglist & CAM_ARG_VERBOSE) {
5892 cam_error_print(device, ccb, CAM_ESF_ALL,
5893 CAM_EPF_ALL, stderr);
5896 goto scsisanitize_bailout;
5899 status = ccb->ccb_h.status & CAM_STATUS_MASK;
5901 if ((status != CAM_REQ_CMP)
5902 && (status == CAM_SCSI_STATUS_ERROR)
5903 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
5904 struct scsi_sense_data *sense;
5905 int error_code, sense_key, asc, ascq;
5907 sense = &ccb->csio.sense_data;
5908 scsi_extract_sense_len(sense, ccb->csio.sense_len -
5909 ccb->csio.sense_resid, &error_code, &sense_key,
5910 &asc, &ascq, /*show_errors*/ 1);
5913 * According to the SCSI-3 spec, a drive that is in the
5914 * middle of a sanitize should return NOT READY with an
5915 * ASC of "logical unit not ready, sanitize in
5916 * progress". The sense key specific bytes will then
5917 * be a progress indicator.
5919 if ((sense_key == SSD_KEY_NOT_READY)
5920 && (asc == 0x04) && (ascq == 0x1b)) {
5923 if ((scsi_get_sks(sense, ccb->csio.sense_len -
5924 ccb->csio.sense_resid, sks) == 0)
5927 u_int64_t percentage;
5929 val = scsi_2btoul(&sks[1]);
5930 percentage = 10000 * val;
5933 "\rSanitizing: %ju.%02u %% "
5935 (uintmax_t)(percentage /
5937 (unsigned)((percentage /
5941 } else if ((quiet == 0)
5942 && (++num_warnings <= 1)) {
5943 warnx("Unexpected SCSI Sense Key "
5944 "Specific value returned "
5945 "during sanitize:");
5946 scsi_sense_print(device, &ccb->csio,
5948 warnx("Unable to print status "
5949 "information, but sanitze will "
5951 warnx("will exit when sanitize is "
5956 warnx("Unexpected SCSI error during sanitize");
5957 cam_error_print(device, ccb, CAM_ESF_ALL,
5958 CAM_EPF_ALL, stderr);
5960 goto scsisanitize_bailout;
5963 } else if (status != CAM_REQ_CMP) {
5964 warnx("Unexpected CAM status %#x", status);
5965 if (arglist & CAM_ARG_VERBOSE)
5966 cam_error_print(device, ccb, CAM_ESF_ALL,
5967 CAM_EPF_ALL, stderr);
5969 goto scsisanitize_bailout;
5971 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
5974 fprintf(stdout, "\nSanitize Complete\n");
5976 scsisanitize_bailout:
5979 if (data_ptr != NULL)
5987 scsireportluns(struct cam_device *device, int argc, char **argv,
5988 char *combinedopt, int retry_count, int timeout)
5991 int c, countonly, lunsonly;
5992 struct scsi_report_luns_data *lundata;
5994 uint8_t report_type;
5995 uint32_t list_len, i, j;
6000 report_type = RPL_REPORT_DEFAULT;
6001 ccb = cam_getccb(device);
6004 warnx("%s: error allocating ccb", __func__);
6008 bzero(&(&ccb->ccb_h)[1],
6009 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6014 while ((c = getopt(argc, argv, combinedopt)) != -1) {
6023 if (strcasecmp(optarg, "default") == 0)
6024 report_type = RPL_REPORT_DEFAULT;
6025 else if (strcasecmp(optarg, "wellknown") == 0)
6026 report_type = RPL_REPORT_WELLKNOWN;
6027 else if (strcasecmp(optarg, "all") == 0)
6028 report_type = RPL_REPORT_ALL;
6030 warnx("%s: invalid report type \"%s\"",
6041 if ((countonly != 0)
6042 && (lunsonly != 0)) {
6043 warnx("%s: you can only specify one of -c or -l", __func__);
6048 * According to SPC-4, the allocation length must be at least 16
6049 * bytes -- enough for the header and one LUN.
6051 alloc_len = sizeof(*lundata) + 8;
6055 lundata = malloc(alloc_len);
6057 if (lundata == NULL) {
6058 warn("%s: error mallocing %d bytes", __func__, alloc_len);
6063 scsi_report_luns(&ccb->csio,
6064 /*retries*/ retry_count,
6066 /*tag_action*/ MSG_SIMPLE_Q_TAG,
6067 /*select_report*/ report_type,
6068 /*rpl_buf*/ lundata,
6069 /*alloc_len*/ alloc_len,
6070 /*sense_len*/ SSD_FULL_SIZE,
6071 /*timeout*/ timeout ? timeout : 5000);
6073 /* Disable freezing the device queue */
6074 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6076 if (arglist & CAM_ARG_ERR_RECOVER)
6077 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6079 if (cam_send_ccb(device, ccb) < 0) {
6080 warn("error sending REPORT LUNS command");
6082 if (arglist & CAM_ARG_VERBOSE)
6083 cam_error_print(device, ccb, CAM_ESF_ALL,
6084 CAM_EPF_ALL, stderr);
6090 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6091 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6097 list_len = scsi_4btoul(lundata->length);
6100 * If we need to list the LUNs, and our allocation
6101 * length was too short, reallocate and retry.
6103 if ((countonly == 0)
6104 && (list_len > (alloc_len - sizeof(*lundata)))) {
6105 alloc_len = list_len + sizeof(*lundata);
6111 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
6112 ((list_len / 8) > 1) ? "s" : "");
6117 for (i = 0; i < (list_len / 8); i++) {
6121 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
6123 fprintf(stdout, ",");
6124 switch (lundata->luns[i].lundata[j] &
6125 RPL_LUNDATA_ATYP_MASK) {
6126 case RPL_LUNDATA_ATYP_PERIPH:
6127 if ((lundata->luns[i].lundata[j] &
6128 RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
6129 fprintf(stdout, "%d:",
6130 lundata->luns[i].lundata[j] &
6131 RPL_LUNDATA_PERIPH_BUS_MASK);
6133 && ((lundata->luns[i].lundata[j+2] &
6134 RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
6137 fprintf(stdout, "%d",
6138 lundata->luns[i].lundata[j+1]);
6140 case RPL_LUNDATA_ATYP_FLAT: {
6142 tmplun[0] = lundata->luns[i].lundata[j] &
6143 RPL_LUNDATA_FLAT_LUN_MASK;
6144 tmplun[1] = lundata->luns[i].lundata[j+1];
6146 fprintf(stdout, "%d", scsi_2btoul(tmplun));
6150 case RPL_LUNDATA_ATYP_LUN:
6151 fprintf(stdout, "%d:%d:%d",
6152 (lundata->luns[i].lundata[j+1] &
6153 RPL_LUNDATA_LUN_BUS_MASK) >> 5,
6154 lundata->luns[i].lundata[j] &
6155 RPL_LUNDATA_LUN_TARG_MASK,
6156 lundata->luns[i].lundata[j+1] &
6157 RPL_LUNDATA_LUN_LUN_MASK);
6159 case RPL_LUNDATA_ATYP_EXTLUN: {
6160 int field_len_code, eam_code;
6162 eam_code = lundata->luns[i].lundata[j] &
6163 RPL_LUNDATA_EXT_EAM_MASK;
6164 field_len_code = (lundata->luns[i].lundata[j] &
6165 RPL_LUNDATA_EXT_LEN_MASK) >> 4;
6167 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
6168 && (field_len_code == 0x00)) {
6169 fprintf(stdout, "%d",
6170 lundata->luns[i].lundata[j+1]);
6171 } else if ((eam_code ==
6172 RPL_LUNDATA_EXT_EAM_NOT_SPEC)
6173 && (field_len_code == 0x03)) {
6177 * This format takes up all 8 bytes.
6178 * If we aren't starting at offset 0,
6182 fprintf(stdout, "Invalid "
6185 "specified format", j);
6189 bzero(tmp_lun, sizeof(tmp_lun));
6190 bcopy(&lundata->luns[i].lundata[j+1],
6191 &tmp_lun[1], sizeof(tmp_lun) - 1);
6192 fprintf(stdout, "%#jx",
6193 (intmax_t)scsi_8btou64(tmp_lun));
6196 fprintf(stderr, "Unknown Extended LUN"
6197 "Address method %#x, length "
6198 "code %#x", eam_code,
6205 fprintf(stderr, "Unknown LUN address method "
6206 "%#x\n", lundata->luns[i].lundata[0] &
6207 RPL_LUNDATA_ATYP_MASK);
6211 * For the flat addressing method, there are no
6212 * other levels after it.
6217 fprintf(stdout, "\n");
6230 scsireadcapacity(struct cam_device *device, int argc, char **argv,
6231 char *combinedopt, int retry_count, int timeout)
6234 int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
6235 struct scsi_read_capacity_data rcap;
6236 struct scsi_read_capacity_data_long rcaplong;
6250 ccb = cam_getccb(device);
6253 warnx("%s: error allocating ccb", __func__);
6257 bzero(&(&ccb->ccb_h)[1],
6258 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6260 while ((c = getopt(argc, argv, combinedopt)) != -1) {
6287 if ((blocksizeonly != 0)
6288 && (numblocks != 0)) {
6289 warnx("%s: you can only specify one of -b or -N", __func__);
6294 if ((blocksizeonly != 0)
6295 && (sizeonly != 0)) {
6296 warnx("%s: you can only specify one of -b or -s", __func__);
6303 warnx("%s: you can only specify one of -h/-H or -q", __func__);
6309 && (blocksizeonly != 0)) {
6310 warnx("%s: you can only specify one of -h/-H or -b", __func__);
6315 scsi_read_capacity(&ccb->csio,
6316 /*retries*/ retry_count,
6318 /*tag_action*/ MSG_SIMPLE_Q_TAG,
6321 /*timeout*/ timeout ? timeout : 5000);
6323 /* Disable freezing the device queue */
6324 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6326 if (arglist & CAM_ARG_ERR_RECOVER)
6327 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6329 if (cam_send_ccb(device, ccb) < 0) {
6330 warn("error sending READ CAPACITY command");
6332 if (arglist & CAM_ARG_VERBOSE)
6333 cam_error_print(device, ccb, CAM_ESF_ALL,
6334 CAM_EPF_ALL, stderr);
6340 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6341 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6346 maxsector = scsi_4btoul(rcap.addr);
6347 block_len = scsi_4btoul(rcap.length);
6350 * A last block of 2^32-1 means that the true capacity is over 2TB,
6351 * and we need to issue the long READ CAPACITY to get the real
6352 * capacity. Otherwise, we're all set.
6354 if (maxsector != 0xffffffff)
6357 scsi_read_capacity_16(&ccb->csio,
6358 /*retries*/ retry_count,
6360 /*tag_action*/ MSG_SIMPLE_Q_TAG,
6364 /*rcap_buf*/ (uint8_t *)&rcaplong,
6365 /*rcap_buf_len*/ sizeof(rcaplong),
6366 /*sense_len*/ SSD_FULL_SIZE,
6367 /*timeout*/ timeout ? timeout : 5000);
6369 /* Disable freezing the device queue */
6370 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6372 if (arglist & CAM_ARG_ERR_RECOVER)
6373 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6375 if (cam_send_ccb(device, ccb) < 0) {
6376 warn("error sending READ CAPACITY (16) command");
6378 if (arglist & CAM_ARG_VERBOSE)
6379 cam_error_print(device, ccb, CAM_ESF_ALL,
6380 CAM_EPF_ALL, stderr);
6386 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6387 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6392 maxsector = scsi_8btou64(rcaplong.addr);
6393 block_len = scsi_4btoul(rcaplong.length);
6396 if (blocksizeonly == 0) {
6398 * Humanize implies !quiet, and also implies numblocks.
6400 if (humanize != 0) {
6405 tmpbytes = (maxsector + 1) * block_len;
6406 ret = humanize_number(tmpstr, sizeof(tmpstr),
6407 tmpbytes, "", HN_AUTOSCALE,
6410 HN_DIVISOR_1000 : 0));
6412 warnx("%s: humanize_number failed!", __func__);
6416 fprintf(stdout, "Device Size: %s%s", tmpstr,
6417 (sizeonly == 0) ? ", " : "\n");
6418 } else if (numblocks != 0) {
6419 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6420 "Blocks: " : "", (uintmax_t)maxsector + 1,
6421 (sizeonly == 0) ? ", " : "\n");
6423 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6424 "Last Block: " : "", (uintmax_t)maxsector,
6425 (sizeonly == 0) ? ", " : "\n");
6429 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
6430 "Block Length: " : "", block_len, (quiet == 0) ?
6439 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
6440 int retry_count, int timeout)
6444 uint8_t *smp_request = NULL, *smp_response = NULL;
6445 int request_size = 0, response_size = 0;
6446 int fd_request = 0, fd_response = 0;
6447 char *datastr = NULL;
6448 struct get_hook hook;
6453 * Note that at the moment we don't support sending SMP CCBs to
6454 * devices that aren't probed by CAM.
6456 ccb = cam_getccb(device);
6458 warnx("%s: error allocating CCB", __func__);
6462 bzero(&(&ccb->ccb_h)[1],
6463 sizeof(union ccb) - sizeof(struct ccb_hdr));
6465 while ((c = getopt(argc, argv, combinedopt)) != -1) {
6468 arglist |= CAM_ARG_CMD_IN;
6469 response_size = strtol(optarg, NULL, 0);
6470 if (response_size <= 0) {
6471 warnx("invalid number of response bytes %d",
6474 goto smpcmd_bailout;
6476 hook.argc = argc - optind;
6477 hook.argv = argv + optind;
6480 datastr = cget(&hook, NULL);
6482 * If the user supplied "-" instead of a format, he
6483 * wants the data to be written to stdout.
6485 if ((datastr != NULL)
6486 && (datastr[0] == '-'))
6489 smp_response = (u_int8_t *)malloc(response_size);
6490 if (smp_response == NULL) {
6491 warn("can't malloc memory for SMP response");
6493 goto smpcmd_bailout;
6497 arglist |= CAM_ARG_CMD_OUT;
6498 request_size = strtol(optarg, NULL, 0);
6499 if (request_size <= 0) {
6500 warnx("invalid number of request bytes %d",
6503 goto smpcmd_bailout;
6505 hook.argc = argc - optind;
6506 hook.argv = argv + optind;
6508 datastr = cget(&hook, NULL);
6509 smp_request = (u_int8_t *)malloc(request_size);
6510 if (smp_request == NULL) {
6511 warn("can't malloc memory for SMP request");
6513 goto smpcmd_bailout;
6515 bzero(smp_request, request_size);
6517 * If the user supplied "-" instead of a format, he
6518 * wants the data to be read from stdin.
6520 if ((datastr != NULL)
6521 && (datastr[0] == '-'))
6524 buff_encode_visit(smp_request, request_size,
6535 * If fd_data is set, and we're writing to the device, we need to
6536 * read the data the user wants written from stdin.
6538 if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
6540 int amt_to_read = request_size;
6541 u_int8_t *buf_ptr = smp_request;
6543 for (amt_read = 0; amt_to_read > 0;
6544 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
6545 if (amt_read == -1) {
6546 warn("error reading data from stdin");
6548 goto smpcmd_bailout;
6550 amt_to_read -= amt_read;
6551 buf_ptr += amt_read;
6555 if (((arglist & CAM_ARG_CMD_IN) == 0)
6556 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
6557 warnx("%s: need both the request (-r) and response (-R) "
6558 "arguments", __func__);
6560 goto smpcmd_bailout;
6563 flags |= CAM_DEV_QFRZDIS;
6565 cam_fill_smpio(&ccb->smpio,
6566 /*retries*/ retry_count,
6569 /*smp_request*/ smp_request,
6570 /*smp_request_len*/ request_size,
6571 /*smp_response*/ smp_response,
6572 /*smp_response_len*/ response_size,
6573 /*timeout*/ timeout ? timeout : 5000);
6575 ccb->smpio.flags = SMP_FLAG_NONE;
6577 if (((retval = cam_send_ccb(device, ccb)) < 0)
6578 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6579 const char warnstr[] = "error sending command";
6586 if (arglist & CAM_ARG_VERBOSE) {
6587 cam_error_print(device, ccb, CAM_ESF_ALL,
6588 CAM_EPF_ALL, stderr);
6592 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
6593 && (response_size > 0)) {
6594 if (fd_response == 0) {
6595 buff_decode_visit(smp_response, response_size,
6596 datastr, arg_put, NULL);
6597 fprintf(stdout, "\n");
6599 ssize_t amt_written;
6600 int amt_to_write = response_size;
6601 u_int8_t *buf_ptr = smp_response;
6603 for (amt_written = 0; (amt_to_write > 0) &&
6604 (amt_written = write(STDOUT_FILENO, buf_ptr,
6605 amt_to_write)) > 0;){
6606 amt_to_write -= amt_written;
6607 buf_ptr += amt_written;
6609 if (amt_written == -1) {
6610 warn("error writing data to stdout");
6612 goto smpcmd_bailout;
6613 } else if ((amt_written == 0)
6614 && (amt_to_write > 0)) {
6615 warnx("only wrote %u bytes out of %u",
6616 response_size - amt_to_write,
6625 if (smp_request != NULL)
6628 if (smp_response != NULL)
6635 smpreportgeneral(struct cam_device *device, int argc, char **argv,
6636 char *combinedopt, int retry_count, int timeout)
6639 struct smp_report_general_request *request = NULL;
6640 struct smp_report_general_response *response = NULL;
6641 struct sbuf *sb = NULL;
6643 int c, long_response = 0;
6647 * Note that at the moment we don't support sending SMP CCBs to
6648 * devices that aren't probed by CAM.
6650 ccb = cam_getccb(device);
6652 warnx("%s: error allocating CCB", __func__);
6656 bzero(&(&ccb->ccb_h)[1],
6657 sizeof(union ccb) - sizeof(struct ccb_hdr));
6659 while ((c = getopt(argc, argv, combinedopt)) != -1) {
6668 request = malloc(sizeof(*request));
6669 if (request == NULL) {
6670 warn("%s: unable to allocate %zd bytes", __func__,
6676 response = malloc(sizeof(*response));
6677 if (response == NULL) {
6678 warn("%s: unable to allocate %zd bytes", __func__,
6685 smp_report_general(&ccb->smpio,
6689 /*request_len*/ sizeof(*request),
6690 (uint8_t *)response,
6691 /*response_len*/ sizeof(*response),
6692 /*long_response*/ long_response,
6695 if (((retval = cam_send_ccb(device, ccb)) < 0)
6696 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6697 const char warnstr[] = "error sending command";
6704 if (arglist & CAM_ARG_VERBOSE) {
6705 cam_error_print(device, ccb, CAM_ESF_ALL,
6706 CAM_EPF_ALL, stderr);
6713 * If the device supports the long response bit, try again and see
6714 * if we can get all of the data.
6716 if ((response->long_response & SMP_RG_LONG_RESPONSE)
6717 && (long_response == 0)) {
6718 ccb->ccb_h.status = CAM_REQ_INPROG;
6719 bzero(&(&ccb->ccb_h)[1],
6720 sizeof(union ccb) - sizeof(struct ccb_hdr));
6726 * XXX KDM detect and decode SMP errors here.
6728 sb = sbuf_new_auto();
6730 warnx("%s: error allocating sbuf", __func__);
6734 smp_report_general_sbuf(response, sizeof(*response), sb);
6736 if (sbuf_finish(sb) != 0) {
6737 warnx("%s: sbuf_finish", __func__);
6741 printf("%s", sbuf_data(sb));
6747 if (request != NULL)
6750 if (response != NULL)
6759 static struct camcontrol_opts phy_ops[] = {
6760 {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
6761 {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
6762 {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
6763 {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
6764 {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
6765 {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
6766 {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
6767 {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
6768 {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
6773 smpphycontrol(struct cam_device *device, int argc, char **argv,
6774 char *combinedopt, int retry_count, int timeout)
6777 struct smp_phy_control_request *request = NULL;
6778 struct smp_phy_control_response *response = NULL;
6779 int long_response = 0;
6782 uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
6784 uint64_t attached_dev_name = 0;
6785 int dev_name_set = 0;
6786 uint32_t min_plr = 0, max_plr = 0;
6787 uint32_t pp_timeout_val = 0;
6788 int slumber_partial = 0;
6789 int set_pp_timeout_val = 0;
6793 * Note that at the moment we don't support sending SMP CCBs to
6794 * devices that aren't probed by CAM.
6796 ccb = cam_getccb(device);
6798 warnx("%s: error allocating CCB", __func__);
6802 bzero(&(&ccb->ccb_h)[1],
6803 sizeof(union ccb) - sizeof(struct ccb_hdr));
6805 while ((c = getopt(argc, argv, combinedopt)) != -1) {
6813 if (strcasecmp(optarg, "enable") == 0)
6815 else if (strcasecmp(optarg, "disable") == 0)
6818 warnx("%s: Invalid argument %s", __func__,
6825 slumber_partial |= enable <<
6826 SMP_PC_SAS_SLUMBER_SHIFT;
6829 slumber_partial |= enable <<
6830 SMP_PC_SAS_PARTIAL_SHIFT;
6833 slumber_partial |= enable <<
6834 SMP_PC_SATA_SLUMBER_SHIFT;
6837 slumber_partial |= enable <<
6838 SMP_PC_SATA_PARTIAL_SHIFT;
6841 warnx("%s: programmer error", __func__);
6844 break; /*NOTREACHED*/
6849 attached_dev_name = (uintmax_t)strtoumax(optarg,
6858 * We don't do extensive checking here, so this
6859 * will continue to work when new speeds come out.
6861 min_plr = strtoul(optarg, NULL, 0);
6863 || (min_plr > 0xf)) {
6864 warnx("%s: invalid link rate %x",
6872 * We don't do extensive checking here, so this
6873 * will continue to work when new speeds come out.
6875 max_plr = strtoul(optarg, NULL, 0);
6877 || (max_plr > 0xf)) {
6878 warnx("%s: invalid link rate %x",
6885 camcontrol_optret optreturn;
6886 cam_argmask argnums;
6889 if (phy_op_set != 0) {
6890 warnx("%s: only one phy operation argument "
6891 "(-o) allowed", __func__);
6899 * Allow the user to specify the phy operation
6900 * numerically, as well as with a name. This will
6901 * future-proof it a bit, so options that are added
6902 * in future specs can be used.
6904 if (isdigit(optarg[0])) {
6905 phy_operation = strtoul(optarg, NULL, 0);
6906 if ((phy_operation == 0)
6907 || (phy_operation > 0xff)) {
6908 warnx("%s: invalid phy operation %#x",
6909 __func__, phy_operation);
6915 optreturn = getoption(phy_ops, optarg, &phy_operation,
6918 if (optreturn == CC_OR_AMBIGUOUS) {
6919 warnx("%s: ambiguous option %s", __func__,
6924 } else if (optreturn == CC_OR_NOT_FOUND) {
6925 warnx("%s: option %s not found", __func__,
6937 pp_timeout_val = strtoul(optarg, NULL, 0);
6938 if (pp_timeout_val > 15) {
6939 warnx("%s: invalid partial pathway timeout "
6940 "value %u, need a value less than 16",
6941 __func__, pp_timeout_val);
6945 set_pp_timeout_val = 1;
6953 warnx("%s: a PHY (-p phy) argument is required",__func__);
6958 if (((dev_name_set != 0)
6959 && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
6960 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
6961 && (dev_name_set == 0))) {
6962 warnx("%s: -d name and -o setdevname arguments both "
6963 "required to set device name", __func__);
6968 request = malloc(sizeof(*request));
6969 if (request == NULL) {
6970 warn("%s: unable to allocate %zd bytes", __func__,
6976 response = malloc(sizeof(*response));
6977 if (response == NULL) {
6978 warn("%s: unable to allocate %zd bytes", __func__,
6984 smp_phy_control(&ccb->smpio,
6989 (uint8_t *)response,
6992 /*expected_exp_change_count*/ 0,
6995 (set_pp_timeout_val != 0) ? 1 : 0,
7003 if (((retval = cam_send_ccb(device, ccb)) < 0)
7004 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7005 const char warnstr[] = "error sending command";
7012 if (arglist & CAM_ARG_VERBOSE) {
7014 * Use CAM_EPF_NORMAL so we only get one line of
7015 * SMP command decoding.
7017 cam_error_print(device, ccb, CAM_ESF_ALL,
7018 CAM_EPF_NORMAL, stderr);
7024 /* XXX KDM print out something here for success? */
7029 if (request != NULL)
7032 if (response != NULL)
7039 smpmaninfo(struct cam_device *device, int argc, char **argv,
7040 char *combinedopt, int retry_count, int timeout)
7043 struct smp_report_manuf_info_request request;
7044 struct smp_report_manuf_info_response response;
7045 struct sbuf *sb = NULL;
7046 int long_response = 0;
7051 * Note that at the moment we don't support sending SMP CCBs to
7052 * devices that aren't probed by CAM.
7054 ccb = cam_getccb(device);
7056 warnx("%s: error allocating CCB", __func__);
7060 bzero(&(&ccb->ccb_h)[1],
7061 sizeof(union ccb) - sizeof(struct ccb_hdr));
7063 while ((c = getopt(argc, argv, combinedopt)) != -1) {
7072 bzero(&request, sizeof(request));
7073 bzero(&response, sizeof(response));
7075 smp_report_manuf_info(&ccb->smpio,
7080 (uint8_t *)&response,
7085 if (((retval = cam_send_ccb(device, ccb)) < 0)
7086 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7087 const char warnstr[] = "error sending command";
7094 if (arglist & CAM_ARG_VERBOSE) {
7095 cam_error_print(device, ccb, CAM_ESF_ALL,
7096 CAM_EPF_ALL, stderr);
7102 sb = sbuf_new_auto();
7104 warnx("%s: error allocating sbuf", __func__);
7108 smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
7110 if (sbuf_finish(sb) != 0) {
7111 warnx("%s: sbuf_finish", __func__);
7115 printf("%s", sbuf_data(sb));
7129 getdevid(struct cam_devitem *item)
7132 union ccb *ccb = NULL;
7134 struct cam_device *dev;
7136 dev = cam_open_btl(item->dev_match.path_id,
7137 item->dev_match.target_id,
7138 item->dev_match.target_lun, O_RDWR, NULL);
7141 warnx("%s", cam_errbuf);
7146 item->device_id_len = 0;
7148 ccb = cam_getccb(dev);
7150 warnx("%s: error allocating CCB", __func__);
7155 bzero(&(&ccb->ccb_h)[1],
7156 sizeof(union ccb) - sizeof(struct ccb_hdr));
7159 * On the first try, we just probe for the size of the data, and
7160 * then allocate that much memory and try again.
7163 ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
7164 ccb->ccb_h.flags = CAM_DIR_IN;
7165 ccb->cdai.flags = 0;
7166 ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
7167 ccb->cdai.bufsiz = item->device_id_len;
7168 if (item->device_id_len != 0)
7169 ccb->cdai.buf = (uint8_t *)item->device_id;
7171 if (cam_send_ccb(dev, ccb) < 0) {
7172 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
7177 if (ccb->ccb_h.status != CAM_REQ_CMP) {
7178 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
7183 if (item->device_id_len == 0) {
7185 * This is our first time through. Allocate the buffer,
7186 * and then go back to get the data.
7188 if (ccb->cdai.provsiz == 0) {
7189 warnx("%s: invalid .provsiz field returned with "
7190 "XPT_GDEV_ADVINFO CCB", __func__);
7194 item->device_id_len = ccb->cdai.provsiz;
7195 item->device_id = malloc(item->device_id_len);
7196 if (item->device_id == NULL) {
7197 warn("%s: unable to allocate %d bytes", __func__,
7198 item->device_id_len);
7202 ccb->ccb_h.status = CAM_REQ_INPROG;
7208 cam_close_device(dev);
7217 * XXX KDM merge this code with getdevtree()?
7220 buildbusdevlist(struct cam_devlist *devlist)
7223 int bufsize, fd = -1;
7224 struct dev_match_pattern *patterns;
7225 struct cam_devitem *item = NULL;
7226 int skip_device = 0;
7229 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
7230 warn("couldn't open %s", XPT_DEVICE);
7234 bzero(&ccb, sizeof(union ccb));
7236 ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
7237 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
7238 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
7240 ccb.ccb_h.func_code = XPT_DEV_MATCH;
7241 bufsize = sizeof(struct dev_match_result) * 100;
7242 ccb.cdm.match_buf_len = bufsize;
7243 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
7244 if (ccb.cdm.matches == NULL) {
7245 warnx("can't malloc memory for matches");
7249 ccb.cdm.num_matches = 0;
7250 ccb.cdm.num_patterns = 2;
7251 ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
7252 ccb.cdm.num_patterns;
7254 patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
7255 if (patterns == NULL) {
7256 warnx("can't malloc memory for patterns");
7261 ccb.cdm.patterns = patterns;
7262 bzero(patterns, ccb.cdm.pattern_buf_len);
7264 patterns[0].type = DEV_MATCH_DEVICE;
7265 patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
7266 patterns[0].pattern.device_pattern.path_id = devlist->path_id;
7267 patterns[1].type = DEV_MATCH_PERIPH;
7268 patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
7269 patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
7272 * We do the ioctl multiple times if necessary, in case there are
7273 * more than 100 nodes in the EDT.
7278 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
7279 warn("error sending CAMIOCOMMAND ioctl");
7284 if ((ccb.ccb_h.status != CAM_REQ_CMP)
7285 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
7286 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
7287 warnx("got CAM error %#x, CDM error %d\n",
7288 ccb.ccb_h.status, ccb.cdm.status);
7293 for (i = 0; i < ccb.cdm.num_matches; i++) {
7294 switch (ccb.cdm.matches[i].type) {
7295 case DEV_MATCH_DEVICE: {
7296 struct device_match_result *dev_result;
7299 &ccb.cdm.matches[i].result.device_result;
7301 if (dev_result->flags &
7302 DEV_RESULT_UNCONFIGURED) {
7308 item = malloc(sizeof(*item));
7310 warn("%s: unable to allocate %zd bytes",
7311 __func__, sizeof(*item));
7315 bzero(item, sizeof(*item));
7316 bcopy(dev_result, &item->dev_match,
7317 sizeof(*dev_result));
7318 STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
7321 if (getdevid(item) != 0) {
7327 case DEV_MATCH_PERIPH: {
7328 struct periph_match_result *periph_result;
7331 &ccb.cdm.matches[i].result.periph_result;
7333 if (skip_device != 0)
7335 item->num_periphs++;
7336 item->periph_matches = realloc(
7337 item->periph_matches,
7339 sizeof(struct periph_match_result));
7340 if (item->periph_matches == NULL) {
7341 warn("%s: error allocating periph "
7346 bcopy(periph_result, &item->periph_matches[
7347 item->num_periphs - 1],
7348 sizeof(*periph_result));
7352 fprintf(stderr, "%s: unexpected match "
7353 "type %d\n", __func__,
7354 ccb.cdm.matches[i].type);
7357 break; /*NOTREACHED*/
7360 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
7361 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
7369 free(ccb.cdm.matches);
7372 freebusdevlist(devlist);
7378 freebusdevlist(struct cam_devlist *devlist)
7380 struct cam_devitem *item, *item2;
7382 STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
7383 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
7385 free(item->device_id);
7386 free(item->periph_matches);
7391 static struct cam_devitem *
7392 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
7394 struct cam_devitem *item;
7396 STAILQ_FOREACH(item, &devlist->dev_queue, links) {
7397 struct scsi_vpd_id_descriptor *idd;
7400 * XXX KDM look for LUN IDs as well?
7402 idd = scsi_get_devid(item->device_id,
7403 item->device_id_len,
7404 scsi_devid_is_sas_target);
7408 if (scsi_8btou64(idd->identifier) == sasaddr)
7416 smpphylist(struct cam_device *device, int argc, char **argv,
7417 char *combinedopt, int retry_count, int timeout)
7419 struct smp_report_general_request *rgrequest = NULL;
7420 struct smp_report_general_response *rgresponse = NULL;
7421 struct smp_discover_request *disrequest = NULL;
7422 struct smp_discover_response *disresponse = NULL;
7423 struct cam_devlist devlist;
7425 int long_response = 0;
7432 * Note that at the moment we don't support sending SMP CCBs to
7433 * devices that aren't probed by CAM.
7435 ccb = cam_getccb(device);
7437 warnx("%s: error allocating CCB", __func__);
7441 bzero(&(&ccb->ccb_h)[1],
7442 sizeof(union ccb) - sizeof(struct ccb_hdr));
7443 STAILQ_INIT(&devlist.dev_queue);
7445 rgrequest = malloc(sizeof(*rgrequest));
7446 if (rgrequest == NULL) {
7447 warn("%s: unable to allocate %zd bytes", __func__,
7448 sizeof(*rgrequest));
7453 rgresponse = malloc(sizeof(*rgresponse));
7454 if (rgresponse == NULL) {
7455 warn("%s: unable to allocate %zd bytes", __func__,
7456 sizeof(*rgresponse));
7461 while ((c = getopt(argc, argv, combinedopt)) != -1) {
7474 smp_report_general(&ccb->smpio,
7478 /*request_len*/ sizeof(*rgrequest),
7479 (uint8_t *)rgresponse,
7480 /*response_len*/ sizeof(*rgresponse),
7481 /*long_response*/ long_response,
7484 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7486 if (((retval = cam_send_ccb(device, ccb)) < 0)
7487 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7488 const char warnstr[] = "error sending command";
7495 if (arglist & CAM_ARG_VERBOSE) {
7496 cam_error_print(device, ccb, CAM_ESF_ALL,
7497 CAM_EPF_ALL, stderr);
7503 num_phys = rgresponse->num_phys;
7505 if (num_phys == 0) {
7507 fprintf(stdout, "%s: No Phys reported\n", __func__);
7512 devlist.path_id = device->path_id;
7514 retval = buildbusdevlist(&devlist);
7519 fprintf(stdout, "%d PHYs:\n", num_phys);
7520 fprintf(stdout, "PHY Attached SAS Address\n");
7523 disrequest = malloc(sizeof(*disrequest));
7524 if (disrequest == NULL) {
7525 warn("%s: unable to allocate %zd bytes", __func__,
7526 sizeof(*disrequest));
7531 disresponse = malloc(sizeof(*disresponse));
7532 if (disresponse == NULL) {
7533 warn("%s: unable to allocate %zd bytes", __func__,
7534 sizeof(*disresponse));
7539 for (i = 0; i < num_phys; i++) {
7540 struct cam_devitem *item;
7541 struct device_match_result *dev_match;
7542 char vendor[16], product[48], revision[16];
7546 bzero(&(&ccb->ccb_h)[1],
7547 sizeof(union ccb) - sizeof(struct ccb_hdr));
7549 ccb->ccb_h.status = CAM_REQ_INPROG;
7550 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7552 smp_discover(&ccb->smpio,
7556 sizeof(*disrequest),
7557 (uint8_t *)disresponse,
7558 sizeof(*disresponse),
7560 /*ignore_zone_group*/ 0,
7564 if (((retval = cam_send_ccb(device, ccb)) < 0)
7565 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
7566 && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
7567 const char warnstr[] = "error sending command";
7574 if (arglist & CAM_ARG_VERBOSE) {
7575 cam_error_print(device, ccb, CAM_ESF_ALL,
7576 CAM_EPF_ALL, stderr);
7582 if (disresponse->function_result == SMP_FR_PHY_VACANT) {
7584 fprintf(stdout, "%3d <vacant>\n", i);
7588 if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) {
7591 item = findsasdevice(&devlist,
7592 scsi_8btou64(disresponse->attached_sas_address));
7596 || (item != NULL)) {
7597 fprintf(stdout, "%3d 0x%016jx", i,
7598 (uintmax_t)scsi_8btou64(
7599 disresponse->attached_sas_address));
7601 fprintf(stdout, "\n");
7604 } else if (quiet != 0)
7607 dev_match = &item->dev_match;
7609 if (dev_match->protocol == PROTO_SCSI) {
7610 cam_strvis(vendor, dev_match->inq_data.vendor,
7611 sizeof(dev_match->inq_data.vendor),
7613 cam_strvis(product, dev_match->inq_data.product,
7614 sizeof(dev_match->inq_data.product),
7616 cam_strvis(revision, dev_match->inq_data.revision,
7617 sizeof(dev_match->inq_data.revision),
7619 sprintf(tmpstr, "<%s %s %s>", vendor, product,
7621 } else if ((dev_match->protocol == PROTO_ATA)
7622 || (dev_match->protocol == PROTO_SATAPM)) {
7623 cam_strvis(product, dev_match->ident_data.model,
7624 sizeof(dev_match->ident_data.model),
7626 cam_strvis(revision, dev_match->ident_data.revision,
7627 sizeof(dev_match->ident_data.revision),
7629 sprintf(tmpstr, "<%s %s>", product, revision);
7631 sprintf(tmpstr, "<>");
7633 fprintf(stdout, " %-33s ", tmpstr);
7636 * If we have 0 periphs, that's a bug...
7638 if (item->num_periphs == 0) {
7639 fprintf(stdout, "\n");
7643 fprintf(stdout, "(");
7644 for (j = 0; j < item->num_periphs; j++) {
7646 fprintf(stdout, ",");
7648 fprintf(stdout, "%s%d",
7649 item->periph_matches[j].periph_name,
7650 item->periph_matches[j].unit_number);
7653 fprintf(stdout, ")\n");
7667 freebusdevlist(&devlist);
7673 atapm(struct cam_device *device, int argc, char **argv,
7674 char *combinedopt, int retry_count, int timeout)
7682 ccb = cam_getccb(device);
7685 warnx("%s: error allocating ccb", __func__);
7689 while ((c = getopt(argc, argv, combinedopt)) != -1) {
7698 if (strcmp(argv[1], "idle") == 0) {
7700 cmd = ATA_IDLE_IMMEDIATE;
7703 } else if (strcmp(argv[1], "standby") == 0) {
7705 cmd = ATA_STANDBY_IMMEDIATE;
7707 cmd = ATA_STANDBY_CMD;
7715 else if (t <= (240 * 5))
7717 else if (t <= (252 * 5))
7718 /* special encoding for 21 minutes */
7720 else if (t <= (11 * 30 * 60))
7721 sc = (t - 1) / (30 * 60) + 241;
7725 cam_fill_ataio(&ccb->ataio,
7728 /*flags*/CAM_DIR_NONE,
7732 timeout ? timeout : 30 * 1000);
7733 ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
7735 /* Disable freezing the device queue */
7736 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7738 if (arglist & CAM_ARG_ERR_RECOVER)
7739 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
7741 if (cam_send_ccb(device, ccb) < 0) {
7742 warn("error sending command");
7744 if (arglist & CAM_ARG_VERBOSE)
7745 cam_error_print(device, ccb, CAM_ESF_ALL,
7746 CAM_EPF_ALL, stderr);
7752 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
7753 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
7762 #endif /* MINIMALISTIC */
7765 usage(int printlong)
7768 fprintf(printlong ? stdout : stderr,
7769 "usage: camcontrol <command> [device id][generic args][command args]\n"
7770 " camcontrol devlist [-v]\n"
7771 #ifndef MINIMALISTIC
7772 " camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
7773 " camcontrol tur [dev_id][generic args]\n"
7774 " camcontrol inquiry [dev_id][generic args] [-D] [-S] [-R]\n"
7775 " camcontrol identify [dev_id][generic args] [-v]\n"
7776 " camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
7777 " camcontrol readcap [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
7779 " camcontrol start [dev_id][generic args]\n"
7780 " camcontrol stop [dev_id][generic args]\n"
7781 " camcontrol load [dev_id][generic args]\n"
7782 " camcontrol eject [dev_id][generic args]\n"
7783 #endif /* MINIMALISTIC */
7784 " camcontrol rescan <all | bus[:target:lun]>\n"
7785 " camcontrol reset <all | bus[:target:lun]>\n"
7786 #ifndef MINIMALISTIC
7787 " camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n"
7788 " camcontrol modepage [dev_id][generic args] <-m page | -l>\n"
7789 " [-P pagectl][-e | -b][-d]\n"
7790 " camcontrol cmd [dev_id][generic args]\n"
7791 " <-a cmd [args] | -c cmd [args]>\n"
7792 " [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
7793 " camcontrol smpcmd [dev_id][generic args]\n"
7794 " <-r len fmt [args]> <-R len fmt [args]>\n"
7795 " camcontrol smprg [dev_id][generic args][-l]\n"
7796 " camcontrol smppc [dev_id][generic args] <-p phy> [-l]\n"
7797 " [-o operation][-d name][-m rate][-M rate]\n"
7798 " [-T pp_timeout][-a enable|disable]\n"
7799 " [-A enable|disable][-s enable|disable]\n"
7800 " [-S enable|disable]\n"
7801 " camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
7802 " camcontrol smpmaninfo [dev_id][generic args][-l]\n"
7803 " camcontrol debug [-I][-P][-T][-S][-X][-c]\n"
7804 " <all|bus[:target[:lun]]|off>\n"
7805 " camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n"
7806 " camcontrol negotiate [dev_id][generic args] [-a][-c]\n"
7807 " [-D <enable|disable>][-M mode][-O offset]\n"
7808 " [-q][-R syncrate][-v][-T <enable|disable>]\n"
7809 " [-U][-W bus_width]\n"
7810 " camcontrol format [dev_id][generic args][-q][-r][-w][-y]\n"
7811 " camcontrol sanitize [dev_id][generic args]\n"
7812 " [-a overwrite|block|crypto|exitfailure]\n"
7813 " [-c passes][-I][-P pattern][-q][-U][-r][-w]\n"
7815 " camcontrol idle [dev_id][generic args][-t time]\n"
7816 " camcontrol standby [dev_id][generic args][-t time]\n"
7817 " camcontrol sleep [dev_id][generic args]\n"
7818 " camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-y][-s]\n"
7819 " camcontrol security [dev_id][generic args]\n"
7820 " <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
7821 " [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
7822 " [-U <user|master>] [-y]\n"
7823 " camcontrol hpa [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n"
7824 " [-q] [-s max_sectors] [-U pwd] [-y]\n"
7825 " camcontrol persist [dev_id][generic args] <-i action|-o action>\n"
7826 " [-a][-I tid][-k key][-K sa_key][-p][-R rtp]\n"
7827 " [-s scope][-S][-T type][-U]\n"
7828 #endif /* MINIMALISTIC */
7829 " camcontrol help\n");
7832 #ifndef MINIMALISTIC
7834 "Specify one of the following options:\n"
7835 "devlist list all CAM devices\n"
7836 "periphlist list all CAM peripheral drivers attached to a device\n"
7837 "tur send a test unit ready to the named device\n"
7838 "inquiry send a SCSI inquiry command to the named device\n"
7839 "identify send a ATA identify command to the named device\n"
7840 "reportluns send a SCSI report luns command to the device\n"
7841 "readcap send a SCSI read capacity command to the device\n"
7842 "start send a Start Unit command to the device\n"
7843 "stop send a Stop Unit command to the device\n"
7844 "load send a Start Unit command to the device with the load bit set\n"
7845 "eject send a Stop Unit command to the device with the eject bit set\n"
7846 "rescan rescan all busses, the given bus, or bus:target:lun\n"
7847 "reset reset all busses, the given bus, or bus:target:lun\n"
7848 "defects read the defect list of the specified device\n"
7849 "modepage display or edit (-e) the given mode page\n"
7850 "cmd send the given SCSI command, may need -i or -o as well\n"
7851 "smpcmd send the given SMP command, requires -o and -i\n"
7852 "smprg send the SMP Report General command\n"
7853 "smppc send the SMP PHY Control command, requires -p\n"
7854 "smpphylist display phys attached to a SAS expander\n"
7855 "smpmaninfo send the SMP Report Manufacturer Info command\n"
7856 "debug turn debugging on/off for a bus, target, or lun, or all devices\n"
7857 "tags report or set the number of transaction slots for a device\n"
7858 "negotiate report or set device negotiation parameters\n"
7859 "format send the SCSI FORMAT UNIT command to the named device\n"
7860 "sanitize send the SCSI SANITIZE command to the named device\n"
7861 "idle send the ATA IDLE command to the named device\n"
7862 "standby send the ATA STANDBY command to the named device\n"
7863 "sleep send the ATA SLEEP command to the named device\n"
7864 "fwdownload program firmware of the named device with the given image\n"
7865 "security report or send ATA security commands to the named device\n"
7866 "persist send the SCSI PERSISTENT RESERVE IN or OUT commands\n"
7867 "help this message\n"
7868 "Device Identifiers:\n"
7869 "bus:target specify the bus and target, lun defaults to 0\n"
7870 "bus:target:lun specify the bus, target and lun\n"
7871 "deviceUNIT specify the device name, like \"da4\" or \"cd2\"\n"
7872 "Generic arguments:\n"
7873 "-v be verbose, print out sense information\n"
7874 "-t timeout command timeout in seconds, overrides default timeout\n"
7875 "-n dev_name specify device name, e.g. \"da\", \"cd\"\n"
7876 "-u unit specify unit number, e.g. \"0\", \"5\"\n"
7877 "-E have the kernel attempt to perform SCSI error recovery\n"
7878 "-C count specify the SCSI command retry count (needs -E to work)\n"
7879 "modepage arguments:\n"
7880 "-l list all available mode pages\n"
7881 "-m page specify the mode page to view or edit\n"
7882 "-e edit the specified mode page\n"
7883 "-b force view to binary mode\n"
7884 "-d disable block descriptors for mode sense\n"
7885 "-P pgctl page control field 0-3\n"
7886 "defects arguments:\n"
7887 "-f format specify defect list format (block, bfi or phys)\n"
7888 "-G get the grown defect list\n"
7889 "-P get the permanent defect list\n"
7890 "inquiry arguments:\n"
7891 "-D get the standard inquiry data\n"
7892 "-S get the serial number\n"
7893 "-R get the transfer rate, etc.\n"
7894 "reportluns arguments:\n"
7895 "-c only report a count of available LUNs\n"
7896 "-l only print out luns, and not a count\n"
7897 "-r <reporttype> specify \"default\", \"wellknown\" or \"all\"\n"
7898 "readcap arguments\n"
7899 "-b only report the blocksize\n"
7900 "-h human readable device size, base 2\n"
7901 "-H human readable device size, base 10\n"
7902 "-N print the number of blocks instead of last block\n"
7903 "-q quiet, print numbers only\n"
7904 "-s only report the last block/device size\n"
7906 "-c cdb [args] specify the SCSI CDB\n"
7907 "-i len fmt specify input data and input data format\n"
7908 "-o len fmt [args] specify output data and output data fmt\n"
7909 "smpcmd arguments:\n"
7910 "-r len fmt [args] specify the SMP command to be sent\n"
7911 "-R len fmt [args] specify SMP response format\n"
7912 "smprg arguments:\n"
7913 "-l specify the long response format\n"
7914 "smppc arguments:\n"
7915 "-p phy specify the PHY to operate on\n"
7916 "-l specify the long request/response format\n"
7917 "-o operation specify the phy control operation\n"
7918 "-d name set the attached device name\n"
7919 "-m rate set the minimum physical link rate\n"
7920 "-M rate set the maximum physical link rate\n"
7921 "-T pp_timeout set the partial pathway timeout value\n"
7922 "-a enable|disable enable or disable SATA slumber\n"
7923 "-A enable|disable enable or disable SATA partial phy power\n"
7924 "-s enable|disable enable or disable SAS slumber\n"
7925 "-S enable|disable enable or disable SAS partial phy power\n"
7926 "smpphylist arguments:\n"
7927 "-l specify the long response format\n"
7928 "-q only print phys with attached devices\n"
7929 "smpmaninfo arguments:\n"
7930 "-l specify the long response format\n"
7931 "debug arguments:\n"
7932 "-I CAM_DEBUG_INFO -- scsi commands, errors, data\n"
7933 "-T CAM_DEBUG_TRACE -- routine flow tracking\n"
7934 "-S CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
7935 "-c CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
7937 "-N tags specify the number of tags to use for this device\n"
7938 "-q be quiet, don't report the number of tags\n"
7939 "-v report a number of tag-related parameters\n"
7940 "negotiate arguments:\n"
7941 "-a send a test unit ready after negotiation\n"
7942 "-c report/set current negotiation settings\n"
7943 "-D <arg> \"enable\" or \"disable\" disconnection\n"
7944 "-M mode set ATA mode\n"
7945 "-O offset set command delay offset\n"
7946 "-q be quiet, don't report anything\n"
7947 "-R syncrate synchronization rate in MHz\n"
7948 "-T <arg> \"enable\" or \"disable\" tagged queueing\n"
7949 "-U report/set user negotiation settings\n"
7950 "-W bus_width set the bus width in bits (8, 16 or 32)\n"
7951 "-v also print a Path Inquiry CCB for the controller\n"
7952 "format arguments:\n"
7953 "-q be quiet, don't print status messages\n"
7954 "-r run in report only mode\n"
7955 "-w don't send immediate format command\n"
7956 "-y don't ask any questions\n"
7957 "sanitize arguments:\n"
7958 "-a operation operation mode: overwrite, block, crypto or exitfailure\n"
7959 "-c passes overwrite passes to perform (1 to 31)\n"
7960 "-I invert overwrite pattern after each pass\n"
7961 "-P pattern path to overwrite pattern file\n"
7962 "-q be quiet, don't print status messages\n"
7963 "-r run in report only mode\n"
7964 "-U run operation in unrestricted completion exit mode\n"
7965 "-w don't send immediate sanitize command\n"
7966 "-y don't ask any questions\n"
7967 "idle/standby arguments:\n"
7968 "-t <arg> number of seconds before respective state.\n"
7969 "fwdownload arguments:\n"
7970 "-f fw_image path to firmware image file\n"
7971 "-y don't ask any questions\n"
7972 "-s run in simulation mode\n"
7973 "-v print info for every firmware segment sent to device\n"
7974 "security arguments:\n"
7975 "-d pwd disable security using the given password for the selected\n"
7977 "-e pwd erase the device using the given pwd for the selected user\n"
7978 "-f freeze the security configuration of the specified device\n"
7979 "-h pwd enhanced erase the device using the given pwd for the\n"
7981 "-k pwd unlock the device using the given pwd for the selected\n"
7983 "-l <high|maximum> specifies which security level to set: high or maximum\n"
7984 "-q be quiet, do not print any status messages\n"
7985 "-s pwd password the device (enable security) using the given\n"
7986 " pwd for the selected user\n"
7987 "-T timeout overrides the timeout (seconds) used for erase operation\n"
7988 "-U <user|master> specifies which user to set: user or master\n"
7989 "-y don't ask any questions\n"
7991 "-f freeze the HPA configuration of the device\n"
7992 "-l lock the HPA configuration of the device\n"
7993 "-P make the HPA max sectors persist\n"
7994 "-p pwd Set the HPA configuration password required for unlock\n"
7996 "-q be quiet, do not print any status messages\n"
7997 "-s sectors configures the maximum user accessible sectors of the\n"
7999 "-U pwd unlock the HPA configuration of the device\n"
8000 "-y don't ask any questions\n"
8001 "persist arguments:\n"
8002 "-i action specify read_keys, read_reservation, report_cap, or\n"
8003 " read_full_status\n"
8004 "-o action specify register, register_ignore, reserve, release,\n"
8005 " clear, preempt, preempt_abort, register_move, replace_lost\n"
8006 "-a set the All Target Ports (ALL_TG_PT) bit\n"
8007 "-I tid specify a Transport ID, e.g.: sas,0x1234567812345678\n"
8008 "-k key specify the Reservation Key\n"
8009 "-K sa_key specify the Service Action Reservation Key\n"
8010 "-p set the Activate Persist Through Power Loss bit\n"
8011 "-R rtp specify the Relative Target Port\n"
8012 "-s scope specify the scope: lun, extent, element or a number\n"
8013 "-S specify Transport ID for register, requires -I\n"
8014 "-T res_type specify the reservation type: read_shared, wr_ex, rd_ex,\n"
8015 " ex_ac, wr_ex_ro, ex_ac_ro, wr_ex_ar, ex_ac_ar\n"
8016 "-U unregister the current initiator for register_move\n"
8018 #endif /* MINIMALISTIC */
8022 main(int argc, char **argv)
8025 char *device = NULL;
8027 struct cam_device *cam_dev = NULL;
8028 int timeout = 0, retry_count = 1;
8029 camcontrol_optret optreturn;
8031 const char *mainopt = "C:En:t:u:v";
8032 const char *subopt = NULL;
8033 char combinedopt[256];
8034 int error = 0, optstart = 2;
8036 #ifndef MINIMALISTIC
8040 #endif /* MINIMALISTIC */
8042 cmdlist = CAM_CMD_NONE;
8043 arglist = CAM_ARG_NONE;
8051 * Get the base option.
8053 optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
8055 if (optreturn == CC_OR_AMBIGUOUS) {
8056 warnx("ambiguous option %s", argv[1]);
8059 } else if (optreturn == CC_OR_NOT_FOUND) {
8060 warnx("option %s not found", argv[1]);
8066 * Ahh, getopt(3) is a pain.
8068 * This is a gross hack. There really aren't many other good
8069 * options (excuse the pun) for parsing options in a situation like
8070 * this. getopt is kinda braindead, so you end up having to run
8071 * through the options twice, and give each invocation of getopt
8072 * the option string for the other invocation.
8074 * You would think that you could just have two groups of options.
8075 * The first group would get parsed by the first invocation of
8076 * getopt, and the second group would get parsed by the second
8077 * invocation of getopt. It doesn't quite work out that way. When
8078 * the first invocation of getopt finishes, it leaves optind pointing
8079 * to the argument _after_ the first argument in the second group.
8080 * So when the second invocation of getopt comes around, it doesn't
8081 * recognize the first argument it gets and then bails out.
8083 * A nice alternative would be to have a flag for getopt that says
8084 * "just keep parsing arguments even when you encounter an unknown
8085 * argument", but there isn't one. So there's no real clean way to
8086 * easily parse two sets of arguments without having one invocation
8087 * of getopt know about the other.
8089 * Without this hack, the first invocation of getopt would work as
8090 * long as the generic arguments are first, but the second invocation
8091 * (in the subfunction) would fail in one of two ways. In the case
8092 * where you don't set optreset, it would fail because optind may be
8093 * pointing to the argument after the one it should be pointing at.
8094 * In the case where you do set optreset, and reset optind, it would
8095 * fail because getopt would run into the first set of options, which
8096 * it doesn't understand.
8098 * All of this would "sort of" work if you could somehow figure out
8099 * whether optind had been incremented one option too far. The
8100 * mechanics of that, however, are more daunting than just giving
8101 * both invocations all of the expect options for either invocation.
8103 * Needless to say, I wouldn't mind if someone invented a better
8104 * (non-GPL!) command line parsing interface than getopt. I
8105 * wouldn't mind if someone added more knobs to getopt to make it
8106 * work better. Who knows, I may talk myself into doing it someday,
8107 * if the standards weenies let me. As it is, it just leads to
8108 * hackery like this and causes people to avoid it in some cases.
8110 * KDM, September 8th, 1998
8113 sprintf(combinedopt, "%s%s", mainopt, subopt);
8115 sprintf(combinedopt, "%s", mainopt);
8118 * For these options we do not parse optional device arguments and
8119 * we do not open a passthrough device.
8121 if ((cmdlist == CAM_CMD_RESCAN)
8122 || (cmdlist == CAM_CMD_RESET)
8123 || (cmdlist == CAM_CMD_DEVTREE)
8124 || (cmdlist == CAM_CMD_USAGE)
8125 || (cmdlist == CAM_CMD_DEBUG))
8128 #ifndef MINIMALISTIC
8130 && (argc > 2 && argv[2][0] != '-')) {
8134 if (isdigit(argv[2][0])) {
8135 /* device specified as bus:target[:lun] */
8136 rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
8138 errx(1, "numeric device specification must "
8139 "be either bus:target, or "
8141 /* default to 0 if lun was not specified */
8142 if ((arglist & CAM_ARG_LUN) == 0) {
8144 arglist |= CAM_ARG_LUN;
8148 if (cam_get_device(argv[2], name, sizeof name, &unit)
8150 errx(1, "%s", cam_errbuf);
8151 device = strdup(name);
8152 arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
8156 #endif /* MINIMALISTIC */
8158 * Start getopt processing at argv[2/3], since we've already
8159 * accepted argv[1..2] as the command name, and as a possible
8165 * Now we run through the argument list looking for generic
8166 * options, and ignoring options that possibly belong to
8169 while ((c = getopt(argc, argv, combinedopt))!= -1){
8172 retry_count = strtol(optarg, NULL, 0);
8173 if (retry_count < 0)
8174 errx(1, "retry count %d is < 0",
8176 arglist |= CAM_ARG_RETRIES;
8179 arglist |= CAM_ARG_ERR_RECOVER;
8182 arglist |= CAM_ARG_DEVICE;
8184 while (isspace(*tstr) && (*tstr != '\0'))
8186 device = (char *)strdup(tstr);
8189 timeout = strtol(optarg, NULL, 0);
8191 errx(1, "invalid timeout %d", timeout);
8192 /* Convert the timeout from seconds to ms */
8194 arglist |= CAM_ARG_TIMEOUT;
8197 arglist |= CAM_ARG_UNIT;
8198 unit = strtol(optarg, NULL, 0);
8201 arglist |= CAM_ARG_VERBOSE;
8208 #ifndef MINIMALISTIC
8210 * For most commands we'll want to open the passthrough device
8211 * associated with the specified device. In the case of the rescan
8212 * commands, we don't use a passthrough device at all, just the
8213 * transport layer device.
8216 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
8217 && (((arglist & CAM_ARG_DEVICE) == 0)
8218 || ((arglist & CAM_ARG_UNIT) == 0))) {
8219 errx(1, "subcommand \"%s\" requires a valid device "
8220 "identifier", argv[1]);
8223 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
8224 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
8225 cam_open_spec_device(device,unit,O_RDWR,NULL)))
8227 errx(1,"%s", cam_errbuf);
8229 #endif /* MINIMALISTIC */
8232 * Reset optind to 2, and reset getopt, so these routines can parse
8233 * the arguments again.
8239 #ifndef MINIMALISTIC
8240 case CAM_CMD_DEVLIST:
8241 error = getdevlist(cam_dev);
8244 error = atahpa(cam_dev, retry_count, timeout,
8245 argc, argv, combinedopt);
8247 #endif /* MINIMALISTIC */
8248 case CAM_CMD_DEVTREE:
8249 error = getdevtree(argc, argv, combinedopt);
8251 #ifndef MINIMALISTIC
8253 error = testunitready(cam_dev, retry_count, timeout, 0);
8255 case CAM_CMD_INQUIRY:
8256 error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
8257 retry_count, timeout);
8259 case CAM_CMD_IDENTIFY:
8260 error = ataidentify(cam_dev, retry_count, timeout);
8262 case CAM_CMD_STARTSTOP:
8263 error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
8264 arglist & CAM_ARG_EJECT, retry_count,
8267 #endif /* MINIMALISTIC */
8268 case CAM_CMD_RESCAN:
8269 error = dorescan_or_reset(argc, argv, 1);
8272 error = dorescan_or_reset(argc, argv, 0);
8274 #ifndef MINIMALISTIC
8275 case CAM_CMD_READ_DEFECTS:
8276 error = readdefects(cam_dev, argc, argv, combinedopt,
8277 retry_count, timeout);
8279 case CAM_CMD_MODE_PAGE:
8280 modepage(cam_dev, argc, argv, combinedopt,
8281 retry_count, timeout);
8283 case CAM_CMD_SCSI_CMD:
8284 error = scsicmd(cam_dev, argc, argv, combinedopt,
8285 retry_count, timeout);
8287 case CAM_CMD_SMP_CMD:
8288 error = smpcmd(cam_dev, argc, argv, combinedopt,
8289 retry_count, timeout);
8291 case CAM_CMD_SMP_RG:
8292 error = smpreportgeneral(cam_dev, argc, argv,
8293 combinedopt, retry_count,
8296 case CAM_CMD_SMP_PC:
8297 error = smpphycontrol(cam_dev, argc, argv, combinedopt,
8298 retry_count, timeout);
8300 case CAM_CMD_SMP_PHYLIST:
8301 error = smpphylist(cam_dev, argc, argv, combinedopt,
8302 retry_count, timeout);
8304 case CAM_CMD_SMP_MANINFO:
8305 error = smpmaninfo(cam_dev, argc, argv, combinedopt,
8306 retry_count, timeout);
8309 error = camdebug(argc, argv, combinedopt);
8312 error = tagcontrol(cam_dev, argc, argv, combinedopt);
8315 error = ratecontrol(cam_dev, retry_count, timeout,
8316 argc, argv, combinedopt);
8318 case CAM_CMD_FORMAT:
8319 error = scsiformat(cam_dev, argc, argv,
8320 combinedopt, retry_count, timeout);
8322 case CAM_CMD_REPORTLUNS:
8323 error = scsireportluns(cam_dev, argc, argv,
8324 combinedopt, retry_count,
8327 case CAM_CMD_READCAP:
8328 error = scsireadcapacity(cam_dev, argc, argv,
8329 combinedopt, retry_count,
8333 case CAM_CMD_STANDBY:
8335 error = atapm(cam_dev, argc, argv,
8336 combinedopt, retry_count, timeout);
8338 case CAM_CMD_SECURITY:
8339 error = atasecurity(cam_dev, retry_count, timeout,
8340 argc, argv, combinedopt);
8342 case CAM_CMD_DOWNLOAD_FW:
8343 error = fwdownload(cam_dev, argc, argv, combinedopt,
8344 arglist & CAM_ARG_VERBOSE, retry_count, timeout,
8345 get_disk_type(cam_dev));
8347 case CAM_CMD_SANITIZE:
8348 error = scsisanitize(cam_dev, argc, argv,
8349 combinedopt, retry_count, timeout);
8351 case CAM_CMD_PERSIST:
8352 error = scsipersist(cam_dev, argc, argv, combinedopt,
8353 retry_count, timeout, arglist & CAM_ARG_VERBOSE,
8354 arglist & CAM_ARG_ERR_RECOVER);
8356 #endif /* MINIMALISTIC */
8366 if (cam_dev != NULL)
8367 cam_close_device(cam_dev);