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>
35 #include <sys/endian.h>
47 #include <cam/cam_debug.h>
48 #include <cam/cam_ccb.h>
49 #include <cam/scsi/scsi_all.h>
50 #include <cam/scsi/scsi_da.h>
51 #include <cam/scsi/scsi_pass.h>
52 #include <cam/scsi/scsi_message.h>
53 #include <cam/ata/ata_all.h>
55 #include "camcontrol.h"
58 CAM_CMD_NONE = 0x00000000,
59 CAM_CMD_DEVLIST = 0x00000001,
60 CAM_CMD_TUR = 0x00000002,
61 CAM_CMD_INQUIRY = 0x00000003,
62 CAM_CMD_STARTSTOP = 0x00000004,
63 CAM_CMD_RESCAN = 0x00000005,
64 CAM_CMD_READ_DEFECTS = 0x00000006,
65 CAM_CMD_MODE_PAGE = 0x00000007,
66 CAM_CMD_SCSI_CMD = 0x00000008,
67 CAM_CMD_DEVTREE = 0x00000009,
68 CAM_CMD_USAGE = 0x0000000a,
69 CAM_CMD_DEBUG = 0x0000000b,
70 CAM_CMD_RESET = 0x0000000c,
71 CAM_CMD_FORMAT = 0x0000000d,
72 CAM_CMD_TAG = 0x0000000e,
73 CAM_CMD_RATE = 0x0000000f,
74 CAM_CMD_DETACH = 0x00000010,
75 CAM_CMD_REPORTLUNS = 0x00000011,
76 CAM_CMD_READCAP = 0x00000012,
77 CAM_CMD_IDENTIFY = 0x00000013,
78 CAM_CMD_IDLE = 0x00000014,
79 CAM_CMD_STANDBY = 0x00000015,
80 CAM_CMD_SLEEP = 0x00000016
84 CAM_ARG_NONE = 0x00000000,
85 CAM_ARG_VERBOSE = 0x00000001,
86 CAM_ARG_DEVICE = 0x00000002,
87 CAM_ARG_BUS = 0x00000004,
88 CAM_ARG_TARGET = 0x00000008,
89 CAM_ARG_LUN = 0x00000010,
90 CAM_ARG_EJECT = 0x00000020,
91 CAM_ARG_UNIT = 0x00000040,
92 CAM_ARG_FORMAT_BLOCK = 0x00000080,
93 CAM_ARG_FORMAT_BFI = 0x00000100,
94 CAM_ARG_FORMAT_PHYS = 0x00000200,
95 CAM_ARG_PLIST = 0x00000400,
96 CAM_ARG_GLIST = 0x00000800,
97 CAM_ARG_GET_SERIAL = 0x00001000,
98 CAM_ARG_GET_STDINQ = 0x00002000,
99 CAM_ARG_GET_XFERRATE = 0x00004000,
100 CAM_ARG_INQ_MASK = 0x00007000,
101 CAM_ARG_MODE_EDIT = 0x00008000,
102 CAM_ARG_PAGE_CNTL = 0x00010000,
103 CAM_ARG_TIMEOUT = 0x00020000,
104 CAM_ARG_CMD_IN = 0x00040000,
105 CAM_ARG_CMD_OUT = 0x00080000,
106 CAM_ARG_DBD = 0x00100000,
107 CAM_ARG_ERR_RECOVER = 0x00200000,
108 CAM_ARG_RETRIES = 0x00400000,
109 CAM_ARG_START_UNIT = 0x00800000,
110 CAM_ARG_DEBUG_INFO = 0x01000000,
111 CAM_ARG_DEBUG_TRACE = 0x02000000,
112 CAM_ARG_DEBUG_SUBTRACE = 0x04000000,
113 CAM_ARG_DEBUG_CDB = 0x08000000,
114 CAM_ARG_DEBUG_XPT = 0x10000000,
115 CAM_ARG_DEBUG_PERIPH = 0x20000000,
116 CAM_ARG_DEBUG_PROBE = 0x40000000,
119 struct camcontrol_opts {
127 static const char scsicmd_opts[] = "a:c:dfi:o:r";
128 static const char readdefect_opts[] = "f:GP";
129 static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
132 struct camcontrol_opts option_table[] = {
134 {"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
135 {"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
136 {"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
137 {"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
138 {"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
139 {"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
140 {"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
141 {"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
142 {"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"},
143 #endif /* MINIMALISTIC */
144 {"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
145 {"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
147 {"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
148 {"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
149 {"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
150 {"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
151 #endif /* MINIMALISTIC */
152 {"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, NULL},
154 {"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
155 {"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
156 {"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
157 {"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
158 {"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
159 {"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXcp"},
160 {"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
161 {"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"},
162 {"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"},
163 {"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""},
164 #endif /* MINIMALISTIC */
165 {"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
166 {"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
167 {"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
181 camcontrol_optret getoption(char *arg, cam_cmdmask *cmdnum, cam_argmask *argnum,
182 const char **subopt);
184 static int getdevlist(struct cam_device *device);
185 #endif /* MINIMALISTIC */
186 static int getdevtree(void);
188 static int testunitready(struct cam_device *device, int retry_count,
189 int timeout, int quiet);
190 static int scsistart(struct cam_device *device, int startstop, int loadeject,
191 int retry_count, int timeout);
192 static int scsidoinquiry(struct cam_device *device, int argc, char **argv,
193 char *combinedopt, int retry_count, int timeout);
194 static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
195 static int scsiserial(struct cam_device *device, int retry_count, int timeout);
196 static int camxferrate(struct cam_device *device);
197 #endif /* MINIMALISTIC */
198 static int parse_btl(char *tstr, int *bus, int *target, int *lun,
199 cam_argmask *arglst);
200 static int dorescan_or_reset(int argc, char **argv, int rescan);
201 static int rescan_or_reset_bus(int bus, int rescan);
202 static int scanlun_or_reset_dev(int bus, int target, int lun, int scan);
204 static int readdefects(struct cam_device *device, int argc, char **argv,
205 char *combinedopt, int retry_count, int timeout);
206 static void modepage(struct cam_device *device, int argc, char **argv,
207 char *combinedopt, int retry_count, int timeout);
208 static int scsicmd(struct cam_device *device, int argc, char **argv,
209 char *combinedopt, int retry_count, int timeout);
210 static int tagcontrol(struct cam_device *device, int argc, char **argv,
212 static void cts_print(struct cam_device *device,
213 struct ccb_trans_settings *cts);
214 static void cpi_print(struct ccb_pathinq *cpi);
215 static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
216 static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd);
217 static int get_print_cts(struct cam_device *device, int user_settings,
218 int quiet, struct ccb_trans_settings *cts);
219 static int ratecontrol(struct cam_device *device, int retry_count,
220 int timeout, int argc, char **argv, char *combinedopt);
221 static int scsiformat(struct cam_device *device, int argc, char **argv,
222 char *combinedopt, int retry_count, int timeout);
223 static int scsireportluns(struct cam_device *device, int argc, char **argv,
224 char *combinedopt, int retry_count, int timeout);
225 static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
226 char *combinedopt, int retry_count, int timeout);
227 static int atapm(struct cam_device *device, int argc, char **argv,
228 char *combinedopt, int retry_count, int timeout);
229 #endif /* MINIMALISTIC */
231 #define min(a,b) (((a)<(b))?(a):(b))
234 #define max(a,b) (((a)>(b))?(a):(b))
238 getoption(char *arg, cam_cmdmask *cmdnum, cam_argmask *argnum,
241 struct camcontrol_opts *opts;
244 for (opts = option_table; (opts != NULL) && (opts->optname != NULL);
246 if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
247 *cmdnum = opts->cmdnum;
248 *argnum = opts->argnum;
249 *subopt = opts->subopt;
250 if (++num_matches > 1)
251 return(CC_OR_AMBIGUOUS);
258 return(CC_OR_NOT_FOUND);
263 getdevlist(struct cam_device *device)
269 ccb = cam_getccb(device);
271 ccb->ccb_h.func_code = XPT_GDEVLIST;
272 ccb->ccb_h.flags = CAM_DIR_NONE;
273 ccb->ccb_h.retry_count = 1;
275 ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
276 while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
277 if (cam_send_ccb(device, ccb) < 0) {
278 perror("error getting device list");
285 switch (ccb->cgdl.status) {
286 case CAM_GDEVLIST_MORE_DEVS:
287 strcpy(status, "MORE");
289 case CAM_GDEVLIST_LAST_DEVICE:
290 strcpy(status, "LAST");
292 case CAM_GDEVLIST_LIST_CHANGED:
293 strcpy(status, "CHANGED");
295 case CAM_GDEVLIST_ERROR:
296 strcpy(status, "ERROR");
301 fprintf(stdout, "%s%d: generation: %d index: %d status: %s\n",
302 ccb->cgdl.periph_name,
303 ccb->cgdl.unit_number,
304 ccb->cgdl.generation,
309 * If the list has changed, we need to start over from the
312 if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
320 #endif /* MINIMALISTIC */
332 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
333 warn("couldn't open %s", XPT_DEVICE);
337 bzero(&ccb, sizeof(union ccb));
339 ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
340 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
341 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
343 ccb.ccb_h.func_code = XPT_DEV_MATCH;
344 bufsize = sizeof(struct dev_match_result) * 100;
345 ccb.cdm.match_buf_len = bufsize;
346 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
347 if (ccb.cdm.matches == NULL) {
348 warnx("can't malloc memory for matches");
352 ccb.cdm.num_matches = 0;
355 * We fetch all nodes, since we display most of them in the default
356 * case, and all in the verbose case.
358 ccb.cdm.num_patterns = 0;
359 ccb.cdm.pattern_buf_len = 0;
362 * We do the ioctl multiple times if necessary, in case there are
363 * more than 100 nodes in the EDT.
366 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
367 warn("error sending CAMIOCOMMAND ioctl");
372 if ((ccb.ccb_h.status != CAM_REQ_CMP)
373 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
374 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
375 warnx("got CAM error %#x, CDM error %d\n",
376 ccb.ccb_h.status, ccb.cdm.status);
381 for (i = 0; i < ccb.cdm.num_matches; i++) {
382 switch (ccb.cdm.matches[i].type) {
383 case DEV_MATCH_BUS: {
384 struct bus_match_result *bus_result;
387 * Only print the bus information if the
388 * user turns on the verbose flag.
390 if ((arglist & CAM_ARG_VERBOSE) == 0)
394 &ccb.cdm.matches[i].result.bus_result;
397 fprintf(stdout, ")\n");
401 fprintf(stdout, "scbus%d on %s%d bus %d:\n",
403 bus_result->dev_name,
404 bus_result->unit_number,
408 case DEV_MATCH_DEVICE: {
409 struct device_match_result *dev_result;
410 char vendor[16], product[48], revision[16];
414 &ccb.cdm.matches[i].result.device_result;
416 if ((dev_result->flags
417 & DEV_RESULT_UNCONFIGURED)
418 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
424 if (dev_result->protocol == PROTO_SCSI) {
425 cam_strvis(vendor, dev_result->inq_data.vendor,
426 sizeof(dev_result->inq_data.vendor),
429 dev_result->inq_data.product,
430 sizeof(dev_result->inq_data.product),
433 dev_result->inq_data.revision,
434 sizeof(dev_result->inq_data.revision),
436 sprintf(tmpstr, "<%s %s %s>", vendor, product,
438 } else if (dev_result->protocol == PROTO_ATA ||
439 dev_result->protocol == PROTO_SATAPM) {
441 dev_result->ident_data.model,
442 sizeof(dev_result->ident_data.model),
445 dev_result->ident_data.revision,
446 sizeof(dev_result->ident_data.revision),
448 sprintf(tmpstr, "<%s %s>", product,
451 sprintf(tmpstr, "<>");
454 fprintf(stdout, ")\n");
458 fprintf(stdout, "%-33s at scbus%d "
459 "target %d lun %d (",
462 dev_result->target_id,
463 dev_result->target_lun);
469 case DEV_MATCH_PERIPH: {
470 struct periph_match_result *periph_result;
473 &ccb.cdm.matches[i].result.periph_result;
475 if (skip_device != 0)
479 fprintf(stdout, ",");
481 fprintf(stdout, "%s%d",
482 periph_result->periph_name,
483 periph_result->unit_number);
489 fprintf(stdout, "unknown match type\n");
494 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
495 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
498 fprintf(stdout, ")\n");
507 testunitready(struct cam_device *device, int retry_count, int timeout,
513 ccb = cam_getccb(device);
515 scsi_test_unit_ready(&ccb->csio,
516 /* retries */ retry_count,
518 /* tag_action */ MSG_SIMPLE_Q_TAG,
519 /* sense_len */ SSD_FULL_SIZE,
520 /* timeout */ timeout ? timeout : 5000);
522 /* Disable freezing the device queue */
523 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
525 if (arglist & CAM_ARG_ERR_RECOVER)
526 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
528 if (cam_send_ccb(device, ccb) < 0) {
530 perror("error sending test unit ready");
532 if (arglist & CAM_ARG_VERBOSE) {
533 cam_error_print(device, ccb, CAM_ESF_ALL,
534 CAM_EPF_ALL, stderr);
541 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
543 fprintf(stdout, "Unit is ready\n");
546 fprintf(stdout, "Unit is not ready\n");
549 if (arglist & CAM_ARG_VERBOSE) {
550 cam_error_print(device, ccb, CAM_ESF_ALL,
551 CAM_EPF_ALL, stderr);
561 scsistart(struct cam_device *device, int startstop, int loadeject,
562 int retry_count, int timeout)
567 ccb = cam_getccb(device);
570 * If we're stopping, send an ordered tag so the drive in question
571 * will finish any previously queued writes before stopping. If
572 * the device isn't capable of tagged queueing, or if tagged
573 * queueing is turned off, the tag action is a no-op.
575 scsi_start_stop(&ccb->csio,
576 /* retries */ retry_count,
578 /* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
580 /* start/stop */ startstop,
581 /* load_eject */ loadeject,
583 /* sense_len */ SSD_FULL_SIZE,
584 /* timeout */ timeout ? timeout : 120000);
586 /* Disable freezing the device queue */
587 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
589 if (arglist & CAM_ARG_ERR_RECOVER)
590 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
592 if (cam_send_ccb(device, ccb) < 0) {
593 perror("error sending start unit");
595 if (arglist & CAM_ARG_VERBOSE) {
596 cam_error_print(device, ccb, CAM_ESF_ALL,
597 CAM_EPF_ALL, stderr);
604 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
606 fprintf(stdout, "Unit started successfully");
608 fprintf(stdout,", Media loaded\n");
610 fprintf(stdout,"\n");
612 fprintf(stdout, "Unit stopped successfully");
614 fprintf(stdout, ", Media ejected\n");
616 fprintf(stdout, "\n");
622 "Error received from start unit command\n");
625 "Error received from stop unit command\n");
627 if (arglist & CAM_ARG_VERBOSE) {
628 cam_error_print(device, ccb, CAM_ESF_ALL,
629 CAM_EPF_ALL, stderr);
639 scsidoinquiry(struct cam_device *device, int argc, char **argv,
640 char *combinedopt, int retry_count, int timeout)
645 while ((c = getopt(argc, argv, combinedopt)) != -1) {
648 arglist |= CAM_ARG_GET_STDINQ;
651 arglist |= CAM_ARG_GET_XFERRATE;
654 arglist |= CAM_ARG_GET_SERIAL;
662 * If the user didn't specify any inquiry options, he wants all of
665 if ((arglist & CAM_ARG_INQ_MASK) == 0)
666 arglist |= CAM_ARG_INQ_MASK;
668 if (arglist & CAM_ARG_GET_STDINQ)
669 error = scsiinquiry(device, retry_count, timeout);
674 if (arglist & CAM_ARG_GET_SERIAL)
675 scsiserial(device, retry_count, timeout);
680 if (arglist & CAM_ARG_GET_XFERRATE)
681 error = camxferrate(device);
687 scsiinquiry(struct cam_device *device, int retry_count, int timeout)
690 struct scsi_inquiry_data *inq_buf;
693 ccb = cam_getccb(device);
696 warnx("couldn't allocate CCB");
700 /* cam_getccb cleans up the header, caller has to zero the payload */
701 bzero(&(&ccb->ccb_h)[1],
702 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
704 inq_buf = (struct scsi_inquiry_data *)malloc(
705 sizeof(struct scsi_inquiry_data));
707 if (inq_buf == NULL) {
709 warnx("can't malloc memory for inquiry\n");
712 bzero(inq_buf, sizeof(*inq_buf));
715 * Note that although the size of the inquiry buffer is the full
716 * 256 bytes specified in the SCSI spec, we only tell the device
717 * that we have allocated SHORT_INQUIRY_LENGTH bytes. There are
718 * two reasons for this:
720 * - The SCSI spec says that when a length field is only 1 byte,
721 * a value of 0 will be interpreted as 256. Therefore
722 * scsi_inquiry() will convert an inq_len (which is passed in as
723 * a u_int32_t, but the field in the CDB is only 1 byte) of 256
724 * to 0. Evidently, very few devices meet the spec in that
725 * regard. Some devices, like many Seagate disks, take the 0 as
726 * 0, and don't return any data. One Pioneer DVD-R drive
727 * returns more data than the command asked for.
729 * So, since there are numerous devices that just don't work
730 * right with the full inquiry size, we don't send the full size.
732 * - The second reason not to use the full inquiry data length is
733 * that we don't need it here. The only reason we issue a
734 * standard inquiry is to get the vendor name, device name,
735 * and revision so scsi_print_inquiry() can print them.
737 * If, at some point in the future, more inquiry data is needed for
738 * some reason, this code should use a procedure similar to the
739 * probe code. i.e., issue a short inquiry, and determine from
740 * the additional length passed back from the device how much
741 * inquiry data the device supports. Once the amount the device
742 * supports is determined, issue an inquiry for that amount and no
747 scsi_inquiry(&ccb->csio,
748 /* retries */ retry_count,
750 /* tag_action */ MSG_SIMPLE_Q_TAG,
751 /* inq_buf */ (u_int8_t *)inq_buf,
752 /* inq_len */ SHORT_INQUIRY_LENGTH,
755 /* sense_len */ SSD_FULL_SIZE,
756 /* timeout */ timeout ? timeout : 5000);
758 /* Disable freezing the device queue */
759 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
761 if (arglist & CAM_ARG_ERR_RECOVER)
762 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
764 if (cam_send_ccb(device, ccb) < 0) {
765 perror("error sending SCSI inquiry");
767 if (arglist & CAM_ARG_VERBOSE) {
768 cam_error_print(device, ccb, CAM_ESF_ALL,
769 CAM_EPF_ALL, stderr);
776 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
779 if (arglist & CAM_ARG_VERBOSE) {
780 cam_error_print(device, ccb, CAM_ESF_ALL,
781 CAM_EPF_ALL, stderr);
792 fprintf(stdout, "%s%d: ", device->device_name,
793 device->dev_unit_num);
794 scsi_print_inquiry(inq_buf);
802 scsiserial(struct cam_device *device, int retry_count, int timeout)
805 struct scsi_vpd_unit_serial_number *serial_buf;
806 char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
809 ccb = cam_getccb(device);
812 warnx("couldn't allocate CCB");
816 /* cam_getccb cleans up the header, caller has to zero the payload */
817 bzero(&(&ccb->ccb_h)[1],
818 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
820 serial_buf = (struct scsi_vpd_unit_serial_number *)
821 malloc(sizeof(*serial_buf));
823 if (serial_buf == NULL) {
825 warnx("can't malloc memory for serial number");
829 scsi_inquiry(&ccb->csio,
830 /*retries*/ retry_count,
832 /* tag_action */ MSG_SIMPLE_Q_TAG,
833 /* inq_buf */ (u_int8_t *)serial_buf,
834 /* inq_len */ sizeof(*serial_buf),
836 /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
837 /* sense_len */ SSD_FULL_SIZE,
838 /* timeout */ timeout ? timeout : 5000);
840 /* Disable freezing the device queue */
841 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
843 if (arglist & CAM_ARG_ERR_RECOVER)
844 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
846 if (cam_send_ccb(device, ccb) < 0) {
847 warn("error getting serial number");
849 if (arglist & CAM_ARG_VERBOSE) {
850 cam_error_print(device, ccb, CAM_ESF_ALL,
851 CAM_EPF_ALL, stderr);
859 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
862 if (arglist & CAM_ARG_VERBOSE) {
863 cam_error_print(device, ccb, CAM_ESF_ALL,
864 CAM_EPF_ALL, stderr);
875 bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
876 serial_num[serial_buf->length] = '\0';
878 if ((arglist & CAM_ARG_GET_STDINQ)
879 || (arglist & CAM_ARG_GET_XFERRATE))
880 fprintf(stdout, "%s%d: Serial Number ",
881 device->device_name, device->dev_unit_num);
883 fprintf(stdout, "%.60s\n", serial_num);
891 camxferrate(struct cam_device *device)
893 struct ccb_pathinq cpi;
900 if ((retval = get_cpi(device, &cpi)) != 0)
903 ccb = cam_getccb(device);
906 warnx("couldn't allocate CCB");
910 bzero(&(&ccb->ccb_h)[1],
911 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
913 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
914 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
916 if (((retval = cam_send_ccb(device, ccb)) < 0)
917 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
918 const char error_string[] = "error getting transfer settings";
925 if (arglist & CAM_ARG_VERBOSE)
926 cam_error_print(device, ccb, CAM_ESF_ALL,
927 CAM_EPF_ALL, stderr);
931 goto xferrate_bailout;
935 speed = cpi.base_transfer_speed;
937 if (ccb->cts.transport == XPORT_SPI) {
938 struct ccb_trans_settings_spi *spi =
939 &ccb->cts.xport_specific.spi;
941 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
942 freq = scsi_calc_syncsrate(spi->sync_period);
945 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
946 speed *= (0x01 << spi->bus_width);
948 } else if (ccb->cts.transport == XPORT_FC) {
949 struct ccb_trans_settings_fc *fc =
950 &ccb->cts.xport_specific.fc;
952 if (fc->valid & CTS_FC_VALID_SPEED)
954 } else if (ccb->cts.transport == XPORT_SAS) {
955 struct ccb_trans_settings_sas *sas =
956 &ccb->cts.xport_specific.sas;
958 if (sas->valid & CTS_SAS_VALID_SPEED)
959 speed = sas->bitrate;
960 } else if (ccb->cts.transport == XPORT_ATA) {
961 struct ccb_trans_settings_pata *pata =
962 &ccb->cts.xport_specific.ata;
964 if (pata->valid & CTS_ATA_VALID_MODE)
965 speed = ata_mode2speed(pata->mode);
966 } else if (ccb->cts.transport == XPORT_SATA) {
967 struct ccb_trans_settings_sata *sata =
968 &ccb->cts.xport_specific.sata;
970 if (sata->valid & CTS_SATA_VALID_REVISION)
971 speed = ata_revision2speed(sata->revision);
976 fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
977 device->device_name, device->dev_unit_num,
980 fprintf(stdout, "%s%d: %dKB/s transfers",
981 device->device_name, device->dev_unit_num,
985 if (ccb->cts.transport == XPORT_SPI) {
986 struct ccb_trans_settings_spi *spi =
987 &ccb->cts.xport_specific.spi;
989 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
990 && (spi->sync_offset != 0))
991 fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
992 freq % 1000, spi->sync_offset);
994 if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
995 && (spi->bus_width > 0)) {
996 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
997 && (spi->sync_offset != 0)) {
998 fprintf(stdout, ", ");
1000 fprintf(stdout, " (");
1002 fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
1003 } else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1004 && (spi->sync_offset != 0)) {
1005 fprintf(stdout, ")");
1007 } else if (ccb->cts.transport == XPORT_ATA) {
1008 struct ccb_trans_settings_pata *pata =
1009 &ccb->cts.xport_specific.ata;
1012 if (pata->valid & CTS_ATA_VALID_MODE)
1013 printf("%s, ", ata_mode2string(pata->mode));
1014 if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0)
1015 printf("ATAPI %dbytes, ", pata->atapi);
1016 if (pata->valid & CTS_ATA_VALID_BYTECOUNT)
1017 printf("PIO %dbytes", pata->bytecount);
1019 } else if (ccb->cts.transport == XPORT_SATA) {
1020 struct ccb_trans_settings_sata *sata =
1021 &ccb->cts.xport_specific.sata;
1024 if (sata->valid & CTS_SATA_VALID_REVISION)
1025 printf("SATA %d.x, ", sata->revision);
1028 if (sata->valid & CTS_SATA_VALID_MODE)
1029 printf("%s, ", ata_mode2string(sata->mode));
1030 if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
1031 printf("ATAPI %dbytes, ", sata->atapi);
1032 if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1033 printf("PIO %dbytes", sata->bytecount);
1037 if (ccb->cts.protocol == PROTO_SCSI) {
1038 struct ccb_trans_settings_scsi *scsi =
1039 &ccb->cts.proto_specific.scsi;
1040 if (scsi->valid & CTS_SCSI_VALID_TQ) {
1041 if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1042 fprintf(stdout, ", Command Queueing Enabled");
1047 fprintf(stdout, "\n");
1057 atacapprint(struct ata_params *parm)
1059 u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1060 ((u_int32_t)parm->lba_size_2 << 16);
1062 u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1063 ((u_int64_t)parm->lba_size48_2 << 16) |
1064 ((u_int64_t)parm->lba_size48_3 << 32) |
1065 ((u_int64_t)parm->lba_size48_4 << 48);
1068 printf("protocol ");
1069 printf("ATA/ATAPI-%d", ata_version(parm->version_major));
1070 if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1071 if (parm->satacapabilities & ATA_SATA_GEN3)
1072 printf(" SATA 3.x\n");
1073 else if (parm->satacapabilities & ATA_SATA_GEN2)
1074 printf(" SATA 2.x\n");
1075 else if (parm->satacapabilities & ATA_SATA_GEN1)
1076 printf(" SATA 1.x\n");
1082 printf("device model %.40s\n", parm->model);
1083 printf("firmware revision %.8s\n", parm->revision);
1084 printf("serial number %.20s\n", parm->serial);
1085 if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
1086 printf("WWN %04x%04x%04x%04x\n",
1087 parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
1089 if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
1090 printf("media serial number %.30s\n",
1091 parm->media_serial);
1094 printf("cylinders %d\n", parm->cylinders);
1095 printf("heads %d\n", parm->heads);
1096 printf("sectors/track %d\n", parm->sectors);
1097 printf("sector size logical %u, physical %lu, offset %lu\n",
1098 ata_logical_sector_size(parm),
1099 (unsigned long)ata_physical_sector_size(parm),
1100 (unsigned long)ata_logical_sector_offset(parm));
1102 if (parm->config == ATA_PROTO_CFA ||
1103 (parm->support.command2 & ATA_SUPPORT_CFA))
1104 printf("CFA supported\n");
1106 printf("LBA%ssupported ",
1107 parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1109 printf("%d sectors\n", lbasize);
1113 printf("LBA48%ssupported ",
1114 parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1116 printf("%ju sectors\n", (uintmax_t)lbasize48);
1120 printf("PIO supported PIO");
1121 switch (ata_max_pmode(parm)) {
1137 if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0)
1138 printf(" w/o IORDY");
1141 printf("DMA%ssupported ",
1142 parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1143 if (parm->capabilities1 & ATA_SUPPORT_DMA) {
1144 if (parm->mwdmamodes & 0xff) {
1146 if (parm->mwdmamodes & 0x04)
1148 else if (parm->mwdmamodes & 0x02)
1150 else if (parm->mwdmamodes & 0x01)
1154 if ((parm->atavalid & ATA_FLAG_88) &&
1155 (parm->udmamodes & 0xff)) {
1157 if (parm->udmamodes & 0x40)
1159 else if (parm->udmamodes & 0x20)
1161 else if (parm->udmamodes & 0x10)
1163 else if (parm->udmamodes & 0x08)
1165 else if (parm->udmamodes & 0x04)
1167 else if (parm->udmamodes & 0x02)
1169 else if (parm->udmamodes & 0x01)
1176 if (parm->media_rotation_rate == 1) {
1177 printf("media RPM non-rotating\n");
1178 } else if (parm->media_rotation_rate >= 0x0401 &&
1179 parm->media_rotation_rate <= 0xFFFE) {
1180 printf("media RPM %d\n",
1181 parm->media_rotation_rate);
1185 "Support Enabled Value Vendor\n");
1186 printf("read ahead %s %s\n",
1187 parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1188 parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1189 printf("write cache %s %s\n",
1190 parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1191 parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1192 printf("flush cache %s %s\n",
1193 parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no",
1194 parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no");
1195 printf("overlap %s\n",
1196 parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no");
1197 printf("Tagged Command Queuing (TCQ) %s %s",
1198 parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1199 parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no");
1200 if (parm->support.command2 & ATA_SUPPORT_QUEUED) {
1201 printf(" %d tags\n",
1202 ATA_QUEUE_LEN(parm->queue) + 1);
1205 printf("Native Command Queuing (NCQ) ");
1206 if (parm->satacapabilities != 0xffff &&
1207 (parm->satacapabilities & ATA_SUPPORT_NCQ)) {
1208 printf("yes %d tags\n",
1209 ATA_QUEUE_LEN(parm->queue) + 1);
1212 printf("SMART %s %s\n",
1213 parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1214 parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1215 printf("microcode download %s %s\n",
1216 parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1217 parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1218 printf("security %s %s\n",
1219 parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1220 parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1221 printf("power management %s %s\n",
1222 parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1223 parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1224 printf("advanced power management %s %s",
1225 parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1226 parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no");
1227 if (parm->support.command2 & ATA_SUPPORT_APM) {
1228 printf(" %d/0x%02X\n",
1229 parm->apm_value, parm->apm_value);
1232 printf("automatic acoustic management %s %s",
1233 parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1234 parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no");
1235 if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) {
1236 printf(" %d/0x%02X %d/0x%02X\n",
1237 ATA_ACOUSTIC_CURRENT(parm->acoustic),
1238 ATA_ACOUSTIC_CURRENT(parm->acoustic),
1239 ATA_ACOUSTIC_VENDOR(parm->acoustic),
1240 ATA_ACOUSTIC_VENDOR(parm->acoustic));
1243 printf("media status notification %s %s\n",
1244 parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1245 parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1246 printf("power-up in Standby %s %s\n",
1247 parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1248 parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1249 printf("write-read-verify %s %s",
1250 parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1251 parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no");
1252 if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) {
1253 printf(" %d/0x%x\n",
1254 parm->wrv_mode, parm->wrv_mode);
1257 printf("unload %s %s\n",
1258 parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1259 parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1260 printf("free-fall %s %s\n",
1261 parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1262 parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1263 printf("data set management (TRIM) %s\n",
1264 parm->support_dsm & ATA_SUPPORT_DSM_TRIM ? "yes" : "no");
1268 ataidentify(struct cam_device *device, int retry_count, int timeout)
1271 struct ata_params *ident_buf;
1272 struct ccb_getdev cgd;
1276 if (get_cgd(device, &cgd) != 0) {
1277 warnx("couldn't get CGD");
1280 ccb = cam_getccb(device);
1283 warnx("couldn't allocate CCB");
1287 /* cam_getccb cleans up the header, caller has to zero the payload */
1288 bzero(&(&ccb->ccb_h)[1],
1289 sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));
1291 ptr = (uint16_t *)malloc(sizeof(struct ata_params));
1295 warnx("can't malloc memory for identify\n");
1298 bzero(ptr, sizeof(struct ata_params));
1300 cam_fill_ataio(&ccb->ataio,
1303 /*flags*/CAM_DIR_IN,
1305 /*data_ptr*/(u_int8_t *)ptr,
1306 /*dxfer_len*/sizeof(struct ata_params),
1307 timeout ? timeout : 30 * 1000);
1308 if (cgd.protocol == PROTO_ATA)
1309 ata_28bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
1311 ata_28bit_cmd(&ccb->ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
1313 /* Disable freezing the device queue */
1314 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1316 if (arglist & CAM_ARG_ERR_RECOVER)
1317 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1319 if (cam_send_ccb(device, ccb) < 0) {
1320 perror("error sending ATA identify");
1322 if (arglist & CAM_ARG_VERBOSE) {
1323 cam_error_print(device, ccb, CAM_ESF_ALL,
1324 CAM_EPF_ALL, stderr);
1332 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1335 if (arglist & CAM_ARG_VERBOSE) {
1336 cam_error_print(device, ccb, CAM_ESF_ALL,
1337 CAM_EPF_ALL, stderr);
1348 for (i = 0; i < sizeof(struct ata_params) / 2; i++)
1349 ptr[i] = le16toh(ptr[i]);
1350 if (arglist & CAM_ARG_VERBOSE) {
1351 fprintf(stdout, "%s%d: Raw identify data:\n",
1352 device->device_name, device->dev_unit_num);
1353 for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
1355 fprintf(stdout, " %3d: ", i);
1356 fprintf(stdout, "%04x ", (uint16_t)ptr[i]);
1358 fprintf(stdout, "\n");
1361 ident_buf = (struct ata_params *)ptr;
1362 if (strncmp(ident_buf->model, "FX", 2) &&
1363 strncmp(ident_buf->model, "NEC", 3) &&
1364 strncmp(ident_buf->model, "Pioneer", 7) &&
1365 strncmp(ident_buf->model, "SHARP", 5)) {
1366 ata_bswap(ident_buf->model, sizeof(ident_buf->model));
1367 ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
1368 ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
1369 ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1371 ata_btrim(ident_buf->model, sizeof(ident_buf->model));
1372 ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
1373 ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
1374 ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
1375 ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
1376 ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
1377 ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1378 ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
1379 sizeof(ident_buf->media_serial));
1381 fprintf(stdout, "%s%d: ", device->device_name,
1382 device->dev_unit_num);
1383 ata_print_ident(ident_buf);
1384 camxferrate(device);
1385 atacapprint(ident_buf);
1391 #endif /* MINIMALISTIC */
1394 * Parse out a bus, or a bus, target and lun in the following
1400 * Returns the number of parsed components, or 0.
1403 parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglst)
1408 while (isspace(*tstr) && (*tstr != '\0'))
1411 tmpstr = (char *)strtok(tstr, ":");
1412 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1413 *bus = strtol(tmpstr, NULL, 0);
1414 *arglst |= CAM_ARG_BUS;
1416 tmpstr = (char *)strtok(NULL, ":");
1417 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1418 *target = strtol(tmpstr, NULL, 0);
1419 *arglst |= CAM_ARG_TARGET;
1421 tmpstr = (char *)strtok(NULL, ":");
1422 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1423 *lun = strtol(tmpstr, NULL, 0);
1424 *arglst |= CAM_ARG_LUN;
1434 dorescan_or_reset(int argc, char **argv, int rescan)
1436 static const char must[] =
1437 "you must specify \"all\", a bus, or a bus:target:lun to %s";
1439 int bus = -1, target = -1, lun = -1;
1443 warnx(must, rescan? "rescan" : "reset");
1447 tstr = argv[optind];
1448 while (isspace(*tstr) && (*tstr != '\0'))
1450 if (strncasecmp(tstr, "all", strlen("all")) == 0)
1451 arglist |= CAM_ARG_BUS;
1453 rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
1454 if (rv != 1 && rv != 3) {
1455 warnx(must, rescan? "rescan" : "reset");
1460 if ((arglist & CAM_ARG_BUS)
1461 && (arglist & CAM_ARG_TARGET)
1462 && (arglist & CAM_ARG_LUN))
1463 error = scanlun_or_reset_dev(bus, target, lun, rescan);
1465 error = rescan_or_reset_bus(bus, rescan);
1471 rescan_or_reset_bus(int bus, int rescan)
1473 union ccb ccb, matchccb;
1479 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1480 warnx("error opening transport layer device %s", XPT_DEVICE);
1481 warn("%s", XPT_DEVICE);
1486 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
1487 ccb.ccb_h.path_id = bus;
1488 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1489 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1490 ccb.crcn.flags = CAM_FLAG_NONE;
1492 /* run this at a low priority */
1493 ccb.ccb_h.pinfo.priority = 5;
1495 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1496 warn("CAMIOCOMMAND ioctl failed");
1501 if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
1502 fprintf(stdout, "%s of bus %d was successful\n",
1503 rescan ? "Re-scan" : "Reset", bus);
1505 fprintf(stdout, "%s of bus %d returned error %#x\n",
1506 rescan ? "Re-scan" : "Reset", bus,
1507 ccb.ccb_h.status & CAM_STATUS_MASK);
1518 * The right way to handle this is to modify the xpt so that it can
1519 * handle a wildcarded bus in a rescan or reset CCB. At the moment
1520 * that isn't implemented, so instead we enumerate the busses and
1521 * send the rescan or reset to those busses in the case where the
1522 * given bus is -1 (wildcard). We don't send a rescan or reset
1523 * to the xpt bus; sending a rescan to the xpt bus is effectively a
1524 * no-op, sending a rescan to the xpt bus would result in a status of
1527 bzero(&(&matchccb.ccb_h)[1],
1528 sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
1529 matchccb.ccb_h.func_code = XPT_DEV_MATCH;
1530 matchccb.ccb_h.path_id = CAM_BUS_WILDCARD;
1531 bufsize = sizeof(struct dev_match_result) * 20;
1532 matchccb.cdm.match_buf_len = bufsize;
1533 matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
1534 if (matchccb.cdm.matches == NULL) {
1535 warnx("can't malloc memory for matches");
1539 matchccb.cdm.num_matches = 0;
1541 matchccb.cdm.num_patterns = 1;
1542 matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
1544 matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
1545 matchccb.cdm.pattern_buf_len);
1546 if (matchccb.cdm.patterns == NULL) {
1547 warnx("can't malloc memory for patterns");
1551 matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
1552 matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
1557 if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
1558 warn("CAMIOCOMMAND ioctl failed");
1563 if ((matchccb.ccb_h.status != CAM_REQ_CMP)
1564 || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
1565 && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
1566 warnx("got CAM error %#x, CDM error %d\n",
1567 matchccb.ccb_h.status, matchccb.cdm.status);
1572 for (i = 0; i < matchccb.cdm.num_matches; i++) {
1573 struct bus_match_result *bus_result;
1575 /* This shouldn't happen. */
1576 if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
1579 bus_result = &matchccb.cdm.matches[i].result.bus_result;
1582 * We don't want to rescan or reset the xpt bus.
1585 if ((int)bus_result->path_id == -1)
1588 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
1590 ccb.ccb_h.path_id = bus_result->path_id;
1591 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1592 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1593 ccb.crcn.flags = CAM_FLAG_NONE;
1595 /* run this at a low priority */
1596 ccb.ccb_h.pinfo.priority = 5;
1598 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1599 warn("CAMIOCOMMAND ioctl failed");
1604 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
1605 fprintf(stdout, "%s of bus %d was successful\n",
1606 rescan? "Re-scan" : "Reset",
1607 bus_result->path_id);
1610 * Don't bail out just yet, maybe the other
1611 * rescan or reset commands will complete
1614 fprintf(stderr, "%s of bus %d returned error "
1615 "%#x\n", rescan? "Re-scan" : "Reset",
1616 bus_result->path_id,
1617 ccb.ccb_h.status & CAM_STATUS_MASK);
1621 } while ((matchccb.ccb_h.status == CAM_REQ_CMP)
1622 && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
1629 if (matchccb.cdm.patterns != NULL)
1630 free(matchccb.cdm.patterns);
1631 if (matchccb.cdm.matches != NULL)
1632 free(matchccb.cdm.matches);
1638 scanlun_or_reset_dev(int bus, int target, int lun, int scan)
1641 struct cam_device *device;
1647 warnx("invalid bus number %d", bus);
1652 warnx("invalid target number %d", target);
1657 warnx("invalid lun number %d", lun);
1663 bzero(&ccb, sizeof(union ccb));
1666 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1667 warnx("error opening transport layer device %s\n",
1669 warn("%s", XPT_DEVICE);
1673 device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
1674 if (device == NULL) {
1675 warnx("%s", cam_errbuf);
1680 ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
1681 ccb.ccb_h.path_id = bus;
1682 ccb.ccb_h.target_id = target;
1683 ccb.ccb_h.target_lun = lun;
1684 ccb.ccb_h.timeout = 5000;
1685 ccb.crcn.flags = CAM_FLAG_NONE;
1687 /* run this at a low priority */
1688 ccb.ccb_h.pinfo.priority = 5;
1691 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
1692 warn("CAMIOCOMMAND ioctl failed");
1697 if (cam_send_ccb(device, &ccb) < 0) {
1698 warn("error sending XPT_RESET_DEV CCB");
1699 cam_close_device(device);
1707 cam_close_device(device);
1710 * An error code of CAM_BDR_SENT is normal for a BDR request.
1712 if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1714 && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
1715 fprintf(stdout, "%s of %d:%d:%d was successful\n",
1716 scan? "Re-scan" : "Reset", bus, target, lun);
1719 fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
1720 scan? "Re-scan" : "Reset", bus, target, lun,
1721 ccb.ccb_h.status & CAM_STATUS_MASK);
1726 #ifndef MINIMALISTIC
1728 readdefects(struct cam_device *device, int argc, char **argv,
1729 char *combinedopt, int retry_count, int timeout)
1731 union ccb *ccb = NULL;
1732 struct scsi_read_defect_data_10 *rdd_cdb;
1733 u_int8_t *defect_list = NULL;
1734 u_int32_t dlist_length = 65000;
1735 u_int32_t returned_length = 0;
1736 u_int32_t num_returned = 0;
1737 u_int8_t returned_format;
1740 int lists_specified = 0;
1742 while ((c = getopt(argc, argv, combinedopt)) != -1) {
1748 while (isspace(*tstr) && (*tstr != '\0'))
1750 if (strcmp(tstr, "block") == 0)
1751 arglist |= CAM_ARG_FORMAT_BLOCK;
1752 else if (strcmp(tstr, "bfi") == 0)
1753 arglist |= CAM_ARG_FORMAT_BFI;
1754 else if (strcmp(tstr, "phys") == 0)
1755 arglist |= CAM_ARG_FORMAT_PHYS;
1758 warnx("invalid defect format %s", tstr);
1759 goto defect_bailout;
1764 arglist |= CAM_ARG_GLIST;
1767 arglist |= CAM_ARG_PLIST;
1774 ccb = cam_getccb(device);
1777 * Hopefully 65000 bytes is enough to hold the defect list. If it
1778 * isn't, the disk is probably dead already. We'd have to go with
1779 * 12 byte command (i.e. alloc_length is 32 bits instead of 16)
1782 defect_list = malloc(dlist_length);
1783 if (defect_list == NULL) {
1784 warnx("can't malloc memory for defect list");
1786 goto defect_bailout;
1789 rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
1792 * cam_getccb() zeros the CCB header only. So we need to zero the
1793 * payload portion of the ccb.
1795 bzero(&(&ccb->ccb_h)[1],
1796 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1798 cam_fill_csio(&ccb->csio,
1799 /*retries*/ retry_count,
1801 /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
1802 CAM_PASS_ERR_RECOVER : 0),
1803 /*tag_action*/ MSG_SIMPLE_Q_TAG,
1804 /*data_ptr*/ defect_list,
1805 /*dxfer_len*/ dlist_length,
1806 /*sense_len*/ SSD_FULL_SIZE,
1807 /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
1808 /*timeout*/ timeout ? timeout : 5000);
1810 rdd_cdb->opcode = READ_DEFECT_DATA_10;
1811 if (arglist & CAM_ARG_FORMAT_BLOCK)
1812 rdd_cdb->format = SRDD10_BLOCK_FORMAT;
1813 else if (arglist & CAM_ARG_FORMAT_BFI)
1814 rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
1815 else if (arglist & CAM_ARG_FORMAT_PHYS)
1816 rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
1819 warnx("no defect list format specified");
1820 goto defect_bailout;
1822 if (arglist & CAM_ARG_PLIST) {
1823 rdd_cdb->format |= SRDD10_PLIST;
1827 if (arglist & CAM_ARG_GLIST) {
1828 rdd_cdb->format |= SRDD10_GLIST;
1832 scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
1834 /* Disable freezing the device queue */
1835 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1837 if (cam_send_ccb(device, ccb) < 0) {
1838 perror("error reading defect list");
1840 if (arglist & CAM_ARG_VERBOSE) {
1841 cam_error_print(device, ccb, CAM_ESF_ALL,
1842 CAM_EPF_ALL, stderr);
1846 goto defect_bailout;
1849 returned_length = scsi_2btoul(((struct
1850 scsi_read_defect_data_hdr_10 *)defect_list)->length);
1852 returned_format = ((struct scsi_read_defect_data_hdr_10 *)
1853 defect_list)->format;
1855 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
1856 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
1857 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
1858 struct scsi_sense_data *sense;
1859 int error_code, sense_key, asc, ascq;
1861 sense = &ccb->csio.sense_data;
1862 scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq);
1865 * According to the SCSI spec, if the disk doesn't support
1866 * the requested format, it will generally return a sense
1867 * key of RECOVERED ERROR, and an additional sense code
1868 * of "DEFECT LIST NOT FOUND". So, we check for that, and
1869 * also check to make sure that the returned length is
1870 * greater than 0, and then print out whatever format the
1873 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
1874 && (asc == 0x1c) && (ascq == 0x00)
1875 && (returned_length > 0)) {
1876 warnx("requested defect format not available");
1877 switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
1878 case SRDD10_BLOCK_FORMAT:
1879 warnx("Device returned block format");
1881 case SRDD10_BYTES_FROM_INDEX_FORMAT:
1882 warnx("Device returned bytes from index"
1885 case SRDD10_PHYSICAL_SECTOR_FORMAT:
1886 warnx("Device returned physical sector format");
1890 warnx("Device returned unknown defect"
1891 " data format %#x", returned_format);
1892 goto defect_bailout;
1893 break; /* NOTREACHED */
1897 warnx("Error returned from read defect data command");
1898 if (arglist & CAM_ARG_VERBOSE)
1899 cam_error_print(device, ccb, CAM_ESF_ALL,
1900 CAM_EPF_ALL, stderr);
1901 goto defect_bailout;
1903 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1905 warnx("Error returned from read defect data command");
1906 if (arglist & CAM_ARG_VERBOSE)
1907 cam_error_print(device, ccb, CAM_ESF_ALL,
1908 CAM_EPF_ALL, stderr);
1909 goto defect_bailout;
1913 * XXX KDM I should probably clean up the printout format for the
1916 switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
1917 case SRDDH10_PHYSICAL_SECTOR_FORMAT:
1919 struct scsi_defect_desc_phys_sector *dlist;
1921 dlist = (struct scsi_defect_desc_phys_sector *)
1923 sizeof(struct scsi_read_defect_data_hdr_10));
1925 num_returned = returned_length /
1926 sizeof(struct scsi_defect_desc_phys_sector);
1928 fprintf(stderr, "Got %d defect", num_returned);
1930 if ((lists_specified == 0) || (num_returned == 0)) {
1931 fprintf(stderr, "s.\n");
1933 } else if (num_returned == 1)
1934 fprintf(stderr, ":\n");
1936 fprintf(stderr, "s:\n");
1938 for (i = 0; i < num_returned; i++) {
1939 fprintf(stdout, "%d:%d:%d\n",
1940 scsi_3btoul(dlist[i].cylinder),
1942 scsi_4btoul(dlist[i].sector));
1946 case SRDDH10_BYTES_FROM_INDEX_FORMAT:
1948 struct scsi_defect_desc_bytes_from_index *dlist;
1950 dlist = (struct scsi_defect_desc_bytes_from_index *)
1952 sizeof(struct scsi_read_defect_data_hdr_10));
1954 num_returned = returned_length /
1955 sizeof(struct scsi_defect_desc_bytes_from_index);
1957 fprintf(stderr, "Got %d defect", num_returned);
1959 if ((lists_specified == 0) || (num_returned == 0)) {
1960 fprintf(stderr, "s.\n");
1962 } else if (num_returned == 1)
1963 fprintf(stderr, ":\n");
1965 fprintf(stderr, "s:\n");
1967 for (i = 0; i < num_returned; i++) {
1968 fprintf(stdout, "%d:%d:%d\n",
1969 scsi_3btoul(dlist[i].cylinder),
1971 scsi_4btoul(dlist[i].bytes_from_index));
1975 case SRDDH10_BLOCK_FORMAT:
1977 struct scsi_defect_desc_block *dlist;
1979 dlist = (struct scsi_defect_desc_block *)(defect_list +
1980 sizeof(struct scsi_read_defect_data_hdr_10));
1982 num_returned = returned_length /
1983 sizeof(struct scsi_defect_desc_block);
1985 fprintf(stderr, "Got %d defect", num_returned);
1987 if ((lists_specified == 0) || (num_returned == 0)) {
1988 fprintf(stderr, "s.\n");
1990 } else if (num_returned == 1)
1991 fprintf(stderr, ":\n");
1993 fprintf(stderr, "s:\n");
1995 for (i = 0; i < num_returned; i++)
1996 fprintf(stdout, "%u\n",
1997 scsi_4btoul(dlist[i].address));
2001 fprintf(stderr, "Unknown defect format %d\n",
2002 returned_format & SRDDH10_DLIST_FORMAT_MASK);
2008 if (defect_list != NULL)
2016 #endif /* MINIMALISTIC */
2020 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
2024 ccb = cam_getccb(device);
2030 #ifndef MINIMALISTIC
2032 mode_sense(struct cam_device *device, int mode_page, int page_control,
2033 int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
2038 ccb = cam_getccb(device);
2041 errx(1, "mode_sense: couldn't allocate CCB");
2043 bzero(&(&ccb->ccb_h)[1],
2044 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2046 scsi_mode_sense(&ccb->csio,
2047 /* retries */ retry_count,
2049 /* tag_action */ MSG_SIMPLE_Q_TAG,
2051 /* page_code */ page_control << 6,
2052 /* page */ mode_page,
2053 /* param_buf */ data,
2054 /* param_len */ datalen,
2055 /* sense_len */ SSD_FULL_SIZE,
2056 /* timeout */ timeout ? timeout : 5000);
2058 if (arglist & CAM_ARG_ERR_RECOVER)
2059 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2061 /* Disable freezing the device queue */
2062 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2064 if (((retval = cam_send_ccb(device, ccb)) < 0)
2065 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2066 if (arglist & CAM_ARG_VERBOSE) {
2067 cam_error_print(device, ccb, CAM_ESF_ALL,
2068 CAM_EPF_ALL, stderr);
2071 cam_close_device(device);
2073 err(1, "error sending mode sense command");
2075 errx(1, "error sending mode sense command");
2082 mode_select(struct cam_device *device, int save_pages, int retry_count,
2083 int timeout, u_int8_t *data, int datalen)
2088 ccb = cam_getccb(device);
2091 errx(1, "mode_select: couldn't allocate CCB");
2093 bzero(&(&ccb->ccb_h)[1],
2094 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2096 scsi_mode_select(&ccb->csio,
2097 /* retries */ retry_count,
2099 /* tag_action */ MSG_SIMPLE_Q_TAG,
2100 /* scsi_page_fmt */ 1,
2101 /* save_pages */ save_pages,
2102 /* param_buf */ data,
2103 /* param_len */ datalen,
2104 /* sense_len */ SSD_FULL_SIZE,
2105 /* timeout */ timeout ? timeout : 5000);
2107 if (arglist & CAM_ARG_ERR_RECOVER)
2108 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2110 /* Disable freezing the device queue */
2111 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2113 if (((retval = cam_send_ccb(device, ccb)) < 0)
2114 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2115 if (arglist & CAM_ARG_VERBOSE) {
2116 cam_error_print(device, ccb, CAM_ESF_ALL,
2117 CAM_EPF_ALL, stderr);
2120 cam_close_device(device);
2123 err(1, "error sending mode select command");
2125 errx(1, "error sending mode select command");
2133 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
2134 int retry_count, int timeout)
2136 int c, mode_page = -1, page_control = 0;
2137 int binary = 0, list = 0;
2139 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2145 arglist |= CAM_ARG_DBD;
2148 arglist |= CAM_ARG_MODE_EDIT;
2154 mode_page = strtol(optarg, NULL, 0);
2156 errx(1, "invalid mode page %d", mode_page);
2159 page_control = strtol(optarg, NULL, 0);
2160 if ((page_control < 0) || (page_control > 3))
2161 errx(1, "invalid page control field %d",
2163 arglist |= CAM_ARG_PAGE_CNTL;
2170 if (mode_page == -1 && list == 0)
2171 errx(1, "you must specify a mode page!");
2174 mode_list(device, page_control, arglist & CAM_ARG_DBD,
2175 retry_count, timeout);
2177 mode_edit(device, mode_page, page_control,
2178 arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
2179 retry_count, timeout);
2184 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
2185 int retry_count, int timeout)
2188 u_int32_t flags = CAM_DIR_NONE;
2189 u_int8_t *data_ptr = NULL;
2191 u_int8_t atacmd[12];
2192 struct get_hook hook;
2193 int c, data_bytes = 0;
2199 char *datastr = NULL, *tstr, *resstr = NULL;
2201 int fd_data = 0, fd_res = 0;
2204 ccb = cam_getccb(device);
2207 warnx("scsicmd: error allocating ccb");
2211 bzero(&(&ccb->ccb_h)[1],
2212 sizeof(union ccb) - sizeof(struct ccb_hdr));
2214 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2218 while (isspace(*tstr) && (*tstr != '\0'))
2220 hook.argc = argc - optind;
2221 hook.argv = argv + optind;
2223 atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
2226 * Increment optind by the number of arguments the
2227 * encoding routine processed. After each call to
2228 * getopt(3), optind points to the argument that
2229 * getopt should process _next_. In this case,
2230 * that means it points to the first command string
2231 * argument, if there is one. Once we increment
2232 * this, it should point to either the next command
2233 * line argument, or it should be past the end of
2240 while (isspace(*tstr) && (*tstr != '\0'))
2242 hook.argc = argc - optind;
2243 hook.argv = argv + optind;
2245 cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
2248 * Increment optind by the number of arguments the
2249 * encoding routine processed. After each call to
2250 * getopt(3), optind points to the argument that
2251 * getopt should process _next_. In this case,
2252 * that means it points to the first command string
2253 * argument, if there is one. Once we increment
2254 * this, it should point to either the next command
2255 * line argument, or it should be past the end of
2267 if (arglist & CAM_ARG_CMD_OUT) {
2268 warnx("command must either be "
2269 "read or write, not both");
2271 goto scsicmd_bailout;
2273 arglist |= CAM_ARG_CMD_IN;
2275 data_bytes = strtol(optarg, NULL, 0);
2276 if (data_bytes <= 0) {
2277 warnx("invalid number of input bytes %d",
2280 goto scsicmd_bailout;
2282 hook.argc = argc - optind;
2283 hook.argv = argv + optind;
2286 datastr = cget(&hook, NULL);
2288 * If the user supplied "-" instead of a format, he
2289 * wants the data to be written to stdout.
2291 if ((datastr != NULL)
2292 && (datastr[0] == '-'))
2295 data_ptr = (u_int8_t *)malloc(data_bytes);
2296 if (data_ptr == NULL) {
2297 warnx("can't malloc memory for data_ptr");
2299 goto scsicmd_bailout;
2303 if (arglist & CAM_ARG_CMD_IN) {
2304 warnx("command must either be "
2305 "read or write, not both");
2307 goto scsicmd_bailout;
2309 arglist |= CAM_ARG_CMD_OUT;
2310 flags = CAM_DIR_OUT;
2311 data_bytes = strtol(optarg, NULL, 0);
2312 if (data_bytes <= 0) {
2313 warnx("invalid number of output bytes %d",
2316 goto scsicmd_bailout;
2318 hook.argc = argc - optind;
2319 hook.argv = argv + optind;
2321 datastr = cget(&hook, NULL);
2322 data_ptr = (u_int8_t *)malloc(data_bytes);
2323 if (data_ptr == NULL) {
2324 warnx("can't malloc memory for data_ptr");
2326 goto scsicmd_bailout;
2328 bzero(data_ptr, data_bytes);
2330 * If the user supplied "-" instead of a format, he
2331 * wants the data to be read from stdin.
2333 if ((datastr != NULL)
2334 && (datastr[0] == '-'))
2337 buff_encode_visit(data_ptr, data_bytes, datastr,
2343 hook.argc = argc - optind;
2344 hook.argv = argv + optind;
2346 resstr = cget(&hook, NULL);
2347 if ((resstr != NULL) && (resstr[0] == '-'))
2357 * If fd_data is set, and we're writing to the device, we need to
2358 * read the data the user wants written from stdin.
2360 if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
2362 int amt_to_read = data_bytes;
2363 u_int8_t *buf_ptr = data_ptr;
2365 for (amt_read = 0; amt_to_read > 0;
2366 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
2367 if (amt_read == -1) {
2368 warn("error reading data from stdin");
2370 goto scsicmd_bailout;
2372 amt_to_read -= amt_read;
2373 buf_ptr += amt_read;
2377 if (arglist & CAM_ARG_ERR_RECOVER)
2378 flags |= CAM_PASS_ERR_RECOVER;
2380 /* Disable freezing the device queue */
2381 flags |= CAM_DEV_QFRZDIS;
2385 * This is taken from the SCSI-3 draft spec.
2386 * (T10/1157D revision 0.3)
2387 * The top 3 bits of an opcode are the group code.
2388 * The next 5 bits are the command code.
2389 * Group 0: six byte commands
2390 * Group 1: ten byte commands
2391 * Group 2: ten byte commands
2393 * Group 4: sixteen byte commands
2394 * Group 5: twelve byte commands
2395 * Group 6: vendor specific
2396 * Group 7: vendor specific
2398 switch((cdb[0] >> 5) & 0x7) {
2409 /* computed by buff_encode_visit */
2420 * We should probably use csio_build_visit or something like that
2421 * here, but it's easier to encode arguments as you go. The
2422 * alternative would be skipping the CDB argument and then encoding
2423 * it here, since we've got the data buffer argument by now.
2425 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
2427 cam_fill_csio(&ccb->csio,
2428 /*retries*/ retry_count,
2431 /*tag_action*/ MSG_SIMPLE_Q_TAG,
2432 /*data_ptr*/ data_ptr,
2433 /*dxfer_len*/ data_bytes,
2434 /*sense_len*/ SSD_FULL_SIZE,
2435 /*cdb_len*/ cdb_len,
2436 /*timeout*/ timeout ? timeout : 5000);
2439 bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
2441 ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
2443 ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
2445 ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
2447 cam_fill_ataio(&ccb->ataio,
2448 /*retries*/ retry_count,
2452 /*data_ptr*/ data_ptr,
2453 /*dxfer_len*/ data_bytes,
2454 /*timeout*/ timeout ? timeout : 5000);
2457 if (((retval = cam_send_ccb(device, ccb)) < 0)
2458 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2460 warn("error sending command");
2462 warnx("error sending command");
2464 if (arglist & CAM_ARG_VERBOSE) {
2465 cam_error_print(device, ccb, CAM_ESF_ALL,
2466 CAM_EPF_ALL, stderr);
2470 goto scsicmd_bailout;
2473 if (atacmd_len && need_res) {
2475 buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
2477 fprintf(stdout, "\n");
2480 "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
2481 ccb->ataio.res.status,
2482 ccb->ataio.res.error,
2483 ccb->ataio.res.lba_low,
2484 ccb->ataio.res.lba_mid,
2485 ccb->ataio.res.lba_high,
2486 ccb->ataio.res.device,
2487 ccb->ataio.res.lba_low_exp,
2488 ccb->ataio.res.lba_mid_exp,
2489 ccb->ataio.res.lba_high_exp,
2490 ccb->ataio.res.sector_count,
2491 ccb->ataio.res.sector_count_exp);
2496 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
2497 && (arglist & CAM_ARG_CMD_IN)
2498 && (data_bytes > 0)) {
2500 buff_decode_visit(data_ptr, data_bytes, datastr,
2502 fprintf(stdout, "\n");
2504 ssize_t amt_written;
2505 int amt_to_write = data_bytes;
2506 u_int8_t *buf_ptr = data_ptr;
2508 for (amt_written = 0; (amt_to_write > 0) &&
2509 (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
2510 amt_to_write -= amt_written;
2511 buf_ptr += amt_written;
2513 if (amt_written == -1) {
2514 warn("error writing data to stdout");
2516 goto scsicmd_bailout;
2517 } else if ((amt_written == 0)
2518 && (amt_to_write > 0)) {
2519 warnx("only wrote %u bytes out of %u",
2520 data_bytes - amt_to_write, data_bytes);
2527 if ((data_bytes > 0) && (data_ptr != NULL))
2536 camdebug(int argc, char **argv, char *combinedopt)
2539 int bus = -1, target = -1, lun = -1;
2540 char *tstr, *tmpstr = NULL;
2544 bzero(&ccb, sizeof(union ccb));
2546 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2549 arglist |= CAM_ARG_DEBUG_INFO;
2550 ccb.cdbg.flags |= CAM_DEBUG_INFO;
2553 arglist |= CAM_ARG_DEBUG_PERIPH;
2554 ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
2557 arglist |= CAM_ARG_DEBUG_SUBTRACE;
2558 ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
2561 arglist |= CAM_ARG_DEBUG_TRACE;
2562 ccb.cdbg.flags |= CAM_DEBUG_TRACE;
2565 arglist |= CAM_ARG_DEBUG_XPT;
2566 ccb.cdbg.flags |= CAM_DEBUG_XPT;
2569 arglist |= CAM_ARG_DEBUG_CDB;
2570 ccb.cdbg.flags |= CAM_DEBUG_CDB;
2573 arglist |= CAM_ARG_DEBUG_PROBE;
2574 ccb.cdbg.flags |= CAM_DEBUG_PROBE;
2581 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
2582 warnx("error opening transport layer device %s", XPT_DEVICE);
2583 warn("%s", XPT_DEVICE);
2590 warnx("you must specify \"off\", \"all\" or a bus,");
2591 warnx("bus:target, or bus:target:lun");
2598 while (isspace(*tstr) && (*tstr != '\0'))
2601 if (strncmp(tstr, "off", 3) == 0) {
2602 ccb.cdbg.flags = CAM_DEBUG_NONE;
2603 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
2604 CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
2605 CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE);
2606 } else if (strncmp(tstr, "all", 3) != 0) {
2607 tmpstr = (char *)strtok(tstr, ":");
2608 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2609 bus = strtol(tmpstr, NULL, 0);
2610 arglist |= CAM_ARG_BUS;
2611 tmpstr = (char *)strtok(NULL, ":");
2612 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2613 target = strtol(tmpstr, NULL, 0);
2614 arglist |= CAM_ARG_TARGET;
2615 tmpstr = (char *)strtok(NULL, ":");
2616 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2617 lun = strtol(tmpstr, NULL, 0);
2618 arglist |= CAM_ARG_LUN;
2623 warnx("you must specify \"all\", \"off\", or a bus,");
2624 warnx("bus:target, or bus:target:lun to debug");
2630 ccb.ccb_h.func_code = XPT_DEBUG;
2631 ccb.ccb_h.path_id = bus;
2632 ccb.ccb_h.target_id = target;
2633 ccb.ccb_h.target_lun = lun;
2635 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
2636 warn("CAMIOCOMMAND ioctl failed");
2641 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
2642 CAM_FUNC_NOTAVAIL) {
2643 warnx("CAM debugging not available");
2644 warnx("you need to put options CAMDEBUG in"
2645 " your kernel config file!");
2647 } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
2649 warnx("XPT_DEBUG CCB failed with status %#x",
2653 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
2655 "Debugging turned off\n");
2658 "Debugging enabled for "
2671 tagcontrol(struct cam_device *device, int argc, char **argv,
2681 ccb = cam_getccb(device);
2684 warnx("tagcontrol: error allocating ccb");
2688 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2691 numtags = strtol(optarg, NULL, 0);
2693 warnx("tag count %d is < 0", numtags);
2695 goto tagcontrol_bailout;
2706 cam_path_string(device, pathstr, sizeof(pathstr));
2709 bzero(&(&ccb->ccb_h)[1],
2710 sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
2711 ccb->ccb_h.func_code = XPT_REL_SIMQ;
2712 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
2713 ccb->crs.openings = numtags;
2716 if (cam_send_ccb(device, ccb) < 0) {
2717 perror("error sending XPT_REL_SIMQ CCB");
2719 goto tagcontrol_bailout;
2722 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2723 warnx("XPT_REL_SIMQ CCB failed");
2724 cam_error_print(device, ccb, CAM_ESF_ALL,
2725 CAM_EPF_ALL, stderr);
2727 goto tagcontrol_bailout;
2732 fprintf(stdout, "%stagged openings now %d\n",
2733 pathstr, ccb->crs.openings);
2736 bzero(&(&ccb->ccb_h)[1],
2737 sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
2739 ccb->ccb_h.func_code = XPT_GDEV_STATS;
2741 if (cam_send_ccb(device, ccb) < 0) {
2742 perror("error sending XPT_GDEV_STATS CCB");
2744 goto tagcontrol_bailout;
2747 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2748 warnx("XPT_GDEV_STATS CCB failed");
2749 cam_error_print(device, ccb, CAM_ESF_ALL,
2750 CAM_EPF_ALL, stderr);
2752 goto tagcontrol_bailout;
2755 if (arglist & CAM_ARG_VERBOSE) {
2756 fprintf(stdout, "%s", pathstr);
2757 fprintf(stdout, "dev_openings %d\n", ccb->cgds.dev_openings);
2758 fprintf(stdout, "%s", pathstr);
2759 fprintf(stdout, "dev_active %d\n", ccb->cgds.dev_active);
2760 fprintf(stdout, "%s", pathstr);
2761 fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
2762 fprintf(stdout, "%s", pathstr);
2763 fprintf(stdout, "devq_queued %d\n", ccb->cgds.devq_queued);
2764 fprintf(stdout, "%s", pathstr);
2765 fprintf(stdout, "held %d\n", ccb->cgds.held);
2766 fprintf(stdout, "%s", pathstr);
2767 fprintf(stdout, "mintags %d\n", ccb->cgds.mintags);
2768 fprintf(stdout, "%s", pathstr);
2769 fprintf(stdout, "maxtags %d\n", ccb->cgds.maxtags);
2772 fprintf(stdout, "%s", pathstr);
2773 fprintf(stdout, "device openings: ");
2775 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
2776 ccb->cgds.dev_active);
2786 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
2790 cam_path_string(device, pathstr, sizeof(pathstr));
2792 if (cts->transport == XPORT_SPI) {
2793 struct ccb_trans_settings_spi *spi =
2794 &cts->xport_specific.spi;
2796 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
2798 fprintf(stdout, "%ssync parameter: %d\n", pathstr,
2801 if (spi->sync_offset != 0) {
2804 freq = scsi_calc_syncsrate(spi->sync_period);
2805 fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
2806 pathstr, freq / 1000, freq % 1000);
2810 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
2811 fprintf(stdout, "%soffset: %d\n", pathstr,
2815 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
2816 fprintf(stdout, "%sbus width: %d bits\n", pathstr,
2817 (0x01 << spi->bus_width) * 8);
2820 if (spi->valid & CTS_SPI_VALID_DISC) {
2821 fprintf(stdout, "%sdisconnection is %s\n", pathstr,
2822 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
2823 "enabled" : "disabled");
2826 if (cts->transport == XPORT_FC) {
2827 struct ccb_trans_settings_fc *fc =
2828 &cts->xport_specific.fc;
2830 if (fc->valid & CTS_FC_VALID_WWNN)
2831 fprintf(stdout, "%sWWNN: 0x%llx", pathstr,
2832 (long long) fc->wwnn);
2833 if (fc->valid & CTS_FC_VALID_WWPN)
2834 fprintf(stdout, "%sWWPN: 0x%llx", pathstr,
2835 (long long) fc->wwpn);
2836 if (fc->valid & CTS_FC_VALID_PORT)
2837 fprintf(stdout, "%sPortID: 0x%x", pathstr, fc->port);
2838 if (fc->valid & CTS_FC_VALID_SPEED)
2839 fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
2840 pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
2842 if (cts->transport == XPORT_SAS) {
2843 struct ccb_trans_settings_sas *sas =
2844 &cts->xport_specific.sas;
2846 if (sas->valid & CTS_SAS_VALID_SPEED)
2847 fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
2848 pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
2850 if (cts->transport == XPORT_ATA) {
2851 struct ccb_trans_settings_pata *pata =
2852 &cts->xport_specific.ata;
2854 if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
2855 fprintf(stdout, "%sATA mode: %s\n", pathstr,
2856 ata_mode2string(pata->mode));
2858 if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
2859 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2862 if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
2863 fprintf(stdout, "%sPIO transaction length: %d\n",
2864 pathstr, pata->bytecount);
2867 if (cts->transport == XPORT_SATA) {
2868 struct ccb_trans_settings_sata *sata =
2869 &cts->xport_specific.sata;
2871 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
2872 fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
2875 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
2876 fprintf(stdout, "%sATA mode: %s\n", pathstr,
2877 ata_mode2string(sata->mode));
2879 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
2880 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2883 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
2884 fprintf(stdout, "%sPIO transaction length: %d\n",
2885 pathstr, sata->bytecount);
2887 if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
2888 fprintf(stdout, "%sPMP presence: %d\n", pathstr,
2891 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
2892 fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
2895 if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
2896 fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
2900 if (cts->protocol == PROTO_ATA) {
2901 struct ccb_trans_settings_ata *ata=
2902 &cts->proto_specific.ata;
2904 if (ata->valid & CTS_ATA_VALID_TQ) {
2905 fprintf(stdout, "%stagged queueing: %s\n", pathstr,
2906 (ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
2907 "enabled" : "disabled");
2910 if (cts->protocol == PROTO_SCSI) {
2911 struct ccb_trans_settings_scsi *scsi=
2912 &cts->proto_specific.scsi;
2914 if (scsi->valid & CTS_SCSI_VALID_TQ) {
2915 fprintf(stdout, "%stagged queueing: %s\n", pathstr,
2916 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
2917 "enabled" : "disabled");
2924 * Get a path inquiry CCB for the specified device.
2927 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
2932 ccb = cam_getccb(device);
2934 warnx("get_cpi: couldn't allocate CCB");
2937 bzero(&(&ccb->ccb_h)[1],
2938 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2939 ccb->ccb_h.func_code = XPT_PATH_INQ;
2940 if (cam_send_ccb(device, ccb) < 0) {
2941 warn("get_cpi: error sending Path Inquiry CCB");
2942 if (arglist & CAM_ARG_VERBOSE)
2943 cam_error_print(device, ccb, CAM_ESF_ALL,
2944 CAM_EPF_ALL, stderr);
2946 goto get_cpi_bailout;
2948 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2949 if (arglist & CAM_ARG_VERBOSE)
2950 cam_error_print(device, ccb, CAM_ESF_ALL,
2951 CAM_EPF_ALL, stderr);
2953 goto get_cpi_bailout;
2955 bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
2963 * Get a get device CCB for the specified device.
2966 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
2971 ccb = cam_getccb(device);
2973 warnx("get_cgd: couldn't allocate CCB");
2976 bzero(&(&ccb->ccb_h)[1],
2977 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2978 ccb->ccb_h.func_code = XPT_GDEV_TYPE;
2979 if (cam_send_ccb(device, ccb) < 0) {
2980 warn("get_cgd: error sending Path Inquiry CCB");
2981 if (arglist & CAM_ARG_VERBOSE)
2982 cam_error_print(device, ccb, CAM_ESF_ALL,
2983 CAM_EPF_ALL, stderr);
2985 goto get_cgd_bailout;
2987 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2988 if (arglist & CAM_ARG_VERBOSE)
2989 cam_error_print(device, ccb, CAM_ESF_ALL,
2990 CAM_EPF_ALL, stderr);
2992 goto get_cgd_bailout;
2994 bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
3002 cpi_print(struct ccb_pathinq *cpi)
3004 char adapter_str[1024];
3007 snprintf(adapter_str, sizeof(adapter_str),
3008 "%s%d:", cpi->dev_name, cpi->unit_number);
3010 fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
3013 for (i = 1; i < 0xff; i = i << 1) {
3016 if ((i & cpi->hba_inquiry) == 0)
3019 fprintf(stdout, "%s supports ", adapter_str);
3023 str = "MDP message";
3026 str = "32 bit wide SCSI";
3029 str = "16 bit wide SCSI";
3032 str = "SDTR message";
3035 str = "linked CDBs";
3038 str = "tag queue messages";
3041 str = "soft reset alternative";
3044 str = "SATA Port Multiplier";
3047 str = "unknown PI bit set";
3050 fprintf(stdout, "%s\n", str);
3053 for (i = 1; i < 0xff; i = i << 1) {
3056 if ((i & cpi->hba_misc) == 0)
3059 fprintf(stdout, "%s ", adapter_str);
3063 str = "bus scans from high ID to low ID";
3066 str = "removable devices not included in scan";
3068 case PIM_NOINITIATOR:
3069 str = "initiator role not supported";
3071 case PIM_NOBUSRESET:
3072 str = "user has disabled initial BUS RESET or"
3073 " controller is in target/mixed mode";
3076 str = "do not send 6-byte commands";
3079 str = "scan bus sequentially";
3082 str = "unknown PIM bit set";
3085 fprintf(stdout, "%s\n", str);
3088 for (i = 1; i < 0xff; i = i << 1) {
3091 if ((i & cpi->target_sprt) == 0)
3094 fprintf(stdout, "%s supports ", adapter_str);
3097 str = "target mode processor mode";
3100 str = "target mode phase cog. mode";
3102 case PIT_DISCONNECT:
3103 str = "disconnects in target mode";
3106 str = "terminate I/O message in target mode";
3109 str = "group 6 commands in target mode";
3112 str = "group 7 commands in target mode";
3115 str = "unknown PIT bit set";
3119 fprintf(stdout, "%s\n", str);
3121 fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
3123 fprintf(stdout, "%s maximum target: %d\n", adapter_str,
3125 fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
3127 fprintf(stdout, "%s highest path ID in subsystem: %d\n",
3128 adapter_str, cpi->hpath_id);
3129 fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
3131 fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
3132 fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
3133 fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
3134 fprintf(stdout, "%s base transfer speed: ", adapter_str);
3135 if (cpi->base_transfer_speed > 1000)
3136 fprintf(stdout, "%d.%03dMB/sec\n",
3137 cpi->base_transfer_speed / 1000,
3138 cpi->base_transfer_speed % 1000);
3140 fprintf(stdout, "%dKB/sec\n",
3141 (cpi->base_transfer_speed % 1000) * 1000);
3145 get_print_cts(struct cam_device *device, int user_settings, int quiet,
3146 struct ccb_trans_settings *cts)
3152 ccb = cam_getccb(device);
3155 warnx("get_print_cts: error allocating ccb");
3159 bzero(&(&ccb->ccb_h)[1],
3160 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3162 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
3164 if (user_settings == 0)
3165 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
3167 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
3169 if (cam_send_ccb(device, ccb) < 0) {
3170 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
3171 if (arglist & CAM_ARG_VERBOSE)
3172 cam_error_print(device, ccb, CAM_ESF_ALL,
3173 CAM_EPF_ALL, stderr);
3175 goto get_print_cts_bailout;
3178 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3179 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
3180 if (arglist & CAM_ARG_VERBOSE)
3181 cam_error_print(device, ccb, CAM_ESF_ALL,
3182 CAM_EPF_ALL, stderr);
3184 goto get_print_cts_bailout;
3188 cts_print(device, &ccb->cts);
3191 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
3193 get_print_cts_bailout:
3201 ratecontrol(struct cam_device *device, int retry_count, int timeout,
3202 int argc, char **argv, char *combinedopt)
3206 int user_settings = 0;
3208 int disc_enable = -1, tag_enable = -1;
3211 double syncrate = -1;
3214 int change_settings = 0, send_tur = 0;
3215 struct ccb_pathinq cpi;
3217 ccb = cam_getccb(device);
3219 warnx("ratecontrol: error allocating ccb");
3222 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3231 if (strncasecmp(optarg, "enable", 6) == 0)
3233 else if (strncasecmp(optarg, "disable", 7) == 0)
3236 warnx("-D argument \"%s\" is unknown", optarg);
3238 goto ratecontrol_bailout;
3240 change_settings = 1;
3243 mode = ata_string2mode(optarg);
3245 warnx("unknown mode '%s'", optarg);
3247 goto ratecontrol_bailout;
3249 change_settings = 1;
3252 offset = strtol(optarg, NULL, 0);
3254 warnx("offset value %d is < 0", offset);
3256 goto ratecontrol_bailout;
3258 change_settings = 1;
3264 syncrate = atof(optarg);
3266 warnx("sync rate %f is < 0", syncrate);
3268 goto ratecontrol_bailout;
3270 change_settings = 1;
3273 if (strncasecmp(optarg, "enable", 6) == 0)
3275 else if (strncasecmp(optarg, "disable", 7) == 0)
3278 warnx("-T argument \"%s\" is unknown", optarg);
3280 goto ratecontrol_bailout;
3282 change_settings = 1;
3288 bus_width = strtol(optarg, NULL, 0);
3289 if (bus_width < 0) {
3290 warnx("bus width %d is < 0", bus_width);
3292 goto ratecontrol_bailout;
3294 change_settings = 1;
3300 bzero(&(&ccb->ccb_h)[1],
3301 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3303 * Grab path inquiry information, so we can determine whether
3304 * or not the initiator is capable of the things that the user
3307 ccb->ccb_h.func_code = XPT_PATH_INQ;
3308 if (cam_send_ccb(device, ccb) < 0) {
3309 perror("error sending XPT_PATH_INQ CCB");
3310 if (arglist & CAM_ARG_VERBOSE) {
3311 cam_error_print(device, ccb, CAM_ESF_ALL,
3312 CAM_EPF_ALL, stderr);
3315 goto ratecontrol_bailout;
3317 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3318 warnx("XPT_PATH_INQ CCB failed");
3319 if (arglist & CAM_ARG_VERBOSE) {
3320 cam_error_print(device, ccb, CAM_ESF_ALL,
3321 CAM_EPF_ALL, stderr);
3324 goto ratecontrol_bailout;
3326 bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
3327 bzero(&(&ccb->ccb_h)[1],
3328 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3330 fprintf(stdout, "%s parameters:\n",
3331 user_settings ? "User" : "Current");
3333 retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
3335 goto ratecontrol_bailout;
3337 if (arglist & CAM_ARG_VERBOSE)
3340 if (change_settings) {
3341 int didsettings = 0;
3342 struct ccb_trans_settings_spi *spi = NULL;
3343 struct ccb_trans_settings_pata *pata = NULL;
3344 struct ccb_trans_settings_sata *sata = NULL;
3345 struct ccb_trans_settings_ata *ata = NULL;
3346 struct ccb_trans_settings_scsi *scsi = NULL;
3348 if (ccb->cts.transport == XPORT_SPI)
3349 spi = &ccb->cts.xport_specific.spi;
3350 if (ccb->cts.transport == XPORT_ATA)
3351 pata = &ccb->cts.xport_specific.ata;
3352 if (ccb->cts.transport == XPORT_SATA)
3353 sata = &ccb->cts.xport_specific.sata;
3354 if (ccb->cts.protocol == PROTO_ATA)
3355 ata = &ccb->cts.proto_specific.ata;
3356 if (ccb->cts.protocol == PROTO_SCSI)
3357 scsi = &ccb->cts.proto_specific.scsi;
3358 ccb->cts.xport_specific.valid = 0;
3359 ccb->cts.proto_specific.valid = 0;
3360 if (spi && disc_enable != -1) {
3361 spi->valid |= CTS_SPI_VALID_DISC;
3362 if (disc_enable == 0)
3363 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
3365 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
3368 if (tag_enable != -1) {
3369 if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
3370 warnx("HBA does not support tagged queueing, "
3371 "so you cannot modify tag settings");
3373 goto ratecontrol_bailout;
3376 ata->valid |= CTS_SCSI_VALID_TQ;
3377 if (tag_enable == 0)
3378 ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
3380 ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
3383 scsi->valid |= CTS_SCSI_VALID_TQ;
3384 if (tag_enable == 0)
3385 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
3387 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
3391 if (spi && offset != -1) {
3392 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3393 warnx("HBA is not capable of changing offset");
3395 goto ratecontrol_bailout;
3397 spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
3398 spi->sync_offset = offset;
3401 if (spi && syncrate != -1) {
3402 int prelim_sync_period;
3405 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3406 warnx("HBA is not capable of changing "
3409 goto ratecontrol_bailout;
3411 spi->valid |= CTS_SPI_VALID_SYNC_RATE;
3413 * The sync rate the user gives us is in MHz.
3414 * We need to translate it into KHz for this
3419 * Next, we calculate a "preliminary" sync period
3420 * in tenths of a nanosecond.
3423 prelim_sync_period = 0;
3425 prelim_sync_period = 10000000 / syncrate;
3427 scsi_calc_syncparam(prelim_sync_period);
3428 freq = scsi_calc_syncsrate(spi->sync_period);
3431 if (sata && syncrate != -1) {
3432 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3433 warnx("HBA is not capable of changing "
3436 goto ratecontrol_bailout;
3438 if (!user_settings) {
3439 warnx("You can modify only user rate "
3440 "settings for SATA");
3442 goto ratecontrol_bailout;
3444 sata->revision = ata_speed2revision(syncrate * 100);
3445 if (sata->revision < 0) {
3446 warnx("Invalid rate %f", syncrate);
3448 goto ratecontrol_bailout;
3450 sata->valid |= CTS_SATA_VALID_REVISION;
3453 if ((pata || sata) && mode != -1) {
3454 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3455 warnx("HBA is not capable of changing "
3458 goto ratecontrol_bailout;
3460 if (!user_settings) {
3461 warnx("You can modify only user mode "
3462 "settings for ATA/SATA");
3464 goto ratecontrol_bailout;
3468 pata->valid |= CTS_ATA_VALID_MODE;
3471 sata->valid |= CTS_SATA_VALID_MODE;
3476 * The bus_width argument goes like this:
3480 * Therefore, if you shift the number of bits given on the
3481 * command line right by 4, you should get the correct
3484 if (spi && bus_width != -1) {
3486 * We might as well validate things here with a
3487 * decipherable error message, rather than what
3488 * will probably be an indecipherable error message
3489 * by the time it gets back to us.
3491 if ((bus_width == 16)
3492 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
3493 warnx("HBA does not support 16 bit bus width");
3495 goto ratecontrol_bailout;
3496 } else if ((bus_width == 32)
3497 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
3498 warnx("HBA does not support 32 bit bus width");
3500 goto ratecontrol_bailout;
3501 } else if ((bus_width != 8)
3502 && (bus_width != 16)
3503 && (bus_width != 32)) {
3504 warnx("Invalid bus width %d", bus_width);
3506 goto ratecontrol_bailout;
3508 spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
3509 spi->bus_width = bus_width >> 4;
3512 if (didsettings == 0) {
3513 goto ratecontrol_bailout;
3515 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
3516 if (cam_send_ccb(device, ccb) < 0) {
3517 perror("error sending XPT_SET_TRAN_SETTINGS CCB");
3518 if (arglist & CAM_ARG_VERBOSE) {
3519 cam_error_print(device, ccb, CAM_ESF_ALL,
3520 CAM_EPF_ALL, stderr);
3523 goto ratecontrol_bailout;
3525 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3526 warnx("XPT_SET_TRANS_SETTINGS CCB failed");
3527 if (arglist & CAM_ARG_VERBOSE) {
3528 cam_error_print(device, ccb, CAM_ESF_ALL,
3529 CAM_EPF_ALL, stderr);
3532 goto ratecontrol_bailout;
3536 retval = testunitready(device, retry_count, timeout,
3537 (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
3539 * If the TUR didn't succeed, just bail.
3543 fprintf(stderr, "Test Unit Ready failed\n");
3544 goto ratecontrol_bailout;
3547 if ((change_settings || send_tur) && !quiet &&
3548 (ccb->cts.transport == XPORT_ATA ||
3549 ccb->cts.transport == XPORT_SATA || send_tur)) {
3550 fprintf(stdout, "New parameters:\n");
3551 retval = get_print_cts(device, user_settings, 0, NULL);
3554 ratecontrol_bailout:
3560 scsiformat(struct cam_device *device, int argc, char **argv,
3561 char *combinedopt, int retry_count, int timeout)
3565 int ycount = 0, quiet = 0;
3566 int error = 0, response = 0, retval = 0;
3567 int use_timeout = 10800 * 1000;
3569 struct format_defect_list_header fh;
3570 u_int8_t *data_ptr = NULL;
3571 u_int32_t dxfer_len = 0;
3573 int num_warnings = 0;
3576 ccb = cam_getccb(device);
3579 warnx("scsiformat: error allocating ccb");
3583 bzero(&(&ccb->ccb_h)[1],
3584 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3586 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3607 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
3608 "following device:\n");
3610 error = scsidoinquiry(device, argc, argv, combinedopt,
3611 retry_count, timeout);
3614 warnx("scsiformat: error sending inquiry");
3615 goto scsiformat_bailout;
3624 fprintf(stdout, "Are you SURE you want to do "
3627 if (fgets(str, sizeof(str), stdin) != NULL) {
3629 if (strncasecmp(str, "yes", 3) == 0)
3631 else if (strncasecmp(str, "no", 2) == 0)
3634 fprintf(stdout, "Please answer"
3635 " \"yes\" or \"no\"\n");
3638 } while (response == 0);
3640 if (response == -1) {
3642 goto scsiformat_bailout;
3647 use_timeout = timeout;
3650 fprintf(stdout, "Current format timeout is %d seconds\n",
3651 use_timeout / 1000);
3655 * If the user hasn't disabled questions and didn't specify a
3656 * timeout on the command line, ask them if they want the current
3660 && (timeout == 0)) {
3662 int new_timeout = 0;
3664 fprintf(stdout, "Enter new timeout in seconds or press\n"
3665 "return to keep the current timeout [%d] ",
3666 use_timeout / 1000);
3668 if (fgets(str, sizeof(str), stdin) != NULL) {
3670 new_timeout = atoi(str);
3673 if (new_timeout != 0) {
3674 use_timeout = new_timeout * 1000;
3675 fprintf(stdout, "Using new timeout value %d\n",
3676 use_timeout / 1000);
3681 * Keep this outside the if block below to silence any unused
3682 * variable warnings.
3684 bzero(&fh, sizeof(fh));
3687 * If we're in immediate mode, we've got to include the format
3690 if (immediate != 0) {
3691 fh.byte2 = FU_DLH_IMMED;
3692 data_ptr = (u_int8_t *)&fh;
3693 dxfer_len = sizeof(fh);
3694 byte2 = FU_FMT_DATA;
3695 } else if (quiet == 0) {
3696 fprintf(stdout, "Formatting...");
3700 scsi_format_unit(&ccb->csio,
3701 /* retries */ retry_count,
3703 /* tag_action */ MSG_SIMPLE_Q_TAG,
3706 /* data_ptr */ data_ptr,
3707 /* dxfer_len */ dxfer_len,
3708 /* sense_len */ SSD_FULL_SIZE,
3709 /* timeout */ use_timeout);
3711 /* Disable freezing the device queue */
3712 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3714 if (arglist & CAM_ARG_ERR_RECOVER)
3715 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3717 if (((retval = cam_send_ccb(device, ccb)) < 0)
3718 || ((immediate == 0)
3719 && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
3720 const char errstr[] = "error sending format command";
3727 if (arglist & CAM_ARG_VERBOSE) {
3728 cam_error_print(device, ccb, CAM_ESF_ALL,
3729 CAM_EPF_ALL, stderr);
3732 goto scsiformat_bailout;
3736 * If we ran in non-immediate mode, we already checked for errors
3737 * above and printed out any necessary information. If we're in
3738 * immediate mode, we need to loop through and get status
3739 * information periodically.
3741 if (immediate == 0) {
3743 fprintf(stdout, "Format Complete\n");
3745 goto scsiformat_bailout;
3752 bzero(&(&ccb->ccb_h)[1],
3753 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3756 * There's really no need to do error recovery or
3757 * retries here, since we're just going to sit in a
3758 * loop and wait for the device to finish formatting.
3760 scsi_test_unit_ready(&ccb->csio,
3763 /* tag_action */ MSG_SIMPLE_Q_TAG,
3764 /* sense_len */ SSD_FULL_SIZE,
3765 /* timeout */ 5000);
3767 /* Disable freezing the device queue */
3768 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3770 retval = cam_send_ccb(device, ccb);
3773 * If we get an error from the ioctl, bail out. SCSI
3774 * errors are expected.
3777 warn("error sending CAMIOCOMMAND ioctl");
3778 if (arglist & CAM_ARG_VERBOSE) {
3779 cam_error_print(device, ccb, CAM_ESF_ALL,
3780 CAM_EPF_ALL, stderr);
3783 goto scsiformat_bailout;
3786 status = ccb->ccb_h.status & CAM_STATUS_MASK;
3788 if ((status != CAM_REQ_CMP)
3789 && (status == CAM_SCSI_STATUS_ERROR)
3790 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3791 struct scsi_sense_data *sense;
3792 int error_code, sense_key, asc, ascq;
3794 sense = &ccb->csio.sense_data;
3795 scsi_extract_sense(sense, &error_code, &sense_key,
3799 * According to the SCSI-2 and SCSI-3 specs, a
3800 * drive that is in the middle of a format should
3801 * return NOT READY with an ASC of "logical unit
3802 * not ready, format in progress". The sense key
3803 * specific bytes will then be a progress indicator.
3805 if ((sense_key == SSD_KEY_NOT_READY)
3806 && (asc == 0x04) && (ascq == 0x04)) {
3807 if ((sense->extra_len >= 10)
3808 && ((sense->sense_key_spec[0] &
3809 SSD_SCS_VALID) != 0)
3812 u_int64_t percentage;
3815 &sense->sense_key_spec[1]);
3816 percentage = 10000 * val;
3819 "\rFormatting: %ju.%02u %% "
3821 (uintmax_t)(percentage /
3823 (unsigned)((percentage /
3827 } else if ((quiet == 0)
3828 && (++num_warnings <= 1)) {
3829 warnx("Unexpected SCSI Sense Key "
3830 "Specific value returned "
3832 scsi_sense_print(device, &ccb->csio,
3834 warnx("Unable to print status "
3835 "information, but format will "
3837 warnx("will exit when format is "
3842 warnx("Unexpected SCSI error during format");
3843 cam_error_print(device, ccb, CAM_ESF_ALL,
3844 CAM_EPF_ALL, stderr);
3846 goto scsiformat_bailout;
3849 } else if (status != CAM_REQ_CMP) {
3850 warnx("Unexpected CAM status %#x", status);
3851 if (arglist & CAM_ARG_VERBOSE)
3852 cam_error_print(device, ccb, CAM_ESF_ALL,
3853 CAM_EPF_ALL, stderr);
3855 goto scsiformat_bailout;
3858 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
3861 fprintf(stdout, "\nFormat Complete\n");
3871 scsireportluns(struct cam_device *device, int argc, char **argv,
3872 char *combinedopt, int retry_count, int timeout)
3875 int c, countonly, lunsonly;
3876 struct scsi_report_luns_data *lundata;
3878 uint8_t report_type;
3879 uint32_t list_len, i, j;
3884 report_type = RPL_REPORT_DEFAULT;
3885 ccb = cam_getccb(device);
3888 warnx("%s: error allocating ccb", __func__);
3892 bzero(&(&ccb->ccb_h)[1],
3893 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3898 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3907 if (strcasecmp(optarg, "default") == 0)
3908 report_type = RPL_REPORT_DEFAULT;
3909 else if (strcasecmp(optarg, "wellknown") == 0)
3910 report_type = RPL_REPORT_WELLKNOWN;
3911 else if (strcasecmp(optarg, "all") == 0)
3912 report_type = RPL_REPORT_ALL;
3914 warnx("%s: invalid report type \"%s\"",
3925 if ((countonly != 0)
3926 && (lunsonly != 0)) {
3927 warnx("%s: you can only specify one of -c or -l", __func__);
3932 * According to SPC-4, the allocation length must be at least 16
3933 * bytes -- enough for the header and one LUN.
3935 alloc_len = sizeof(*lundata) + 8;
3939 lundata = malloc(alloc_len);
3941 if (lundata == NULL) {
3942 warn("%s: error mallocing %d bytes", __func__, alloc_len);
3947 scsi_report_luns(&ccb->csio,
3948 /*retries*/ retry_count,
3950 /*tag_action*/ MSG_SIMPLE_Q_TAG,
3951 /*select_report*/ report_type,
3952 /*rpl_buf*/ lundata,
3953 /*alloc_len*/ alloc_len,
3954 /*sense_len*/ SSD_FULL_SIZE,
3955 /*timeout*/ timeout ? timeout : 5000);
3957 /* Disable freezing the device queue */
3958 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3960 if (arglist & CAM_ARG_ERR_RECOVER)
3961 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3963 if (cam_send_ccb(device, ccb) < 0) {
3964 warn("error sending REPORT LUNS command");
3966 if (arglist & CAM_ARG_VERBOSE)
3967 cam_error_print(device, ccb, CAM_ESF_ALL,
3968 CAM_EPF_ALL, stderr);
3974 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3975 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
3981 list_len = scsi_4btoul(lundata->length);
3984 * If we need to list the LUNs, and our allocation
3985 * length was too short, reallocate and retry.
3987 if ((countonly == 0)
3988 && (list_len > (alloc_len - sizeof(*lundata)))) {
3989 alloc_len = list_len + sizeof(*lundata);
3995 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
3996 ((list_len / 8) > 1) ? "s" : "");
4001 for (i = 0; i < (list_len / 8); i++) {
4005 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
4007 fprintf(stdout, ",");
4008 switch (lundata->luns[i].lundata[j] &
4009 RPL_LUNDATA_ATYP_MASK) {
4010 case RPL_LUNDATA_ATYP_PERIPH:
4011 if ((lundata->luns[i].lundata[j] &
4012 RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
4013 fprintf(stdout, "%d:",
4014 lundata->luns[i].lundata[j] &
4015 RPL_LUNDATA_PERIPH_BUS_MASK);
4017 && ((lundata->luns[i].lundata[j+2] &
4018 RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
4021 fprintf(stdout, "%d",
4022 lundata->luns[i].lundata[j+1]);
4024 case RPL_LUNDATA_ATYP_FLAT: {
4026 tmplun[0] = lundata->luns[i].lundata[j] &
4027 RPL_LUNDATA_FLAT_LUN_MASK;
4028 tmplun[1] = lundata->luns[i].lundata[j+1];
4030 fprintf(stdout, "%d", scsi_2btoul(tmplun));
4034 case RPL_LUNDATA_ATYP_LUN:
4035 fprintf(stdout, "%d:%d:%d",
4036 (lundata->luns[i].lundata[j+1] &
4037 RPL_LUNDATA_LUN_BUS_MASK) >> 5,
4038 lundata->luns[i].lundata[j] &
4039 RPL_LUNDATA_LUN_TARG_MASK,
4040 lundata->luns[i].lundata[j+1] &
4041 RPL_LUNDATA_LUN_LUN_MASK);
4043 case RPL_LUNDATA_ATYP_EXTLUN: {
4044 int field_len, field_len_code, eam_code;
4046 eam_code = lundata->luns[i].lundata[j] &
4047 RPL_LUNDATA_EXT_EAM_MASK;
4048 field_len_code = (lundata->luns[i].lundata[j] &
4049 RPL_LUNDATA_EXT_LEN_MASK) >> 4;
4050 field_len = field_len_code * 2;
4052 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
4053 && (field_len_code == 0x00)) {
4054 fprintf(stdout, "%d",
4055 lundata->luns[i].lundata[j+1]);
4056 } else if ((eam_code ==
4057 RPL_LUNDATA_EXT_EAM_NOT_SPEC)
4058 && (field_len_code == 0x03)) {
4062 * This format takes up all 8 bytes.
4063 * If we aren't starting at offset 0,
4067 fprintf(stdout, "Invalid "
4070 "specified format", j);
4074 bzero(tmp_lun, sizeof(tmp_lun));
4075 bcopy(&lundata->luns[i].lundata[j+1],
4076 &tmp_lun[1], sizeof(tmp_lun) - 1);
4077 fprintf(stdout, "%#jx",
4078 (intmax_t)scsi_8btou64(tmp_lun));
4081 fprintf(stderr, "Unknown Extended LUN"
4082 "Address method %#x, length "
4083 "code %#x", eam_code,
4090 fprintf(stderr, "Unknown LUN address method "
4091 "%#x\n", lundata->luns[i].lundata[0] &
4092 RPL_LUNDATA_ATYP_MASK);
4096 * For the flat addressing method, there are no
4097 * other levels after it.
4102 fprintf(stdout, "\n");
4115 scsireadcapacity(struct cam_device *device, int argc, char **argv,
4116 char *combinedopt, int retry_count, int timeout)
4119 int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
4120 struct scsi_read_capacity_data rcap;
4121 struct scsi_read_capacity_data_long rcaplong;
4135 ccb = cam_getccb(device);
4138 warnx("%s: error allocating ccb", __func__);
4142 bzero(&(&ccb->ccb_h)[1],
4143 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4145 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4172 if ((blocksizeonly != 0)
4173 && (numblocks != 0)) {
4174 warnx("%s: you can only specify one of -b or -N", __func__);
4179 if ((blocksizeonly != 0)
4180 && (sizeonly != 0)) {
4181 warnx("%s: you can only specify one of -b or -s", __func__);
4188 warnx("%s: you can only specify one of -h/-H or -q", __func__);
4194 && (blocksizeonly != 0)) {
4195 warnx("%s: you can only specify one of -h/-H or -b", __func__);
4200 scsi_read_capacity(&ccb->csio,
4201 /*retries*/ retry_count,
4203 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4206 /*timeout*/ timeout ? timeout : 5000);
4208 /* Disable freezing the device queue */
4209 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4211 if (arglist & CAM_ARG_ERR_RECOVER)
4212 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4214 if (cam_send_ccb(device, ccb) < 0) {
4215 warn("error sending READ CAPACITY command");
4217 if (arglist & CAM_ARG_VERBOSE)
4218 cam_error_print(device, ccb, CAM_ESF_ALL,
4219 CAM_EPF_ALL, stderr);
4225 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4226 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4231 maxsector = scsi_4btoul(rcap.addr);
4232 block_len = scsi_4btoul(rcap.length);
4235 * A last block of 2^32-1 means that the true capacity is over 2TB,
4236 * and we need to issue the long READ CAPACITY to get the real
4237 * capacity. Otherwise, we're all set.
4239 if (maxsector != 0xffffffff)
4242 scsi_read_capacity_16(&ccb->csio,
4243 /*retries*/ retry_count,
4245 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4250 /*sense_len*/ SSD_FULL_SIZE,
4251 /*timeout*/ timeout ? timeout : 5000);
4253 /* Disable freezing the device queue */
4254 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4256 if (arglist & CAM_ARG_ERR_RECOVER)
4257 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4259 if (cam_send_ccb(device, ccb) < 0) {
4260 warn("error sending READ CAPACITY (16) command");
4262 if (arglist & CAM_ARG_VERBOSE)
4263 cam_error_print(device, ccb, CAM_ESF_ALL,
4264 CAM_EPF_ALL, stderr);
4270 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4271 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4276 maxsector = scsi_8btou64(rcaplong.addr);
4277 block_len = scsi_4btoul(rcaplong.length);
4280 if (blocksizeonly == 0) {
4282 * Humanize implies !quiet, and also implies numblocks.
4284 if (humanize != 0) {
4289 tmpbytes = (maxsector + 1) * block_len;
4290 ret = humanize_number(tmpstr, sizeof(tmpstr),
4291 tmpbytes, "", HN_AUTOSCALE,
4294 HN_DIVISOR_1000 : 0));
4296 warnx("%s: humanize_number failed!", __func__);
4300 fprintf(stdout, "Device Size: %s%s", tmpstr,
4301 (sizeonly == 0) ? ", " : "\n");
4302 } else if (numblocks != 0) {
4303 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4304 "Blocks: " : "", (uintmax_t)maxsector + 1,
4305 (sizeonly == 0) ? ", " : "\n");
4307 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4308 "Last Block: " : "", (uintmax_t)maxsector,
4309 (sizeonly == 0) ? ", " : "\n");
4313 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
4314 "Block Length: " : "", block_len, (quiet == 0) ?
4323 atapm(struct cam_device *device, int argc, char **argv,
4324 char *combinedopt, int retry_count, int timeout)
4332 ccb = cam_getccb(device);
4335 warnx("%s: error allocating ccb", __func__);
4339 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4348 if (strcmp(argv[1], "idle") == 0) {
4350 cmd = ATA_IDLE_IMMEDIATE;
4353 } else if (strcmp(argv[1], "standby") == 0) {
4355 cmd = ATA_STANDBY_IMMEDIATE;
4357 cmd = ATA_STANDBY_CMD;
4365 else if (t <= (240 * 5))
4367 else if (t <= (252 * 5))
4368 /* special encoding for 21 minutes */
4370 else if (t <= (11 * 30 * 60))
4371 sc = (t - 1) / (30 * 60) + 241;
4375 cam_fill_ataio(&ccb->ataio,
4378 /*flags*/CAM_DIR_NONE,
4382 timeout ? timeout : 30 * 1000);
4383 ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
4385 /* Disable freezing the device queue */
4386 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4388 if (arglist & CAM_ARG_ERR_RECOVER)
4389 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4391 if (cam_send_ccb(device, ccb) < 0) {
4392 warn("error sending command");
4394 if (arglist & CAM_ARG_VERBOSE)
4395 cam_error_print(device, ccb, CAM_ESF_ALL,
4396 CAM_EPF_ALL, stderr);
4402 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4403 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4412 #endif /* MINIMALISTIC */
4417 fprintf(verbose ? stdout : stderr,
4418 "usage: camcontrol <command> [device id][generic args][command args]\n"
4419 " camcontrol devlist [-v]\n"
4420 #ifndef MINIMALISTIC
4421 " camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
4422 " camcontrol tur [dev_id][generic args]\n"
4423 " camcontrol inquiry [dev_id][generic args] [-D] [-S] [-R]\n"
4424 " camcontrol identify [dev_id][generic args] [-v]\n"
4425 " camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
4426 " camcontrol readcap [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
4428 " camcontrol start [dev_id][generic args]\n"
4429 " camcontrol stop [dev_id][generic args]\n"
4430 " camcontrol load [dev_id][generic args]\n"
4431 " camcontrol eject [dev_id][generic args]\n"
4432 #endif /* MINIMALISTIC */
4433 " camcontrol rescan <all | bus[:target:lun]>\n"
4434 " camcontrol reset <all | bus[:target:lun]>\n"
4435 #ifndef MINIMALISTIC
4436 " camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n"
4437 " camcontrol modepage [dev_id][generic args] <-m page | -l>\n"
4438 " [-P pagectl][-e | -b][-d]\n"
4439 " camcontrol cmd [dev_id][generic args]\n"
4440 " <-a cmd [args] | -c cmd [args]>\n"
4441 " [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
4442 " camcontrol debug [-I][-P][-T][-S][-X][-c]\n"
4443 " <all|bus[:target[:lun]]|off>\n"
4444 " camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n"
4445 " camcontrol negotiate [dev_id][generic args] [-a][-c]\n"
4446 " [-D <enable|disable>][-M mode][-O offset]\n"
4447 " [-q][-R syncrate][-v][-T <enable|disable>]\n"
4448 " [-U][-W bus_width]\n"
4449 " camcontrol format [dev_id][generic args][-q][-r][-w][-y]\n"
4450 " camcontrol idle [dev_id][generic args][-t time]\n"
4451 " camcontrol standby [dev_id][generic args][-t time]\n"
4452 " camcontrol sleep [dev_id][generic args]\n"
4453 #endif /* MINIMALISTIC */
4454 " camcontrol help\n");
4457 #ifndef MINIMALISTIC
4459 "Specify one of the following options:\n"
4460 "devlist list all CAM devices\n"
4461 "periphlist list all CAM peripheral drivers attached to a device\n"
4462 "tur send a test unit ready to the named device\n"
4463 "inquiry send a SCSI inquiry command to the named device\n"
4464 "identify send a ATA identify command to the named device\n"
4465 "reportluns send a SCSI report luns command to the device\n"
4466 "readcap send a SCSI read capacity command to the device\n"
4467 "start send a Start Unit command to the device\n"
4468 "stop send a Stop Unit command to the device\n"
4469 "load send a Start Unit command to the device with the load bit set\n"
4470 "eject send a Stop Unit command to the device with the eject bit set\n"
4471 "rescan rescan all busses, the given bus, or bus:target:lun\n"
4472 "reset reset all busses, the given bus, or bus:target:lun\n"
4473 "defects read the defect list of the specified device\n"
4474 "modepage display or edit (-e) the given mode page\n"
4475 "cmd send the given scsi command, may need -i or -o as well\n"
4476 "debug turn debugging on/off for a bus, target, or lun, or all devices\n"
4477 "tags report or set the number of transaction slots for a device\n"
4478 "negotiate report or set device negotiation parameters\n"
4479 "format send the SCSI FORMAT UNIT command to the named device\n"
4480 "idle send the ATA IDLE command to the named device\n"
4481 "standby send the ATA STANDBY command to the named device\n"
4482 "sleep send the ATA SLEEP command to the named device\n"
4483 "help this message\n"
4484 "Device Identifiers:\n"
4485 "bus:target specify the bus and target, lun defaults to 0\n"
4486 "bus:target:lun specify the bus, target and lun\n"
4487 "deviceUNIT specify the device name, like \"da4\" or \"cd2\"\n"
4488 "Generic arguments:\n"
4489 "-v be verbose, print out sense information\n"
4490 "-t timeout command timeout in seconds, overrides default timeout\n"
4491 "-n dev_name specify device name, e.g. \"da\", \"cd\"\n"
4492 "-u unit specify unit number, e.g. \"0\", \"5\"\n"
4493 "-E have the kernel attempt to perform SCSI error recovery\n"
4494 "-C count specify the SCSI command retry count (needs -E to work)\n"
4495 "modepage arguments:\n"
4496 "-l list all available mode pages\n"
4497 "-m page specify the mode page to view or edit\n"
4498 "-e edit the specified mode page\n"
4499 "-b force view to binary mode\n"
4500 "-d disable block descriptors for mode sense\n"
4501 "-P pgctl page control field 0-3\n"
4502 "defects arguments:\n"
4503 "-f format specify defect list format (block, bfi or phys)\n"
4504 "-G get the grown defect list\n"
4505 "-P get the permanant defect list\n"
4506 "inquiry arguments:\n"
4507 "-D get the standard inquiry data\n"
4508 "-S get the serial number\n"
4509 "-R get the transfer rate, etc.\n"
4510 "reportluns arguments:\n"
4511 "-c only report a count of available LUNs\n"
4512 "-l only print out luns, and not a count\n"
4513 "-r <reporttype> specify \"default\", \"wellknown\" or \"all\"\n"
4514 "readcap arguments\n"
4515 "-b only report the blocksize\n"
4516 "-h human readable device size, base 2\n"
4517 "-H human readable device size, base 10\n"
4518 "-N print the number of blocks instead of last block\n"
4519 "-q quiet, print numbers only\n"
4520 "-s only report the last block/device size\n"
4522 "-c cdb [args] specify the SCSI CDB\n"
4523 "-i len fmt specify input data and input data format\n"
4524 "-o len fmt [args] specify output data and output data fmt\n"
4525 "debug arguments:\n"
4526 "-I CAM_DEBUG_INFO -- scsi commands, errors, data\n"
4527 "-T CAM_DEBUG_TRACE -- routine flow tracking\n"
4528 "-S CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
4529 "-c CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
4531 "-N tags specify the number of tags to use for this device\n"
4532 "-q be quiet, don't report the number of tags\n"
4533 "-v report a number of tag-related parameters\n"
4534 "negotiate arguments:\n"
4535 "-a send a test unit ready after negotiation\n"
4536 "-c report/set current negotiation settings\n"
4537 "-D <arg> \"enable\" or \"disable\" disconnection\n"
4538 "-M mode set ATA mode\n"
4539 "-O offset set command delay offset\n"
4540 "-q be quiet, don't report anything\n"
4541 "-R syncrate synchronization rate in MHz\n"
4542 "-T <arg> \"enable\" or \"disable\" tagged queueing\n"
4543 "-U report/set user negotiation settings\n"
4544 "-W bus_width set the bus width in bits (8, 16 or 32)\n"
4545 "-v also print a Path Inquiry CCB for the controller\n"
4546 "format arguments:\n"
4547 "-q be quiet, don't print status messages\n"
4548 "-r run in report only mode\n"
4549 "-w don't send immediate format command\n"
4550 "-y don't ask any questions\n"
4551 "idle/standby arguments:\n"
4552 "-t <arg> number of seconds before respective state.\n");
4553 #endif /* MINIMALISTIC */
4557 main(int argc, char **argv)
4560 char *device = NULL;
4562 struct cam_device *cam_dev = NULL;
4563 int timeout = 0, retry_count = 1;
4564 camcontrol_optret optreturn;
4566 const char *mainopt = "C:En:t:u:v";
4567 const char *subopt = NULL;
4568 char combinedopt[256];
4569 int error = 0, optstart = 2;
4571 #ifndef MINIMALISTIC
4572 int bus, target, lun;
4573 #endif /* MINIMALISTIC */
4575 cmdlist = CAM_CMD_NONE;
4576 arglist = CAM_ARG_NONE;
4584 * Get the base option.
4586 optreturn = getoption(argv[1], &cmdlist, &arglist, &subopt);
4588 if (optreturn == CC_OR_AMBIGUOUS) {
4589 warnx("ambiguous option %s", argv[1]);
4592 } else if (optreturn == CC_OR_NOT_FOUND) {
4593 warnx("option %s not found", argv[1]);
4599 * Ahh, getopt(3) is a pain.
4601 * This is a gross hack. There really aren't many other good
4602 * options (excuse the pun) for parsing options in a situation like
4603 * this. getopt is kinda braindead, so you end up having to run
4604 * through the options twice, and give each invocation of getopt
4605 * the option string for the other invocation.
4607 * You would think that you could just have two groups of options.
4608 * The first group would get parsed by the first invocation of
4609 * getopt, and the second group would get parsed by the second
4610 * invocation of getopt. It doesn't quite work out that way. When
4611 * the first invocation of getopt finishes, it leaves optind pointing
4612 * to the argument _after_ the first argument in the second group.
4613 * So when the second invocation of getopt comes around, it doesn't
4614 * recognize the first argument it gets and then bails out.
4616 * A nice alternative would be to have a flag for getopt that says
4617 * "just keep parsing arguments even when you encounter an unknown
4618 * argument", but there isn't one. So there's no real clean way to
4619 * easily parse two sets of arguments without having one invocation
4620 * of getopt know about the other.
4622 * Without this hack, the first invocation of getopt would work as
4623 * long as the generic arguments are first, but the second invocation
4624 * (in the subfunction) would fail in one of two ways. In the case
4625 * where you don't set optreset, it would fail because optind may be
4626 * pointing to the argument after the one it should be pointing at.
4627 * In the case where you do set optreset, and reset optind, it would
4628 * fail because getopt would run into the first set of options, which
4629 * it doesn't understand.
4631 * All of this would "sort of" work if you could somehow figure out
4632 * whether optind had been incremented one option too far. The
4633 * mechanics of that, however, are more daunting than just giving
4634 * both invocations all of the expect options for either invocation.
4636 * Needless to say, I wouldn't mind if someone invented a better
4637 * (non-GPL!) command line parsing interface than getopt. I
4638 * wouldn't mind if someone added more knobs to getopt to make it
4639 * work better. Who knows, I may talk myself into doing it someday,
4640 * if the standards weenies let me. As it is, it just leads to
4641 * hackery like this and causes people to avoid it in some cases.
4643 * KDM, September 8th, 1998
4646 sprintf(combinedopt, "%s%s", mainopt, subopt);
4648 sprintf(combinedopt, "%s", mainopt);
4651 * For these options we do not parse optional device arguments and
4652 * we do not open a passthrough device.
4654 if ((cmdlist == CAM_CMD_RESCAN)
4655 || (cmdlist == CAM_CMD_RESET)
4656 || (cmdlist == CAM_CMD_DEVTREE)
4657 || (cmdlist == CAM_CMD_USAGE)
4658 || (cmdlist == CAM_CMD_DEBUG))
4661 #ifndef MINIMALISTIC
4663 && (argc > 2 && argv[2][0] != '-')) {
4667 if (isdigit(argv[2][0])) {
4668 /* device specified as bus:target[:lun] */
4669 rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
4671 errx(1, "numeric device specification must "
4672 "be either bus:target, or "
4674 /* default to 0 if lun was not specified */
4675 if ((arglist & CAM_ARG_LUN) == 0) {
4677 arglist |= CAM_ARG_LUN;
4681 if (cam_get_device(argv[2], name, sizeof name, &unit)
4683 errx(1, "%s", cam_errbuf);
4684 device = strdup(name);
4685 arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
4689 #endif /* MINIMALISTIC */
4691 * Start getopt processing at argv[2/3], since we've already
4692 * accepted argv[1..2] as the command name, and as a possible
4698 * Now we run through the argument list looking for generic
4699 * options, and ignoring options that possibly belong to
4702 while ((c = getopt(argc, argv, combinedopt))!= -1){
4705 retry_count = strtol(optarg, NULL, 0);
4706 if (retry_count < 0)
4707 errx(1, "retry count %d is < 0",
4709 arglist |= CAM_ARG_RETRIES;
4712 arglist |= CAM_ARG_ERR_RECOVER;
4715 arglist |= CAM_ARG_DEVICE;
4717 while (isspace(*tstr) && (*tstr != '\0'))
4719 device = (char *)strdup(tstr);
4722 timeout = strtol(optarg, NULL, 0);
4724 errx(1, "invalid timeout %d", timeout);
4725 /* Convert the timeout from seconds to ms */
4727 arglist |= CAM_ARG_TIMEOUT;
4730 arglist |= CAM_ARG_UNIT;
4731 unit = strtol(optarg, NULL, 0);
4734 arglist |= CAM_ARG_VERBOSE;
4741 #ifndef MINIMALISTIC
4743 * For most commands we'll want to open the passthrough device
4744 * associated with the specified device. In the case of the rescan
4745 * commands, we don't use a passthrough device at all, just the
4746 * transport layer device.
4749 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
4750 && (((arglist & CAM_ARG_DEVICE) == 0)
4751 || ((arglist & CAM_ARG_UNIT) == 0))) {
4752 errx(1, "subcommand \"%s\" requires a valid device "
4753 "identifier", argv[1]);
4756 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
4757 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
4758 cam_open_spec_device(device,unit,O_RDWR,NULL)))
4760 errx(1,"%s", cam_errbuf);
4762 #endif /* MINIMALISTIC */
4765 * Reset optind to 2, and reset getopt, so these routines can parse
4766 * the arguments again.
4772 #ifndef MINIMALISTIC
4773 case CAM_CMD_DEVLIST:
4774 error = getdevlist(cam_dev);
4776 #endif /* MINIMALISTIC */
4777 case CAM_CMD_DEVTREE:
4778 error = getdevtree();
4780 #ifndef MINIMALISTIC
4782 error = testunitready(cam_dev, retry_count, timeout, 0);
4784 case CAM_CMD_INQUIRY:
4785 error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
4786 retry_count, timeout);
4788 case CAM_CMD_IDENTIFY:
4789 error = ataidentify(cam_dev, retry_count, timeout);
4791 case CAM_CMD_STARTSTOP:
4792 error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
4793 arglist & CAM_ARG_EJECT, retry_count,
4796 #endif /* MINIMALISTIC */
4797 case CAM_CMD_RESCAN:
4798 error = dorescan_or_reset(argc, argv, 1);
4801 error = dorescan_or_reset(argc, argv, 0);
4803 #ifndef MINIMALISTIC
4804 case CAM_CMD_READ_DEFECTS:
4805 error = readdefects(cam_dev, argc, argv, combinedopt,
4806 retry_count, timeout);
4808 case CAM_CMD_MODE_PAGE:
4809 modepage(cam_dev, argc, argv, combinedopt,
4810 retry_count, timeout);
4812 case CAM_CMD_SCSI_CMD:
4813 error = scsicmd(cam_dev, argc, argv, combinedopt,
4814 retry_count, timeout);
4817 error = camdebug(argc, argv, combinedopt);
4820 error = tagcontrol(cam_dev, argc, argv, combinedopt);
4823 error = ratecontrol(cam_dev, retry_count, timeout,
4824 argc, argv, combinedopt);
4826 case CAM_CMD_FORMAT:
4827 error = scsiformat(cam_dev, argc, argv,
4828 combinedopt, retry_count, timeout);
4830 case CAM_CMD_REPORTLUNS:
4831 error = scsireportluns(cam_dev, argc, argv,
4832 combinedopt, retry_count,
4835 case CAM_CMD_READCAP:
4836 error = scsireadcapacity(cam_dev, argc, argv,
4837 combinedopt, retry_count,
4841 case CAM_CMD_STANDBY:
4843 error = atapm(cam_dev, argc, argv,
4844 combinedopt, retry_count,
4847 #endif /* MINIMALISTIC */
4857 if (cam_dev != NULL)
4858 cam_close_device(cam_dev);