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>
50 #include <cam/cam_debug.h>
51 #include <cam/cam_ccb.h>
52 #include <cam/scsi/scsi_all.h>
53 #include <cam/scsi/scsi_da.h>
54 #include <cam/scsi/scsi_pass.h>
55 #include <cam/scsi/scsi_message.h>
56 #include <cam/scsi/smp_all.h>
57 #include <cam/ata/ata_all.h>
59 #include "camcontrol.h"
62 CAM_CMD_NONE = 0x00000000,
63 CAM_CMD_DEVLIST = 0x00000001,
64 CAM_CMD_TUR = 0x00000002,
65 CAM_CMD_INQUIRY = 0x00000003,
66 CAM_CMD_STARTSTOP = 0x00000004,
67 CAM_CMD_RESCAN = 0x00000005,
68 CAM_CMD_READ_DEFECTS = 0x00000006,
69 CAM_CMD_MODE_PAGE = 0x00000007,
70 CAM_CMD_SCSI_CMD = 0x00000008,
71 CAM_CMD_DEVTREE = 0x00000009,
72 CAM_CMD_USAGE = 0x0000000a,
73 CAM_CMD_DEBUG = 0x0000000b,
74 CAM_CMD_RESET = 0x0000000c,
75 CAM_CMD_FORMAT = 0x0000000d,
76 CAM_CMD_TAG = 0x0000000e,
77 CAM_CMD_RATE = 0x0000000f,
78 CAM_CMD_DETACH = 0x00000010,
79 CAM_CMD_REPORTLUNS = 0x00000011,
80 CAM_CMD_READCAP = 0x00000012,
81 CAM_CMD_IDENTIFY = 0x00000013,
82 CAM_CMD_IDLE = 0x00000014,
83 CAM_CMD_STANDBY = 0x00000015,
84 CAM_CMD_SLEEP = 0x00000016,
85 CAM_CMD_SMP_CMD = 0x00000017,
86 CAM_CMD_SMP_RG = 0x00000018,
87 CAM_CMD_SMP_PC = 0x00000019,
88 CAM_CMD_SMP_PHYLIST = 0x0000001a,
89 CAM_CMD_SMP_MANINFO = 0x0000001b
93 CAM_ARG_NONE = 0x00000000,
94 CAM_ARG_VERBOSE = 0x00000001,
95 CAM_ARG_DEVICE = 0x00000002,
96 CAM_ARG_BUS = 0x00000004,
97 CAM_ARG_TARGET = 0x00000008,
98 CAM_ARG_LUN = 0x00000010,
99 CAM_ARG_EJECT = 0x00000020,
100 CAM_ARG_UNIT = 0x00000040,
101 CAM_ARG_FORMAT_BLOCK = 0x00000080,
102 CAM_ARG_FORMAT_BFI = 0x00000100,
103 CAM_ARG_FORMAT_PHYS = 0x00000200,
104 CAM_ARG_PLIST = 0x00000400,
105 CAM_ARG_GLIST = 0x00000800,
106 CAM_ARG_GET_SERIAL = 0x00001000,
107 CAM_ARG_GET_STDINQ = 0x00002000,
108 CAM_ARG_GET_XFERRATE = 0x00004000,
109 CAM_ARG_INQ_MASK = 0x00007000,
110 CAM_ARG_MODE_EDIT = 0x00008000,
111 CAM_ARG_PAGE_CNTL = 0x00010000,
112 CAM_ARG_TIMEOUT = 0x00020000,
113 CAM_ARG_CMD_IN = 0x00040000,
114 CAM_ARG_CMD_OUT = 0x00080000,
115 CAM_ARG_DBD = 0x00100000,
116 CAM_ARG_ERR_RECOVER = 0x00200000,
117 CAM_ARG_RETRIES = 0x00400000,
118 CAM_ARG_START_UNIT = 0x00800000,
119 CAM_ARG_DEBUG_INFO = 0x01000000,
120 CAM_ARG_DEBUG_TRACE = 0x02000000,
121 CAM_ARG_DEBUG_SUBTRACE = 0x04000000,
122 CAM_ARG_DEBUG_CDB = 0x08000000,
123 CAM_ARG_DEBUG_XPT = 0x10000000,
124 CAM_ARG_DEBUG_PERIPH = 0x20000000,
127 struct camcontrol_opts {
135 static const char scsicmd_opts[] = "a:c:dfi:o:r";
136 static const char readdefect_opts[] = "f:GP";
137 static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
138 static const char smprg_opts[] = "l";
139 static const char smppc_opts[] = "a:A:d:lm:M:o:p:s:S:T:";
140 static const char smpphylist_opts[] = "lq";
143 struct camcontrol_opts option_table[] = {
145 {"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
146 {"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
147 {"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
148 {"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
149 {"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
150 {"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
151 {"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
152 {"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
153 {"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"},
154 #endif /* MINIMALISTIC */
155 {"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
156 {"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
158 {"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
159 {"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
160 {"smpcmd", CAM_CMD_SMP_CMD, CAM_ARG_NONE, "r:R:"},
161 {"smprg", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
162 {"smpreportgeneral", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
163 {"smppc", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
164 {"smpphycontrol", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
165 {"smpplist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
166 {"smpphylist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
167 {"smpmaninfo", CAM_CMD_SMP_MANINFO, CAM_ARG_NONE, "l"},
168 {"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
169 {"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
170 #endif /* MINIMALISTIC */
171 {"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, NULL},
173 {"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
174 {"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
175 {"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
176 {"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
177 {"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
178 {"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXc"},
179 {"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
180 {"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"},
181 {"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"},
182 {"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""},
183 #endif /* MINIMALISTIC */
184 {"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
185 {"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
186 {"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
197 struct device_match_result dev_match;
199 struct periph_match_result *periph_matches;
200 struct scsi_vpd_device_id *device_id;
202 STAILQ_ENTRY(cam_devitem) links;
206 STAILQ_HEAD(, cam_devitem) dev_queue;
213 camcontrol_optret getoption(struct camcontrol_opts *table, char *arg,
214 uint32_t *cmdnum, cam_argmask *argnum,
215 const char **subopt);
217 static int getdevlist(struct cam_device *device);
218 #endif /* MINIMALISTIC */
219 static int getdevtree(void);
221 static int testunitready(struct cam_device *device, int retry_count,
222 int timeout, int quiet);
223 static int scsistart(struct cam_device *device, int startstop, int loadeject,
224 int retry_count, int timeout);
225 static int scsidoinquiry(struct cam_device *device, int argc, char **argv,
226 char *combinedopt, int retry_count, int timeout);
227 static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
228 static int scsiserial(struct cam_device *device, int retry_count, int timeout);
229 static int camxferrate(struct cam_device *device);
230 #endif /* MINIMALISTIC */
231 static int parse_btl(char *tstr, int *bus, int *target, int *lun,
232 cam_argmask *arglst);
233 static int dorescan_or_reset(int argc, char **argv, int rescan);
234 static int rescan_or_reset_bus(int bus, int rescan);
235 static int scanlun_or_reset_dev(int bus, int target, int lun, int scan);
237 static int readdefects(struct cam_device *device, int argc, char **argv,
238 char *combinedopt, int retry_count, int timeout);
239 static void modepage(struct cam_device *device, int argc, char **argv,
240 char *combinedopt, int retry_count, int timeout);
241 static int scsicmd(struct cam_device *device, int argc, char **argv,
242 char *combinedopt, int retry_count, int timeout);
243 static int smpcmd(struct cam_device *device, int argc, char **argv,
244 char *combinedopt, int retry_count, int timeout);
245 static int smpreportgeneral(struct cam_device *device, int argc, char **argv,
246 char *combinedopt, int retry_count, int timeout);
247 static int smpphycontrol(struct cam_device *device, int argc, char **argv,
248 char *combinedopt, int retry_count, int timeout);
249 static int smpmaninfo(struct cam_device *device, int argc, char **argv,
250 char *combinedopt, int retry_count, int timeout);
251 static int getdevid(struct cam_devitem *item);
252 static int buildbusdevlist(struct cam_devlist *devlist);
253 static void freebusdevlist(struct cam_devlist *devlist);
254 static struct cam_devitem *findsasdevice(struct cam_devlist *devlist,
256 static int smpphylist(struct cam_device *device, int argc, char **argv,
257 char *combinedopt, int retry_count, int timeout);
258 static int tagcontrol(struct cam_device *device, int argc, char **argv,
260 static void cts_print(struct cam_device *device,
261 struct ccb_trans_settings *cts);
262 static void cpi_print(struct ccb_pathinq *cpi);
263 static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
264 static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd);
265 static int get_print_cts(struct cam_device *device, int user_settings,
266 int quiet, struct ccb_trans_settings *cts);
267 static int ratecontrol(struct cam_device *device, int retry_count,
268 int timeout, int argc, char **argv, char *combinedopt);
269 static int scsiformat(struct cam_device *device, int argc, char **argv,
270 char *combinedopt, int retry_count, int timeout);
271 static int scsireportluns(struct cam_device *device, int argc, char **argv,
272 char *combinedopt, int retry_count, int timeout);
273 static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
274 char *combinedopt, int retry_count, int timeout);
275 static int atapm(struct cam_device *device, int argc, char **argv,
276 char *combinedopt, int retry_count, int timeout);
277 #endif /* MINIMALISTIC */
279 #define min(a,b) (((a)<(b))?(a):(b))
282 #define max(a,b) (((a)>(b))?(a):(b))
286 getoption(struct camcontrol_opts *table, char *arg, uint32_t *cmdnum,
287 cam_argmask *argnum, const char **subopt)
289 struct camcontrol_opts *opts;
292 for (opts = table; (opts != NULL) && (opts->optname != NULL);
294 if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
295 *cmdnum = opts->cmdnum;
296 *argnum = opts->argnum;
297 *subopt = opts->subopt;
298 if (++num_matches > 1)
299 return(CC_OR_AMBIGUOUS);
306 return(CC_OR_NOT_FOUND);
311 getdevlist(struct cam_device *device)
317 ccb = cam_getccb(device);
319 ccb->ccb_h.func_code = XPT_GDEVLIST;
320 ccb->ccb_h.flags = CAM_DIR_NONE;
321 ccb->ccb_h.retry_count = 1;
323 ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
324 while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
325 if (cam_send_ccb(device, ccb) < 0) {
326 perror("error getting device list");
333 switch (ccb->cgdl.status) {
334 case CAM_GDEVLIST_MORE_DEVS:
335 strcpy(status, "MORE");
337 case CAM_GDEVLIST_LAST_DEVICE:
338 strcpy(status, "LAST");
340 case CAM_GDEVLIST_LIST_CHANGED:
341 strcpy(status, "CHANGED");
343 case CAM_GDEVLIST_ERROR:
344 strcpy(status, "ERROR");
349 fprintf(stdout, "%s%d: generation: %d index: %d status: %s\n",
350 ccb->cgdl.periph_name,
351 ccb->cgdl.unit_number,
352 ccb->cgdl.generation,
357 * If the list has changed, we need to start over from the
360 if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
368 #endif /* MINIMALISTIC */
380 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
381 warn("couldn't open %s", XPT_DEVICE);
385 bzero(&ccb, sizeof(union ccb));
387 ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
388 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
389 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
391 ccb.ccb_h.func_code = XPT_DEV_MATCH;
392 bufsize = sizeof(struct dev_match_result) * 100;
393 ccb.cdm.match_buf_len = bufsize;
394 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
395 if (ccb.cdm.matches == NULL) {
396 warnx("can't malloc memory for matches");
400 ccb.cdm.num_matches = 0;
403 * We fetch all nodes, since we display most of them in the default
404 * case, and all in the verbose case.
406 ccb.cdm.num_patterns = 0;
407 ccb.cdm.pattern_buf_len = 0;
410 * We do the ioctl multiple times if necessary, in case there are
411 * more than 100 nodes in the EDT.
414 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
415 warn("error sending CAMIOCOMMAND ioctl");
420 if ((ccb.ccb_h.status != CAM_REQ_CMP)
421 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
422 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
423 warnx("got CAM error %#x, CDM error %d\n",
424 ccb.ccb_h.status, ccb.cdm.status);
429 for (i = 0; i < ccb.cdm.num_matches; i++) {
430 switch (ccb.cdm.matches[i].type) {
431 case DEV_MATCH_BUS: {
432 struct bus_match_result *bus_result;
435 * Only print the bus information if the
436 * user turns on the verbose flag.
438 if ((arglist & CAM_ARG_VERBOSE) == 0)
442 &ccb.cdm.matches[i].result.bus_result;
445 fprintf(stdout, ")\n");
449 fprintf(stdout, "scbus%d on %s%d bus %d:\n",
451 bus_result->dev_name,
452 bus_result->unit_number,
456 case DEV_MATCH_DEVICE: {
457 struct device_match_result *dev_result;
458 char vendor[16], product[48], revision[16];
462 &ccb.cdm.matches[i].result.device_result;
464 if ((dev_result->flags
465 & DEV_RESULT_UNCONFIGURED)
466 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
472 if (dev_result->protocol == PROTO_SCSI) {
473 cam_strvis(vendor, dev_result->inq_data.vendor,
474 sizeof(dev_result->inq_data.vendor),
477 dev_result->inq_data.product,
478 sizeof(dev_result->inq_data.product),
481 dev_result->inq_data.revision,
482 sizeof(dev_result->inq_data.revision),
484 sprintf(tmpstr, "<%s %s %s>", vendor, product,
486 } else if (dev_result->protocol == PROTO_ATA ||
487 dev_result->protocol == PROTO_SATAPM) {
489 dev_result->ident_data.model,
490 sizeof(dev_result->ident_data.model),
493 dev_result->ident_data.revision,
494 sizeof(dev_result->ident_data.revision),
496 sprintf(tmpstr, "<%s %s>", product,
499 sprintf(tmpstr, "<>");
502 fprintf(stdout, ")\n");
506 fprintf(stdout, "%-33s at scbus%d "
507 "target %d lun %d (",
510 dev_result->target_id,
511 dev_result->target_lun);
517 case DEV_MATCH_PERIPH: {
518 struct periph_match_result *periph_result;
521 &ccb.cdm.matches[i].result.periph_result;
523 if (skip_device != 0)
527 fprintf(stdout, ",");
529 fprintf(stdout, "%s%d",
530 periph_result->periph_name,
531 periph_result->unit_number);
537 fprintf(stdout, "unknown match type\n");
542 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
543 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
546 fprintf(stdout, ")\n");
555 testunitready(struct cam_device *device, int retry_count, int timeout,
561 ccb = cam_getccb(device);
563 scsi_test_unit_ready(&ccb->csio,
564 /* retries */ retry_count,
566 /* tag_action */ MSG_SIMPLE_Q_TAG,
567 /* sense_len */ SSD_FULL_SIZE,
568 /* timeout */ timeout ? timeout : 5000);
570 /* Disable freezing the device queue */
571 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
573 if (arglist & CAM_ARG_ERR_RECOVER)
574 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
576 if (cam_send_ccb(device, ccb) < 0) {
578 perror("error sending test unit ready");
580 if (arglist & CAM_ARG_VERBOSE) {
581 cam_error_print(device, ccb, CAM_ESF_ALL,
582 CAM_EPF_ALL, stderr);
589 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
591 fprintf(stdout, "Unit is ready\n");
594 fprintf(stdout, "Unit is not ready\n");
597 if (arglist & CAM_ARG_VERBOSE) {
598 cam_error_print(device, ccb, CAM_ESF_ALL,
599 CAM_EPF_ALL, stderr);
609 scsistart(struct cam_device *device, int startstop, int loadeject,
610 int retry_count, int timeout)
615 ccb = cam_getccb(device);
618 * If we're stopping, send an ordered tag so the drive in question
619 * will finish any previously queued writes before stopping. If
620 * the device isn't capable of tagged queueing, or if tagged
621 * queueing is turned off, the tag action is a no-op.
623 scsi_start_stop(&ccb->csio,
624 /* retries */ retry_count,
626 /* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
628 /* start/stop */ startstop,
629 /* load_eject */ loadeject,
631 /* sense_len */ SSD_FULL_SIZE,
632 /* timeout */ timeout ? timeout : 120000);
634 /* Disable freezing the device queue */
635 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
637 if (arglist & CAM_ARG_ERR_RECOVER)
638 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
640 if (cam_send_ccb(device, ccb) < 0) {
641 perror("error sending start unit");
643 if (arglist & CAM_ARG_VERBOSE) {
644 cam_error_print(device, ccb, CAM_ESF_ALL,
645 CAM_EPF_ALL, stderr);
652 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
654 fprintf(stdout, "Unit started successfully");
656 fprintf(stdout,", Media loaded\n");
658 fprintf(stdout,"\n");
660 fprintf(stdout, "Unit stopped successfully");
662 fprintf(stdout, ", Media ejected\n");
664 fprintf(stdout, "\n");
670 "Error received from start unit command\n");
673 "Error received from stop unit command\n");
675 if (arglist & CAM_ARG_VERBOSE) {
676 cam_error_print(device, ccb, CAM_ESF_ALL,
677 CAM_EPF_ALL, stderr);
687 scsidoinquiry(struct cam_device *device, int argc, char **argv,
688 char *combinedopt, int retry_count, int timeout)
693 while ((c = getopt(argc, argv, combinedopt)) != -1) {
696 arglist |= CAM_ARG_GET_STDINQ;
699 arglist |= CAM_ARG_GET_XFERRATE;
702 arglist |= CAM_ARG_GET_SERIAL;
710 * If the user didn't specify any inquiry options, he wants all of
713 if ((arglist & CAM_ARG_INQ_MASK) == 0)
714 arglist |= CAM_ARG_INQ_MASK;
716 if (arglist & CAM_ARG_GET_STDINQ)
717 error = scsiinquiry(device, retry_count, timeout);
722 if (arglist & CAM_ARG_GET_SERIAL)
723 scsiserial(device, retry_count, timeout);
728 if (arglist & CAM_ARG_GET_XFERRATE)
729 error = camxferrate(device);
735 scsiinquiry(struct cam_device *device, int retry_count, int timeout)
738 struct scsi_inquiry_data *inq_buf;
741 ccb = cam_getccb(device);
744 warnx("couldn't allocate CCB");
748 /* cam_getccb cleans up the header, caller has to zero the payload */
749 bzero(&(&ccb->ccb_h)[1],
750 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
752 inq_buf = (struct scsi_inquiry_data *)malloc(
753 sizeof(struct scsi_inquiry_data));
755 if (inq_buf == NULL) {
757 warnx("can't malloc memory for inquiry\n");
760 bzero(inq_buf, sizeof(*inq_buf));
763 * Note that although the size of the inquiry buffer is the full
764 * 256 bytes specified in the SCSI spec, we only tell the device
765 * that we have allocated SHORT_INQUIRY_LENGTH bytes. There are
766 * two reasons for this:
768 * - The SCSI spec says that when a length field is only 1 byte,
769 * a value of 0 will be interpreted as 256. Therefore
770 * scsi_inquiry() will convert an inq_len (which is passed in as
771 * a u_int32_t, but the field in the CDB is only 1 byte) of 256
772 * to 0. Evidently, very few devices meet the spec in that
773 * regard. Some devices, like many Seagate disks, take the 0 as
774 * 0, and don't return any data. One Pioneer DVD-R drive
775 * returns more data than the command asked for.
777 * So, since there are numerous devices that just don't work
778 * right with the full inquiry size, we don't send the full size.
780 * - The second reason not to use the full inquiry data length is
781 * that we don't need it here. The only reason we issue a
782 * standard inquiry is to get the vendor name, device name,
783 * and revision so scsi_print_inquiry() can print them.
785 * If, at some point in the future, more inquiry data is needed for
786 * some reason, this code should use a procedure similar to the
787 * probe code. i.e., issue a short inquiry, and determine from
788 * the additional length passed back from the device how much
789 * inquiry data the device supports. Once the amount the device
790 * supports is determined, issue an inquiry for that amount and no
795 scsi_inquiry(&ccb->csio,
796 /* retries */ retry_count,
798 /* tag_action */ MSG_SIMPLE_Q_TAG,
799 /* inq_buf */ (u_int8_t *)inq_buf,
800 /* inq_len */ SHORT_INQUIRY_LENGTH,
803 /* sense_len */ SSD_FULL_SIZE,
804 /* timeout */ timeout ? timeout : 5000);
806 /* Disable freezing the device queue */
807 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
809 if (arglist & CAM_ARG_ERR_RECOVER)
810 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
812 if (cam_send_ccb(device, ccb) < 0) {
813 perror("error sending SCSI inquiry");
815 if (arglist & CAM_ARG_VERBOSE) {
816 cam_error_print(device, ccb, CAM_ESF_ALL,
817 CAM_EPF_ALL, stderr);
824 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
827 if (arglist & CAM_ARG_VERBOSE) {
828 cam_error_print(device, ccb, CAM_ESF_ALL,
829 CAM_EPF_ALL, stderr);
840 fprintf(stdout, "%s%d: ", device->device_name,
841 device->dev_unit_num);
842 scsi_print_inquiry(inq_buf);
850 scsiserial(struct cam_device *device, int retry_count, int timeout)
853 struct scsi_vpd_unit_serial_number *serial_buf;
854 char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
857 ccb = cam_getccb(device);
860 warnx("couldn't allocate CCB");
864 /* cam_getccb cleans up the header, caller has to zero the payload */
865 bzero(&(&ccb->ccb_h)[1],
866 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
868 serial_buf = (struct scsi_vpd_unit_serial_number *)
869 malloc(sizeof(*serial_buf));
871 if (serial_buf == NULL) {
873 warnx("can't malloc memory for serial number");
877 scsi_inquiry(&ccb->csio,
878 /*retries*/ retry_count,
880 /* tag_action */ MSG_SIMPLE_Q_TAG,
881 /* inq_buf */ (u_int8_t *)serial_buf,
882 /* inq_len */ sizeof(*serial_buf),
884 /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
885 /* sense_len */ SSD_FULL_SIZE,
886 /* timeout */ timeout ? timeout : 5000);
888 /* Disable freezing the device queue */
889 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
891 if (arglist & CAM_ARG_ERR_RECOVER)
892 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
894 if (cam_send_ccb(device, ccb) < 0) {
895 warn("error getting serial number");
897 if (arglist & CAM_ARG_VERBOSE) {
898 cam_error_print(device, ccb, CAM_ESF_ALL,
899 CAM_EPF_ALL, stderr);
907 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
910 if (arglist & CAM_ARG_VERBOSE) {
911 cam_error_print(device, ccb, CAM_ESF_ALL,
912 CAM_EPF_ALL, stderr);
923 bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
924 serial_num[serial_buf->length] = '\0';
926 if ((arglist & CAM_ARG_GET_STDINQ)
927 || (arglist & CAM_ARG_GET_XFERRATE))
928 fprintf(stdout, "%s%d: Serial Number ",
929 device->device_name, device->dev_unit_num);
931 fprintf(stdout, "%.60s\n", serial_num);
939 camxferrate(struct cam_device *device)
941 struct ccb_pathinq cpi;
948 if ((retval = get_cpi(device, &cpi)) != 0)
951 ccb = cam_getccb(device);
954 warnx("couldn't allocate CCB");
958 bzero(&(&ccb->ccb_h)[1],
959 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
961 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
962 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
964 if (((retval = cam_send_ccb(device, ccb)) < 0)
965 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
966 const char error_string[] = "error getting transfer settings";
973 if (arglist & CAM_ARG_VERBOSE)
974 cam_error_print(device, ccb, CAM_ESF_ALL,
975 CAM_EPF_ALL, stderr);
979 goto xferrate_bailout;
983 speed = cpi.base_transfer_speed;
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_RATE) != 0) {
990 freq = scsi_calc_syncsrate(spi->sync_period);
993 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
994 speed *= (0x01 << spi->bus_width);
996 } else if (ccb->cts.transport == XPORT_FC) {
997 struct ccb_trans_settings_fc *fc =
998 &ccb->cts.xport_specific.fc;
1000 if (fc->valid & CTS_FC_VALID_SPEED)
1001 speed = fc->bitrate;
1002 } else if (ccb->cts.transport == XPORT_SAS) {
1003 struct ccb_trans_settings_sas *sas =
1004 &ccb->cts.xport_specific.sas;
1006 if (sas->valid & CTS_SAS_VALID_SPEED)
1007 speed = sas->bitrate;
1008 } else if (ccb->cts.transport == XPORT_ATA) {
1009 struct ccb_trans_settings_ata *ata =
1010 &ccb->cts.xport_specific.ata;
1012 if (ata->valid & CTS_ATA_VALID_MODE)
1013 speed = ata_mode2speed(ata->mode);
1014 } else if (ccb->cts.transport == XPORT_SATA) {
1015 struct ccb_trans_settings_sata *sata =
1016 &ccb->cts.xport_specific.sata;
1018 if (sata->valid & CTS_SATA_VALID_REVISION)
1019 speed = ata_revision2speed(sata->revision);
1024 fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
1025 device->device_name, device->dev_unit_num,
1028 fprintf(stdout, "%s%d: %dKB/s transfers",
1029 device->device_name, device->dev_unit_num,
1033 if (ccb->cts.transport == XPORT_SPI) {
1034 struct ccb_trans_settings_spi *spi =
1035 &ccb->cts.xport_specific.spi;
1037 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1038 && (spi->sync_offset != 0))
1039 fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
1040 freq % 1000, spi->sync_offset);
1042 if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
1043 && (spi->bus_width > 0)) {
1044 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1045 && (spi->sync_offset != 0)) {
1046 fprintf(stdout, ", ");
1048 fprintf(stdout, " (");
1050 fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
1051 } else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1052 && (spi->sync_offset != 0)) {
1053 fprintf(stdout, ")");
1055 } else if (ccb->cts.transport == XPORT_ATA) {
1056 struct ccb_trans_settings_ata *ata =
1057 &ccb->cts.xport_specific.ata;
1060 if (ata->valid & CTS_ATA_VALID_MODE)
1061 printf("%s, ", ata_mode2string(ata->mode));
1062 if ((ata->valid & CTS_ATA_VALID_ATAPI) && ata->atapi != 0)
1063 printf("ATAPI %dbytes, ", ata->atapi);
1064 if (ata->valid & CTS_ATA_VALID_BYTECOUNT)
1065 printf("PIO %dbytes", ata->bytecount);
1067 } else if (ccb->cts.transport == XPORT_SATA) {
1068 struct ccb_trans_settings_sata *sata =
1069 &ccb->cts.xport_specific.sata;
1072 if (sata->valid & CTS_SATA_VALID_REVISION)
1073 printf("SATA %d.x, ", sata->revision);
1076 if (sata->valid & CTS_SATA_VALID_MODE)
1077 printf("%s, ", ata_mode2string(sata->mode));
1078 if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
1079 printf("ATAPI %dbytes, ", sata->atapi);
1080 if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1081 printf("PIO %dbytes", sata->bytecount);
1085 if (ccb->cts.protocol == PROTO_SCSI) {
1086 struct ccb_trans_settings_scsi *scsi =
1087 &ccb->cts.proto_specific.scsi;
1088 if (scsi->valid & CTS_SCSI_VALID_TQ) {
1089 if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1090 fprintf(stdout, ", Command Queueing Enabled");
1095 fprintf(stdout, "\n");
1105 atacapprint(struct ata_params *parm)
1107 u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1108 ((u_int32_t)parm->lba_size_2 << 16);
1110 u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1111 ((u_int64_t)parm->lba_size48_2 << 16) |
1112 ((u_int64_t)parm->lba_size48_3 << 32) |
1113 ((u_int64_t)parm->lba_size48_4 << 48);
1116 printf("protocol ");
1117 printf("ATA/ATAPI-%d", ata_version(parm->version_major));
1118 if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1119 if (parm->satacapabilities & ATA_SATA_GEN3)
1120 printf(" SATA 3.x\n");
1121 else if (parm->satacapabilities & ATA_SATA_GEN2)
1122 printf(" SATA 2.x\n");
1123 else if (parm->satacapabilities & ATA_SATA_GEN1)
1124 printf(" SATA 1.x\n");
1130 printf("device model %.40s\n", parm->model);
1131 printf("firmware revision %.8s\n", parm->revision);
1132 printf("serial number %.20s\n", parm->serial);
1133 if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
1134 printf("WWN %04x%04x%04x%04x\n",
1135 parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
1137 if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
1138 printf("media serial number %.30s\n",
1139 parm->media_serial);
1142 printf("cylinders %d\n", parm->cylinders);
1143 printf("heads %d\n", parm->heads);
1144 printf("sectors/track %d\n", parm->sectors);
1145 printf("sector size logical %u, physical %lu, offset %lu\n",
1146 ata_logical_sector_size(parm),
1147 (unsigned long)ata_physical_sector_size(parm),
1148 (unsigned long)ata_logical_sector_offset(parm));
1150 if (parm->config == ATA_PROTO_CFA ||
1151 (parm->support.command2 & ATA_SUPPORT_CFA))
1152 printf("CFA supported\n");
1154 printf("LBA%ssupported ",
1155 parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1157 printf("%d sectors\n", lbasize);
1161 printf("LBA48%ssupported ",
1162 parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1164 printf("%ju sectors\n", (uintmax_t)lbasize48);
1168 printf("PIO supported PIO");
1169 switch (ata_max_pmode(parm)) {
1185 if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0)
1186 printf(" w/o IORDY");
1189 printf("DMA%ssupported ",
1190 parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1191 if (parm->capabilities1 & ATA_SUPPORT_DMA) {
1192 if (parm->mwdmamodes & 0xff) {
1194 if (parm->mwdmamodes & 0x04)
1196 else if (parm->mwdmamodes & 0x02)
1198 else if (parm->mwdmamodes & 0x01)
1202 if ((parm->atavalid & ATA_FLAG_88) &&
1203 (parm->udmamodes & 0xff)) {
1205 if (parm->udmamodes & 0x40)
1207 else if (parm->udmamodes & 0x20)
1209 else if (parm->udmamodes & 0x10)
1211 else if (parm->udmamodes & 0x08)
1213 else if (parm->udmamodes & 0x04)
1215 else if (parm->udmamodes & 0x02)
1217 else if (parm->udmamodes & 0x01)
1224 if (parm->media_rotation_rate == 1) {
1225 printf("media RPM non-rotating\n");
1226 } else if (parm->media_rotation_rate >= 0x0401 &&
1227 parm->media_rotation_rate <= 0xFFFE) {
1228 printf("media RPM %d\n",
1229 parm->media_rotation_rate);
1233 "Support Enabled Value Vendor\n");
1234 printf("read ahead %s %s\n",
1235 parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1236 parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1237 printf("write cache %s %s\n",
1238 parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1239 parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1240 printf("flush cache %s %s\n",
1241 parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no",
1242 parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no");
1243 printf("overlap %s\n",
1244 parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no");
1245 printf("Tagged Command Queuing (TCQ) %s %s",
1246 parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1247 parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no");
1248 if (parm->support.command2 & ATA_SUPPORT_QUEUED) {
1249 printf(" %d tags\n",
1250 ATA_QUEUE_LEN(parm->queue) + 1);
1253 printf("Native Command Queuing (NCQ) ");
1254 if (parm->satacapabilities != 0xffff &&
1255 (parm->satacapabilities & ATA_SUPPORT_NCQ)) {
1256 printf("yes %d tags\n",
1257 ATA_QUEUE_LEN(parm->queue) + 1);
1260 printf("SMART %s %s\n",
1261 parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1262 parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1263 printf("microcode download %s %s\n",
1264 parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1265 parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1266 printf("security %s %s\n",
1267 parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1268 parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1269 printf("power management %s %s\n",
1270 parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1271 parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1272 printf("advanced power management %s %s",
1273 parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1274 parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no");
1275 if (parm->support.command2 & ATA_SUPPORT_APM) {
1276 printf(" %d/0x%02X\n",
1277 parm->apm_value, parm->apm_value);
1280 printf("automatic acoustic management %s %s",
1281 parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1282 parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no");
1283 if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) {
1284 printf(" %d/0x%02X %d/0x%02X\n",
1285 ATA_ACOUSTIC_CURRENT(parm->acoustic),
1286 ATA_ACOUSTIC_CURRENT(parm->acoustic),
1287 ATA_ACOUSTIC_VENDOR(parm->acoustic),
1288 ATA_ACOUSTIC_VENDOR(parm->acoustic));
1291 printf("media status notification %s %s\n",
1292 parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1293 parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1294 printf("power-up in Standby %s %s\n",
1295 parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1296 parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1297 printf("write-read-verify %s %s",
1298 parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1299 parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no");
1300 if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) {
1301 printf(" %d/0x%x\n",
1302 parm->wrv_mode, parm->wrv_mode);
1305 printf("unload %s %s\n",
1306 parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1307 parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1308 printf("free-fall %s %s\n",
1309 parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1310 parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1311 printf("data set management (TRIM) %s\n",
1312 parm->support_dsm & ATA_SUPPORT_DSM_TRIM ? "yes" : "no");
1316 ataidentify(struct cam_device *device, int retry_count, int timeout)
1319 struct ata_params *ident_buf;
1320 struct ccb_getdev cgd;
1324 if (get_cgd(device, &cgd) != 0) {
1325 warnx("couldn't get CGD");
1328 ccb = cam_getccb(device);
1331 warnx("couldn't allocate CCB");
1335 /* cam_getccb cleans up the header, caller has to zero the payload */
1336 bzero(&(&ccb->ccb_h)[1],
1337 sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));
1339 ptr = (uint16_t *)malloc(sizeof(struct ata_params));
1343 warnx("can't malloc memory for identify\n");
1346 bzero(ptr, sizeof(struct ata_params));
1348 cam_fill_ataio(&ccb->ataio,
1351 /*flags*/CAM_DIR_IN,
1353 /*data_ptr*/(u_int8_t *)ptr,
1354 /*dxfer_len*/sizeof(struct ata_params),
1355 timeout ? timeout : 30 * 1000);
1356 if (cgd.protocol == PROTO_ATA)
1357 ata_28bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
1359 ata_28bit_cmd(&ccb->ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
1361 /* Disable freezing the device queue */
1362 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1364 if (arglist & CAM_ARG_ERR_RECOVER)
1365 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1367 if (cam_send_ccb(device, ccb) < 0) {
1368 perror("error sending ATA identify");
1370 if (arglist & CAM_ARG_VERBOSE) {
1371 cam_error_print(device, ccb, CAM_ESF_ALL,
1372 CAM_EPF_ALL, stderr);
1380 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1383 if (arglist & CAM_ARG_VERBOSE) {
1384 cam_error_print(device, ccb, CAM_ESF_ALL,
1385 CAM_EPF_ALL, stderr);
1396 for (i = 0; i < sizeof(struct ata_params) / 2; i++)
1397 ptr[i] = le16toh(ptr[i]);
1398 if (arglist & CAM_ARG_VERBOSE) {
1399 fprintf(stdout, "%s%d: Raw identify data:\n",
1400 device->device_name, device->dev_unit_num);
1401 for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
1403 fprintf(stdout, " %3d: ", i);
1404 fprintf(stdout, "%04x ", (uint16_t)ptr[i]);
1406 fprintf(stdout, "\n");
1409 ident_buf = (struct ata_params *)ptr;
1410 if (strncmp(ident_buf->model, "FX", 2) &&
1411 strncmp(ident_buf->model, "NEC", 3) &&
1412 strncmp(ident_buf->model, "Pioneer", 7) &&
1413 strncmp(ident_buf->model, "SHARP", 5)) {
1414 ata_bswap(ident_buf->model, sizeof(ident_buf->model));
1415 ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
1416 ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
1417 ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1419 ata_btrim(ident_buf->model, sizeof(ident_buf->model));
1420 ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
1421 ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
1422 ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
1423 ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
1424 ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
1425 ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1426 ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
1427 sizeof(ident_buf->media_serial));
1429 fprintf(stdout, "%s%d: ", device->device_name,
1430 device->dev_unit_num);
1431 ata_print_ident(ident_buf);
1432 camxferrate(device);
1433 atacapprint(ident_buf);
1439 #endif /* MINIMALISTIC */
1442 * Parse out a bus, or a bus, target and lun in the following
1448 * Returns the number of parsed components, or 0.
1451 parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglst)
1456 while (isspace(*tstr) && (*tstr != '\0'))
1459 tmpstr = (char *)strtok(tstr, ":");
1460 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1461 *bus = strtol(tmpstr, NULL, 0);
1462 *arglst |= CAM_ARG_BUS;
1464 tmpstr = (char *)strtok(NULL, ":");
1465 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1466 *target = strtol(tmpstr, NULL, 0);
1467 *arglst |= CAM_ARG_TARGET;
1469 tmpstr = (char *)strtok(NULL, ":");
1470 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1471 *lun = strtol(tmpstr, NULL, 0);
1472 *arglst |= CAM_ARG_LUN;
1482 dorescan_or_reset(int argc, char **argv, int rescan)
1484 static const char must[] =
1485 "you must specify \"all\", a bus, or a bus:target:lun to %s";
1487 int bus = -1, target = -1, lun = -1;
1491 warnx(must, rescan? "rescan" : "reset");
1495 tstr = argv[optind];
1496 while (isspace(*tstr) && (*tstr != '\0'))
1498 if (strncasecmp(tstr, "all", strlen("all")) == 0)
1499 arglist |= CAM_ARG_BUS;
1501 rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
1502 if (rv != 1 && rv != 3) {
1503 warnx(must, rescan? "rescan" : "reset");
1508 if ((arglist & CAM_ARG_BUS)
1509 && (arglist & CAM_ARG_TARGET)
1510 && (arglist & CAM_ARG_LUN))
1511 error = scanlun_or_reset_dev(bus, target, lun, rescan);
1513 error = rescan_or_reset_bus(bus, rescan);
1519 rescan_or_reset_bus(int bus, int rescan)
1521 union ccb ccb, matchccb;
1527 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1528 warnx("error opening transport layer device %s", XPT_DEVICE);
1529 warn("%s", XPT_DEVICE);
1534 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
1535 ccb.ccb_h.path_id = bus;
1536 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1537 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1538 ccb.crcn.flags = CAM_FLAG_NONE;
1540 /* run this at a low priority */
1541 ccb.ccb_h.pinfo.priority = 5;
1543 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1544 warn("CAMIOCOMMAND ioctl failed");
1549 if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
1550 fprintf(stdout, "%s of bus %d was successful\n",
1551 rescan ? "Re-scan" : "Reset", bus);
1553 fprintf(stdout, "%s of bus %d returned error %#x\n",
1554 rescan ? "Re-scan" : "Reset", bus,
1555 ccb.ccb_h.status & CAM_STATUS_MASK);
1566 * The right way to handle this is to modify the xpt so that it can
1567 * handle a wildcarded bus in a rescan or reset CCB. At the moment
1568 * that isn't implemented, so instead we enumerate the busses and
1569 * send the rescan or reset to those busses in the case where the
1570 * given bus is -1 (wildcard). We don't send a rescan or reset
1571 * to the xpt bus; sending a rescan to the xpt bus is effectively a
1572 * no-op, sending a rescan to the xpt bus would result in a status of
1575 bzero(&(&matchccb.ccb_h)[1],
1576 sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
1577 matchccb.ccb_h.func_code = XPT_DEV_MATCH;
1578 matchccb.ccb_h.path_id = CAM_BUS_WILDCARD;
1579 bufsize = sizeof(struct dev_match_result) * 20;
1580 matchccb.cdm.match_buf_len = bufsize;
1581 matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
1582 if (matchccb.cdm.matches == NULL) {
1583 warnx("can't malloc memory for matches");
1587 matchccb.cdm.num_matches = 0;
1589 matchccb.cdm.num_patterns = 1;
1590 matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
1592 matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
1593 matchccb.cdm.pattern_buf_len);
1594 if (matchccb.cdm.patterns == NULL) {
1595 warnx("can't malloc memory for patterns");
1599 matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
1600 matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
1605 if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
1606 warn("CAMIOCOMMAND ioctl failed");
1611 if ((matchccb.ccb_h.status != CAM_REQ_CMP)
1612 || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
1613 && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
1614 warnx("got CAM error %#x, CDM error %d\n",
1615 matchccb.ccb_h.status, matchccb.cdm.status);
1620 for (i = 0; i < matchccb.cdm.num_matches; i++) {
1621 struct bus_match_result *bus_result;
1623 /* This shouldn't happen. */
1624 if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
1627 bus_result = &matchccb.cdm.matches[i].result.bus_result;
1630 * We don't want to rescan or reset the xpt bus.
1633 if ((int)bus_result->path_id == -1)
1636 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
1638 ccb.ccb_h.path_id = bus_result->path_id;
1639 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1640 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1641 ccb.crcn.flags = CAM_FLAG_NONE;
1643 /* run this at a low priority */
1644 ccb.ccb_h.pinfo.priority = 5;
1646 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1647 warn("CAMIOCOMMAND ioctl failed");
1652 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
1653 fprintf(stdout, "%s of bus %d was successful\n",
1654 rescan? "Re-scan" : "Reset",
1655 bus_result->path_id);
1658 * Don't bail out just yet, maybe the other
1659 * rescan or reset commands will complete
1662 fprintf(stderr, "%s of bus %d returned error "
1663 "%#x\n", rescan? "Re-scan" : "Reset",
1664 bus_result->path_id,
1665 ccb.ccb_h.status & CAM_STATUS_MASK);
1669 } while ((matchccb.ccb_h.status == CAM_REQ_CMP)
1670 && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
1677 if (matchccb.cdm.patterns != NULL)
1678 free(matchccb.cdm.patterns);
1679 if (matchccb.cdm.matches != NULL)
1680 free(matchccb.cdm.matches);
1686 scanlun_or_reset_dev(int bus, int target, int lun, int scan)
1689 struct cam_device *device;
1695 warnx("invalid bus number %d", bus);
1700 warnx("invalid target number %d", target);
1705 warnx("invalid lun number %d", lun);
1711 bzero(&ccb, sizeof(union ccb));
1714 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1715 warnx("error opening transport layer device %s\n",
1717 warn("%s", XPT_DEVICE);
1721 device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
1722 if (device == NULL) {
1723 warnx("%s", cam_errbuf);
1728 ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
1729 ccb.ccb_h.path_id = bus;
1730 ccb.ccb_h.target_id = target;
1731 ccb.ccb_h.target_lun = lun;
1732 ccb.ccb_h.timeout = 5000;
1733 ccb.crcn.flags = CAM_FLAG_NONE;
1735 /* run this at a low priority */
1736 ccb.ccb_h.pinfo.priority = 5;
1739 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
1740 warn("CAMIOCOMMAND ioctl failed");
1745 if (cam_send_ccb(device, &ccb) < 0) {
1746 warn("error sending XPT_RESET_DEV CCB");
1747 cam_close_device(device);
1755 cam_close_device(device);
1758 * An error code of CAM_BDR_SENT is normal for a BDR request.
1760 if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1762 && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
1763 fprintf(stdout, "%s of %d:%d:%d was successful\n",
1764 scan? "Re-scan" : "Reset", bus, target, lun);
1767 fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
1768 scan? "Re-scan" : "Reset", bus, target, lun,
1769 ccb.ccb_h.status & CAM_STATUS_MASK);
1774 #ifndef MINIMALISTIC
1776 readdefects(struct cam_device *device, int argc, char **argv,
1777 char *combinedopt, int retry_count, int timeout)
1779 union ccb *ccb = NULL;
1780 struct scsi_read_defect_data_10 *rdd_cdb;
1781 u_int8_t *defect_list = NULL;
1782 u_int32_t dlist_length = 65000;
1783 u_int32_t returned_length = 0;
1784 u_int32_t num_returned = 0;
1785 u_int8_t returned_format;
1788 int lists_specified = 0;
1790 while ((c = getopt(argc, argv, combinedopt)) != -1) {
1796 while (isspace(*tstr) && (*tstr != '\0'))
1798 if (strcmp(tstr, "block") == 0)
1799 arglist |= CAM_ARG_FORMAT_BLOCK;
1800 else if (strcmp(tstr, "bfi") == 0)
1801 arglist |= CAM_ARG_FORMAT_BFI;
1802 else if (strcmp(tstr, "phys") == 0)
1803 arglist |= CAM_ARG_FORMAT_PHYS;
1806 warnx("invalid defect format %s", tstr);
1807 goto defect_bailout;
1812 arglist |= CAM_ARG_GLIST;
1815 arglist |= CAM_ARG_PLIST;
1822 ccb = cam_getccb(device);
1825 * Hopefully 65000 bytes is enough to hold the defect list. If it
1826 * isn't, the disk is probably dead already. We'd have to go with
1827 * 12 byte command (i.e. alloc_length is 32 bits instead of 16)
1830 defect_list = malloc(dlist_length);
1831 if (defect_list == NULL) {
1832 warnx("can't malloc memory for defect list");
1834 goto defect_bailout;
1837 rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
1840 * cam_getccb() zeros the CCB header only. So we need to zero the
1841 * payload portion of the ccb.
1843 bzero(&(&ccb->ccb_h)[1],
1844 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1846 cam_fill_csio(&ccb->csio,
1847 /*retries*/ retry_count,
1849 /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
1850 CAM_PASS_ERR_RECOVER : 0),
1851 /*tag_action*/ MSG_SIMPLE_Q_TAG,
1852 /*data_ptr*/ defect_list,
1853 /*dxfer_len*/ dlist_length,
1854 /*sense_len*/ SSD_FULL_SIZE,
1855 /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
1856 /*timeout*/ timeout ? timeout : 5000);
1858 rdd_cdb->opcode = READ_DEFECT_DATA_10;
1859 if (arglist & CAM_ARG_FORMAT_BLOCK)
1860 rdd_cdb->format = SRDD10_BLOCK_FORMAT;
1861 else if (arglist & CAM_ARG_FORMAT_BFI)
1862 rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
1863 else if (arglist & CAM_ARG_FORMAT_PHYS)
1864 rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
1867 warnx("no defect list format specified");
1868 goto defect_bailout;
1870 if (arglist & CAM_ARG_PLIST) {
1871 rdd_cdb->format |= SRDD10_PLIST;
1875 if (arglist & CAM_ARG_GLIST) {
1876 rdd_cdb->format |= SRDD10_GLIST;
1880 scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
1882 /* Disable freezing the device queue */
1883 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1885 if (cam_send_ccb(device, ccb) < 0) {
1886 perror("error reading defect list");
1888 if (arglist & CAM_ARG_VERBOSE) {
1889 cam_error_print(device, ccb, CAM_ESF_ALL,
1890 CAM_EPF_ALL, stderr);
1894 goto defect_bailout;
1897 returned_length = scsi_2btoul(((struct
1898 scsi_read_defect_data_hdr_10 *)defect_list)->length);
1900 returned_format = ((struct scsi_read_defect_data_hdr_10 *)
1901 defect_list)->format;
1903 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
1904 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
1905 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
1906 struct scsi_sense_data *sense;
1907 int error_code, sense_key, asc, ascq;
1909 sense = &ccb->csio.sense_data;
1910 scsi_extract_sense_len(sense, ccb->csio.sense_len -
1911 ccb->csio.sense_resid, &error_code, &sense_key, &asc,
1912 &ascq, /*show_errors*/ 1);
1915 * According to the SCSI spec, if the disk doesn't support
1916 * the requested format, it will generally return a sense
1917 * key of RECOVERED ERROR, and an additional sense code
1918 * of "DEFECT LIST NOT FOUND". So, we check for that, and
1919 * also check to make sure that the returned length is
1920 * greater than 0, and then print out whatever format the
1923 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
1924 && (asc == 0x1c) && (ascq == 0x00)
1925 && (returned_length > 0)) {
1926 warnx("requested defect format not available");
1927 switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
1928 case SRDD10_BLOCK_FORMAT:
1929 warnx("Device returned block format");
1931 case SRDD10_BYTES_FROM_INDEX_FORMAT:
1932 warnx("Device returned bytes from index"
1935 case SRDD10_PHYSICAL_SECTOR_FORMAT:
1936 warnx("Device returned physical sector format");
1940 warnx("Device returned unknown defect"
1941 " data format %#x", returned_format);
1942 goto defect_bailout;
1943 break; /* NOTREACHED */
1947 warnx("Error returned from read defect data command");
1948 if (arglist & CAM_ARG_VERBOSE)
1949 cam_error_print(device, ccb, CAM_ESF_ALL,
1950 CAM_EPF_ALL, stderr);
1951 goto defect_bailout;
1953 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1955 warnx("Error returned from read defect data command");
1956 if (arglist & CAM_ARG_VERBOSE)
1957 cam_error_print(device, ccb, CAM_ESF_ALL,
1958 CAM_EPF_ALL, stderr);
1959 goto defect_bailout;
1963 * XXX KDM I should probably clean up the printout format for the
1966 switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
1967 case SRDDH10_PHYSICAL_SECTOR_FORMAT:
1969 struct scsi_defect_desc_phys_sector *dlist;
1971 dlist = (struct scsi_defect_desc_phys_sector *)
1973 sizeof(struct scsi_read_defect_data_hdr_10));
1975 num_returned = returned_length /
1976 sizeof(struct scsi_defect_desc_phys_sector);
1978 fprintf(stderr, "Got %d defect", num_returned);
1980 if ((lists_specified == 0) || (num_returned == 0)) {
1981 fprintf(stderr, "s.\n");
1983 } else if (num_returned == 1)
1984 fprintf(stderr, ":\n");
1986 fprintf(stderr, "s:\n");
1988 for (i = 0; i < num_returned; i++) {
1989 fprintf(stdout, "%d:%d:%d\n",
1990 scsi_3btoul(dlist[i].cylinder),
1992 scsi_4btoul(dlist[i].sector));
1996 case SRDDH10_BYTES_FROM_INDEX_FORMAT:
1998 struct scsi_defect_desc_bytes_from_index *dlist;
2000 dlist = (struct scsi_defect_desc_bytes_from_index *)
2002 sizeof(struct scsi_read_defect_data_hdr_10));
2004 num_returned = returned_length /
2005 sizeof(struct scsi_defect_desc_bytes_from_index);
2007 fprintf(stderr, "Got %d defect", num_returned);
2009 if ((lists_specified == 0) || (num_returned == 0)) {
2010 fprintf(stderr, "s.\n");
2012 } else if (num_returned == 1)
2013 fprintf(stderr, ":\n");
2015 fprintf(stderr, "s:\n");
2017 for (i = 0; i < num_returned; i++) {
2018 fprintf(stdout, "%d:%d:%d\n",
2019 scsi_3btoul(dlist[i].cylinder),
2021 scsi_4btoul(dlist[i].bytes_from_index));
2025 case SRDDH10_BLOCK_FORMAT:
2027 struct scsi_defect_desc_block *dlist;
2029 dlist = (struct scsi_defect_desc_block *)(defect_list +
2030 sizeof(struct scsi_read_defect_data_hdr_10));
2032 num_returned = returned_length /
2033 sizeof(struct scsi_defect_desc_block);
2035 fprintf(stderr, "Got %d defect", num_returned);
2037 if ((lists_specified == 0) || (num_returned == 0)) {
2038 fprintf(stderr, "s.\n");
2040 } else if (num_returned == 1)
2041 fprintf(stderr, ":\n");
2043 fprintf(stderr, "s:\n");
2045 for (i = 0; i < num_returned; i++)
2046 fprintf(stdout, "%u\n",
2047 scsi_4btoul(dlist[i].address));
2051 fprintf(stderr, "Unknown defect format %d\n",
2052 returned_format & SRDDH10_DLIST_FORMAT_MASK);
2058 if (defect_list != NULL)
2066 #endif /* MINIMALISTIC */
2070 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
2074 ccb = cam_getccb(device);
2080 #ifndef MINIMALISTIC
2082 mode_sense(struct cam_device *device, int mode_page, int page_control,
2083 int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
2088 ccb = cam_getccb(device);
2091 errx(1, "mode_sense: couldn't allocate CCB");
2093 bzero(&(&ccb->ccb_h)[1],
2094 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2096 scsi_mode_sense(&ccb->csio,
2097 /* retries */ retry_count,
2099 /* tag_action */ MSG_SIMPLE_Q_TAG,
2101 /* page_code */ page_control << 6,
2102 /* page */ mode_page,
2103 /* param_buf */ data,
2104 /* param_len */ datalen,
2105 /* sense_len */ SSD_FULL_SIZE,
2106 /* timeout */ timeout ? timeout : 5000);
2108 if (arglist & CAM_ARG_ERR_RECOVER)
2109 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2111 /* Disable freezing the device queue */
2112 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2114 if (((retval = cam_send_ccb(device, ccb)) < 0)
2115 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2116 if (arglist & CAM_ARG_VERBOSE) {
2117 cam_error_print(device, ccb, CAM_ESF_ALL,
2118 CAM_EPF_ALL, stderr);
2121 cam_close_device(device);
2123 err(1, "error sending mode sense command");
2125 errx(1, "error sending mode sense command");
2132 mode_select(struct cam_device *device, int save_pages, int retry_count,
2133 int timeout, u_int8_t *data, int datalen)
2138 ccb = cam_getccb(device);
2141 errx(1, "mode_select: couldn't allocate CCB");
2143 bzero(&(&ccb->ccb_h)[1],
2144 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2146 scsi_mode_select(&ccb->csio,
2147 /* retries */ retry_count,
2149 /* tag_action */ MSG_SIMPLE_Q_TAG,
2150 /* scsi_page_fmt */ 1,
2151 /* save_pages */ save_pages,
2152 /* param_buf */ data,
2153 /* param_len */ datalen,
2154 /* sense_len */ SSD_FULL_SIZE,
2155 /* timeout */ timeout ? timeout : 5000);
2157 if (arglist & CAM_ARG_ERR_RECOVER)
2158 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2160 /* Disable freezing the device queue */
2161 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2163 if (((retval = cam_send_ccb(device, ccb)) < 0)
2164 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2165 if (arglist & CAM_ARG_VERBOSE) {
2166 cam_error_print(device, ccb, CAM_ESF_ALL,
2167 CAM_EPF_ALL, stderr);
2170 cam_close_device(device);
2173 err(1, "error sending mode select command");
2175 errx(1, "error sending mode select command");
2183 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
2184 int retry_count, int timeout)
2186 int c, mode_page = -1, page_control = 0;
2187 int binary = 0, list = 0;
2189 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2195 arglist |= CAM_ARG_DBD;
2198 arglist |= CAM_ARG_MODE_EDIT;
2204 mode_page = strtol(optarg, NULL, 0);
2206 errx(1, "invalid mode page %d", mode_page);
2209 page_control = strtol(optarg, NULL, 0);
2210 if ((page_control < 0) || (page_control > 3))
2211 errx(1, "invalid page control field %d",
2213 arglist |= CAM_ARG_PAGE_CNTL;
2220 if (mode_page == -1 && list == 0)
2221 errx(1, "you must specify a mode page!");
2224 mode_list(device, page_control, arglist & CAM_ARG_DBD,
2225 retry_count, timeout);
2227 mode_edit(device, mode_page, page_control,
2228 arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
2229 retry_count, timeout);
2234 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
2235 int retry_count, int timeout)
2238 u_int32_t flags = CAM_DIR_NONE;
2239 u_int8_t *data_ptr = NULL;
2241 u_int8_t atacmd[12];
2242 struct get_hook hook;
2243 int c, data_bytes = 0;
2249 char *datastr = NULL, *tstr, *resstr = NULL;
2251 int fd_data = 0, fd_res = 0;
2254 ccb = cam_getccb(device);
2257 warnx("scsicmd: error allocating ccb");
2261 bzero(&(&ccb->ccb_h)[1],
2262 sizeof(union ccb) - sizeof(struct ccb_hdr));
2264 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2268 while (isspace(*tstr) && (*tstr != '\0'))
2270 hook.argc = argc - optind;
2271 hook.argv = argv + optind;
2273 atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
2276 * Increment optind by the number of arguments the
2277 * encoding routine processed. After each call to
2278 * getopt(3), optind points to the argument that
2279 * getopt should process _next_. In this case,
2280 * that means it points to the first command string
2281 * argument, if there is one. Once we increment
2282 * this, it should point to either the next command
2283 * line argument, or it should be past the end of
2290 while (isspace(*tstr) && (*tstr != '\0'))
2292 hook.argc = argc - optind;
2293 hook.argv = argv + optind;
2295 cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
2298 * Increment optind by the number of arguments the
2299 * encoding routine processed. After each call to
2300 * getopt(3), optind points to the argument that
2301 * getopt should process _next_. In this case,
2302 * that means it points to the first command string
2303 * argument, if there is one. Once we increment
2304 * this, it should point to either the next command
2305 * line argument, or it should be past the end of
2317 if (arglist & CAM_ARG_CMD_OUT) {
2318 warnx("command must either be "
2319 "read or write, not both");
2321 goto scsicmd_bailout;
2323 arglist |= CAM_ARG_CMD_IN;
2325 data_bytes = strtol(optarg, NULL, 0);
2326 if (data_bytes <= 0) {
2327 warnx("invalid number of input bytes %d",
2330 goto scsicmd_bailout;
2332 hook.argc = argc - optind;
2333 hook.argv = argv + optind;
2336 datastr = cget(&hook, NULL);
2338 * If the user supplied "-" instead of a format, he
2339 * wants the data to be written to stdout.
2341 if ((datastr != NULL)
2342 && (datastr[0] == '-'))
2345 data_ptr = (u_int8_t *)malloc(data_bytes);
2346 if (data_ptr == NULL) {
2347 warnx("can't malloc memory for data_ptr");
2349 goto scsicmd_bailout;
2353 if (arglist & CAM_ARG_CMD_IN) {
2354 warnx("command must either be "
2355 "read or write, not both");
2357 goto scsicmd_bailout;
2359 arglist |= CAM_ARG_CMD_OUT;
2360 flags = CAM_DIR_OUT;
2361 data_bytes = strtol(optarg, NULL, 0);
2362 if (data_bytes <= 0) {
2363 warnx("invalid number of output bytes %d",
2366 goto scsicmd_bailout;
2368 hook.argc = argc - optind;
2369 hook.argv = argv + optind;
2371 datastr = cget(&hook, NULL);
2372 data_ptr = (u_int8_t *)malloc(data_bytes);
2373 if (data_ptr == NULL) {
2374 warnx("can't malloc memory for data_ptr");
2376 goto scsicmd_bailout;
2378 bzero(data_ptr, data_bytes);
2380 * If the user supplied "-" instead of a format, he
2381 * wants the data to be read from stdin.
2383 if ((datastr != NULL)
2384 && (datastr[0] == '-'))
2387 buff_encode_visit(data_ptr, data_bytes, datastr,
2393 hook.argc = argc - optind;
2394 hook.argv = argv + optind;
2396 resstr = cget(&hook, NULL);
2397 if ((resstr != NULL) && (resstr[0] == '-'))
2407 * If fd_data is set, and we're writing to the device, we need to
2408 * read the data the user wants written from stdin.
2410 if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
2412 int amt_to_read = data_bytes;
2413 u_int8_t *buf_ptr = data_ptr;
2415 for (amt_read = 0; amt_to_read > 0;
2416 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
2417 if (amt_read == -1) {
2418 warn("error reading data from stdin");
2420 goto scsicmd_bailout;
2422 amt_to_read -= amt_read;
2423 buf_ptr += amt_read;
2427 if (arglist & CAM_ARG_ERR_RECOVER)
2428 flags |= CAM_PASS_ERR_RECOVER;
2430 /* Disable freezing the device queue */
2431 flags |= CAM_DEV_QFRZDIS;
2435 * This is taken from the SCSI-3 draft spec.
2436 * (T10/1157D revision 0.3)
2437 * The top 3 bits of an opcode are the group code.
2438 * The next 5 bits are the command code.
2439 * Group 0: six byte commands
2440 * Group 1: ten byte commands
2441 * Group 2: ten byte commands
2443 * Group 4: sixteen byte commands
2444 * Group 5: twelve byte commands
2445 * Group 6: vendor specific
2446 * Group 7: vendor specific
2448 switch((cdb[0] >> 5) & 0x7) {
2459 /* computed by buff_encode_visit */
2470 * We should probably use csio_build_visit or something like that
2471 * here, but it's easier to encode arguments as you go. The
2472 * alternative would be skipping the CDB argument and then encoding
2473 * it here, since we've got the data buffer argument by now.
2475 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
2477 cam_fill_csio(&ccb->csio,
2478 /*retries*/ retry_count,
2481 /*tag_action*/ MSG_SIMPLE_Q_TAG,
2482 /*data_ptr*/ data_ptr,
2483 /*dxfer_len*/ data_bytes,
2484 /*sense_len*/ SSD_FULL_SIZE,
2485 /*cdb_len*/ cdb_len,
2486 /*timeout*/ timeout ? timeout : 5000);
2489 bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
2491 ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
2493 ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
2495 ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
2497 cam_fill_ataio(&ccb->ataio,
2498 /*retries*/ retry_count,
2502 /*data_ptr*/ data_ptr,
2503 /*dxfer_len*/ data_bytes,
2504 /*timeout*/ timeout ? timeout : 5000);
2507 if (((retval = cam_send_ccb(device, ccb)) < 0)
2508 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2509 const char warnstr[] = "error sending command";
2516 if (arglist & CAM_ARG_VERBOSE) {
2517 cam_error_print(device, ccb, CAM_ESF_ALL,
2518 CAM_EPF_ALL, stderr);
2522 goto scsicmd_bailout;
2525 if (atacmd_len && need_res) {
2527 buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
2529 fprintf(stdout, "\n");
2532 "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
2533 ccb->ataio.res.status,
2534 ccb->ataio.res.error,
2535 ccb->ataio.res.lba_low,
2536 ccb->ataio.res.lba_mid,
2537 ccb->ataio.res.lba_high,
2538 ccb->ataio.res.device,
2539 ccb->ataio.res.lba_low_exp,
2540 ccb->ataio.res.lba_mid_exp,
2541 ccb->ataio.res.lba_high_exp,
2542 ccb->ataio.res.sector_count,
2543 ccb->ataio.res.sector_count_exp);
2548 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
2549 && (arglist & CAM_ARG_CMD_IN)
2550 && (data_bytes > 0)) {
2552 buff_decode_visit(data_ptr, data_bytes, datastr,
2554 fprintf(stdout, "\n");
2556 ssize_t amt_written;
2557 int amt_to_write = data_bytes;
2558 u_int8_t *buf_ptr = data_ptr;
2560 for (amt_written = 0; (amt_to_write > 0) &&
2561 (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
2562 amt_to_write -= amt_written;
2563 buf_ptr += amt_written;
2565 if (amt_written == -1) {
2566 warn("error writing data to stdout");
2568 goto scsicmd_bailout;
2569 } else if ((amt_written == 0)
2570 && (amt_to_write > 0)) {
2571 warnx("only wrote %u bytes out of %u",
2572 data_bytes - amt_to_write, data_bytes);
2579 if ((data_bytes > 0) && (data_ptr != NULL))
2588 camdebug(int argc, char **argv, char *combinedopt)
2591 int bus = -1, target = -1, lun = -1;
2592 char *tstr, *tmpstr = NULL;
2596 bzero(&ccb, sizeof(union ccb));
2598 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2601 arglist |= CAM_ARG_DEBUG_INFO;
2602 ccb.cdbg.flags |= CAM_DEBUG_INFO;
2605 arglist |= CAM_ARG_DEBUG_PERIPH;
2606 ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
2609 arglist |= CAM_ARG_DEBUG_SUBTRACE;
2610 ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
2613 arglist |= CAM_ARG_DEBUG_TRACE;
2614 ccb.cdbg.flags |= CAM_DEBUG_TRACE;
2617 arglist |= CAM_ARG_DEBUG_XPT;
2618 ccb.cdbg.flags |= CAM_DEBUG_XPT;
2621 arglist |= CAM_ARG_DEBUG_CDB;
2622 ccb.cdbg.flags |= CAM_DEBUG_CDB;
2629 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
2630 warnx("error opening transport layer device %s", XPT_DEVICE);
2631 warn("%s", XPT_DEVICE);
2638 warnx("you must specify \"off\", \"all\" or a bus,");
2639 warnx("bus:target, or bus:target:lun");
2646 while (isspace(*tstr) && (*tstr != '\0'))
2649 if (strncmp(tstr, "off", 3) == 0) {
2650 ccb.cdbg.flags = CAM_DEBUG_NONE;
2651 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
2652 CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
2654 } else if (strncmp(tstr, "all", 3) != 0) {
2655 tmpstr = (char *)strtok(tstr, ":");
2656 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2657 bus = strtol(tmpstr, NULL, 0);
2658 arglist |= CAM_ARG_BUS;
2659 tmpstr = (char *)strtok(NULL, ":");
2660 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2661 target = strtol(tmpstr, NULL, 0);
2662 arglist |= CAM_ARG_TARGET;
2663 tmpstr = (char *)strtok(NULL, ":");
2664 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2665 lun = strtol(tmpstr, NULL, 0);
2666 arglist |= CAM_ARG_LUN;
2671 warnx("you must specify \"all\", \"off\", or a bus,");
2672 warnx("bus:target, or bus:target:lun to debug");
2678 ccb.ccb_h.func_code = XPT_DEBUG;
2679 ccb.ccb_h.path_id = bus;
2680 ccb.ccb_h.target_id = target;
2681 ccb.ccb_h.target_lun = lun;
2683 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
2684 warn("CAMIOCOMMAND ioctl failed");
2689 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
2690 CAM_FUNC_NOTAVAIL) {
2691 warnx("CAM debugging not available");
2692 warnx("you need to put options CAMDEBUG in"
2693 " your kernel config file!");
2695 } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
2697 warnx("XPT_DEBUG CCB failed with status %#x",
2701 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
2703 "Debugging turned off\n");
2706 "Debugging enabled for "
2719 tagcontrol(struct cam_device *device, int argc, char **argv,
2729 ccb = cam_getccb(device);
2732 warnx("tagcontrol: error allocating ccb");
2736 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2739 numtags = strtol(optarg, NULL, 0);
2741 warnx("tag count %d is < 0", numtags);
2743 goto tagcontrol_bailout;
2754 cam_path_string(device, pathstr, sizeof(pathstr));
2757 bzero(&(&ccb->ccb_h)[1],
2758 sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
2759 ccb->ccb_h.func_code = XPT_REL_SIMQ;
2760 ccb->ccb_h.flags = CAM_DEV_QFREEZE;
2761 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
2762 ccb->crs.openings = numtags;
2765 if (cam_send_ccb(device, ccb) < 0) {
2766 perror("error sending XPT_REL_SIMQ CCB");
2768 goto tagcontrol_bailout;
2771 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2772 warnx("XPT_REL_SIMQ CCB failed");
2773 cam_error_print(device, ccb, CAM_ESF_ALL,
2774 CAM_EPF_ALL, stderr);
2776 goto tagcontrol_bailout;
2781 fprintf(stdout, "%stagged openings now %d\n",
2782 pathstr, ccb->crs.openings);
2785 bzero(&(&ccb->ccb_h)[1],
2786 sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
2788 ccb->ccb_h.func_code = XPT_GDEV_STATS;
2790 if (cam_send_ccb(device, ccb) < 0) {
2791 perror("error sending XPT_GDEV_STATS CCB");
2793 goto tagcontrol_bailout;
2796 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2797 warnx("XPT_GDEV_STATS CCB failed");
2798 cam_error_print(device, ccb, CAM_ESF_ALL,
2799 CAM_EPF_ALL, stderr);
2801 goto tagcontrol_bailout;
2804 if (arglist & CAM_ARG_VERBOSE) {
2805 fprintf(stdout, "%s", pathstr);
2806 fprintf(stdout, "dev_openings %d\n", ccb->cgds.dev_openings);
2807 fprintf(stdout, "%s", pathstr);
2808 fprintf(stdout, "dev_active %d\n", ccb->cgds.dev_active);
2809 fprintf(stdout, "%s", pathstr);
2810 fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
2811 fprintf(stdout, "%s", pathstr);
2812 fprintf(stdout, "devq_queued %d\n", ccb->cgds.devq_queued);
2813 fprintf(stdout, "%s", pathstr);
2814 fprintf(stdout, "held %d\n", ccb->cgds.held);
2815 fprintf(stdout, "%s", pathstr);
2816 fprintf(stdout, "mintags %d\n", ccb->cgds.mintags);
2817 fprintf(stdout, "%s", pathstr);
2818 fprintf(stdout, "maxtags %d\n", ccb->cgds.maxtags);
2821 fprintf(stdout, "%s", pathstr);
2822 fprintf(stdout, "device openings: ");
2824 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
2825 ccb->cgds.dev_active);
2835 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
2839 cam_path_string(device, pathstr, sizeof(pathstr));
2841 if (cts->transport == XPORT_SPI) {
2842 struct ccb_trans_settings_spi *spi =
2843 &cts->xport_specific.spi;
2845 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
2847 fprintf(stdout, "%ssync parameter: %d\n", pathstr,
2850 if (spi->sync_offset != 0) {
2853 freq = scsi_calc_syncsrate(spi->sync_period);
2854 fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
2855 pathstr, freq / 1000, freq % 1000);
2859 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
2860 fprintf(stdout, "%soffset: %d\n", pathstr,
2864 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
2865 fprintf(stdout, "%sbus width: %d bits\n", pathstr,
2866 (0x01 << spi->bus_width) * 8);
2869 if (spi->valid & CTS_SPI_VALID_DISC) {
2870 fprintf(stdout, "%sdisconnection is %s\n", pathstr,
2871 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
2872 "enabled" : "disabled");
2875 if (cts->transport == XPORT_ATA) {
2876 struct ccb_trans_settings_ata *ata =
2877 &cts->xport_specific.ata;
2879 if ((ata->valid & CTS_ATA_VALID_MODE) != 0) {
2880 fprintf(stdout, "%sATA mode: %s\n", pathstr,
2881 ata_mode2string(ata->mode));
2883 if ((ata->valid & CTS_ATA_VALID_ATAPI) != 0) {
2884 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2887 if ((ata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
2888 fprintf(stdout, "%sPIO transaction length: %d\n",
2889 pathstr, ata->bytecount);
2892 if (cts->transport == XPORT_SATA) {
2893 struct ccb_trans_settings_sata *sata =
2894 &cts->xport_specific.sata;
2896 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
2897 fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
2900 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
2901 fprintf(stdout, "%sATA mode: %s\n", pathstr,
2902 ata_mode2string(sata->mode));
2904 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
2905 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2908 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
2909 fprintf(stdout, "%sPIO transaction length: %d\n",
2910 pathstr, sata->bytecount);
2912 if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
2913 fprintf(stdout, "%sPMP presence: %d\n", pathstr,
2916 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
2917 fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
2920 if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
2921 fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
2925 if (cts->protocol == PROTO_SCSI) {
2926 struct ccb_trans_settings_scsi *scsi=
2927 &cts->proto_specific.scsi;
2929 if (scsi->valid & CTS_SCSI_VALID_TQ) {
2930 fprintf(stdout, "%stagged queueing is %s\n", pathstr,
2931 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
2932 "enabled" : "disabled");
2939 * Get a path inquiry CCB for the specified device.
2942 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
2947 ccb = cam_getccb(device);
2949 warnx("get_cpi: couldn't allocate CCB");
2952 bzero(&(&ccb->ccb_h)[1],
2953 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2954 ccb->ccb_h.func_code = XPT_PATH_INQ;
2955 if (cam_send_ccb(device, ccb) < 0) {
2956 warn("get_cpi: error sending Path Inquiry CCB");
2957 if (arglist & CAM_ARG_VERBOSE)
2958 cam_error_print(device, ccb, CAM_ESF_ALL,
2959 CAM_EPF_ALL, stderr);
2961 goto get_cpi_bailout;
2963 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2964 if (arglist & CAM_ARG_VERBOSE)
2965 cam_error_print(device, ccb, CAM_ESF_ALL,
2966 CAM_EPF_ALL, stderr);
2968 goto get_cpi_bailout;
2970 bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
2978 * Get a get device CCB for the specified device.
2981 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
2986 ccb = cam_getccb(device);
2988 warnx("get_cgd: couldn't allocate CCB");
2991 bzero(&(&ccb->ccb_h)[1],
2992 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2993 ccb->ccb_h.func_code = XPT_GDEV_TYPE;
2994 if (cam_send_ccb(device, ccb) < 0) {
2995 warn("get_cgd: error sending Path Inquiry CCB");
2996 if (arglist & CAM_ARG_VERBOSE)
2997 cam_error_print(device, ccb, CAM_ESF_ALL,
2998 CAM_EPF_ALL, stderr);
3000 goto get_cgd_bailout;
3002 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3003 if (arglist & CAM_ARG_VERBOSE)
3004 cam_error_print(device, ccb, CAM_ESF_ALL,
3005 CAM_EPF_ALL, stderr);
3007 goto get_cgd_bailout;
3009 bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
3017 cpi_print(struct ccb_pathinq *cpi)
3019 char adapter_str[1024];
3022 snprintf(adapter_str, sizeof(adapter_str),
3023 "%s%d:", cpi->dev_name, cpi->unit_number);
3025 fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
3028 for (i = 1; i < 0xff; i = i << 1) {
3031 if ((i & cpi->hba_inquiry) == 0)
3034 fprintf(stdout, "%s supports ", adapter_str);
3038 str = "MDP message";
3041 str = "32 bit wide SCSI";
3044 str = "16 bit wide SCSI";
3047 str = "SDTR message";
3050 str = "linked CDBs";
3053 str = "tag queue messages";
3056 str = "soft reset alternative";
3059 str = "SATA Port Multiplier";
3062 str = "unknown PI bit set";
3065 fprintf(stdout, "%s\n", str);
3068 for (i = 1; i < 0xff; i = i << 1) {
3071 if ((i & cpi->hba_misc) == 0)
3074 fprintf(stdout, "%s ", adapter_str);
3078 str = "bus scans from high ID to low ID";
3081 str = "removable devices not included in scan";
3083 case PIM_NOINITIATOR:
3084 str = "initiator role not supported";
3086 case PIM_NOBUSRESET:
3087 str = "user has disabled initial BUS RESET or"
3088 " controller is in target/mixed mode";
3091 str = "do not send 6-byte commands";
3094 str = "scan bus sequentially";
3097 str = "unknown PIM bit set";
3100 fprintf(stdout, "%s\n", str);
3103 for (i = 1; i < 0xff; i = i << 1) {
3106 if ((i & cpi->target_sprt) == 0)
3109 fprintf(stdout, "%s supports ", adapter_str);
3112 str = "target mode processor mode";
3115 str = "target mode phase cog. mode";
3117 case PIT_DISCONNECT:
3118 str = "disconnects in target mode";
3121 str = "terminate I/O message in target mode";
3124 str = "group 6 commands in target mode";
3127 str = "group 7 commands in target mode";
3130 str = "unknown PIT bit set";
3134 fprintf(stdout, "%s\n", str);
3136 fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
3138 fprintf(stdout, "%s maximum target: %d\n", adapter_str,
3140 fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
3142 fprintf(stdout, "%s highest path ID in subsystem: %d\n",
3143 adapter_str, cpi->hpath_id);
3144 fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
3146 fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
3147 fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
3148 fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
3149 adapter_str, cpi->hba_vendor);
3150 fprintf(stdout, "%s HBA device ID: 0x%04x\n",
3151 adapter_str, cpi->hba_device);
3152 fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
3153 adapter_str, cpi->hba_subvendor);
3154 fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
3155 adapter_str, cpi->hba_subdevice);
3156 fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
3157 fprintf(stdout, "%s base transfer speed: ", adapter_str);
3158 if (cpi->base_transfer_speed > 1000)
3159 fprintf(stdout, "%d.%03dMB/sec\n",
3160 cpi->base_transfer_speed / 1000,
3161 cpi->base_transfer_speed % 1000);
3163 fprintf(stdout, "%dKB/sec\n",
3164 (cpi->base_transfer_speed % 1000) * 1000);
3165 fprintf(stdout, "%s maximum transfer size: %u bytes\n",
3166 adapter_str, cpi->maxio);
3170 get_print_cts(struct cam_device *device, int user_settings, int quiet,
3171 struct ccb_trans_settings *cts)
3177 ccb = cam_getccb(device);
3180 warnx("get_print_cts: error allocating ccb");
3184 bzero(&(&ccb->ccb_h)[1],
3185 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3187 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
3189 if (user_settings == 0)
3190 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
3192 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
3194 if (cam_send_ccb(device, ccb) < 0) {
3195 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
3196 if (arglist & CAM_ARG_VERBOSE)
3197 cam_error_print(device, ccb, CAM_ESF_ALL,
3198 CAM_EPF_ALL, stderr);
3200 goto get_print_cts_bailout;
3203 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3204 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
3205 if (arglist & CAM_ARG_VERBOSE)
3206 cam_error_print(device, ccb, CAM_ESF_ALL,
3207 CAM_EPF_ALL, stderr);
3209 goto get_print_cts_bailout;
3213 cts_print(device, &ccb->cts);
3216 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
3218 get_print_cts_bailout:
3226 ratecontrol(struct cam_device *device, int retry_count, int timeout,
3227 int argc, char **argv, char *combinedopt)
3231 int user_settings = 0;
3233 int disc_enable = -1, tag_enable = -1;
3236 double syncrate = -1;
3239 int change_settings = 0, send_tur = 0;
3240 struct ccb_pathinq cpi;
3242 ccb = cam_getccb(device);
3244 warnx("ratecontrol: error allocating ccb");
3247 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3256 if (strncasecmp(optarg, "enable", 6) == 0)
3258 else if (strncasecmp(optarg, "disable", 7) == 0)
3261 warnx("-D argument \"%s\" is unknown", optarg);
3263 goto ratecontrol_bailout;
3265 change_settings = 1;
3268 mode = ata_string2mode(optarg);
3270 warnx("unknown mode '%s'", optarg);
3272 goto ratecontrol_bailout;
3274 change_settings = 1;
3277 offset = strtol(optarg, NULL, 0);
3279 warnx("offset value %d is < 0", offset);
3281 goto ratecontrol_bailout;
3283 change_settings = 1;
3289 syncrate = atof(optarg);
3291 warnx("sync rate %f is < 0", syncrate);
3293 goto ratecontrol_bailout;
3295 change_settings = 1;
3298 if (strncasecmp(optarg, "enable", 6) == 0)
3300 else if (strncasecmp(optarg, "disable", 7) == 0)
3303 warnx("-T argument \"%s\" is unknown", optarg);
3305 goto ratecontrol_bailout;
3307 change_settings = 1;
3313 bus_width = strtol(optarg, NULL, 0);
3314 if (bus_width < 0) {
3315 warnx("bus width %d is < 0", bus_width);
3317 goto ratecontrol_bailout;
3319 change_settings = 1;
3325 bzero(&(&ccb->ccb_h)[1],
3326 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3328 * Grab path inquiry information, so we can determine whether
3329 * or not the initiator is capable of the things that the user
3332 ccb->ccb_h.func_code = XPT_PATH_INQ;
3333 if (cam_send_ccb(device, ccb) < 0) {
3334 perror("error sending XPT_PATH_INQ CCB");
3335 if (arglist & CAM_ARG_VERBOSE) {
3336 cam_error_print(device, ccb, CAM_ESF_ALL,
3337 CAM_EPF_ALL, stderr);
3340 goto ratecontrol_bailout;
3342 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3343 warnx("XPT_PATH_INQ CCB failed");
3344 if (arglist & CAM_ARG_VERBOSE) {
3345 cam_error_print(device, ccb, CAM_ESF_ALL,
3346 CAM_EPF_ALL, stderr);
3349 goto ratecontrol_bailout;
3351 bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
3352 bzero(&(&ccb->ccb_h)[1],
3353 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3355 fprintf(stdout, "%s parameters:\n",
3356 user_settings ? "User" : "Current");
3358 retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
3360 goto ratecontrol_bailout;
3362 if (arglist & CAM_ARG_VERBOSE)
3365 if (change_settings) {
3366 int didsettings = 0;
3367 struct ccb_trans_settings_spi *spi = NULL;
3368 struct ccb_trans_settings_ata *ata = NULL;
3369 struct ccb_trans_settings_sata *sata = NULL;
3370 struct ccb_trans_settings_scsi *scsi = NULL;
3372 if (ccb->cts.transport == XPORT_SPI)
3373 spi = &ccb->cts.xport_specific.spi;
3374 if (ccb->cts.transport == XPORT_ATA)
3375 ata = &ccb->cts.xport_specific.ata;
3376 if (ccb->cts.transport == XPORT_SATA)
3377 sata = &ccb->cts.xport_specific.sata;
3378 if (ccb->cts.protocol == PROTO_SCSI)
3379 scsi = &ccb->cts.proto_specific.scsi;
3380 ccb->cts.xport_specific.valid = 0;
3381 ccb->cts.proto_specific.valid = 0;
3382 if (spi && disc_enable != -1) {
3383 spi->valid |= CTS_SPI_VALID_DISC;
3384 if (disc_enable == 0)
3385 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
3387 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
3390 if (scsi && tag_enable != -1) {
3391 if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
3392 warnx("HBA does not support tagged queueing, "
3393 "so you cannot modify tag settings");
3395 goto ratecontrol_bailout;
3397 scsi->valid |= CTS_SCSI_VALID_TQ;
3398 if (tag_enable == 0)
3399 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
3401 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
3404 if (spi && offset != -1) {
3405 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3406 warnx("HBA is not capable of changing offset");
3408 goto ratecontrol_bailout;
3410 spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
3411 spi->sync_offset = offset;
3414 if (spi && syncrate != -1) {
3415 int prelim_sync_period;
3417 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3418 warnx("HBA is not capable of changing "
3421 goto ratecontrol_bailout;
3423 spi->valid |= CTS_SPI_VALID_SYNC_RATE;
3425 * The sync rate the user gives us is in MHz.
3426 * We need to translate it into KHz for this
3431 * Next, we calculate a "preliminary" sync period
3432 * in tenths of a nanosecond.
3435 prelim_sync_period = 0;
3437 prelim_sync_period = 10000000 / syncrate;
3439 scsi_calc_syncparam(prelim_sync_period);
3442 if (sata && syncrate != -1) {
3443 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3444 warnx("HBA is not capable of changing "
3447 goto ratecontrol_bailout;
3449 sata->revision = ata_speed2revision(syncrate * 100);
3450 if (sata->revision < 0) {
3451 warnx("Invalid rate %f", syncrate);
3453 goto ratecontrol_bailout;
3455 sata->valid |= CTS_SATA_VALID_REVISION;
3458 if ((ata || sata) && mode != -1) {
3459 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3460 warnx("HBA is not capable of changing "
3463 goto ratecontrol_bailout;
3467 ata->valid |= CTS_ATA_VALID_MODE;
3470 sata->valid |= CTS_SATA_VALID_MODE;
3475 * The bus_width argument goes like this:
3479 * Therefore, if you shift the number of bits given on the
3480 * command line right by 4, you should get the correct
3483 if (spi && bus_width != -1) {
3485 * We might as well validate things here with a
3486 * decipherable error message, rather than what
3487 * will probably be an indecipherable error message
3488 * by the time it gets back to us.
3490 if ((bus_width == 16)
3491 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
3492 warnx("HBA does not support 16 bit bus width");
3494 goto ratecontrol_bailout;
3495 } else if ((bus_width == 32)
3496 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
3497 warnx("HBA does not support 32 bit bus width");
3499 goto ratecontrol_bailout;
3500 } else if ((bus_width != 8)
3501 && (bus_width != 16)
3502 && (bus_width != 32)) {
3503 warnx("Invalid bus width %d", bus_width);
3505 goto ratecontrol_bailout;
3507 spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
3508 spi->bus_width = bus_width >> 4;
3511 if (didsettings == 0) {
3512 goto ratecontrol_bailout;
3514 if (!user_settings && (ata || sata)) {
3515 warnx("You can modify only user settings for ATA/SATA");
3517 goto ratecontrol_bailout;
3519 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
3520 if (cam_send_ccb(device, ccb) < 0) {
3521 perror("error sending XPT_SET_TRAN_SETTINGS CCB");
3522 if (arglist & CAM_ARG_VERBOSE) {
3523 cam_error_print(device, ccb, CAM_ESF_ALL,
3524 CAM_EPF_ALL, stderr);
3527 goto ratecontrol_bailout;
3529 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3530 warnx("XPT_SET_TRANS_SETTINGS CCB failed");
3531 if (arglist & CAM_ARG_VERBOSE) {
3532 cam_error_print(device, ccb, CAM_ESF_ALL,
3533 CAM_EPF_ALL, stderr);
3536 goto ratecontrol_bailout;
3540 retval = testunitready(device, retry_count, timeout,
3541 (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
3543 * If the TUR didn't succeed, just bail.
3547 fprintf(stderr, "Test Unit Ready failed\n");
3548 goto ratecontrol_bailout;
3551 * If the user wants things quiet, there's no sense in
3552 * getting the transfer settings, if we're not going
3556 goto ratecontrol_bailout;
3557 fprintf(stdout, "New parameters:\n");
3558 retval = get_print_cts(device, user_settings, 0, NULL);
3561 ratecontrol_bailout:
3567 scsiformat(struct cam_device *device, int argc, char **argv,
3568 char *combinedopt, int retry_count, int timeout)
3572 int ycount = 0, quiet = 0;
3573 int error = 0, response = 0, retval = 0;
3574 int use_timeout = 10800 * 1000;
3576 struct format_defect_list_header fh;
3577 u_int8_t *data_ptr = NULL;
3578 u_int32_t dxfer_len = 0;
3580 int num_warnings = 0;
3583 ccb = cam_getccb(device);
3586 warnx("scsiformat: error allocating ccb");
3590 bzero(&(&ccb->ccb_h)[1],
3591 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3593 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3614 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
3615 "following device:\n");
3617 error = scsidoinquiry(device, argc, argv, combinedopt,
3618 retry_count, timeout);
3621 warnx("scsiformat: error sending inquiry");
3622 goto scsiformat_bailout;
3631 fprintf(stdout, "Are you SURE you want to do "
3634 if (fgets(str, sizeof(str), stdin) != NULL) {
3636 if (strncasecmp(str, "yes", 3) == 0)
3638 else if (strncasecmp(str, "no", 2) == 0)
3641 fprintf(stdout, "Please answer"
3642 " \"yes\" or \"no\"\n");
3645 } while (response == 0);
3647 if (response == -1) {
3649 goto scsiformat_bailout;
3654 use_timeout = timeout;
3657 fprintf(stdout, "Current format timeout is %d seconds\n",
3658 use_timeout / 1000);
3662 * If the user hasn't disabled questions and didn't specify a
3663 * timeout on the command line, ask them if they want the current
3667 && (timeout == 0)) {
3669 int new_timeout = 0;
3671 fprintf(stdout, "Enter new timeout in seconds or press\n"
3672 "return to keep the current timeout [%d] ",
3673 use_timeout / 1000);
3675 if (fgets(str, sizeof(str), stdin) != NULL) {
3677 new_timeout = atoi(str);
3680 if (new_timeout != 0) {
3681 use_timeout = new_timeout * 1000;
3682 fprintf(stdout, "Using new timeout value %d\n",
3683 use_timeout / 1000);
3688 * Keep this outside the if block below to silence any unused
3689 * variable warnings.
3691 bzero(&fh, sizeof(fh));
3694 * If we're in immediate mode, we've got to include the format
3697 if (immediate != 0) {
3698 fh.byte2 = FU_DLH_IMMED;
3699 data_ptr = (u_int8_t *)&fh;
3700 dxfer_len = sizeof(fh);
3701 byte2 = FU_FMT_DATA;
3702 } else if (quiet == 0) {
3703 fprintf(stdout, "Formatting...");
3707 scsi_format_unit(&ccb->csio,
3708 /* retries */ retry_count,
3710 /* tag_action */ MSG_SIMPLE_Q_TAG,
3713 /* data_ptr */ data_ptr,
3714 /* dxfer_len */ dxfer_len,
3715 /* sense_len */ SSD_FULL_SIZE,
3716 /* timeout */ use_timeout);
3718 /* Disable freezing the device queue */
3719 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3721 if (arglist & CAM_ARG_ERR_RECOVER)
3722 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3724 if (((retval = cam_send_ccb(device, ccb)) < 0)
3725 || ((immediate == 0)
3726 && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
3727 const char errstr[] = "error sending format command";
3734 if (arglist & CAM_ARG_VERBOSE) {
3735 cam_error_print(device, ccb, CAM_ESF_ALL,
3736 CAM_EPF_ALL, stderr);
3739 goto scsiformat_bailout;
3743 * If we ran in non-immediate mode, we already checked for errors
3744 * above and printed out any necessary information. If we're in
3745 * immediate mode, we need to loop through and get status
3746 * information periodically.
3748 if (immediate == 0) {
3750 fprintf(stdout, "Format Complete\n");
3752 goto scsiformat_bailout;
3759 bzero(&(&ccb->ccb_h)[1],
3760 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3763 * There's really no need to do error recovery or
3764 * retries here, since we're just going to sit in a
3765 * loop and wait for the device to finish formatting.
3767 scsi_test_unit_ready(&ccb->csio,
3770 /* tag_action */ MSG_SIMPLE_Q_TAG,
3771 /* sense_len */ SSD_FULL_SIZE,
3772 /* timeout */ 5000);
3774 /* Disable freezing the device queue */
3775 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3777 retval = cam_send_ccb(device, ccb);
3780 * If we get an error from the ioctl, bail out. SCSI
3781 * errors are expected.
3784 warn("error sending CAMIOCOMMAND ioctl");
3785 if (arglist & CAM_ARG_VERBOSE) {
3786 cam_error_print(device, ccb, CAM_ESF_ALL,
3787 CAM_EPF_ALL, stderr);
3790 goto scsiformat_bailout;
3793 status = ccb->ccb_h.status & CAM_STATUS_MASK;
3795 if ((status != CAM_REQ_CMP)
3796 && (status == CAM_SCSI_STATUS_ERROR)
3797 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3798 struct scsi_sense_data *sense;
3799 int error_code, sense_key, asc, ascq;
3801 sense = &ccb->csio.sense_data;
3802 scsi_extract_sense_len(sense, ccb->csio.sense_len -
3803 ccb->csio.sense_resid, &error_code, &sense_key,
3804 &asc, &ascq, /*show_errors*/ 1);
3807 * According to the SCSI-2 and SCSI-3 specs, a
3808 * drive that is in the middle of a format should
3809 * return NOT READY with an ASC of "logical unit
3810 * not ready, format in progress". The sense key
3811 * specific bytes will then be a progress indicator.
3813 if ((sense_key == SSD_KEY_NOT_READY)
3814 && (asc == 0x04) && (ascq == 0x04)) {
3817 if ((scsi_get_sks(sense, ccb->csio.sense_len -
3818 ccb->csio.sense_resid, sks) == 0)
3821 u_int64_t percentage;
3823 val = scsi_2btoul(&sks[1]);
3824 percentage = 10000 * val;
3827 "\rFormatting: %ju.%02u %% "
3829 (uintmax_t)(percentage /
3831 (unsigned)((percentage /
3835 } else if ((quiet == 0)
3836 && (++num_warnings <= 1)) {
3837 warnx("Unexpected SCSI Sense Key "
3838 "Specific value returned "
3840 scsi_sense_print(device, &ccb->csio,
3842 warnx("Unable to print status "
3843 "information, but format will "
3845 warnx("will exit when format is "
3850 warnx("Unexpected SCSI error during format");
3851 cam_error_print(device, ccb, CAM_ESF_ALL,
3852 CAM_EPF_ALL, stderr);
3854 goto scsiformat_bailout;
3857 } else if (status != CAM_REQ_CMP) {
3858 warnx("Unexpected CAM status %#x", status);
3859 if (arglist & CAM_ARG_VERBOSE)
3860 cam_error_print(device, ccb, CAM_ESF_ALL,
3861 CAM_EPF_ALL, stderr);
3863 goto scsiformat_bailout;
3866 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
3869 fprintf(stdout, "\nFormat Complete\n");
3879 scsireportluns(struct cam_device *device, int argc, char **argv,
3880 char *combinedopt, int retry_count, int timeout)
3883 int c, countonly, lunsonly;
3884 struct scsi_report_luns_data *lundata;
3886 uint8_t report_type;
3887 uint32_t list_len, i, j;
3892 report_type = RPL_REPORT_DEFAULT;
3893 ccb = cam_getccb(device);
3896 warnx("%s: error allocating ccb", __func__);
3900 bzero(&(&ccb->ccb_h)[1],
3901 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3906 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3915 if (strcasecmp(optarg, "default") == 0)
3916 report_type = RPL_REPORT_DEFAULT;
3917 else if (strcasecmp(optarg, "wellknown") == 0)
3918 report_type = RPL_REPORT_WELLKNOWN;
3919 else if (strcasecmp(optarg, "all") == 0)
3920 report_type = RPL_REPORT_ALL;
3922 warnx("%s: invalid report type \"%s\"",
3933 if ((countonly != 0)
3934 && (lunsonly != 0)) {
3935 warnx("%s: you can only specify one of -c or -l", __func__);
3940 * According to SPC-4, the allocation length must be at least 16
3941 * bytes -- enough for the header and one LUN.
3943 alloc_len = sizeof(*lundata) + 8;
3947 lundata = malloc(alloc_len);
3949 if (lundata == NULL) {
3950 warn("%s: error mallocing %d bytes", __func__, alloc_len);
3955 scsi_report_luns(&ccb->csio,
3956 /*retries*/ retry_count,
3958 /*tag_action*/ MSG_SIMPLE_Q_TAG,
3959 /*select_report*/ report_type,
3960 /*rpl_buf*/ lundata,
3961 /*alloc_len*/ alloc_len,
3962 /*sense_len*/ SSD_FULL_SIZE,
3963 /*timeout*/ timeout ? timeout : 5000);
3965 /* Disable freezing the device queue */
3966 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3968 if (arglist & CAM_ARG_ERR_RECOVER)
3969 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3971 if (cam_send_ccb(device, ccb) < 0) {
3972 warn("error sending REPORT LUNS command");
3974 if (arglist & CAM_ARG_VERBOSE)
3975 cam_error_print(device, ccb, CAM_ESF_ALL,
3976 CAM_EPF_ALL, stderr);
3982 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3983 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
3989 list_len = scsi_4btoul(lundata->length);
3992 * If we need to list the LUNs, and our allocation
3993 * length was too short, reallocate and retry.
3995 if ((countonly == 0)
3996 && (list_len > (alloc_len - sizeof(*lundata)))) {
3997 alloc_len = list_len + sizeof(*lundata);
4003 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
4004 ((list_len / 8) > 1) ? "s" : "");
4009 for (i = 0; i < (list_len / 8); i++) {
4013 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
4015 fprintf(stdout, ",");
4016 switch (lundata->luns[i].lundata[j] &
4017 RPL_LUNDATA_ATYP_MASK) {
4018 case RPL_LUNDATA_ATYP_PERIPH:
4019 if ((lundata->luns[i].lundata[j] &
4020 RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
4021 fprintf(stdout, "%d:",
4022 lundata->luns[i].lundata[j] &
4023 RPL_LUNDATA_PERIPH_BUS_MASK);
4025 && ((lundata->luns[i].lundata[j+2] &
4026 RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
4029 fprintf(stdout, "%d",
4030 lundata->luns[i].lundata[j+1]);
4032 case RPL_LUNDATA_ATYP_FLAT: {
4034 tmplun[0] = lundata->luns[i].lundata[j] &
4035 RPL_LUNDATA_FLAT_LUN_MASK;
4036 tmplun[1] = lundata->luns[i].lundata[j+1];
4038 fprintf(stdout, "%d", scsi_2btoul(tmplun));
4042 case RPL_LUNDATA_ATYP_LUN:
4043 fprintf(stdout, "%d:%d:%d",
4044 (lundata->luns[i].lundata[j+1] &
4045 RPL_LUNDATA_LUN_BUS_MASK) >> 5,
4046 lundata->luns[i].lundata[j] &
4047 RPL_LUNDATA_LUN_TARG_MASK,
4048 lundata->luns[i].lundata[j+1] &
4049 RPL_LUNDATA_LUN_LUN_MASK);
4051 case RPL_LUNDATA_ATYP_EXTLUN: {
4052 int field_len_code, eam_code;
4054 eam_code = lundata->luns[i].lundata[j] &
4055 RPL_LUNDATA_EXT_EAM_MASK;
4056 field_len_code = (lundata->luns[i].lundata[j] &
4057 RPL_LUNDATA_EXT_LEN_MASK) >> 4;
4059 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
4060 && (field_len_code == 0x00)) {
4061 fprintf(stdout, "%d",
4062 lundata->luns[i].lundata[j+1]);
4063 } else if ((eam_code ==
4064 RPL_LUNDATA_EXT_EAM_NOT_SPEC)
4065 && (field_len_code == 0x03)) {
4069 * This format takes up all 8 bytes.
4070 * If we aren't starting at offset 0,
4074 fprintf(stdout, "Invalid "
4077 "specified format", j);
4081 bzero(tmp_lun, sizeof(tmp_lun));
4082 bcopy(&lundata->luns[i].lundata[j+1],
4083 &tmp_lun[1], sizeof(tmp_lun) - 1);
4084 fprintf(stdout, "%#jx",
4085 (intmax_t)scsi_8btou64(tmp_lun));
4088 fprintf(stderr, "Unknown Extended LUN"
4089 "Address method %#x, length "
4090 "code %#x", eam_code,
4097 fprintf(stderr, "Unknown LUN address method "
4098 "%#x\n", lundata->luns[i].lundata[0] &
4099 RPL_LUNDATA_ATYP_MASK);
4103 * For the flat addressing method, there are no
4104 * other levels after it.
4109 fprintf(stdout, "\n");
4122 scsireadcapacity(struct cam_device *device, int argc, char **argv,
4123 char *combinedopt, int retry_count, int timeout)
4126 int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
4127 struct scsi_read_capacity_data rcap;
4128 struct scsi_read_capacity_data_long rcaplong;
4142 ccb = cam_getccb(device);
4145 warnx("%s: error allocating ccb", __func__);
4149 bzero(&(&ccb->ccb_h)[1],
4150 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4152 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4179 if ((blocksizeonly != 0)
4180 && (numblocks != 0)) {
4181 warnx("%s: you can only specify one of -b or -N", __func__);
4186 if ((blocksizeonly != 0)
4187 && (sizeonly != 0)) {
4188 warnx("%s: you can only specify one of -b or -s", __func__);
4195 warnx("%s: you can only specify one of -h/-H or -q", __func__);
4201 && (blocksizeonly != 0)) {
4202 warnx("%s: you can only specify one of -h/-H or -b", __func__);
4207 scsi_read_capacity(&ccb->csio,
4208 /*retries*/ retry_count,
4210 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4213 /*timeout*/ timeout ? timeout : 5000);
4215 /* Disable freezing the device queue */
4216 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4218 if (arglist & CAM_ARG_ERR_RECOVER)
4219 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4221 if (cam_send_ccb(device, ccb) < 0) {
4222 warn("error sending READ CAPACITY command");
4224 if (arglist & CAM_ARG_VERBOSE)
4225 cam_error_print(device, ccb, CAM_ESF_ALL,
4226 CAM_EPF_ALL, stderr);
4232 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4233 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4238 maxsector = scsi_4btoul(rcap.addr);
4239 block_len = scsi_4btoul(rcap.length);
4242 * A last block of 2^32-1 means that the true capacity is over 2TB,
4243 * and we need to issue the long READ CAPACITY to get the real
4244 * capacity. Otherwise, we're all set.
4246 if (maxsector != 0xffffffff)
4249 scsi_read_capacity_16(&ccb->csio,
4250 /*retries*/ retry_count,
4252 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4257 /*sense_len*/ SSD_FULL_SIZE,
4258 /*timeout*/ timeout ? timeout : 5000);
4260 /* Disable freezing the device queue */
4261 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4263 if (arglist & CAM_ARG_ERR_RECOVER)
4264 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4266 if (cam_send_ccb(device, ccb) < 0) {
4267 warn("error sending READ CAPACITY (16) command");
4269 if (arglist & CAM_ARG_VERBOSE)
4270 cam_error_print(device, ccb, CAM_ESF_ALL,
4271 CAM_EPF_ALL, stderr);
4277 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4278 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4283 maxsector = scsi_8btou64(rcaplong.addr);
4284 block_len = scsi_4btoul(rcaplong.length);
4287 if (blocksizeonly == 0) {
4289 * Humanize implies !quiet, and also implies numblocks.
4291 if (humanize != 0) {
4296 tmpbytes = (maxsector + 1) * block_len;
4297 ret = humanize_number(tmpstr, sizeof(tmpstr),
4298 tmpbytes, "", HN_AUTOSCALE,
4301 HN_DIVISOR_1000 : 0));
4303 warnx("%s: humanize_number failed!", __func__);
4307 fprintf(stdout, "Device Size: %s%s", tmpstr,
4308 (sizeonly == 0) ? ", " : "\n");
4309 } else if (numblocks != 0) {
4310 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4311 "Blocks: " : "", (uintmax_t)maxsector + 1,
4312 (sizeonly == 0) ? ", " : "\n");
4314 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4315 "Last Block: " : "", (uintmax_t)maxsector,
4316 (sizeonly == 0) ? ", " : "\n");
4320 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
4321 "Block Length: " : "", block_len, (quiet == 0) ?
4330 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
4331 int retry_count, int timeout)
4335 uint8_t *smp_request = NULL, *smp_response = NULL;
4336 int request_size = 0, response_size = 0;
4337 int fd_request = 0, fd_response = 0;
4338 char *datastr = NULL;
4339 struct get_hook hook;
4344 * Note that at the moment we don't support sending SMP CCBs to
4345 * devices that aren't probed by CAM.
4347 ccb = cam_getccb(device);
4349 warnx("%s: error allocating CCB", __func__);
4353 bzero(&(&ccb->ccb_h)[1],
4354 sizeof(union ccb) - sizeof(struct ccb_hdr));
4356 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4359 arglist |= CAM_ARG_CMD_IN;
4360 response_size = strtol(optarg, NULL, 0);
4361 if (response_size <= 0) {
4362 warnx("invalid number of response bytes %d",
4365 goto smpcmd_bailout;
4367 hook.argc = argc - optind;
4368 hook.argv = argv + optind;
4371 datastr = cget(&hook, NULL);
4373 * If the user supplied "-" instead of a format, he
4374 * wants the data to be written to stdout.
4376 if ((datastr != NULL)
4377 && (datastr[0] == '-'))
4380 smp_response = (u_int8_t *)malloc(response_size);
4381 if (smp_response == NULL) {
4382 warn("can't malloc memory for SMP response");
4384 goto smpcmd_bailout;
4388 arglist |= CAM_ARG_CMD_OUT;
4389 request_size = strtol(optarg, NULL, 0);
4390 if (request_size <= 0) {
4391 warnx("invalid number of request bytes %d",
4394 goto smpcmd_bailout;
4396 hook.argc = argc - optind;
4397 hook.argv = argv + optind;
4399 datastr = cget(&hook, NULL);
4400 smp_request = (u_int8_t *)malloc(request_size);
4401 if (smp_request == NULL) {
4402 warn("can't malloc memory for SMP request");
4404 goto smpcmd_bailout;
4406 bzero(smp_request, request_size);
4408 * If the user supplied "-" instead of a format, he
4409 * wants the data to be read from stdin.
4411 if ((datastr != NULL)
4412 && (datastr[0] == '-'))
4415 buff_encode_visit(smp_request, request_size,
4426 * If fd_data is set, and we're writing to the device, we need to
4427 * read the data the user wants written from stdin.
4429 if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4431 int amt_to_read = request_size;
4432 u_int8_t *buf_ptr = smp_request;
4434 for (amt_read = 0; amt_to_read > 0;
4435 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4436 if (amt_read == -1) {
4437 warn("error reading data from stdin");
4439 goto smpcmd_bailout;
4441 amt_to_read -= amt_read;
4442 buf_ptr += amt_read;
4446 if (((arglist & CAM_ARG_CMD_IN) == 0)
4447 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
4448 warnx("%s: need both the request (-r) and response (-R) "
4449 "arguments", __func__);
4451 goto smpcmd_bailout;
4454 flags |= CAM_DEV_QFRZDIS;
4456 cam_fill_smpio(&ccb->smpio,
4457 /*retries*/ retry_count,
4460 /*smp_request*/ smp_request,
4461 /*smp_request_len*/ request_size,
4462 /*smp_response*/ smp_response,
4463 /*smp_response_len*/ response_size,
4464 /*timeout*/ timeout ? timeout : 5000);
4466 ccb->smpio.flags = SMP_FLAG_NONE;
4468 if (((retval = cam_send_ccb(device, ccb)) < 0)
4469 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4470 const char warnstr[] = "error sending command";
4477 if (arglist & CAM_ARG_VERBOSE) {
4478 cam_error_print(device, ccb, CAM_ESF_ALL,
4479 CAM_EPF_ALL, stderr);
4483 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4484 && (response_size > 0)) {
4485 if (fd_response == 0) {
4486 buff_decode_visit(smp_response, response_size,
4487 datastr, arg_put, NULL);
4488 fprintf(stdout, "\n");
4490 ssize_t amt_written;
4491 int amt_to_write = response_size;
4492 u_int8_t *buf_ptr = smp_response;
4494 for (amt_written = 0; (amt_to_write > 0) &&
4495 (amt_written = write(STDOUT_FILENO, buf_ptr,
4496 amt_to_write)) > 0;){
4497 amt_to_write -= amt_written;
4498 buf_ptr += amt_written;
4500 if (amt_written == -1) {
4501 warn("error writing data to stdout");
4503 goto smpcmd_bailout;
4504 } else if ((amt_written == 0)
4505 && (amt_to_write > 0)) {
4506 warnx("only wrote %u bytes out of %u",
4507 response_size - amt_to_write,
4516 if (smp_request != NULL)
4519 if (smp_response != NULL)
4526 smpreportgeneral(struct cam_device *device, int argc, char **argv,
4527 char *combinedopt, int retry_count, int timeout)
4530 struct smp_report_general_request *request = NULL;
4531 struct smp_report_general_response *response = NULL;
4532 struct sbuf *sb = NULL;
4534 int c, long_response = 0;
4538 * Note that at the moment we don't support sending SMP CCBs to
4539 * devices that aren't probed by CAM.
4541 ccb = cam_getccb(device);
4543 warnx("%s: error allocating CCB", __func__);
4547 bzero(&(&ccb->ccb_h)[1],
4548 sizeof(union ccb) - sizeof(struct ccb_hdr));
4550 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4559 request = malloc(sizeof(*request));
4560 if (request == NULL) {
4561 warn("%s: unable to allocate %zd bytes", __func__,
4567 response = malloc(sizeof(*response));
4568 if (response == NULL) {
4569 warn("%s: unable to allocate %zd bytes", __func__,
4576 smp_report_general(&ccb->smpio,
4580 /*request_len*/ sizeof(*request),
4581 (uint8_t *)response,
4582 /*response_len*/ sizeof(*response),
4583 /*long_response*/ long_response,
4586 if (((retval = cam_send_ccb(device, ccb)) < 0)
4587 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4588 const char warnstr[] = "error sending command";
4595 if (arglist & CAM_ARG_VERBOSE) {
4596 cam_error_print(device, ccb, CAM_ESF_ALL,
4597 CAM_EPF_ALL, stderr);
4604 * If the device supports the long response bit, try again and see
4605 * if we can get all of the data.
4607 if ((response->long_response & SMP_RG_LONG_RESPONSE)
4608 && (long_response == 0)) {
4609 ccb->ccb_h.status = CAM_REQ_INPROG;
4610 bzero(&(&ccb->ccb_h)[1],
4611 sizeof(union ccb) - sizeof(struct ccb_hdr));
4617 * XXX KDM detect and decode SMP errors here.
4619 sb = sbuf_new_auto();
4621 warnx("%s: error allocating sbuf", __func__);
4625 smp_report_general_sbuf(response, sizeof(*response), sb);
4629 printf("%s", sbuf_data(sb));
4635 if (request != NULL)
4638 if (response != NULL)
4647 struct camcontrol_opts phy_ops[] = {
4648 {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
4649 {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
4650 {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
4651 {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
4652 {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
4653 {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
4654 {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
4655 {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
4656 {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
4661 smpphycontrol(struct cam_device *device, int argc, char **argv,
4662 char *combinedopt, int retry_count, int timeout)
4665 struct smp_phy_control_request *request = NULL;
4666 struct smp_phy_control_response *response = NULL;
4667 int long_response = 0;
4670 uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
4672 uint64_t attached_dev_name = 0;
4673 int dev_name_set = 0;
4674 uint32_t min_plr = 0, max_plr = 0;
4675 uint32_t pp_timeout_val = 0;
4676 int slumber_partial = 0;
4677 int set_pp_timeout_val = 0;
4681 * Note that at the moment we don't support sending SMP CCBs to
4682 * devices that aren't probed by CAM.
4684 ccb = cam_getccb(device);
4686 warnx("%s: error allocating CCB", __func__);
4690 bzero(&(&ccb->ccb_h)[1],
4691 sizeof(union ccb) - sizeof(struct ccb_hdr));
4693 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4701 if (strcasecmp(optarg, "enable") == 0)
4703 else if (strcasecmp(optarg, "disable") == 0)
4706 warnx("%s: Invalid argument %s", __func__,
4713 slumber_partial |= enable <<
4714 SMP_PC_SAS_SLUMBER_SHIFT;
4717 slumber_partial |= enable <<
4718 SMP_PC_SAS_PARTIAL_SHIFT;
4721 slumber_partial |= enable <<
4722 SMP_PC_SATA_SLUMBER_SHIFT;
4725 slumber_partial |= enable <<
4726 SMP_PC_SATA_PARTIAL_SHIFT;
4729 warnx("%s: programmer error", __func__);
4732 break; /*NOTREACHED*/
4737 attached_dev_name = (uintmax_t)strtoumax(optarg,
4746 * We don't do extensive checking here, so this
4747 * will continue to work when new speeds come out.
4749 min_plr = strtoul(optarg, NULL, 0);
4751 || (min_plr > 0xf)) {
4752 warnx("%s: invalid link rate %x",
4760 * We don't do extensive checking here, so this
4761 * will continue to work when new speeds come out.
4763 max_plr = strtoul(optarg, NULL, 0);
4765 || (max_plr > 0xf)) {
4766 warnx("%s: invalid link rate %x",
4773 camcontrol_optret optreturn;
4774 cam_argmask argnums;
4777 if (phy_op_set != 0) {
4778 warnx("%s: only one phy operation argument "
4779 "(-o) allowed", __func__);
4787 * Allow the user to specify the phy operation
4788 * numerically, as well as with a name. This will
4789 * future-proof it a bit, so options that are added
4790 * in future specs can be used.
4792 if (isdigit(optarg[0])) {
4793 phy_operation = strtoul(optarg, NULL, 0);
4794 if ((phy_operation == 0)
4795 || (phy_operation > 0xff)) {
4796 warnx("%s: invalid phy operation %#x",
4797 __func__, phy_operation);
4803 optreturn = getoption(phy_ops, optarg, &phy_operation,
4806 if (optreturn == CC_OR_AMBIGUOUS) {
4807 warnx("%s: ambiguous option %s", __func__,
4812 } else if (optreturn == CC_OR_NOT_FOUND) {
4813 warnx("%s: option %s not found", __func__,
4825 pp_timeout_val = strtoul(optarg, NULL, 0);
4826 if (pp_timeout_val > 15) {
4827 warnx("%s: invalid partial pathway timeout "
4828 "value %u, need a value less than 16",
4829 __func__, pp_timeout_val);
4833 set_pp_timeout_val = 1;
4841 warnx("%s: a PHY (-p phy) argument is required",__func__);
4846 if (((dev_name_set != 0)
4847 && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
4848 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
4849 && (dev_name_set == 0))) {
4850 warnx("%s: -d name and -o setdevname arguments both "
4851 "required to set device name", __func__);
4856 request = malloc(sizeof(*request));
4857 if (request == NULL) {
4858 warn("%s: unable to allocate %zd bytes", __func__,
4864 response = malloc(sizeof(*response));
4865 if (response == NULL) {
4866 warn("%s: unable to allocate %zd bytes", __func__,
4872 smp_phy_control(&ccb->smpio,
4877 (uint8_t *)response,
4880 /*expected_exp_change_count*/ 0,
4883 (set_pp_timeout_val != 0) ? 1 : 0,
4891 if (((retval = cam_send_ccb(device, ccb)) < 0)
4892 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4893 const char warnstr[] = "error sending command";
4900 if (arglist & CAM_ARG_VERBOSE) {
4902 * Use CAM_EPF_NORMAL so we only get one line of
4903 * SMP command decoding.
4905 cam_error_print(device, ccb, CAM_ESF_ALL,
4906 CAM_EPF_NORMAL, stderr);
4912 /* XXX KDM print out something here for success? */
4917 if (request != NULL)
4920 if (response != NULL)
4927 smpmaninfo(struct cam_device *device, int argc, char **argv,
4928 char *combinedopt, int retry_count, int timeout)
4931 struct smp_report_manuf_info_request request;
4932 struct smp_report_manuf_info_response response;
4933 struct sbuf *sb = NULL;
4934 int long_response = 0;
4939 * Note that at the moment we don't support sending SMP CCBs to
4940 * devices that aren't probed by CAM.
4942 ccb = cam_getccb(device);
4944 warnx("%s: error allocating CCB", __func__);
4948 bzero(&(&ccb->ccb_h)[1],
4949 sizeof(union ccb) - sizeof(struct ccb_hdr));
4951 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4960 bzero(&request, sizeof(request));
4961 bzero(&response, sizeof(response));
4963 smp_report_manuf_info(&ccb->smpio,
4968 (uint8_t *)&response,
4973 if (((retval = cam_send_ccb(device, ccb)) < 0)
4974 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4975 const char warnstr[] = "error sending command";
4982 if (arglist & CAM_ARG_VERBOSE) {
4983 cam_error_print(device, ccb, CAM_ESF_ALL,
4984 CAM_EPF_ALL, stderr);
4990 sb = sbuf_new_auto();
4992 warnx("%s: error allocating sbuf", __func__);
4996 smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
5000 printf("%s", sbuf_data(sb));
5014 getdevid(struct cam_devitem *item)
5017 union ccb *ccb = NULL;
5019 struct cam_device *dev;
5021 dev = cam_open_btl(item->dev_match.path_id,
5022 item->dev_match.target_id,
5023 item->dev_match.target_lun, O_RDWR, NULL);
5026 warnx("%s", cam_errbuf);
5031 item->device_id_len = 0;
5033 ccb = cam_getccb(dev);
5035 warnx("%s: error allocating CCB", __func__);
5040 bzero(&(&ccb->ccb_h)[1],
5041 sizeof(union ccb) - sizeof(struct ccb_hdr));
5044 * On the first try, we just probe for the size of the data, and
5045 * then allocate that much memory and try again.
5048 ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
5049 ccb->ccb_h.flags = CAM_DIR_IN;
5050 ccb->cdai.flags = 0;
5051 ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
5052 ccb->cdai.bufsiz = item->device_id_len;
5053 if (item->device_id_len != 0)
5054 ccb->cdai.buf = (uint8_t *)item->device_id;
5056 if (cam_send_ccb(dev, ccb) < 0) {
5057 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
5062 if (ccb->ccb_h.status != CAM_REQ_CMP) {
5063 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
5068 if (item->device_id_len == 0) {
5070 * This is our first time through. Allocate the buffer,
5071 * and then go back to get the data.
5073 if (ccb->cdai.provsiz == 0) {
5074 warnx("%s: invalid .provsiz field returned with "
5075 "XPT_GDEV_ADVINFO CCB", __func__);
5079 item->device_id_len = ccb->cdai.provsiz;
5080 item->device_id = malloc(item->device_id_len);
5081 if (item->device_id == NULL) {
5082 warn("%s: unable to allocate %d bytes", __func__,
5083 item->device_id_len);
5087 ccb->ccb_h.status = CAM_REQ_INPROG;
5093 cam_close_device(dev);
5102 * XXX KDM merge this code with getdevtree()?
5105 buildbusdevlist(struct cam_devlist *devlist)
5108 int bufsize, fd = -1;
5109 struct dev_match_pattern *patterns;
5110 struct cam_devitem *item = NULL;
5111 int skip_device = 0;
5114 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
5115 warn("couldn't open %s", XPT_DEVICE);
5119 bzero(&ccb, sizeof(union ccb));
5121 ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
5122 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
5123 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
5125 ccb.ccb_h.func_code = XPT_DEV_MATCH;
5126 bufsize = sizeof(struct dev_match_result) * 100;
5127 ccb.cdm.match_buf_len = bufsize;
5128 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
5129 if (ccb.cdm.matches == NULL) {
5130 warnx("can't malloc memory for matches");
5134 ccb.cdm.num_matches = 0;
5135 ccb.cdm.num_patterns = 2;
5136 ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
5137 ccb.cdm.num_patterns;
5139 patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
5140 if (patterns == NULL) {
5141 warnx("can't malloc memory for patterns");
5146 ccb.cdm.patterns = patterns;
5147 bzero(patterns, ccb.cdm.pattern_buf_len);
5149 patterns[0].type = DEV_MATCH_DEVICE;
5150 patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
5151 patterns[0].pattern.device_pattern.path_id = devlist->path_id;
5152 patterns[1].type = DEV_MATCH_PERIPH;
5153 patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
5154 patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
5157 * We do the ioctl multiple times if necessary, in case there are
5158 * more than 100 nodes in the EDT.
5163 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
5164 warn("error sending CAMIOCOMMAND ioctl");
5169 if ((ccb.ccb_h.status != CAM_REQ_CMP)
5170 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
5171 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
5172 warnx("got CAM error %#x, CDM error %d\n",
5173 ccb.ccb_h.status, ccb.cdm.status);
5178 for (i = 0; i < ccb.cdm.num_matches; i++) {
5179 switch (ccb.cdm.matches[i].type) {
5180 case DEV_MATCH_DEVICE: {
5181 struct device_match_result *dev_result;
5184 &ccb.cdm.matches[i].result.device_result;
5186 if (dev_result->flags &
5187 DEV_RESULT_UNCONFIGURED) {
5193 item = malloc(sizeof(*item));
5195 warn("%s: unable to allocate %zd bytes",
5196 __func__, sizeof(*item));
5200 bzero(item, sizeof(*item));
5201 bcopy(dev_result, &item->dev_match,
5202 sizeof(*dev_result));
5203 STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
5206 if (getdevid(item) != 0) {
5212 case DEV_MATCH_PERIPH: {
5213 struct periph_match_result *periph_result;
5216 &ccb.cdm.matches[i].result.periph_result;
5218 if (skip_device != 0)
5220 item->num_periphs++;
5221 item->periph_matches = realloc(
5222 item->periph_matches,
5224 sizeof(struct periph_match_result));
5225 if (item->periph_matches == NULL) {
5226 warn("%s: error allocating periph "
5231 bcopy(periph_result, &item->periph_matches[
5232 item->num_periphs - 1],
5233 sizeof(*periph_result));
5237 fprintf(stderr, "%s: unexpected match "
5238 "type %d\n", __func__,
5239 ccb.cdm.matches[i].type);
5242 break; /*NOTREACHED*/
5245 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
5246 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
5254 free(ccb.cdm.matches);
5257 freebusdevlist(devlist);
5263 freebusdevlist(struct cam_devlist *devlist)
5265 struct cam_devitem *item, *item2;
5267 STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
5268 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
5270 free(item->device_id);
5271 free(item->periph_matches);
5276 static struct cam_devitem *
5277 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
5279 struct cam_devitem *item;
5281 STAILQ_FOREACH(item, &devlist->dev_queue, links) {
5285 * XXX KDM look for LUN IDs as well?
5287 item_addr = scsi_get_devid(item->device_id,
5288 item->device_id_len,
5289 scsi_devid_is_sas_target);
5290 if (item_addr == NULL)
5293 if (scsi_8btou64(item_addr) == sasaddr)
5301 smpphylist(struct cam_device *device, int argc, char **argv,
5302 char *combinedopt, int retry_count, int timeout)
5304 struct smp_report_general_request *rgrequest = NULL;
5305 struct smp_report_general_response *rgresponse = NULL;
5306 struct smp_discover_request *disrequest = NULL;
5307 struct smp_discover_response *disresponse = NULL;
5308 struct cam_devlist devlist;
5310 int long_response = 0;
5317 * Note that at the moment we don't support sending SMP CCBs to
5318 * devices that aren't probed by CAM.
5320 ccb = cam_getccb(device);
5322 warnx("%s: error allocating CCB", __func__);
5326 bzero(&(&ccb->ccb_h)[1],
5327 sizeof(union ccb) - sizeof(struct ccb_hdr));
5329 rgrequest = malloc(sizeof(*rgrequest));
5330 if (rgrequest == NULL) {
5331 warn("%s: unable to allocate %zd bytes", __func__,
5332 sizeof(*rgrequest));
5337 rgresponse = malloc(sizeof(*rgresponse));
5338 if (rgresponse == NULL) {
5339 warn("%s: unable to allocate %zd bytes", __func__,
5340 sizeof(*rgresponse));
5345 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5358 smp_report_general(&ccb->smpio,
5362 /*request_len*/ sizeof(*rgrequest),
5363 (uint8_t *)rgresponse,
5364 /*response_len*/ sizeof(*rgresponse),
5365 /*long_response*/ long_response,
5368 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5370 if (((retval = cam_send_ccb(device, ccb)) < 0)
5371 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
5372 const char warnstr[] = "error sending command";
5379 if (arglist & CAM_ARG_VERBOSE) {
5380 cam_error_print(device, ccb, CAM_ESF_ALL,
5381 CAM_EPF_ALL, stderr);
5387 num_phys = rgresponse->num_phys;
5389 if (num_phys == 0) {
5391 fprintf(stdout, "%s: No Phys reported\n", __func__);
5396 STAILQ_INIT(&devlist.dev_queue);
5397 devlist.path_id = device->path_id;
5399 retval = buildbusdevlist(&devlist);
5404 fprintf(stdout, "%d PHYs:\n", num_phys);
5405 fprintf(stdout, "PHY Attached SAS Address\n");
5408 disrequest = malloc(sizeof(*disrequest));
5409 if (disrequest == NULL) {
5410 warn("%s: unable to allocate %zd bytes", __func__,
5411 sizeof(*disrequest));
5416 disresponse = malloc(sizeof(*disresponse));
5417 if (disresponse == NULL) {
5418 warn("%s: unable to allocate %zd bytes", __func__,
5419 sizeof(*disresponse));
5424 for (i = 0; i < num_phys; i++) {
5425 struct cam_devitem *item;
5426 struct device_match_result *dev_match;
5427 char vendor[16], product[48], revision[16];
5431 bzero(&(&ccb->ccb_h)[1],
5432 sizeof(union ccb) - sizeof(struct ccb_hdr));
5434 ccb->ccb_h.status = CAM_REQ_INPROG;
5435 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5437 smp_discover(&ccb->smpio,
5441 sizeof(*disrequest),
5442 (uint8_t *)disresponse,
5443 sizeof(*disresponse),
5445 /*ignore_zone_group*/ 0,
5449 if (((retval = cam_send_ccb(device, ccb)) < 0)
5450 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
5451 && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
5452 const char warnstr[] = "error sending command";
5459 if (arglist & CAM_ARG_VERBOSE) {
5460 cam_error_print(device, ccb, CAM_ESF_ALL,
5461 CAM_EPF_ALL, stderr);
5467 if (disresponse->function_result == SMP_FR_PHY_VACANT) {
5469 fprintf(stdout, "%3d <vacant>\n", i);
5473 item = findsasdevice(&devlist,
5474 scsi_8btou64(disresponse->attached_sas_address));
5477 || (item != NULL)) {
5478 fprintf(stdout, "%3d 0x%016jx", i,
5479 (uintmax_t)scsi_8btou64(
5480 disresponse->attached_sas_address));
5482 fprintf(stdout, "\n");
5485 } else if (quiet != 0)
5488 dev_match = &item->dev_match;
5490 if (dev_match->protocol == PROTO_SCSI) {
5491 cam_strvis(vendor, dev_match->inq_data.vendor,
5492 sizeof(dev_match->inq_data.vendor),
5494 cam_strvis(product, dev_match->inq_data.product,
5495 sizeof(dev_match->inq_data.product),
5497 cam_strvis(revision, dev_match->inq_data.revision,
5498 sizeof(dev_match->inq_data.revision),
5500 sprintf(tmpstr, "<%s %s %s>", vendor, product,
5502 } else if ((dev_match->protocol == PROTO_ATA)
5503 || (dev_match->protocol == PROTO_SATAPM)) {
5504 cam_strvis(product, dev_match->ident_data.model,
5505 sizeof(dev_match->ident_data.model),
5507 cam_strvis(revision, dev_match->ident_data.revision,
5508 sizeof(dev_match->ident_data.revision),
5510 sprintf(tmpstr, "<%s %s>", product, revision);
5512 sprintf(tmpstr, "<>");
5514 fprintf(stdout, " %-33s ", tmpstr);
5517 * If we have 0 periphs, that's a bug...
5519 if (item->num_periphs == 0) {
5520 fprintf(stdout, "\n");
5524 fprintf(stdout, "(");
5525 for (j = 0; j < item->num_periphs; j++) {
5527 fprintf(stdout, ",");
5529 fprintf(stdout, "%s%d",
5530 item->periph_matches[j].periph_name,
5531 item->periph_matches[j].unit_number);
5534 fprintf(stdout, ")\n");
5548 freebusdevlist(&devlist);
5554 atapm(struct cam_device *device, int argc, char **argv,
5555 char *combinedopt, int retry_count, int timeout)
5563 ccb = cam_getccb(device);
5566 warnx("%s: error allocating ccb", __func__);
5570 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5579 if (strcmp(argv[1], "idle") == 0) {
5581 cmd = ATA_IDLE_IMMEDIATE;
5584 } else if (strcmp(argv[1], "standby") == 0) {
5586 cmd = ATA_STANDBY_IMMEDIATE;
5588 cmd = ATA_STANDBY_CMD;
5596 else if (t <= (240 * 5))
5598 else if (t <= (252 * 5))
5599 /* special encoding for 21 minutes */
5601 else if (t <= (11 * 30 * 60))
5602 sc = (t - 1) / (30 * 60) + 241;
5606 cam_fill_ataio(&ccb->ataio,
5609 /*flags*/CAM_DIR_NONE,
5613 timeout ? timeout : 30 * 1000);
5614 ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
5616 /* Disable freezing the device queue */
5617 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5619 if (arglist & CAM_ARG_ERR_RECOVER)
5620 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5622 if (cam_send_ccb(device, ccb) < 0) {
5623 warn("error sending command");
5625 if (arglist & CAM_ARG_VERBOSE)
5626 cam_error_print(device, ccb, CAM_ESF_ALL,
5627 CAM_EPF_ALL, stderr);
5633 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5634 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
5643 #endif /* MINIMALISTIC */
5648 fprintf(verbose ? stdout : stderr,
5649 "usage: camcontrol <command> [device id][generic args][command args]\n"
5650 " camcontrol devlist [-v]\n"
5651 #ifndef MINIMALISTIC
5652 " camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
5653 " camcontrol tur [dev_id][generic args]\n"
5654 " camcontrol inquiry [dev_id][generic args] [-D] [-S] [-R]\n"
5655 " camcontrol identify [dev_id][generic args] [-v]\n"
5656 " camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
5657 " camcontrol readcap [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
5659 " camcontrol start [dev_id][generic args]\n"
5660 " camcontrol stop [dev_id][generic args]\n"
5661 " camcontrol load [dev_id][generic args]\n"
5662 " camcontrol eject [dev_id][generic args]\n"
5663 #endif /* MINIMALISTIC */
5664 " camcontrol rescan <all | bus[:target:lun]>\n"
5665 " camcontrol reset <all | bus[:target:lun]>\n"
5666 #ifndef MINIMALISTIC
5667 " camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n"
5668 " camcontrol modepage [dev_id][generic args] <-m page | -l>\n"
5669 " [-P pagectl][-e | -b][-d]\n"
5670 " camcontrol cmd [dev_id][generic args]\n"
5671 " <-a cmd [args] | -c cmd [args]>\n"
5672 " [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
5673 " camcontrol smpcmd [dev_id][generic args]\n"
5674 " <-r len fmt [args]> <-R len fmt [args]>\n"
5675 " camcontrol smprg [dev_id][generic args][-l]\n"
5676 " camcontrol smppc [dev_id][generic args] <-p phy> [-l]\n"
5677 " [-o operation][-d name][-m rate][-M rate]\n"
5678 " [-T pp_timeout][-a enable|disable]\n"
5679 " [-A enable|disable][-s enable|disable]\n"
5680 " [-S enable|disable]\n"
5681 " camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
5682 " camcontrol smpmaninfo [dev_id][generic args][-l]\n"
5683 " camcontrol debug [-I][-P][-T][-S][-X][-c]\n"
5684 " <all|bus[:target[:lun]]|off>\n"
5685 " camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n"
5686 " camcontrol negotiate [dev_id][generic args] [-a][-c]\n"
5687 " [-D <enable|disable>][-M mode][-O offset]\n"
5688 " [-q][-R syncrate][-v][-T <enable|disable>]\n"
5689 " [-U][-W bus_width]\n"
5690 " camcontrol format [dev_id][generic args][-q][-r][-w][-y]\n"
5691 " camcontrol idle [dev_id][generic args][-t time]\n"
5692 " camcontrol standby [dev_id][generic args][-t time]\n"
5693 " camcontrol sleep [dev_id][generic args]\n"
5694 #endif /* MINIMALISTIC */
5695 " camcontrol help\n");
5698 #ifndef MINIMALISTIC
5700 "Specify one of the following options:\n"
5701 "devlist list all CAM devices\n"
5702 "periphlist list all CAM peripheral drivers attached to a device\n"
5703 "tur send a test unit ready to the named device\n"
5704 "inquiry send a SCSI inquiry command to the named device\n"
5705 "identify send a ATA identify command to the named device\n"
5706 "reportluns send a SCSI report luns command to the device\n"
5707 "readcap send a SCSI read capacity command to the device\n"
5708 "start send a Start Unit command to the device\n"
5709 "stop send a Stop Unit command to the device\n"
5710 "load send a Start Unit command to the device with the load bit set\n"
5711 "eject send a Stop Unit command to the device with the eject bit set\n"
5712 "rescan rescan all busses, the given bus, or bus:target:lun\n"
5713 "reset reset all busses, the given bus, or bus:target:lun\n"
5714 "defects read the defect list of the specified device\n"
5715 "modepage display or edit (-e) the given mode page\n"
5716 "cmd send the given SCSI command, may need -i or -o as well\n"
5717 "smpcmd send the given SMP command, requires -o and -i\n"
5718 "smprg send the SMP Report General command\n"
5719 "smppc send the SMP PHY Control command, requires -p\n"
5720 "smpphylist display phys attached to a SAS expander\n"
5721 "smpmaninfo send the SMP Report Manufacturer Info command\n"
5722 "debug turn debugging on/off for a bus, target, or lun, or all devices\n"
5723 "tags report or set the number of transaction slots for a device\n"
5724 "negotiate report or set device negotiation parameters\n"
5725 "format send the SCSI FORMAT UNIT command to the named device\n"
5726 "idle send the ATA IDLE command to the named device\n"
5727 "standby send the ATA STANDBY command to the named device\n"
5728 "sleep send the ATA SLEEP command to the named device\n"
5729 "help this message\n"
5730 "Device Identifiers:\n"
5731 "bus:target specify the bus and target, lun defaults to 0\n"
5732 "bus:target:lun specify the bus, target and lun\n"
5733 "deviceUNIT specify the device name, like \"da4\" or \"cd2\"\n"
5734 "Generic arguments:\n"
5735 "-v be verbose, print out sense information\n"
5736 "-t timeout command timeout in seconds, overrides default timeout\n"
5737 "-n dev_name specify device name, e.g. \"da\", \"cd\"\n"
5738 "-u unit specify unit number, e.g. \"0\", \"5\"\n"
5739 "-E have the kernel attempt to perform SCSI error recovery\n"
5740 "-C count specify the SCSI command retry count (needs -E to work)\n"
5741 "modepage arguments:\n"
5742 "-l list all available mode pages\n"
5743 "-m page specify the mode page to view or edit\n"
5744 "-e edit the specified mode page\n"
5745 "-b force view to binary mode\n"
5746 "-d disable block descriptors for mode sense\n"
5747 "-P pgctl page control field 0-3\n"
5748 "defects arguments:\n"
5749 "-f format specify defect list format (block, bfi or phys)\n"
5750 "-G get the grown defect list\n"
5751 "-P get the permanant defect list\n"
5752 "inquiry arguments:\n"
5753 "-D get the standard inquiry data\n"
5754 "-S get the serial number\n"
5755 "-R get the transfer rate, etc.\n"
5756 "reportluns arguments:\n"
5757 "-c only report a count of available LUNs\n"
5758 "-l only print out luns, and not a count\n"
5759 "-r <reporttype> specify \"default\", \"wellknown\" or \"all\"\n"
5760 "readcap arguments\n"
5761 "-b only report the blocksize\n"
5762 "-h human readable device size, base 2\n"
5763 "-H human readable device size, base 10\n"
5764 "-N print the number of blocks instead of last block\n"
5765 "-q quiet, print numbers only\n"
5766 "-s only report the last block/device size\n"
5768 "-c cdb [args] specify the SCSI CDB\n"
5769 "-i len fmt specify input data and input data format\n"
5770 "-o len fmt [args] specify output data and output data fmt\n"
5771 "smpcmd arguments:\n"
5772 "-r len fmt [args] specify the SMP command to be sent\n"
5773 "-R len fmt [args] specify SMP response format\n"
5774 "smprg arguments:\n"
5775 "-l specify the long response format\n"
5776 "smppc arguments:\n"
5777 "-p phy specify the PHY to operate on\n"
5778 "-l specify the long request/response format\n"
5779 "-o operation specify the phy control operation\n"
5780 "-d name set the attached device name\n"
5781 "-m rate set the minimum physical link rate\n"
5782 "-M rate set the maximum physical link rate\n"
5783 "-T pp_timeout set the partial pathway timeout value\n"
5784 "-a enable|disable enable or disable SATA slumber\n"
5785 "-A enable|disable enable or disable SATA partial phy power\n"
5786 "-s enable|disable enable or disable SAS slumber\n"
5787 "-S enable|disable enable or disable SAS partial phy power\n"
5788 "smpphylist arguments:\n"
5789 "-l specify the long response format\n"
5790 "-q only print phys with attached devices\n"
5791 "smpmaninfo arguments:\n"
5792 "-l specify the long response format\n"
5793 "debug arguments:\n"
5794 "-I CAM_DEBUG_INFO -- scsi commands, errors, data\n"
5795 "-T CAM_DEBUG_TRACE -- routine flow tracking\n"
5796 "-S CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
5797 "-c CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
5799 "-N tags specify the number of tags to use for this device\n"
5800 "-q be quiet, don't report the number of tags\n"
5801 "-v report a number of tag-related parameters\n"
5802 "negotiate arguments:\n"
5803 "-a send a test unit ready after negotiation\n"
5804 "-c report/set current negotiation settings\n"
5805 "-D <arg> \"enable\" or \"disable\" disconnection\n"
5806 "-M mode set ATA mode\n"
5807 "-O offset set command delay offset\n"
5808 "-q be quiet, don't report anything\n"
5809 "-R syncrate synchronization rate in MHz\n"
5810 "-T <arg> \"enable\" or \"disable\" tagged queueing\n"
5811 "-U report/set user negotiation settings\n"
5812 "-W bus_width set the bus width in bits (8, 16 or 32)\n"
5813 "-v also print a Path Inquiry CCB for the controller\n"
5814 "format arguments:\n"
5815 "-q be quiet, don't print status messages\n"
5816 "-r run in report only mode\n"
5817 "-w don't send immediate format command\n"
5818 "-y don't ask any questions\n"
5819 "idle/standby arguments:\n"
5820 "-t <arg> number of seconds before respective state.\n");
5821 #endif /* MINIMALISTIC */
5825 main(int argc, char **argv)
5828 char *device = NULL;
5830 struct cam_device *cam_dev = NULL;
5831 int timeout = 0, retry_count = 1;
5832 camcontrol_optret optreturn;
5834 const char *mainopt = "C:En:t:u:v";
5835 const char *subopt = NULL;
5836 char combinedopt[256];
5837 int error = 0, optstart = 2;
5839 #ifndef MINIMALISTIC
5840 int bus, target, lun;
5841 #endif /* MINIMALISTIC */
5843 cmdlist = CAM_CMD_NONE;
5844 arglist = CAM_ARG_NONE;
5852 * Get the base option.
5854 optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
5856 if (optreturn == CC_OR_AMBIGUOUS) {
5857 warnx("ambiguous option %s", argv[1]);
5860 } else if (optreturn == CC_OR_NOT_FOUND) {
5861 warnx("option %s not found", argv[1]);
5867 * Ahh, getopt(3) is a pain.
5869 * This is a gross hack. There really aren't many other good
5870 * options (excuse the pun) for parsing options in a situation like
5871 * this. getopt is kinda braindead, so you end up having to run
5872 * through the options twice, and give each invocation of getopt
5873 * the option string for the other invocation.
5875 * You would think that you could just have two groups of options.
5876 * The first group would get parsed by the first invocation of
5877 * getopt, and the second group would get parsed by the second
5878 * invocation of getopt. It doesn't quite work out that way. When
5879 * the first invocation of getopt finishes, it leaves optind pointing
5880 * to the argument _after_ the first argument in the second group.
5881 * So when the second invocation of getopt comes around, it doesn't
5882 * recognize the first argument it gets and then bails out.
5884 * A nice alternative would be to have a flag for getopt that says
5885 * "just keep parsing arguments even when you encounter an unknown
5886 * argument", but there isn't one. So there's no real clean way to
5887 * easily parse two sets of arguments without having one invocation
5888 * of getopt know about the other.
5890 * Without this hack, the first invocation of getopt would work as
5891 * long as the generic arguments are first, but the second invocation
5892 * (in the subfunction) would fail in one of two ways. In the case
5893 * where you don't set optreset, it would fail because optind may be
5894 * pointing to the argument after the one it should be pointing at.
5895 * In the case where you do set optreset, and reset optind, it would
5896 * fail because getopt would run into the first set of options, which
5897 * it doesn't understand.
5899 * All of this would "sort of" work if you could somehow figure out
5900 * whether optind had been incremented one option too far. The
5901 * mechanics of that, however, are more daunting than just giving
5902 * both invocations all of the expect options for either invocation.
5904 * Needless to say, I wouldn't mind if someone invented a better
5905 * (non-GPL!) command line parsing interface than getopt. I
5906 * wouldn't mind if someone added more knobs to getopt to make it
5907 * work better. Who knows, I may talk myself into doing it someday,
5908 * if the standards weenies let me. As it is, it just leads to
5909 * hackery like this and causes people to avoid it in some cases.
5911 * KDM, September 8th, 1998
5914 sprintf(combinedopt, "%s%s", mainopt, subopt);
5916 sprintf(combinedopt, "%s", mainopt);
5919 * For these options we do not parse optional device arguments and
5920 * we do not open a passthrough device.
5922 if ((cmdlist == CAM_CMD_RESCAN)
5923 || (cmdlist == CAM_CMD_RESET)
5924 || (cmdlist == CAM_CMD_DEVTREE)
5925 || (cmdlist == CAM_CMD_USAGE)
5926 || (cmdlist == CAM_CMD_DEBUG))
5929 #ifndef MINIMALISTIC
5931 && (argc > 2 && argv[2][0] != '-')) {
5935 if (isdigit(argv[2][0])) {
5936 /* device specified as bus:target[:lun] */
5937 rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
5939 errx(1, "numeric device specification must "
5940 "be either bus:target, or "
5942 /* default to 0 if lun was not specified */
5943 if ((arglist & CAM_ARG_LUN) == 0) {
5945 arglist |= CAM_ARG_LUN;
5949 if (cam_get_device(argv[2], name, sizeof name, &unit)
5951 errx(1, "%s", cam_errbuf);
5952 device = strdup(name);
5953 arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
5957 #endif /* MINIMALISTIC */
5959 * Start getopt processing at argv[2/3], since we've already
5960 * accepted argv[1..2] as the command name, and as a possible
5966 * Now we run through the argument list looking for generic
5967 * options, and ignoring options that possibly belong to
5970 while ((c = getopt(argc, argv, combinedopt))!= -1){
5973 retry_count = strtol(optarg, NULL, 0);
5974 if (retry_count < 0)
5975 errx(1, "retry count %d is < 0",
5977 arglist |= CAM_ARG_RETRIES;
5980 arglist |= CAM_ARG_ERR_RECOVER;
5983 arglist |= CAM_ARG_DEVICE;
5985 while (isspace(*tstr) && (*tstr != '\0'))
5987 device = (char *)strdup(tstr);
5990 timeout = strtol(optarg, NULL, 0);
5992 errx(1, "invalid timeout %d", timeout);
5993 /* Convert the timeout from seconds to ms */
5995 arglist |= CAM_ARG_TIMEOUT;
5998 arglist |= CAM_ARG_UNIT;
5999 unit = strtol(optarg, NULL, 0);
6002 arglist |= CAM_ARG_VERBOSE;
6009 #ifndef MINIMALISTIC
6011 * For most commands we'll want to open the passthrough device
6012 * associated with the specified device. In the case of the rescan
6013 * commands, we don't use a passthrough device at all, just the
6014 * transport layer device.
6017 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
6018 && (((arglist & CAM_ARG_DEVICE) == 0)
6019 || ((arglist & CAM_ARG_UNIT) == 0))) {
6020 errx(1, "subcommand \"%s\" requires a valid device "
6021 "identifier", argv[1]);
6024 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
6025 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
6026 cam_open_spec_device(device,unit,O_RDWR,NULL)))
6028 errx(1,"%s", cam_errbuf);
6030 #endif /* MINIMALISTIC */
6033 * Reset optind to 2, and reset getopt, so these routines can parse
6034 * the arguments again.
6040 #ifndef MINIMALISTIC
6041 case CAM_CMD_DEVLIST:
6042 error = getdevlist(cam_dev);
6044 #endif /* MINIMALISTIC */
6045 case CAM_CMD_DEVTREE:
6046 error = getdevtree();
6048 #ifndef MINIMALISTIC
6050 error = testunitready(cam_dev, retry_count, timeout, 0);
6052 case CAM_CMD_INQUIRY:
6053 error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
6054 retry_count, timeout);
6056 case CAM_CMD_IDENTIFY:
6057 error = ataidentify(cam_dev, retry_count, timeout);
6059 case CAM_CMD_STARTSTOP:
6060 error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
6061 arglist & CAM_ARG_EJECT, retry_count,
6064 #endif /* MINIMALISTIC */
6065 case CAM_CMD_RESCAN:
6066 error = dorescan_or_reset(argc, argv, 1);
6069 error = dorescan_or_reset(argc, argv, 0);
6071 #ifndef MINIMALISTIC
6072 case CAM_CMD_READ_DEFECTS:
6073 error = readdefects(cam_dev, argc, argv, combinedopt,
6074 retry_count, timeout);
6076 case CAM_CMD_MODE_PAGE:
6077 modepage(cam_dev, argc, argv, combinedopt,
6078 retry_count, timeout);
6080 case CAM_CMD_SCSI_CMD:
6081 error = scsicmd(cam_dev, argc, argv, combinedopt,
6082 retry_count, timeout);
6084 case CAM_CMD_SMP_CMD:
6085 error = smpcmd(cam_dev, argc, argv, combinedopt,
6086 retry_count, timeout);
6088 case CAM_CMD_SMP_RG:
6089 error = smpreportgeneral(cam_dev, argc, argv,
6090 combinedopt, retry_count,
6093 case CAM_CMD_SMP_PC:
6094 error = smpphycontrol(cam_dev, argc, argv, combinedopt,
6095 retry_count, timeout);
6097 case CAM_CMD_SMP_PHYLIST:
6098 error = smpphylist(cam_dev, argc, argv, combinedopt,
6099 retry_count, timeout);
6101 case CAM_CMD_SMP_MANINFO:
6102 error = smpmaninfo(cam_dev, argc, argv, combinedopt,
6103 retry_count, timeout);
6106 error = camdebug(argc, argv, combinedopt);
6109 error = tagcontrol(cam_dev, argc, argv, combinedopt);
6112 error = ratecontrol(cam_dev, retry_count, timeout,
6113 argc, argv, combinedopt);
6115 case CAM_CMD_FORMAT:
6116 error = scsiformat(cam_dev, argc, argv,
6117 combinedopt, retry_count, timeout);
6119 case CAM_CMD_REPORTLUNS:
6120 error = scsireportluns(cam_dev, argc, argv,
6121 combinedopt, retry_count,
6124 case CAM_CMD_READCAP:
6125 error = scsireadcapacity(cam_dev, argc, argv,
6126 combinedopt, retry_count,
6130 case CAM_CMD_STANDBY:
6132 error = atapm(cam_dev, argc, argv,
6133 combinedopt, retry_count,
6136 #endif /* MINIMALISTIC */
6146 if (cam_dev != NULL)
6147 cam_close_device(cam_dev);