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];
459 char fw[5], tmpstr[256];
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,
498 } else if (dev_result->protocol == PROTO_SEMB) {
499 struct sep_identify_data *sid;
501 sid = (struct sep_identify_data *)
502 &dev_result->ident_data;
503 cam_strvis(vendor, sid->vendor_id,
504 sizeof(sid->vendor_id),
506 cam_strvis(product, sid->product_id,
507 sizeof(sid->product_id),
509 cam_strvis(revision, sid->product_rev,
510 sizeof(sid->product_rev),
512 cam_strvis(fw, sid->firmware_rev,
513 sizeof(sid->firmware_rev),
515 sprintf(tmpstr, "<%s %s %s %s>",
516 vendor, product, revision, fw);
518 sprintf(tmpstr, "<>");
521 fprintf(stdout, ")\n");
525 fprintf(stdout, "%-33s at scbus%d "
526 "target %d lun %d (",
529 dev_result->target_id,
530 dev_result->target_lun);
536 case DEV_MATCH_PERIPH: {
537 struct periph_match_result *periph_result;
540 &ccb.cdm.matches[i].result.periph_result;
542 if (skip_device != 0)
546 fprintf(stdout, ",");
548 fprintf(stdout, "%s%d",
549 periph_result->periph_name,
550 periph_result->unit_number);
556 fprintf(stdout, "unknown match type\n");
561 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
562 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
565 fprintf(stdout, ")\n");
574 testunitready(struct cam_device *device, int retry_count, int timeout,
580 ccb = cam_getccb(device);
582 scsi_test_unit_ready(&ccb->csio,
583 /* retries */ retry_count,
585 /* tag_action */ MSG_SIMPLE_Q_TAG,
586 /* sense_len */ SSD_FULL_SIZE,
587 /* timeout */ timeout ? timeout : 5000);
589 /* Disable freezing the device queue */
590 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
592 if (arglist & CAM_ARG_ERR_RECOVER)
593 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
595 if (cam_send_ccb(device, ccb) < 0) {
597 perror("error sending test unit ready");
599 if (arglist & CAM_ARG_VERBOSE) {
600 cam_error_print(device, ccb, CAM_ESF_ALL,
601 CAM_EPF_ALL, stderr);
608 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
610 fprintf(stdout, "Unit is ready\n");
613 fprintf(stdout, "Unit is not ready\n");
616 if (arglist & CAM_ARG_VERBOSE) {
617 cam_error_print(device, ccb, CAM_ESF_ALL,
618 CAM_EPF_ALL, stderr);
628 scsistart(struct cam_device *device, int startstop, int loadeject,
629 int retry_count, int timeout)
634 ccb = cam_getccb(device);
637 * If we're stopping, send an ordered tag so the drive in question
638 * will finish any previously queued writes before stopping. If
639 * the device isn't capable of tagged queueing, or if tagged
640 * queueing is turned off, the tag action is a no-op.
642 scsi_start_stop(&ccb->csio,
643 /* retries */ retry_count,
645 /* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
647 /* start/stop */ startstop,
648 /* load_eject */ loadeject,
650 /* sense_len */ SSD_FULL_SIZE,
651 /* timeout */ timeout ? timeout : 120000);
653 /* Disable freezing the device queue */
654 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
656 if (arglist & CAM_ARG_ERR_RECOVER)
657 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
659 if (cam_send_ccb(device, ccb) < 0) {
660 perror("error sending start unit");
662 if (arglist & CAM_ARG_VERBOSE) {
663 cam_error_print(device, ccb, CAM_ESF_ALL,
664 CAM_EPF_ALL, stderr);
671 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
673 fprintf(stdout, "Unit started successfully");
675 fprintf(stdout,", Media loaded\n");
677 fprintf(stdout,"\n");
679 fprintf(stdout, "Unit stopped successfully");
681 fprintf(stdout, ", Media ejected\n");
683 fprintf(stdout, "\n");
689 "Error received from start unit command\n");
692 "Error received from stop unit command\n");
694 if (arglist & CAM_ARG_VERBOSE) {
695 cam_error_print(device, ccb, CAM_ESF_ALL,
696 CAM_EPF_ALL, stderr);
706 scsidoinquiry(struct cam_device *device, int argc, char **argv,
707 char *combinedopt, int retry_count, int timeout)
712 while ((c = getopt(argc, argv, combinedopt)) != -1) {
715 arglist |= CAM_ARG_GET_STDINQ;
718 arglist |= CAM_ARG_GET_XFERRATE;
721 arglist |= CAM_ARG_GET_SERIAL;
729 * If the user didn't specify any inquiry options, he wants all of
732 if ((arglist & CAM_ARG_INQ_MASK) == 0)
733 arglist |= CAM_ARG_INQ_MASK;
735 if (arglist & CAM_ARG_GET_STDINQ)
736 error = scsiinquiry(device, retry_count, timeout);
741 if (arglist & CAM_ARG_GET_SERIAL)
742 scsiserial(device, retry_count, timeout);
747 if (arglist & CAM_ARG_GET_XFERRATE)
748 error = camxferrate(device);
754 scsiinquiry(struct cam_device *device, int retry_count, int timeout)
757 struct scsi_inquiry_data *inq_buf;
760 ccb = cam_getccb(device);
763 warnx("couldn't allocate CCB");
767 /* cam_getccb cleans up the header, caller has to zero the payload */
768 bzero(&(&ccb->ccb_h)[1],
769 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
771 inq_buf = (struct scsi_inquiry_data *)malloc(
772 sizeof(struct scsi_inquiry_data));
774 if (inq_buf == NULL) {
776 warnx("can't malloc memory for inquiry\n");
779 bzero(inq_buf, sizeof(*inq_buf));
782 * Note that although the size of the inquiry buffer is the full
783 * 256 bytes specified in the SCSI spec, we only tell the device
784 * that we have allocated SHORT_INQUIRY_LENGTH bytes. There are
785 * two reasons for this:
787 * - The SCSI spec says that when a length field is only 1 byte,
788 * a value of 0 will be interpreted as 256. Therefore
789 * scsi_inquiry() will convert an inq_len (which is passed in as
790 * a u_int32_t, but the field in the CDB is only 1 byte) of 256
791 * to 0. Evidently, very few devices meet the spec in that
792 * regard. Some devices, like many Seagate disks, take the 0 as
793 * 0, and don't return any data. One Pioneer DVD-R drive
794 * returns more data than the command asked for.
796 * So, since there are numerous devices that just don't work
797 * right with the full inquiry size, we don't send the full size.
799 * - The second reason not to use the full inquiry data length is
800 * that we don't need it here. The only reason we issue a
801 * standard inquiry is to get the vendor name, device name,
802 * and revision so scsi_print_inquiry() can print them.
804 * If, at some point in the future, more inquiry data is needed for
805 * some reason, this code should use a procedure similar to the
806 * probe code. i.e., issue a short inquiry, and determine from
807 * the additional length passed back from the device how much
808 * inquiry data the device supports. Once the amount the device
809 * supports is determined, issue an inquiry for that amount and no
814 scsi_inquiry(&ccb->csio,
815 /* retries */ retry_count,
817 /* tag_action */ MSG_SIMPLE_Q_TAG,
818 /* inq_buf */ (u_int8_t *)inq_buf,
819 /* inq_len */ SHORT_INQUIRY_LENGTH,
822 /* sense_len */ SSD_FULL_SIZE,
823 /* timeout */ timeout ? timeout : 5000);
825 /* Disable freezing the device queue */
826 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
828 if (arglist & CAM_ARG_ERR_RECOVER)
829 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
831 if (cam_send_ccb(device, ccb) < 0) {
832 perror("error sending SCSI inquiry");
834 if (arglist & CAM_ARG_VERBOSE) {
835 cam_error_print(device, ccb, CAM_ESF_ALL,
836 CAM_EPF_ALL, stderr);
843 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
846 if (arglist & CAM_ARG_VERBOSE) {
847 cam_error_print(device, ccb, CAM_ESF_ALL,
848 CAM_EPF_ALL, stderr);
859 fprintf(stdout, "%s%d: ", device->device_name,
860 device->dev_unit_num);
861 scsi_print_inquiry(inq_buf);
869 scsiserial(struct cam_device *device, int retry_count, int timeout)
872 struct scsi_vpd_unit_serial_number *serial_buf;
873 char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
876 ccb = cam_getccb(device);
879 warnx("couldn't allocate CCB");
883 /* cam_getccb cleans up the header, caller has to zero the payload */
884 bzero(&(&ccb->ccb_h)[1],
885 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
887 serial_buf = (struct scsi_vpd_unit_serial_number *)
888 malloc(sizeof(*serial_buf));
890 if (serial_buf == NULL) {
892 warnx("can't malloc memory for serial number");
896 scsi_inquiry(&ccb->csio,
897 /*retries*/ retry_count,
899 /* tag_action */ MSG_SIMPLE_Q_TAG,
900 /* inq_buf */ (u_int8_t *)serial_buf,
901 /* inq_len */ sizeof(*serial_buf),
903 /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
904 /* sense_len */ SSD_FULL_SIZE,
905 /* timeout */ timeout ? timeout : 5000);
907 /* Disable freezing the device queue */
908 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
910 if (arglist & CAM_ARG_ERR_RECOVER)
911 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
913 if (cam_send_ccb(device, ccb) < 0) {
914 warn("error getting serial number");
916 if (arglist & CAM_ARG_VERBOSE) {
917 cam_error_print(device, ccb, CAM_ESF_ALL,
918 CAM_EPF_ALL, stderr);
926 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
929 if (arglist & CAM_ARG_VERBOSE) {
930 cam_error_print(device, ccb, CAM_ESF_ALL,
931 CAM_EPF_ALL, stderr);
942 bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
943 serial_num[serial_buf->length] = '\0';
945 if ((arglist & CAM_ARG_GET_STDINQ)
946 || (arglist & CAM_ARG_GET_XFERRATE))
947 fprintf(stdout, "%s%d: Serial Number ",
948 device->device_name, device->dev_unit_num);
950 fprintf(stdout, "%.60s\n", serial_num);
958 camxferrate(struct cam_device *device)
960 struct ccb_pathinq cpi;
967 if ((retval = get_cpi(device, &cpi)) != 0)
970 ccb = cam_getccb(device);
973 warnx("couldn't allocate CCB");
977 bzero(&(&ccb->ccb_h)[1],
978 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
980 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
981 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
983 if (((retval = cam_send_ccb(device, ccb)) < 0)
984 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
985 const char error_string[] = "error getting transfer settings";
992 if (arglist & CAM_ARG_VERBOSE)
993 cam_error_print(device, ccb, CAM_ESF_ALL,
994 CAM_EPF_ALL, stderr);
998 goto xferrate_bailout;
1002 speed = cpi.base_transfer_speed;
1004 if (ccb->cts.transport == XPORT_SPI) {
1005 struct ccb_trans_settings_spi *spi =
1006 &ccb->cts.xport_specific.spi;
1008 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
1009 freq = scsi_calc_syncsrate(spi->sync_period);
1012 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
1013 speed *= (0x01 << spi->bus_width);
1015 } else if (ccb->cts.transport == XPORT_FC) {
1016 struct ccb_trans_settings_fc *fc =
1017 &ccb->cts.xport_specific.fc;
1019 if (fc->valid & CTS_FC_VALID_SPEED)
1020 speed = fc->bitrate;
1021 } else if (ccb->cts.transport == XPORT_SAS) {
1022 struct ccb_trans_settings_sas *sas =
1023 &ccb->cts.xport_specific.sas;
1025 if (sas->valid & CTS_SAS_VALID_SPEED)
1026 speed = sas->bitrate;
1027 } else if (ccb->cts.transport == XPORT_ATA) {
1028 struct ccb_trans_settings_ata *ata =
1029 &ccb->cts.xport_specific.ata;
1031 if (ata->valid & CTS_ATA_VALID_MODE)
1032 speed = ata_mode2speed(ata->mode);
1033 } else if (ccb->cts.transport == XPORT_SATA) {
1034 struct ccb_trans_settings_sata *sata =
1035 &ccb->cts.xport_specific.sata;
1037 if (sata->valid & CTS_SATA_VALID_REVISION)
1038 speed = ata_revision2speed(sata->revision);
1043 fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
1044 device->device_name, device->dev_unit_num,
1047 fprintf(stdout, "%s%d: %dKB/s transfers",
1048 device->device_name, device->dev_unit_num,
1052 if (ccb->cts.transport == XPORT_SPI) {
1053 struct ccb_trans_settings_spi *spi =
1054 &ccb->cts.xport_specific.spi;
1056 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1057 && (spi->sync_offset != 0))
1058 fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
1059 freq % 1000, spi->sync_offset);
1061 if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
1062 && (spi->bus_width > 0)) {
1063 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1064 && (spi->sync_offset != 0)) {
1065 fprintf(stdout, ", ");
1067 fprintf(stdout, " (");
1069 fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
1070 } else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1071 && (spi->sync_offset != 0)) {
1072 fprintf(stdout, ")");
1074 } else if (ccb->cts.transport == XPORT_ATA) {
1075 struct ccb_trans_settings_ata *ata =
1076 &ccb->cts.xport_specific.ata;
1079 if (ata->valid & CTS_ATA_VALID_MODE)
1080 printf("%s, ", ata_mode2string(ata->mode));
1081 if ((ata->valid & CTS_ATA_VALID_ATAPI) && ata->atapi != 0)
1082 printf("ATAPI %dbytes, ", ata->atapi);
1083 if (ata->valid & CTS_ATA_VALID_BYTECOUNT)
1084 printf("PIO %dbytes", ata->bytecount);
1086 } else if (ccb->cts.transport == XPORT_SATA) {
1087 struct ccb_trans_settings_sata *sata =
1088 &ccb->cts.xport_specific.sata;
1091 if (sata->valid & CTS_SATA_VALID_REVISION)
1092 printf("SATA %d.x, ", sata->revision);
1095 if (sata->valid & CTS_SATA_VALID_MODE)
1096 printf("%s, ", ata_mode2string(sata->mode));
1097 if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
1098 printf("ATAPI %dbytes, ", sata->atapi);
1099 if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1100 printf("PIO %dbytes", sata->bytecount);
1104 if (ccb->cts.protocol == PROTO_SCSI) {
1105 struct ccb_trans_settings_scsi *scsi =
1106 &ccb->cts.proto_specific.scsi;
1107 if (scsi->valid & CTS_SCSI_VALID_TQ) {
1108 if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1109 fprintf(stdout, ", Command Queueing Enabled");
1114 fprintf(stdout, "\n");
1124 atacapprint(struct ata_params *parm)
1126 u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1127 ((u_int32_t)parm->lba_size_2 << 16);
1129 u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1130 ((u_int64_t)parm->lba_size48_2 << 16) |
1131 ((u_int64_t)parm->lba_size48_3 << 32) |
1132 ((u_int64_t)parm->lba_size48_4 << 48);
1135 printf("protocol ");
1136 printf("ATA/ATAPI-%d", ata_version(parm->version_major));
1137 if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1138 if (parm->satacapabilities & ATA_SATA_GEN3)
1139 printf(" SATA 3.x\n");
1140 else if (parm->satacapabilities & ATA_SATA_GEN2)
1141 printf(" SATA 2.x\n");
1142 else if (parm->satacapabilities & ATA_SATA_GEN1)
1143 printf(" SATA 1.x\n");
1149 printf("device model %.40s\n", parm->model);
1150 printf("firmware revision %.8s\n", parm->revision);
1151 printf("serial number %.20s\n", parm->serial);
1152 if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
1153 printf("WWN %04x%04x%04x%04x\n",
1154 parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
1156 if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
1157 printf("media serial number %.30s\n",
1158 parm->media_serial);
1161 printf("cylinders %d\n", parm->cylinders);
1162 printf("heads %d\n", parm->heads);
1163 printf("sectors/track %d\n", parm->sectors);
1164 printf("sector size logical %u, physical %lu, offset %lu\n",
1165 ata_logical_sector_size(parm),
1166 (unsigned long)ata_physical_sector_size(parm),
1167 (unsigned long)ata_logical_sector_offset(parm));
1169 if (parm->config == ATA_PROTO_CFA ||
1170 (parm->support.command2 & ATA_SUPPORT_CFA))
1171 printf("CFA supported\n");
1173 printf("LBA%ssupported ",
1174 parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1176 printf("%d sectors\n", lbasize);
1180 printf("LBA48%ssupported ",
1181 parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1183 printf("%ju sectors\n", (uintmax_t)lbasize48);
1187 printf("PIO supported PIO");
1188 switch (ata_max_pmode(parm)) {
1204 if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0)
1205 printf(" w/o IORDY");
1208 printf("DMA%ssupported ",
1209 parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1210 if (parm->capabilities1 & ATA_SUPPORT_DMA) {
1211 if (parm->mwdmamodes & 0xff) {
1213 if (parm->mwdmamodes & 0x04)
1215 else if (parm->mwdmamodes & 0x02)
1217 else if (parm->mwdmamodes & 0x01)
1221 if ((parm->atavalid & ATA_FLAG_88) &&
1222 (parm->udmamodes & 0xff)) {
1224 if (parm->udmamodes & 0x40)
1226 else if (parm->udmamodes & 0x20)
1228 else if (parm->udmamodes & 0x10)
1230 else if (parm->udmamodes & 0x08)
1232 else if (parm->udmamodes & 0x04)
1234 else if (parm->udmamodes & 0x02)
1236 else if (parm->udmamodes & 0x01)
1243 if (parm->media_rotation_rate == 1) {
1244 printf("media RPM non-rotating\n");
1245 } else if (parm->media_rotation_rate >= 0x0401 &&
1246 parm->media_rotation_rate <= 0xFFFE) {
1247 printf("media RPM %d\n",
1248 parm->media_rotation_rate);
1252 "Support Enabled Value Vendor\n");
1253 printf("read ahead %s %s\n",
1254 parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1255 parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1256 printf("write cache %s %s\n",
1257 parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1258 parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1259 printf("flush cache %s %s\n",
1260 parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no",
1261 parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no");
1262 printf("overlap %s\n",
1263 parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no");
1264 printf("Tagged Command Queuing (TCQ) %s %s",
1265 parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1266 parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no");
1267 if (parm->support.command2 & ATA_SUPPORT_QUEUED) {
1268 printf(" %d tags\n",
1269 ATA_QUEUE_LEN(parm->queue) + 1);
1272 printf("Native Command Queuing (NCQ) ");
1273 if (parm->satacapabilities != 0xffff &&
1274 (parm->satacapabilities & ATA_SUPPORT_NCQ)) {
1275 printf("yes %d tags\n",
1276 ATA_QUEUE_LEN(parm->queue) + 1);
1279 printf("SMART %s %s\n",
1280 parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1281 parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1282 printf("microcode download %s %s\n",
1283 parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1284 parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1285 printf("security %s %s\n",
1286 parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1287 parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1288 printf("power management %s %s\n",
1289 parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1290 parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1291 printf("advanced power management %s %s",
1292 parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1293 parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no");
1294 if (parm->support.command2 & ATA_SUPPORT_APM) {
1295 printf(" %d/0x%02X\n",
1296 parm->apm_value, parm->apm_value);
1299 printf("automatic acoustic management %s %s",
1300 parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1301 parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no");
1302 if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) {
1303 printf(" %d/0x%02X %d/0x%02X\n",
1304 ATA_ACOUSTIC_CURRENT(parm->acoustic),
1305 ATA_ACOUSTIC_CURRENT(parm->acoustic),
1306 ATA_ACOUSTIC_VENDOR(parm->acoustic),
1307 ATA_ACOUSTIC_VENDOR(parm->acoustic));
1310 printf("media status notification %s %s\n",
1311 parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1312 parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1313 printf("power-up in Standby %s %s\n",
1314 parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1315 parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1316 printf("write-read-verify %s %s",
1317 parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1318 parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no");
1319 if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) {
1320 printf(" %d/0x%x\n",
1321 parm->wrv_mode, parm->wrv_mode);
1324 printf("unload %s %s\n",
1325 parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1326 parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1327 printf("free-fall %s %s\n",
1328 parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1329 parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1330 printf("data set management (TRIM) %s\n",
1331 parm->support_dsm & ATA_SUPPORT_DSM_TRIM ? "yes" : "no");
1335 ataidentify(struct cam_device *device, int retry_count, int timeout)
1338 struct ata_params *ident_buf;
1339 struct ccb_getdev cgd;
1343 if (get_cgd(device, &cgd) != 0) {
1344 warnx("couldn't get CGD");
1347 ccb = cam_getccb(device);
1350 warnx("couldn't allocate CCB");
1354 /* cam_getccb cleans up the header, caller has to zero the payload */
1355 bzero(&(&ccb->ccb_h)[1],
1356 sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));
1358 ptr = (uint16_t *)malloc(sizeof(struct ata_params));
1362 warnx("can't malloc memory for identify\n");
1365 bzero(ptr, sizeof(struct ata_params));
1367 cam_fill_ataio(&ccb->ataio,
1370 /*flags*/CAM_DIR_IN,
1372 /*data_ptr*/(u_int8_t *)ptr,
1373 /*dxfer_len*/sizeof(struct ata_params),
1374 timeout ? timeout : 30 * 1000);
1375 if (cgd.protocol == PROTO_ATA)
1376 ata_28bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
1378 ata_28bit_cmd(&ccb->ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
1380 /* Disable freezing the device queue */
1381 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1383 if (arglist & CAM_ARG_ERR_RECOVER)
1384 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1386 if (cam_send_ccb(device, ccb) < 0) {
1387 perror("error sending ATA identify");
1389 if (arglist & CAM_ARG_VERBOSE) {
1390 cam_error_print(device, ccb, CAM_ESF_ALL,
1391 CAM_EPF_ALL, stderr);
1399 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1402 if (arglist & CAM_ARG_VERBOSE) {
1403 cam_error_print(device, ccb, CAM_ESF_ALL,
1404 CAM_EPF_ALL, stderr);
1415 for (i = 0; i < sizeof(struct ata_params) / 2; i++)
1416 ptr[i] = le16toh(ptr[i]);
1417 if (arglist & CAM_ARG_VERBOSE) {
1418 fprintf(stdout, "%s%d: Raw identify data:\n",
1419 device->device_name, device->dev_unit_num);
1420 for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
1422 fprintf(stdout, " %3d: ", i);
1423 fprintf(stdout, "%04x ", (uint16_t)ptr[i]);
1425 fprintf(stdout, "\n");
1428 ident_buf = (struct ata_params *)ptr;
1429 if (strncmp(ident_buf->model, "FX", 2) &&
1430 strncmp(ident_buf->model, "NEC", 3) &&
1431 strncmp(ident_buf->model, "Pioneer", 7) &&
1432 strncmp(ident_buf->model, "SHARP", 5)) {
1433 ata_bswap(ident_buf->model, sizeof(ident_buf->model));
1434 ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
1435 ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
1436 ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1438 ata_btrim(ident_buf->model, sizeof(ident_buf->model));
1439 ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
1440 ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
1441 ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
1442 ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
1443 ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
1444 ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1445 ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
1446 sizeof(ident_buf->media_serial));
1448 fprintf(stdout, "%s%d: ", device->device_name,
1449 device->dev_unit_num);
1450 ata_print_ident(ident_buf);
1451 camxferrate(device);
1452 atacapprint(ident_buf);
1458 #endif /* MINIMALISTIC */
1461 * Parse out a bus, or a bus, target and lun in the following
1467 * Returns the number of parsed components, or 0.
1470 parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglst)
1475 while (isspace(*tstr) && (*tstr != '\0'))
1478 tmpstr = (char *)strtok(tstr, ":");
1479 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1480 *bus = strtol(tmpstr, NULL, 0);
1481 *arglst |= CAM_ARG_BUS;
1483 tmpstr = (char *)strtok(NULL, ":");
1484 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1485 *target = strtol(tmpstr, NULL, 0);
1486 *arglst |= CAM_ARG_TARGET;
1488 tmpstr = (char *)strtok(NULL, ":");
1489 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1490 *lun = strtol(tmpstr, NULL, 0);
1491 *arglst |= CAM_ARG_LUN;
1501 dorescan_or_reset(int argc, char **argv, int rescan)
1503 static const char must[] =
1504 "you must specify \"all\", a bus, or a bus:target:lun to %s";
1506 int bus = -1, target = -1, lun = -1;
1510 warnx(must, rescan? "rescan" : "reset");
1514 tstr = argv[optind];
1515 while (isspace(*tstr) && (*tstr != '\0'))
1517 if (strncasecmp(tstr, "all", strlen("all")) == 0)
1518 arglist |= CAM_ARG_BUS;
1520 rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
1521 if (rv != 1 && rv != 3) {
1522 warnx(must, rescan? "rescan" : "reset");
1527 if ((arglist & CAM_ARG_BUS)
1528 && (arglist & CAM_ARG_TARGET)
1529 && (arglist & CAM_ARG_LUN))
1530 error = scanlun_or_reset_dev(bus, target, lun, rescan);
1532 error = rescan_or_reset_bus(bus, rescan);
1538 rescan_or_reset_bus(int bus, int rescan)
1540 union ccb ccb, matchccb;
1546 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1547 warnx("error opening transport layer device %s", XPT_DEVICE);
1548 warn("%s", XPT_DEVICE);
1553 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
1554 ccb.ccb_h.path_id = bus;
1555 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1556 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1557 ccb.crcn.flags = CAM_FLAG_NONE;
1559 /* run this at a low priority */
1560 ccb.ccb_h.pinfo.priority = 5;
1562 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1563 warn("CAMIOCOMMAND ioctl failed");
1568 if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
1569 fprintf(stdout, "%s of bus %d was successful\n",
1570 rescan ? "Re-scan" : "Reset", bus);
1572 fprintf(stdout, "%s of bus %d returned error %#x\n",
1573 rescan ? "Re-scan" : "Reset", bus,
1574 ccb.ccb_h.status & CAM_STATUS_MASK);
1585 * The right way to handle this is to modify the xpt so that it can
1586 * handle a wildcarded bus in a rescan or reset CCB. At the moment
1587 * that isn't implemented, so instead we enumerate the busses and
1588 * send the rescan or reset to those busses in the case where the
1589 * given bus is -1 (wildcard). We don't send a rescan or reset
1590 * to the xpt bus; sending a rescan to the xpt bus is effectively a
1591 * no-op, sending a rescan to the xpt bus would result in a status of
1594 bzero(&(&matchccb.ccb_h)[1],
1595 sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
1596 matchccb.ccb_h.func_code = XPT_DEV_MATCH;
1597 matchccb.ccb_h.path_id = CAM_BUS_WILDCARD;
1598 bufsize = sizeof(struct dev_match_result) * 20;
1599 matchccb.cdm.match_buf_len = bufsize;
1600 matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
1601 if (matchccb.cdm.matches == NULL) {
1602 warnx("can't malloc memory for matches");
1606 matchccb.cdm.num_matches = 0;
1608 matchccb.cdm.num_patterns = 1;
1609 matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
1611 matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
1612 matchccb.cdm.pattern_buf_len);
1613 if (matchccb.cdm.patterns == NULL) {
1614 warnx("can't malloc memory for patterns");
1618 matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
1619 matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
1624 if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
1625 warn("CAMIOCOMMAND ioctl failed");
1630 if ((matchccb.ccb_h.status != CAM_REQ_CMP)
1631 || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
1632 && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
1633 warnx("got CAM error %#x, CDM error %d\n",
1634 matchccb.ccb_h.status, matchccb.cdm.status);
1639 for (i = 0; i < matchccb.cdm.num_matches; i++) {
1640 struct bus_match_result *bus_result;
1642 /* This shouldn't happen. */
1643 if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
1646 bus_result = &matchccb.cdm.matches[i].result.bus_result;
1649 * We don't want to rescan or reset the xpt bus.
1652 if ((int)bus_result->path_id == -1)
1655 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
1657 ccb.ccb_h.path_id = bus_result->path_id;
1658 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1659 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1660 ccb.crcn.flags = CAM_FLAG_NONE;
1662 /* run this at a low priority */
1663 ccb.ccb_h.pinfo.priority = 5;
1665 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1666 warn("CAMIOCOMMAND ioctl failed");
1671 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
1672 fprintf(stdout, "%s of bus %d was successful\n",
1673 rescan? "Re-scan" : "Reset",
1674 bus_result->path_id);
1677 * Don't bail out just yet, maybe the other
1678 * rescan or reset commands will complete
1681 fprintf(stderr, "%s of bus %d returned error "
1682 "%#x\n", rescan? "Re-scan" : "Reset",
1683 bus_result->path_id,
1684 ccb.ccb_h.status & CAM_STATUS_MASK);
1688 } while ((matchccb.ccb_h.status == CAM_REQ_CMP)
1689 && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
1696 if (matchccb.cdm.patterns != NULL)
1697 free(matchccb.cdm.patterns);
1698 if (matchccb.cdm.matches != NULL)
1699 free(matchccb.cdm.matches);
1705 scanlun_or_reset_dev(int bus, int target, int lun, int scan)
1708 struct cam_device *device;
1714 warnx("invalid bus number %d", bus);
1719 warnx("invalid target number %d", target);
1724 warnx("invalid lun number %d", lun);
1730 bzero(&ccb, sizeof(union ccb));
1733 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1734 warnx("error opening transport layer device %s\n",
1736 warn("%s", XPT_DEVICE);
1740 device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
1741 if (device == NULL) {
1742 warnx("%s", cam_errbuf);
1747 ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
1748 ccb.ccb_h.path_id = bus;
1749 ccb.ccb_h.target_id = target;
1750 ccb.ccb_h.target_lun = lun;
1751 ccb.ccb_h.timeout = 5000;
1752 ccb.crcn.flags = CAM_FLAG_NONE;
1754 /* run this at a low priority */
1755 ccb.ccb_h.pinfo.priority = 5;
1758 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
1759 warn("CAMIOCOMMAND ioctl failed");
1764 if (cam_send_ccb(device, &ccb) < 0) {
1765 warn("error sending XPT_RESET_DEV CCB");
1766 cam_close_device(device);
1774 cam_close_device(device);
1777 * An error code of CAM_BDR_SENT is normal for a BDR request.
1779 if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1781 && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
1782 fprintf(stdout, "%s of %d:%d:%d was successful\n",
1783 scan? "Re-scan" : "Reset", bus, target, lun);
1786 fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
1787 scan? "Re-scan" : "Reset", bus, target, lun,
1788 ccb.ccb_h.status & CAM_STATUS_MASK);
1793 #ifndef MINIMALISTIC
1795 readdefects(struct cam_device *device, int argc, char **argv,
1796 char *combinedopt, int retry_count, int timeout)
1798 union ccb *ccb = NULL;
1799 struct scsi_read_defect_data_10 *rdd_cdb;
1800 u_int8_t *defect_list = NULL;
1801 u_int32_t dlist_length = 65000;
1802 u_int32_t returned_length = 0;
1803 u_int32_t num_returned = 0;
1804 u_int8_t returned_format;
1807 int lists_specified = 0;
1809 while ((c = getopt(argc, argv, combinedopt)) != -1) {
1815 while (isspace(*tstr) && (*tstr != '\0'))
1817 if (strcmp(tstr, "block") == 0)
1818 arglist |= CAM_ARG_FORMAT_BLOCK;
1819 else if (strcmp(tstr, "bfi") == 0)
1820 arglist |= CAM_ARG_FORMAT_BFI;
1821 else if (strcmp(tstr, "phys") == 0)
1822 arglist |= CAM_ARG_FORMAT_PHYS;
1825 warnx("invalid defect format %s", tstr);
1826 goto defect_bailout;
1831 arglist |= CAM_ARG_GLIST;
1834 arglist |= CAM_ARG_PLIST;
1841 ccb = cam_getccb(device);
1844 * Hopefully 65000 bytes is enough to hold the defect list. If it
1845 * isn't, the disk is probably dead already. We'd have to go with
1846 * 12 byte command (i.e. alloc_length is 32 bits instead of 16)
1849 defect_list = malloc(dlist_length);
1850 if (defect_list == NULL) {
1851 warnx("can't malloc memory for defect list");
1853 goto defect_bailout;
1856 rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
1859 * cam_getccb() zeros the CCB header only. So we need to zero the
1860 * payload portion of the ccb.
1862 bzero(&(&ccb->ccb_h)[1],
1863 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1865 cam_fill_csio(&ccb->csio,
1866 /*retries*/ retry_count,
1868 /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
1869 CAM_PASS_ERR_RECOVER : 0),
1870 /*tag_action*/ MSG_SIMPLE_Q_TAG,
1871 /*data_ptr*/ defect_list,
1872 /*dxfer_len*/ dlist_length,
1873 /*sense_len*/ SSD_FULL_SIZE,
1874 /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
1875 /*timeout*/ timeout ? timeout : 5000);
1877 rdd_cdb->opcode = READ_DEFECT_DATA_10;
1878 if (arglist & CAM_ARG_FORMAT_BLOCK)
1879 rdd_cdb->format = SRDD10_BLOCK_FORMAT;
1880 else if (arglist & CAM_ARG_FORMAT_BFI)
1881 rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
1882 else if (arglist & CAM_ARG_FORMAT_PHYS)
1883 rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
1886 warnx("no defect list format specified");
1887 goto defect_bailout;
1889 if (arglist & CAM_ARG_PLIST) {
1890 rdd_cdb->format |= SRDD10_PLIST;
1894 if (arglist & CAM_ARG_GLIST) {
1895 rdd_cdb->format |= SRDD10_GLIST;
1899 scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
1901 /* Disable freezing the device queue */
1902 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1904 if (cam_send_ccb(device, ccb) < 0) {
1905 perror("error reading defect list");
1907 if (arglist & CAM_ARG_VERBOSE) {
1908 cam_error_print(device, ccb, CAM_ESF_ALL,
1909 CAM_EPF_ALL, stderr);
1913 goto defect_bailout;
1916 returned_length = scsi_2btoul(((struct
1917 scsi_read_defect_data_hdr_10 *)defect_list)->length);
1919 returned_format = ((struct scsi_read_defect_data_hdr_10 *)
1920 defect_list)->format;
1922 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
1923 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
1924 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
1925 struct scsi_sense_data *sense;
1926 int error_code, sense_key, asc, ascq;
1928 sense = &ccb->csio.sense_data;
1929 scsi_extract_sense_len(sense, ccb->csio.sense_len -
1930 ccb->csio.sense_resid, &error_code, &sense_key, &asc,
1931 &ascq, /*show_errors*/ 1);
1934 * According to the SCSI spec, if the disk doesn't support
1935 * the requested format, it will generally return a sense
1936 * key of RECOVERED ERROR, and an additional sense code
1937 * of "DEFECT LIST NOT FOUND". So, we check for that, and
1938 * also check to make sure that the returned length is
1939 * greater than 0, and then print out whatever format the
1942 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
1943 && (asc == 0x1c) && (ascq == 0x00)
1944 && (returned_length > 0)) {
1945 warnx("requested defect format not available");
1946 switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
1947 case SRDD10_BLOCK_FORMAT:
1948 warnx("Device returned block format");
1950 case SRDD10_BYTES_FROM_INDEX_FORMAT:
1951 warnx("Device returned bytes from index"
1954 case SRDD10_PHYSICAL_SECTOR_FORMAT:
1955 warnx("Device returned physical sector format");
1959 warnx("Device returned unknown defect"
1960 " data format %#x", returned_format);
1961 goto defect_bailout;
1962 break; /* NOTREACHED */
1966 warnx("Error returned from read defect data command");
1967 if (arglist & CAM_ARG_VERBOSE)
1968 cam_error_print(device, ccb, CAM_ESF_ALL,
1969 CAM_EPF_ALL, stderr);
1970 goto defect_bailout;
1972 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1974 warnx("Error returned from read defect data command");
1975 if (arglist & CAM_ARG_VERBOSE)
1976 cam_error_print(device, ccb, CAM_ESF_ALL,
1977 CAM_EPF_ALL, stderr);
1978 goto defect_bailout;
1982 * XXX KDM I should probably clean up the printout format for the
1985 switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
1986 case SRDDH10_PHYSICAL_SECTOR_FORMAT:
1988 struct scsi_defect_desc_phys_sector *dlist;
1990 dlist = (struct scsi_defect_desc_phys_sector *)
1992 sizeof(struct scsi_read_defect_data_hdr_10));
1994 num_returned = returned_length /
1995 sizeof(struct scsi_defect_desc_phys_sector);
1997 fprintf(stderr, "Got %d defect", num_returned);
1999 if ((lists_specified == 0) || (num_returned == 0)) {
2000 fprintf(stderr, "s.\n");
2002 } else if (num_returned == 1)
2003 fprintf(stderr, ":\n");
2005 fprintf(stderr, "s:\n");
2007 for (i = 0; i < num_returned; i++) {
2008 fprintf(stdout, "%d:%d:%d\n",
2009 scsi_3btoul(dlist[i].cylinder),
2011 scsi_4btoul(dlist[i].sector));
2015 case SRDDH10_BYTES_FROM_INDEX_FORMAT:
2017 struct scsi_defect_desc_bytes_from_index *dlist;
2019 dlist = (struct scsi_defect_desc_bytes_from_index *)
2021 sizeof(struct scsi_read_defect_data_hdr_10));
2023 num_returned = returned_length /
2024 sizeof(struct scsi_defect_desc_bytes_from_index);
2026 fprintf(stderr, "Got %d defect", num_returned);
2028 if ((lists_specified == 0) || (num_returned == 0)) {
2029 fprintf(stderr, "s.\n");
2031 } else if (num_returned == 1)
2032 fprintf(stderr, ":\n");
2034 fprintf(stderr, "s:\n");
2036 for (i = 0; i < num_returned; i++) {
2037 fprintf(stdout, "%d:%d:%d\n",
2038 scsi_3btoul(dlist[i].cylinder),
2040 scsi_4btoul(dlist[i].bytes_from_index));
2044 case SRDDH10_BLOCK_FORMAT:
2046 struct scsi_defect_desc_block *dlist;
2048 dlist = (struct scsi_defect_desc_block *)(defect_list +
2049 sizeof(struct scsi_read_defect_data_hdr_10));
2051 num_returned = returned_length /
2052 sizeof(struct scsi_defect_desc_block);
2054 fprintf(stderr, "Got %d defect", num_returned);
2056 if ((lists_specified == 0) || (num_returned == 0)) {
2057 fprintf(stderr, "s.\n");
2059 } else if (num_returned == 1)
2060 fprintf(stderr, ":\n");
2062 fprintf(stderr, "s:\n");
2064 for (i = 0; i < num_returned; i++)
2065 fprintf(stdout, "%u\n",
2066 scsi_4btoul(dlist[i].address));
2070 fprintf(stderr, "Unknown defect format %d\n",
2071 returned_format & SRDDH10_DLIST_FORMAT_MASK);
2077 if (defect_list != NULL)
2085 #endif /* MINIMALISTIC */
2089 reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
2093 ccb = cam_getccb(device);
2099 #ifndef MINIMALISTIC
2101 mode_sense(struct cam_device *device, int mode_page, int page_control,
2102 int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
2107 ccb = cam_getccb(device);
2110 errx(1, "mode_sense: couldn't allocate CCB");
2112 bzero(&(&ccb->ccb_h)[1],
2113 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2115 scsi_mode_sense(&ccb->csio,
2116 /* retries */ retry_count,
2118 /* tag_action */ MSG_SIMPLE_Q_TAG,
2120 /* page_code */ page_control << 6,
2121 /* page */ mode_page,
2122 /* param_buf */ data,
2123 /* param_len */ datalen,
2124 /* sense_len */ SSD_FULL_SIZE,
2125 /* timeout */ timeout ? timeout : 5000);
2127 if (arglist & CAM_ARG_ERR_RECOVER)
2128 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2130 /* Disable freezing the device queue */
2131 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2133 if (((retval = cam_send_ccb(device, ccb)) < 0)
2134 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2135 if (arglist & CAM_ARG_VERBOSE) {
2136 cam_error_print(device, ccb, CAM_ESF_ALL,
2137 CAM_EPF_ALL, stderr);
2140 cam_close_device(device);
2142 err(1, "error sending mode sense command");
2144 errx(1, "error sending mode sense command");
2151 mode_select(struct cam_device *device, int save_pages, int retry_count,
2152 int timeout, u_int8_t *data, int datalen)
2157 ccb = cam_getccb(device);
2160 errx(1, "mode_select: couldn't allocate CCB");
2162 bzero(&(&ccb->ccb_h)[1],
2163 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2165 scsi_mode_select(&ccb->csio,
2166 /* retries */ retry_count,
2168 /* tag_action */ MSG_SIMPLE_Q_TAG,
2169 /* scsi_page_fmt */ 1,
2170 /* save_pages */ save_pages,
2171 /* param_buf */ data,
2172 /* param_len */ datalen,
2173 /* sense_len */ SSD_FULL_SIZE,
2174 /* timeout */ timeout ? timeout : 5000);
2176 if (arglist & CAM_ARG_ERR_RECOVER)
2177 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2179 /* Disable freezing the device queue */
2180 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2182 if (((retval = cam_send_ccb(device, ccb)) < 0)
2183 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2184 if (arglist & CAM_ARG_VERBOSE) {
2185 cam_error_print(device, ccb, CAM_ESF_ALL,
2186 CAM_EPF_ALL, stderr);
2189 cam_close_device(device);
2192 err(1, "error sending mode select command");
2194 errx(1, "error sending mode select command");
2202 modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
2203 int retry_count, int timeout)
2205 int c, mode_page = -1, page_control = 0;
2206 int binary = 0, list = 0;
2208 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2214 arglist |= CAM_ARG_DBD;
2217 arglist |= CAM_ARG_MODE_EDIT;
2223 mode_page = strtol(optarg, NULL, 0);
2225 errx(1, "invalid mode page %d", mode_page);
2228 page_control = strtol(optarg, NULL, 0);
2229 if ((page_control < 0) || (page_control > 3))
2230 errx(1, "invalid page control field %d",
2232 arglist |= CAM_ARG_PAGE_CNTL;
2239 if (mode_page == -1 && list == 0)
2240 errx(1, "you must specify a mode page!");
2243 mode_list(device, page_control, arglist & CAM_ARG_DBD,
2244 retry_count, timeout);
2246 mode_edit(device, mode_page, page_control,
2247 arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
2248 retry_count, timeout);
2253 scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
2254 int retry_count, int timeout)
2257 u_int32_t flags = CAM_DIR_NONE;
2258 u_int8_t *data_ptr = NULL;
2260 u_int8_t atacmd[12];
2261 struct get_hook hook;
2262 int c, data_bytes = 0;
2268 char *datastr = NULL, *tstr, *resstr = NULL;
2270 int fd_data = 0, fd_res = 0;
2273 ccb = cam_getccb(device);
2276 warnx("scsicmd: error allocating ccb");
2280 bzero(&(&ccb->ccb_h)[1],
2281 sizeof(union ccb) - sizeof(struct ccb_hdr));
2283 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2287 while (isspace(*tstr) && (*tstr != '\0'))
2289 hook.argc = argc - optind;
2290 hook.argv = argv + optind;
2292 atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
2295 * Increment optind by the number of arguments the
2296 * encoding routine processed. After each call to
2297 * getopt(3), optind points to the argument that
2298 * getopt should process _next_. In this case,
2299 * that means it points to the first command string
2300 * argument, if there is one. Once we increment
2301 * this, it should point to either the next command
2302 * line argument, or it should be past the end of
2309 while (isspace(*tstr) && (*tstr != '\0'))
2311 hook.argc = argc - optind;
2312 hook.argv = argv + optind;
2314 cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
2317 * Increment optind by the number of arguments the
2318 * encoding routine processed. After each call to
2319 * getopt(3), optind points to the argument that
2320 * getopt should process _next_. In this case,
2321 * that means it points to the first command string
2322 * argument, if there is one. Once we increment
2323 * this, it should point to either the next command
2324 * line argument, or it should be past the end of
2336 if (arglist & CAM_ARG_CMD_OUT) {
2337 warnx("command must either be "
2338 "read or write, not both");
2340 goto scsicmd_bailout;
2342 arglist |= CAM_ARG_CMD_IN;
2344 data_bytes = strtol(optarg, NULL, 0);
2345 if (data_bytes <= 0) {
2346 warnx("invalid number of input bytes %d",
2349 goto scsicmd_bailout;
2351 hook.argc = argc - optind;
2352 hook.argv = argv + optind;
2355 datastr = cget(&hook, NULL);
2357 * If the user supplied "-" instead of a format, he
2358 * wants the data to be written to stdout.
2360 if ((datastr != NULL)
2361 && (datastr[0] == '-'))
2364 data_ptr = (u_int8_t *)malloc(data_bytes);
2365 if (data_ptr == NULL) {
2366 warnx("can't malloc memory for data_ptr");
2368 goto scsicmd_bailout;
2372 if (arglist & CAM_ARG_CMD_IN) {
2373 warnx("command must either be "
2374 "read or write, not both");
2376 goto scsicmd_bailout;
2378 arglist |= CAM_ARG_CMD_OUT;
2379 flags = CAM_DIR_OUT;
2380 data_bytes = strtol(optarg, NULL, 0);
2381 if (data_bytes <= 0) {
2382 warnx("invalid number of output bytes %d",
2385 goto scsicmd_bailout;
2387 hook.argc = argc - optind;
2388 hook.argv = argv + optind;
2390 datastr = cget(&hook, NULL);
2391 data_ptr = (u_int8_t *)malloc(data_bytes);
2392 if (data_ptr == NULL) {
2393 warnx("can't malloc memory for data_ptr");
2395 goto scsicmd_bailout;
2397 bzero(data_ptr, data_bytes);
2399 * If the user supplied "-" instead of a format, he
2400 * wants the data to be read from stdin.
2402 if ((datastr != NULL)
2403 && (datastr[0] == '-'))
2406 buff_encode_visit(data_ptr, data_bytes, datastr,
2412 hook.argc = argc - optind;
2413 hook.argv = argv + optind;
2415 resstr = cget(&hook, NULL);
2416 if ((resstr != NULL) && (resstr[0] == '-'))
2426 * If fd_data is set, and we're writing to the device, we need to
2427 * read the data the user wants written from stdin.
2429 if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
2431 int amt_to_read = data_bytes;
2432 u_int8_t *buf_ptr = data_ptr;
2434 for (amt_read = 0; amt_to_read > 0;
2435 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
2436 if (amt_read == -1) {
2437 warn("error reading data from stdin");
2439 goto scsicmd_bailout;
2441 amt_to_read -= amt_read;
2442 buf_ptr += amt_read;
2446 if (arglist & CAM_ARG_ERR_RECOVER)
2447 flags |= CAM_PASS_ERR_RECOVER;
2449 /* Disable freezing the device queue */
2450 flags |= CAM_DEV_QFRZDIS;
2454 * This is taken from the SCSI-3 draft spec.
2455 * (T10/1157D revision 0.3)
2456 * The top 3 bits of an opcode are the group code.
2457 * The next 5 bits are the command code.
2458 * Group 0: six byte commands
2459 * Group 1: ten byte commands
2460 * Group 2: ten byte commands
2462 * Group 4: sixteen byte commands
2463 * Group 5: twelve byte commands
2464 * Group 6: vendor specific
2465 * Group 7: vendor specific
2467 switch((cdb[0] >> 5) & 0x7) {
2478 /* computed by buff_encode_visit */
2489 * We should probably use csio_build_visit or something like that
2490 * here, but it's easier to encode arguments as you go. The
2491 * alternative would be skipping the CDB argument and then encoding
2492 * it here, since we've got the data buffer argument by now.
2494 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
2496 cam_fill_csio(&ccb->csio,
2497 /*retries*/ retry_count,
2500 /*tag_action*/ MSG_SIMPLE_Q_TAG,
2501 /*data_ptr*/ data_ptr,
2502 /*dxfer_len*/ data_bytes,
2503 /*sense_len*/ SSD_FULL_SIZE,
2504 /*cdb_len*/ cdb_len,
2505 /*timeout*/ timeout ? timeout : 5000);
2508 bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
2510 ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
2512 ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
2514 ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
2516 cam_fill_ataio(&ccb->ataio,
2517 /*retries*/ retry_count,
2521 /*data_ptr*/ data_ptr,
2522 /*dxfer_len*/ data_bytes,
2523 /*timeout*/ timeout ? timeout : 5000);
2526 if (((retval = cam_send_ccb(device, ccb)) < 0)
2527 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2528 const char warnstr[] = "error sending command";
2535 if (arglist & CAM_ARG_VERBOSE) {
2536 cam_error_print(device, ccb, CAM_ESF_ALL,
2537 CAM_EPF_ALL, stderr);
2541 goto scsicmd_bailout;
2544 if (atacmd_len && need_res) {
2546 buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
2548 fprintf(stdout, "\n");
2551 "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
2552 ccb->ataio.res.status,
2553 ccb->ataio.res.error,
2554 ccb->ataio.res.lba_low,
2555 ccb->ataio.res.lba_mid,
2556 ccb->ataio.res.lba_high,
2557 ccb->ataio.res.device,
2558 ccb->ataio.res.lba_low_exp,
2559 ccb->ataio.res.lba_mid_exp,
2560 ccb->ataio.res.lba_high_exp,
2561 ccb->ataio.res.sector_count,
2562 ccb->ataio.res.sector_count_exp);
2567 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
2568 && (arglist & CAM_ARG_CMD_IN)
2569 && (data_bytes > 0)) {
2571 buff_decode_visit(data_ptr, data_bytes, datastr,
2573 fprintf(stdout, "\n");
2575 ssize_t amt_written;
2576 int amt_to_write = data_bytes;
2577 u_int8_t *buf_ptr = data_ptr;
2579 for (amt_written = 0; (amt_to_write > 0) &&
2580 (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
2581 amt_to_write -= amt_written;
2582 buf_ptr += amt_written;
2584 if (amt_written == -1) {
2585 warn("error writing data to stdout");
2587 goto scsicmd_bailout;
2588 } else if ((amt_written == 0)
2589 && (amt_to_write > 0)) {
2590 warnx("only wrote %u bytes out of %u",
2591 data_bytes - amt_to_write, data_bytes);
2598 if ((data_bytes > 0) && (data_ptr != NULL))
2607 camdebug(int argc, char **argv, char *combinedopt)
2610 int bus = -1, target = -1, lun = -1;
2611 char *tstr, *tmpstr = NULL;
2615 bzero(&ccb, sizeof(union ccb));
2617 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2620 arglist |= CAM_ARG_DEBUG_INFO;
2621 ccb.cdbg.flags |= CAM_DEBUG_INFO;
2624 arglist |= CAM_ARG_DEBUG_PERIPH;
2625 ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
2628 arglist |= CAM_ARG_DEBUG_SUBTRACE;
2629 ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
2632 arglist |= CAM_ARG_DEBUG_TRACE;
2633 ccb.cdbg.flags |= CAM_DEBUG_TRACE;
2636 arglist |= CAM_ARG_DEBUG_XPT;
2637 ccb.cdbg.flags |= CAM_DEBUG_XPT;
2640 arglist |= CAM_ARG_DEBUG_CDB;
2641 ccb.cdbg.flags |= CAM_DEBUG_CDB;
2648 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
2649 warnx("error opening transport layer device %s", XPT_DEVICE);
2650 warn("%s", XPT_DEVICE);
2657 warnx("you must specify \"off\", \"all\" or a bus,");
2658 warnx("bus:target, or bus:target:lun");
2665 while (isspace(*tstr) && (*tstr != '\0'))
2668 if (strncmp(tstr, "off", 3) == 0) {
2669 ccb.cdbg.flags = CAM_DEBUG_NONE;
2670 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
2671 CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
2673 } else if (strncmp(tstr, "all", 3) != 0) {
2674 tmpstr = (char *)strtok(tstr, ":");
2675 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2676 bus = strtol(tmpstr, NULL, 0);
2677 arglist |= CAM_ARG_BUS;
2678 tmpstr = (char *)strtok(NULL, ":");
2679 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2680 target = strtol(tmpstr, NULL, 0);
2681 arglist |= CAM_ARG_TARGET;
2682 tmpstr = (char *)strtok(NULL, ":");
2683 if ((tmpstr != NULL) && (*tmpstr != '\0')){
2684 lun = strtol(tmpstr, NULL, 0);
2685 arglist |= CAM_ARG_LUN;
2690 warnx("you must specify \"all\", \"off\", or a bus,");
2691 warnx("bus:target, or bus:target:lun to debug");
2697 ccb.ccb_h.func_code = XPT_DEBUG;
2698 ccb.ccb_h.path_id = bus;
2699 ccb.ccb_h.target_id = target;
2700 ccb.ccb_h.target_lun = lun;
2702 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
2703 warn("CAMIOCOMMAND ioctl failed");
2708 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
2709 CAM_FUNC_NOTAVAIL) {
2710 warnx("CAM debugging not available");
2711 warnx("you need to put options CAMDEBUG in"
2712 " your kernel config file!");
2714 } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
2716 warnx("XPT_DEBUG CCB failed with status %#x",
2720 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
2722 "Debugging turned off\n");
2725 "Debugging enabled for "
2738 tagcontrol(struct cam_device *device, int argc, char **argv,
2748 ccb = cam_getccb(device);
2751 warnx("tagcontrol: error allocating ccb");
2755 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2758 numtags = strtol(optarg, NULL, 0);
2760 warnx("tag count %d is < 0", numtags);
2762 goto tagcontrol_bailout;
2773 cam_path_string(device, pathstr, sizeof(pathstr));
2776 bzero(&(&ccb->ccb_h)[1],
2777 sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
2778 ccb->ccb_h.func_code = XPT_REL_SIMQ;
2779 ccb->ccb_h.flags = CAM_DEV_QFREEZE;
2780 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
2781 ccb->crs.openings = numtags;
2784 if (cam_send_ccb(device, ccb) < 0) {
2785 perror("error sending XPT_REL_SIMQ CCB");
2787 goto tagcontrol_bailout;
2790 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2791 warnx("XPT_REL_SIMQ CCB failed");
2792 cam_error_print(device, ccb, CAM_ESF_ALL,
2793 CAM_EPF_ALL, stderr);
2795 goto tagcontrol_bailout;
2800 fprintf(stdout, "%stagged openings now %d\n",
2801 pathstr, ccb->crs.openings);
2804 bzero(&(&ccb->ccb_h)[1],
2805 sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
2807 ccb->ccb_h.func_code = XPT_GDEV_STATS;
2809 if (cam_send_ccb(device, ccb) < 0) {
2810 perror("error sending XPT_GDEV_STATS CCB");
2812 goto tagcontrol_bailout;
2815 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2816 warnx("XPT_GDEV_STATS CCB failed");
2817 cam_error_print(device, ccb, CAM_ESF_ALL,
2818 CAM_EPF_ALL, stderr);
2820 goto tagcontrol_bailout;
2823 if (arglist & CAM_ARG_VERBOSE) {
2824 fprintf(stdout, "%s", pathstr);
2825 fprintf(stdout, "dev_openings %d\n", ccb->cgds.dev_openings);
2826 fprintf(stdout, "%s", pathstr);
2827 fprintf(stdout, "dev_active %d\n", ccb->cgds.dev_active);
2828 fprintf(stdout, "%s", pathstr);
2829 fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
2830 fprintf(stdout, "%s", pathstr);
2831 fprintf(stdout, "devq_queued %d\n", ccb->cgds.devq_queued);
2832 fprintf(stdout, "%s", pathstr);
2833 fprintf(stdout, "held %d\n", ccb->cgds.held);
2834 fprintf(stdout, "%s", pathstr);
2835 fprintf(stdout, "mintags %d\n", ccb->cgds.mintags);
2836 fprintf(stdout, "%s", pathstr);
2837 fprintf(stdout, "maxtags %d\n", ccb->cgds.maxtags);
2840 fprintf(stdout, "%s", pathstr);
2841 fprintf(stdout, "device openings: ");
2843 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
2844 ccb->cgds.dev_active);
2854 cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
2858 cam_path_string(device, pathstr, sizeof(pathstr));
2860 if (cts->transport == XPORT_SPI) {
2861 struct ccb_trans_settings_spi *spi =
2862 &cts->xport_specific.spi;
2864 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
2866 fprintf(stdout, "%ssync parameter: %d\n", pathstr,
2869 if (spi->sync_offset != 0) {
2872 freq = scsi_calc_syncsrate(spi->sync_period);
2873 fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
2874 pathstr, freq / 1000, freq % 1000);
2878 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
2879 fprintf(stdout, "%soffset: %d\n", pathstr,
2883 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
2884 fprintf(stdout, "%sbus width: %d bits\n", pathstr,
2885 (0x01 << spi->bus_width) * 8);
2888 if (spi->valid & CTS_SPI_VALID_DISC) {
2889 fprintf(stdout, "%sdisconnection is %s\n", pathstr,
2890 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
2891 "enabled" : "disabled");
2894 if (cts->transport == XPORT_ATA) {
2895 struct ccb_trans_settings_ata *ata =
2896 &cts->xport_specific.ata;
2898 if ((ata->valid & CTS_ATA_VALID_MODE) != 0) {
2899 fprintf(stdout, "%sATA mode: %s\n", pathstr,
2900 ata_mode2string(ata->mode));
2902 if ((ata->valid & CTS_ATA_VALID_ATAPI) != 0) {
2903 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2906 if ((ata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
2907 fprintf(stdout, "%sPIO transaction length: %d\n",
2908 pathstr, ata->bytecount);
2911 if (cts->transport == XPORT_SATA) {
2912 struct ccb_trans_settings_sata *sata =
2913 &cts->xport_specific.sata;
2915 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
2916 fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
2919 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
2920 fprintf(stdout, "%sATA mode: %s\n", pathstr,
2921 ata_mode2string(sata->mode));
2923 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
2924 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2927 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
2928 fprintf(stdout, "%sPIO transaction length: %d\n",
2929 pathstr, sata->bytecount);
2931 if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
2932 fprintf(stdout, "%sPMP presence: %d\n", pathstr,
2935 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
2936 fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
2939 if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
2940 fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
2944 if (cts->protocol == PROTO_SCSI) {
2945 struct ccb_trans_settings_scsi *scsi=
2946 &cts->proto_specific.scsi;
2948 if (scsi->valid & CTS_SCSI_VALID_TQ) {
2949 fprintf(stdout, "%stagged queueing is %s\n", pathstr,
2950 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
2951 "enabled" : "disabled");
2958 * Get a path inquiry CCB for the specified device.
2961 get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
2966 ccb = cam_getccb(device);
2968 warnx("get_cpi: couldn't allocate CCB");
2971 bzero(&(&ccb->ccb_h)[1],
2972 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2973 ccb->ccb_h.func_code = XPT_PATH_INQ;
2974 if (cam_send_ccb(device, ccb) < 0) {
2975 warn("get_cpi: error sending Path Inquiry CCB");
2976 if (arglist & CAM_ARG_VERBOSE)
2977 cam_error_print(device, ccb, CAM_ESF_ALL,
2978 CAM_EPF_ALL, stderr);
2980 goto get_cpi_bailout;
2982 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2983 if (arglist & CAM_ARG_VERBOSE)
2984 cam_error_print(device, ccb, CAM_ESF_ALL,
2985 CAM_EPF_ALL, stderr);
2987 goto get_cpi_bailout;
2989 bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
2997 * Get a get device CCB for the specified device.
3000 get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
3005 ccb = cam_getccb(device);
3007 warnx("get_cgd: couldn't allocate CCB");
3010 bzero(&(&ccb->ccb_h)[1],
3011 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3012 ccb->ccb_h.func_code = XPT_GDEV_TYPE;
3013 if (cam_send_ccb(device, ccb) < 0) {
3014 warn("get_cgd: error sending Path Inquiry CCB");
3015 if (arglist & CAM_ARG_VERBOSE)
3016 cam_error_print(device, ccb, CAM_ESF_ALL,
3017 CAM_EPF_ALL, stderr);
3019 goto get_cgd_bailout;
3021 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3022 if (arglist & CAM_ARG_VERBOSE)
3023 cam_error_print(device, ccb, CAM_ESF_ALL,
3024 CAM_EPF_ALL, stderr);
3026 goto get_cgd_bailout;
3028 bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
3036 cpi_print(struct ccb_pathinq *cpi)
3038 char adapter_str[1024];
3041 snprintf(adapter_str, sizeof(adapter_str),
3042 "%s%d:", cpi->dev_name, cpi->unit_number);
3044 fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
3047 for (i = 1; i < 0xff; i = i << 1) {
3050 if ((i & cpi->hba_inquiry) == 0)
3053 fprintf(stdout, "%s supports ", adapter_str);
3057 str = "MDP message";
3060 str = "32 bit wide SCSI";
3063 str = "16 bit wide SCSI";
3066 str = "SDTR message";
3069 str = "linked CDBs";
3072 str = "tag queue messages";
3075 str = "soft reset alternative";
3078 str = "SATA Port Multiplier";
3081 str = "unknown PI bit set";
3084 fprintf(stdout, "%s\n", str);
3087 for (i = 1; i < 0xff; i = i << 1) {
3090 if ((i & cpi->hba_misc) == 0)
3093 fprintf(stdout, "%s ", adapter_str);
3097 str = "bus scans from high ID to low ID";
3100 str = "removable devices not included in scan";
3102 case PIM_NOINITIATOR:
3103 str = "initiator role not supported";
3105 case PIM_NOBUSRESET:
3106 str = "user has disabled initial BUS RESET or"
3107 " controller is in target/mixed mode";
3110 str = "do not send 6-byte commands";
3113 str = "scan bus sequentially";
3116 str = "unknown PIM bit set";
3119 fprintf(stdout, "%s\n", str);
3122 for (i = 1; i < 0xff; i = i << 1) {
3125 if ((i & cpi->target_sprt) == 0)
3128 fprintf(stdout, "%s supports ", adapter_str);
3131 str = "target mode processor mode";
3134 str = "target mode phase cog. mode";
3136 case PIT_DISCONNECT:
3137 str = "disconnects in target mode";
3140 str = "terminate I/O message in target mode";
3143 str = "group 6 commands in target mode";
3146 str = "group 7 commands in target mode";
3149 str = "unknown PIT bit set";
3153 fprintf(stdout, "%s\n", str);
3155 fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
3157 fprintf(stdout, "%s maximum target: %d\n", adapter_str,
3159 fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
3161 fprintf(stdout, "%s highest path ID in subsystem: %d\n",
3162 adapter_str, cpi->hpath_id);
3163 fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
3165 fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
3166 fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
3167 fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
3168 adapter_str, cpi->hba_vendor);
3169 fprintf(stdout, "%s HBA device ID: 0x%04x\n",
3170 adapter_str, cpi->hba_device);
3171 fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
3172 adapter_str, cpi->hba_subvendor);
3173 fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
3174 adapter_str, cpi->hba_subdevice);
3175 fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
3176 fprintf(stdout, "%s base transfer speed: ", adapter_str);
3177 if (cpi->base_transfer_speed > 1000)
3178 fprintf(stdout, "%d.%03dMB/sec\n",
3179 cpi->base_transfer_speed / 1000,
3180 cpi->base_transfer_speed % 1000);
3182 fprintf(stdout, "%dKB/sec\n",
3183 (cpi->base_transfer_speed % 1000) * 1000);
3184 fprintf(stdout, "%s maximum transfer size: %u bytes\n",
3185 adapter_str, cpi->maxio);
3189 get_print_cts(struct cam_device *device, int user_settings, int quiet,
3190 struct ccb_trans_settings *cts)
3196 ccb = cam_getccb(device);
3199 warnx("get_print_cts: error allocating ccb");
3203 bzero(&(&ccb->ccb_h)[1],
3204 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3206 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
3208 if (user_settings == 0)
3209 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
3211 ccb->cts.type = CTS_TYPE_USER_SETTINGS;
3213 if (cam_send_ccb(device, ccb) < 0) {
3214 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
3215 if (arglist & CAM_ARG_VERBOSE)
3216 cam_error_print(device, ccb, CAM_ESF_ALL,
3217 CAM_EPF_ALL, stderr);
3219 goto get_print_cts_bailout;
3222 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3223 warnx("XPT_GET_TRANS_SETTINGS CCB failed");
3224 if (arglist & CAM_ARG_VERBOSE)
3225 cam_error_print(device, ccb, CAM_ESF_ALL,
3226 CAM_EPF_ALL, stderr);
3228 goto get_print_cts_bailout;
3232 cts_print(device, &ccb->cts);
3235 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
3237 get_print_cts_bailout:
3245 ratecontrol(struct cam_device *device, int retry_count, int timeout,
3246 int argc, char **argv, char *combinedopt)
3250 int user_settings = 0;
3252 int disc_enable = -1, tag_enable = -1;
3255 double syncrate = -1;
3258 int change_settings = 0, send_tur = 0;
3259 struct ccb_pathinq cpi;
3261 ccb = cam_getccb(device);
3263 warnx("ratecontrol: error allocating ccb");
3266 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3275 if (strncasecmp(optarg, "enable", 6) == 0)
3277 else if (strncasecmp(optarg, "disable", 7) == 0)
3280 warnx("-D argument \"%s\" is unknown", optarg);
3282 goto ratecontrol_bailout;
3284 change_settings = 1;
3287 mode = ata_string2mode(optarg);
3289 warnx("unknown mode '%s'", optarg);
3291 goto ratecontrol_bailout;
3293 change_settings = 1;
3296 offset = strtol(optarg, NULL, 0);
3298 warnx("offset value %d is < 0", offset);
3300 goto ratecontrol_bailout;
3302 change_settings = 1;
3308 syncrate = atof(optarg);
3310 warnx("sync rate %f is < 0", syncrate);
3312 goto ratecontrol_bailout;
3314 change_settings = 1;
3317 if (strncasecmp(optarg, "enable", 6) == 0)
3319 else if (strncasecmp(optarg, "disable", 7) == 0)
3322 warnx("-T argument \"%s\" is unknown", optarg);
3324 goto ratecontrol_bailout;
3326 change_settings = 1;
3332 bus_width = strtol(optarg, NULL, 0);
3333 if (bus_width < 0) {
3334 warnx("bus width %d is < 0", bus_width);
3336 goto ratecontrol_bailout;
3338 change_settings = 1;
3344 bzero(&(&ccb->ccb_h)[1],
3345 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3347 * Grab path inquiry information, so we can determine whether
3348 * or not the initiator is capable of the things that the user
3351 ccb->ccb_h.func_code = XPT_PATH_INQ;
3352 if (cam_send_ccb(device, ccb) < 0) {
3353 perror("error sending XPT_PATH_INQ CCB");
3354 if (arglist & CAM_ARG_VERBOSE) {
3355 cam_error_print(device, ccb, CAM_ESF_ALL,
3356 CAM_EPF_ALL, stderr);
3359 goto ratecontrol_bailout;
3361 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3362 warnx("XPT_PATH_INQ CCB failed");
3363 if (arglist & CAM_ARG_VERBOSE) {
3364 cam_error_print(device, ccb, CAM_ESF_ALL,
3365 CAM_EPF_ALL, stderr);
3368 goto ratecontrol_bailout;
3370 bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
3371 bzero(&(&ccb->ccb_h)[1],
3372 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3374 fprintf(stdout, "%s parameters:\n",
3375 user_settings ? "User" : "Current");
3377 retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
3379 goto ratecontrol_bailout;
3381 if (arglist & CAM_ARG_VERBOSE)
3384 if (change_settings) {
3385 int didsettings = 0;
3386 struct ccb_trans_settings_spi *spi = NULL;
3387 struct ccb_trans_settings_ata *ata = NULL;
3388 struct ccb_trans_settings_sata *sata = NULL;
3389 struct ccb_trans_settings_scsi *scsi = NULL;
3391 if (ccb->cts.transport == XPORT_SPI)
3392 spi = &ccb->cts.xport_specific.spi;
3393 if (ccb->cts.transport == XPORT_ATA)
3394 ata = &ccb->cts.xport_specific.ata;
3395 if (ccb->cts.transport == XPORT_SATA)
3396 sata = &ccb->cts.xport_specific.sata;
3397 if (ccb->cts.protocol == PROTO_SCSI)
3398 scsi = &ccb->cts.proto_specific.scsi;
3399 ccb->cts.xport_specific.valid = 0;
3400 ccb->cts.proto_specific.valid = 0;
3401 if (spi && disc_enable != -1) {
3402 spi->valid |= CTS_SPI_VALID_DISC;
3403 if (disc_enable == 0)
3404 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
3406 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
3409 if (scsi && tag_enable != -1) {
3410 if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
3411 warnx("HBA does not support tagged queueing, "
3412 "so you cannot modify tag settings");
3414 goto ratecontrol_bailout;
3416 scsi->valid |= CTS_SCSI_VALID_TQ;
3417 if (tag_enable == 0)
3418 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
3420 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
3423 if (spi && offset != -1) {
3424 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3425 warnx("HBA is not capable of changing offset");
3427 goto ratecontrol_bailout;
3429 spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
3430 spi->sync_offset = offset;
3433 if (spi && syncrate != -1) {
3434 int prelim_sync_period;
3436 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3437 warnx("HBA is not capable of changing "
3440 goto ratecontrol_bailout;
3442 spi->valid |= CTS_SPI_VALID_SYNC_RATE;
3444 * The sync rate the user gives us is in MHz.
3445 * We need to translate it into KHz for this
3450 * Next, we calculate a "preliminary" sync period
3451 * in tenths of a nanosecond.
3454 prelim_sync_period = 0;
3456 prelim_sync_period = 10000000 / syncrate;
3458 scsi_calc_syncparam(prelim_sync_period);
3461 if (sata && syncrate != -1) {
3462 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3463 warnx("HBA is not capable of changing "
3466 goto ratecontrol_bailout;
3468 sata->revision = ata_speed2revision(syncrate * 100);
3469 if (sata->revision < 0) {
3470 warnx("Invalid rate %f", syncrate);
3472 goto ratecontrol_bailout;
3474 sata->valid |= CTS_SATA_VALID_REVISION;
3477 if ((ata || sata) && mode != -1) {
3478 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3479 warnx("HBA is not capable of changing "
3482 goto ratecontrol_bailout;
3486 ata->valid |= CTS_ATA_VALID_MODE;
3489 sata->valid |= CTS_SATA_VALID_MODE;
3494 * The bus_width argument goes like this:
3498 * Therefore, if you shift the number of bits given on the
3499 * command line right by 4, you should get the correct
3502 if (spi && bus_width != -1) {
3504 * We might as well validate things here with a
3505 * decipherable error message, rather than what
3506 * will probably be an indecipherable error message
3507 * by the time it gets back to us.
3509 if ((bus_width == 16)
3510 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
3511 warnx("HBA does not support 16 bit bus width");
3513 goto ratecontrol_bailout;
3514 } else if ((bus_width == 32)
3515 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
3516 warnx("HBA does not support 32 bit bus width");
3518 goto ratecontrol_bailout;
3519 } else if ((bus_width != 8)
3520 && (bus_width != 16)
3521 && (bus_width != 32)) {
3522 warnx("Invalid bus width %d", bus_width);
3524 goto ratecontrol_bailout;
3526 spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
3527 spi->bus_width = bus_width >> 4;
3530 if (didsettings == 0) {
3531 goto ratecontrol_bailout;
3533 if (!user_settings && (ata || sata)) {
3534 warnx("You can modify only user settings for ATA/SATA");
3536 goto ratecontrol_bailout;
3538 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
3539 if (cam_send_ccb(device, ccb) < 0) {
3540 perror("error sending XPT_SET_TRAN_SETTINGS CCB");
3541 if (arglist & CAM_ARG_VERBOSE) {
3542 cam_error_print(device, ccb, CAM_ESF_ALL,
3543 CAM_EPF_ALL, stderr);
3546 goto ratecontrol_bailout;
3548 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3549 warnx("XPT_SET_TRANS_SETTINGS CCB failed");
3550 if (arglist & CAM_ARG_VERBOSE) {
3551 cam_error_print(device, ccb, CAM_ESF_ALL,
3552 CAM_EPF_ALL, stderr);
3555 goto ratecontrol_bailout;
3559 retval = testunitready(device, retry_count, timeout,
3560 (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
3562 * If the TUR didn't succeed, just bail.
3566 fprintf(stderr, "Test Unit Ready failed\n");
3567 goto ratecontrol_bailout;
3570 * If the user wants things quiet, there's no sense in
3571 * getting the transfer settings, if we're not going
3575 goto ratecontrol_bailout;
3576 fprintf(stdout, "New parameters:\n");
3577 retval = get_print_cts(device, user_settings, 0, NULL);
3580 ratecontrol_bailout:
3586 scsiformat(struct cam_device *device, int argc, char **argv,
3587 char *combinedopt, int retry_count, int timeout)
3591 int ycount = 0, quiet = 0;
3592 int error = 0, response = 0, retval = 0;
3593 int use_timeout = 10800 * 1000;
3595 struct format_defect_list_header fh;
3596 u_int8_t *data_ptr = NULL;
3597 u_int32_t dxfer_len = 0;
3599 int num_warnings = 0;
3602 ccb = cam_getccb(device);
3605 warnx("scsiformat: error allocating ccb");
3609 bzero(&(&ccb->ccb_h)[1],
3610 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3612 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3633 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
3634 "following device:\n");
3636 error = scsidoinquiry(device, argc, argv, combinedopt,
3637 retry_count, timeout);
3640 warnx("scsiformat: error sending inquiry");
3641 goto scsiformat_bailout;
3650 fprintf(stdout, "Are you SURE you want to do "
3653 if (fgets(str, sizeof(str), stdin) != NULL) {
3655 if (strncasecmp(str, "yes", 3) == 0)
3657 else if (strncasecmp(str, "no", 2) == 0)
3660 fprintf(stdout, "Please answer"
3661 " \"yes\" or \"no\"\n");
3664 } while (response == 0);
3666 if (response == -1) {
3668 goto scsiformat_bailout;
3673 use_timeout = timeout;
3676 fprintf(stdout, "Current format timeout is %d seconds\n",
3677 use_timeout / 1000);
3681 * If the user hasn't disabled questions and didn't specify a
3682 * timeout on the command line, ask them if they want the current
3686 && (timeout == 0)) {
3688 int new_timeout = 0;
3690 fprintf(stdout, "Enter new timeout in seconds or press\n"
3691 "return to keep the current timeout [%d] ",
3692 use_timeout / 1000);
3694 if (fgets(str, sizeof(str), stdin) != NULL) {
3696 new_timeout = atoi(str);
3699 if (new_timeout != 0) {
3700 use_timeout = new_timeout * 1000;
3701 fprintf(stdout, "Using new timeout value %d\n",
3702 use_timeout / 1000);
3707 * Keep this outside the if block below to silence any unused
3708 * variable warnings.
3710 bzero(&fh, sizeof(fh));
3713 * If we're in immediate mode, we've got to include the format
3716 if (immediate != 0) {
3717 fh.byte2 = FU_DLH_IMMED;
3718 data_ptr = (u_int8_t *)&fh;
3719 dxfer_len = sizeof(fh);
3720 byte2 = FU_FMT_DATA;
3721 } else if (quiet == 0) {
3722 fprintf(stdout, "Formatting...");
3726 scsi_format_unit(&ccb->csio,
3727 /* retries */ retry_count,
3729 /* tag_action */ MSG_SIMPLE_Q_TAG,
3732 /* data_ptr */ data_ptr,
3733 /* dxfer_len */ dxfer_len,
3734 /* sense_len */ SSD_FULL_SIZE,
3735 /* timeout */ use_timeout);
3737 /* Disable freezing the device queue */
3738 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3740 if (arglist & CAM_ARG_ERR_RECOVER)
3741 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3743 if (((retval = cam_send_ccb(device, ccb)) < 0)
3744 || ((immediate == 0)
3745 && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
3746 const char errstr[] = "error sending format command";
3753 if (arglist & CAM_ARG_VERBOSE) {
3754 cam_error_print(device, ccb, CAM_ESF_ALL,
3755 CAM_EPF_ALL, stderr);
3758 goto scsiformat_bailout;
3762 * If we ran in non-immediate mode, we already checked for errors
3763 * above and printed out any necessary information. If we're in
3764 * immediate mode, we need to loop through and get status
3765 * information periodically.
3767 if (immediate == 0) {
3769 fprintf(stdout, "Format Complete\n");
3771 goto scsiformat_bailout;
3778 bzero(&(&ccb->ccb_h)[1],
3779 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3782 * There's really no need to do error recovery or
3783 * retries here, since we're just going to sit in a
3784 * loop and wait for the device to finish formatting.
3786 scsi_test_unit_ready(&ccb->csio,
3789 /* tag_action */ MSG_SIMPLE_Q_TAG,
3790 /* sense_len */ SSD_FULL_SIZE,
3791 /* timeout */ 5000);
3793 /* Disable freezing the device queue */
3794 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3796 retval = cam_send_ccb(device, ccb);
3799 * If we get an error from the ioctl, bail out. SCSI
3800 * errors are expected.
3803 warn("error sending CAMIOCOMMAND ioctl");
3804 if (arglist & CAM_ARG_VERBOSE) {
3805 cam_error_print(device, ccb, CAM_ESF_ALL,
3806 CAM_EPF_ALL, stderr);
3809 goto scsiformat_bailout;
3812 status = ccb->ccb_h.status & CAM_STATUS_MASK;
3814 if ((status != CAM_REQ_CMP)
3815 && (status == CAM_SCSI_STATUS_ERROR)
3816 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3817 struct scsi_sense_data *sense;
3818 int error_code, sense_key, asc, ascq;
3820 sense = &ccb->csio.sense_data;
3821 scsi_extract_sense_len(sense, ccb->csio.sense_len -
3822 ccb->csio.sense_resid, &error_code, &sense_key,
3823 &asc, &ascq, /*show_errors*/ 1);
3826 * According to the SCSI-2 and SCSI-3 specs, a
3827 * drive that is in the middle of a format should
3828 * return NOT READY with an ASC of "logical unit
3829 * not ready, format in progress". The sense key
3830 * specific bytes will then be a progress indicator.
3832 if ((sense_key == SSD_KEY_NOT_READY)
3833 && (asc == 0x04) && (ascq == 0x04)) {
3836 if ((scsi_get_sks(sense, ccb->csio.sense_len -
3837 ccb->csio.sense_resid, sks) == 0)
3840 u_int64_t percentage;
3842 val = scsi_2btoul(&sks[1]);
3843 percentage = 10000 * val;
3846 "\rFormatting: %ju.%02u %% "
3848 (uintmax_t)(percentage /
3850 (unsigned)((percentage /
3854 } else if ((quiet == 0)
3855 && (++num_warnings <= 1)) {
3856 warnx("Unexpected SCSI Sense Key "
3857 "Specific value returned "
3859 scsi_sense_print(device, &ccb->csio,
3861 warnx("Unable to print status "
3862 "information, but format will "
3864 warnx("will exit when format is "
3869 warnx("Unexpected SCSI error during format");
3870 cam_error_print(device, ccb, CAM_ESF_ALL,
3871 CAM_EPF_ALL, stderr);
3873 goto scsiformat_bailout;
3876 } else if (status != CAM_REQ_CMP) {
3877 warnx("Unexpected CAM status %#x", status);
3878 if (arglist & CAM_ARG_VERBOSE)
3879 cam_error_print(device, ccb, CAM_ESF_ALL,
3880 CAM_EPF_ALL, stderr);
3882 goto scsiformat_bailout;
3885 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
3888 fprintf(stdout, "\nFormat Complete\n");
3898 scsireportluns(struct cam_device *device, int argc, char **argv,
3899 char *combinedopt, int retry_count, int timeout)
3902 int c, countonly, lunsonly;
3903 struct scsi_report_luns_data *lundata;
3905 uint8_t report_type;
3906 uint32_t list_len, i, j;
3911 report_type = RPL_REPORT_DEFAULT;
3912 ccb = cam_getccb(device);
3915 warnx("%s: error allocating ccb", __func__);
3919 bzero(&(&ccb->ccb_h)[1],
3920 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3925 while ((c = getopt(argc, argv, combinedopt)) != -1) {
3934 if (strcasecmp(optarg, "default") == 0)
3935 report_type = RPL_REPORT_DEFAULT;
3936 else if (strcasecmp(optarg, "wellknown") == 0)
3937 report_type = RPL_REPORT_WELLKNOWN;
3938 else if (strcasecmp(optarg, "all") == 0)
3939 report_type = RPL_REPORT_ALL;
3941 warnx("%s: invalid report type \"%s\"",
3952 if ((countonly != 0)
3953 && (lunsonly != 0)) {
3954 warnx("%s: you can only specify one of -c or -l", __func__);
3959 * According to SPC-4, the allocation length must be at least 16
3960 * bytes -- enough for the header and one LUN.
3962 alloc_len = sizeof(*lundata) + 8;
3966 lundata = malloc(alloc_len);
3968 if (lundata == NULL) {
3969 warn("%s: error mallocing %d bytes", __func__, alloc_len);
3974 scsi_report_luns(&ccb->csio,
3975 /*retries*/ retry_count,
3977 /*tag_action*/ MSG_SIMPLE_Q_TAG,
3978 /*select_report*/ report_type,
3979 /*rpl_buf*/ lundata,
3980 /*alloc_len*/ alloc_len,
3981 /*sense_len*/ SSD_FULL_SIZE,
3982 /*timeout*/ timeout ? timeout : 5000);
3984 /* Disable freezing the device queue */
3985 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3987 if (arglist & CAM_ARG_ERR_RECOVER)
3988 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3990 if (cam_send_ccb(device, ccb) < 0) {
3991 warn("error sending REPORT LUNS command");
3993 if (arglist & CAM_ARG_VERBOSE)
3994 cam_error_print(device, ccb, CAM_ESF_ALL,
3995 CAM_EPF_ALL, stderr);
4001 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4002 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4008 list_len = scsi_4btoul(lundata->length);
4011 * If we need to list the LUNs, and our allocation
4012 * length was too short, reallocate and retry.
4014 if ((countonly == 0)
4015 && (list_len > (alloc_len - sizeof(*lundata)))) {
4016 alloc_len = list_len + sizeof(*lundata);
4022 fprintf(stdout, "%u LUN%s found\n", list_len / 8,
4023 ((list_len / 8) > 1) ? "s" : "");
4028 for (i = 0; i < (list_len / 8); i++) {
4032 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
4034 fprintf(stdout, ",");
4035 switch (lundata->luns[i].lundata[j] &
4036 RPL_LUNDATA_ATYP_MASK) {
4037 case RPL_LUNDATA_ATYP_PERIPH:
4038 if ((lundata->luns[i].lundata[j] &
4039 RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
4040 fprintf(stdout, "%d:",
4041 lundata->luns[i].lundata[j] &
4042 RPL_LUNDATA_PERIPH_BUS_MASK);
4044 && ((lundata->luns[i].lundata[j+2] &
4045 RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
4048 fprintf(stdout, "%d",
4049 lundata->luns[i].lundata[j+1]);
4051 case RPL_LUNDATA_ATYP_FLAT: {
4053 tmplun[0] = lundata->luns[i].lundata[j] &
4054 RPL_LUNDATA_FLAT_LUN_MASK;
4055 tmplun[1] = lundata->luns[i].lundata[j+1];
4057 fprintf(stdout, "%d", scsi_2btoul(tmplun));
4061 case RPL_LUNDATA_ATYP_LUN:
4062 fprintf(stdout, "%d:%d:%d",
4063 (lundata->luns[i].lundata[j+1] &
4064 RPL_LUNDATA_LUN_BUS_MASK) >> 5,
4065 lundata->luns[i].lundata[j] &
4066 RPL_LUNDATA_LUN_TARG_MASK,
4067 lundata->luns[i].lundata[j+1] &
4068 RPL_LUNDATA_LUN_LUN_MASK);
4070 case RPL_LUNDATA_ATYP_EXTLUN: {
4071 int field_len_code, eam_code;
4073 eam_code = lundata->luns[i].lundata[j] &
4074 RPL_LUNDATA_EXT_EAM_MASK;
4075 field_len_code = (lundata->luns[i].lundata[j] &
4076 RPL_LUNDATA_EXT_LEN_MASK) >> 4;
4078 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
4079 && (field_len_code == 0x00)) {
4080 fprintf(stdout, "%d",
4081 lundata->luns[i].lundata[j+1]);
4082 } else if ((eam_code ==
4083 RPL_LUNDATA_EXT_EAM_NOT_SPEC)
4084 && (field_len_code == 0x03)) {
4088 * This format takes up all 8 bytes.
4089 * If we aren't starting at offset 0,
4093 fprintf(stdout, "Invalid "
4096 "specified format", j);
4100 bzero(tmp_lun, sizeof(tmp_lun));
4101 bcopy(&lundata->luns[i].lundata[j+1],
4102 &tmp_lun[1], sizeof(tmp_lun) - 1);
4103 fprintf(stdout, "%#jx",
4104 (intmax_t)scsi_8btou64(tmp_lun));
4107 fprintf(stderr, "Unknown Extended LUN"
4108 "Address method %#x, length "
4109 "code %#x", eam_code,
4116 fprintf(stderr, "Unknown LUN address method "
4117 "%#x\n", lundata->luns[i].lundata[0] &
4118 RPL_LUNDATA_ATYP_MASK);
4122 * For the flat addressing method, there are no
4123 * other levels after it.
4128 fprintf(stdout, "\n");
4141 scsireadcapacity(struct cam_device *device, int argc, char **argv,
4142 char *combinedopt, int retry_count, int timeout)
4145 int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
4146 struct scsi_read_capacity_data rcap;
4147 struct scsi_read_capacity_data_long rcaplong;
4161 ccb = cam_getccb(device);
4164 warnx("%s: error allocating ccb", __func__);
4168 bzero(&(&ccb->ccb_h)[1],
4169 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4171 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4198 if ((blocksizeonly != 0)
4199 && (numblocks != 0)) {
4200 warnx("%s: you can only specify one of -b or -N", __func__);
4205 if ((blocksizeonly != 0)
4206 && (sizeonly != 0)) {
4207 warnx("%s: you can only specify one of -b or -s", __func__);
4214 warnx("%s: you can only specify one of -h/-H or -q", __func__);
4220 && (blocksizeonly != 0)) {
4221 warnx("%s: you can only specify one of -h/-H or -b", __func__);
4226 scsi_read_capacity(&ccb->csio,
4227 /*retries*/ retry_count,
4229 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4232 /*timeout*/ timeout ? timeout : 5000);
4234 /* Disable freezing the device queue */
4235 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4237 if (arglist & CAM_ARG_ERR_RECOVER)
4238 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4240 if (cam_send_ccb(device, ccb) < 0) {
4241 warn("error sending READ CAPACITY command");
4243 if (arglist & CAM_ARG_VERBOSE)
4244 cam_error_print(device, ccb, CAM_ESF_ALL,
4245 CAM_EPF_ALL, stderr);
4251 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4252 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4257 maxsector = scsi_4btoul(rcap.addr);
4258 block_len = scsi_4btoul(rcap.length);
4261 * A last block of 2^32-1 means that the true capacity is over 2TB,
4262 * and we need to issue the long READ CAPACITY to get the real
4263 * capacity. Otherwise, we're all set.
4265 if (maxsector != 0xffffffff)
4268 scsi_read_capacity_16(&ccb->csio,
4269 /*retries*/ retry_count,
4271 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4276 /*sense_len*/ SSD_FULL_SIZE,
4277 /*timeout*/ timeout ? timeout : 5000);
4279 /* Disable freezing the device queue */
4280 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4282 if (arglist & CAM_ARG_ERR_RECOVER)
4283 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4285 if (cam_send_ccb(device, ccb) < 0) {
4286 warn("error sending READ CAPACITY (16) command");
4288 if (arglist & CAM_ARG_VERBOSE)
4289 cam_error_print(device, ccb, CAM_ESF_ALL,
4290 CAM_EPF_ALL, stderr);
4296 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4297 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4302 maxsector = scsi_8btou64(rcaplong.addr);
4303 block_len = scsi_4btoul(rcaplong.length);
4306 if (blocksizeonly == 0) {
4308 * Humanize implies !quiet, and also implies numblocks.
4310 if (humanize != 0) {
4315 tmpbytes = (maxsector + 1) * block_len;
4316 ret = humanize_number(tmpstr, sizeof(tmpstr),
4317 tmpbytes, "", HN_AUTOSCALE,
4320 HN_DIVISOR_1000 : 0));
4322 warnx("%s: humanize_number failed!", __func__);
4326 fprintf(stdout, "Device Size: %s%s", tmpstr,
4327 (sizeonly == 0) ? ", " : "\n");
4328 } else if (numblocks != 0) {
4329 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4330 "Blocks: " : "", (uintmax_t)maxsector + 1,
4331 (sizeonly == 0) ? ", " : "\n");
4333 fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4334 "Last Block: " : "", (uintmax_t)maxsector,
4335 (sizeonly == 0) ? ", " : "\n");
4339 fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
4340 "Block Length: " : "", block_len, (quiet == 0) ?
4349 smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
4350 int retry_count, int timeout)
4354 uint8_t *smp_request = NULL, *smp_response = NULL;
4355 int request_size = 0, response_size = 0;
4356 int fd_request = 0, fd_response = 0;
4357 char *datastr = NULL;
4358 struct get_hook hook;
4363 * Note that at the moment we don't support sending SMP CCBs to
4364 * devices that aren't probed by CAM.
4366 ccb = cam_getccb(device);
4368 warnx("%s: error allocating CCB", __func__);
4372 bzero(&(&ccb->ccb_h)[1],
4373 sizeof(union ccb) - sizeof(struct ccb_hdr));
4375 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4378 arglist |= CAM_ARG_CMD_IN;
4379 response_size = strtol(optarg, NULL, 0);
4380 if (response_size <= 0) {
4381 warnx("invalid number of response bytes %d",
4384 goto smpcmd_bailout;
4386 hook.argc = argc - optind;
4387 hook.argv = argv + optind;
4390 datastr = cget(&hook, NULL);
4392 * If the user supplied "-" instead of a format, he
4393 * wants the data to be written to stdout.
4395 if ((datastr != NULL)
4396 && (datastr[0] == '-'))
4399 smp_response = (u_int8_t *)malloc(response_size);
4400 if (smp_response == NULL) {
4401 warn("can't malloc memory for SMP response");
4403 goto smpcmd_bailout;
4407 arglist |= CAM_ARG_CMD_OUT;
4408 request_size = strtol(optarg, NULL, 0);
4409 if (request_size <= 0) {
4410 warnx("invalid number of request bytes %d",
4413 goto smpcmd_bailout;
4415 hook.argc = argc - optind;
4416 hook.argv = argv + optind;
4418 datastr = cget(&hook, NULL);
4419 smp_request = (u_int8_t *)malloc(request_size);
4420 if (smp_request == NULL) {
4421 warn("can't malloc memory for SMP request");
4423 goto smpcmd_bailout;
4425 bzero(smp_request, request_size);
4427 * If the user supplied "-" instead of a format, he
4428 * wants the data to be read from stdin.
4430 if ((datastr != NULL)
4431 && (datastr[0] == '-'))
4434 buff_encode_visit(smp_request, request_size,
4445 * If fd_data is set, and we're writing to the device, we need to
4446 * read the data the user wants written from stdin.
4448 if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4450 int amt_to_read = request_size;
4451 u_int8_t *buf_ptr = smp_request;
4453 for (amt_read = 0; amt_to_read > 0;
4454 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4455 if (amt_read == -1) {
4456 warn("error reading data from stdin");
4458 goto smpcmd_bailout;
4460 amt_to_read -= amt_read;
4461 buf_ptr += amt_read;
4465 if (((arglist & CAM_ARG_CMD_IN) == 0)
4466 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
4467 warnx("%s: need both the request (-r) and response (-R) "
4468 "arguments", __func__);
4470 goto smpcmd_bailout;
4473 flags |= CAM_DEV_QFRZDIS;
4475 cam_fill_smpio(&ccb->smpio,
4476 /*retries*/ retry_count,
4479 /*smp_request*/ smp_request,
4480 /*smp_request_len*/ request_size,
4481 /*smp_response*/ smp_response,
4482 /*smp_response_len*/ response_size,
4483 /*timeout*/ timeout ? timeout : 5000);
4485 ccb->smpio.flags = SMP_FLAG_NONE;
4487 if (((retval = cam_send_ccb(device, ccb)) < 0)
4488 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4489 const char warnstr[] = "error sending command";
4496 if (arglist & CAM_ARG_VERBOSE) {
4497 cam_error_print(device, ccb, CAM_ESF_ALL,
4498 CAM_EPF_ALL, stderr);
4502 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4503 && (response_size > 0)) {
4504 if (fd_response == 0) {
4505 buff_decode_visit(smp_response, response_size,
4506 datastr, arg_put, NULL);
4507 fprintf(stdout, "\n");
4509 ssize_t amt_written;
4510 int amt_to_write = response_size;
4511 u_int8_t *buf_ptr = smp_response;
4513 for (amt_written = 0; (amt_to_write > 0) &&
4514 (amt_written = write(STDOUT_FILENO, buf_ptr,
4515 amt_to_write)) > 0;){
4516 amt_to_write -= amt_written;
4517 buf_ptr += amt_written;
4519 if (amt_written == -1) {
4520 warn("error writing data to stdout");
4522 goto smpcmd_bailout;
4523 } else if ((amt_written == 0)
4524 && (amt_to_write > 0)) {
4525 warnx("only wrote %u bytes out of %u",
4526 response_size - amt_to_write,
4535 if (smp_request != NULL)
4538 if (smp_response != NULL)
4545 smpreportgeneral(struct cam_device *device, int argc, char **argv,
4546 char *combinedopt, int retry_count, int timeout)
4549 struct smp_report_general_request *request = NULL;
4550 struct smp_report_general_response *response = NULL;
4551 struct sbuf *sb = NULL;
4553 int c, long_response = 0;
4557 * Note that at the moment we don't support sending SMP CCBs to
4558 * devices that aren't probed by CAM.
4560 ccb = cam_getccb(device);
4562 warnx("%s: error allocating CCB", __func__);
4566 bzero(&(&ccb->ccb_h)[1],
4567 sizeof(union ccb) - sizeof(struct ccb_hdr));
4569 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4578 request = malloc(sizeof(*request));
4579 if (request == NULL) {
4580 warn("%s: unable to allocate %zd bytes", __func__,
4586 response = malloc(sizeof(*response));
4587 if (response == NULL) {
4588 warn("%s: unable to allocate %zd bytes", __func__,
4595 smp_report_general(&ccb->smpio,
4599 /*request_len*/ sizeof(*request),
4600 (uint8_t *)response,
4601 /*response_len*/ sizeof(*response),
4602 /*long_response*/ long_response,
4605 if (((retval = cam_send_ccb(device, ccb)) < 0)
4606 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4607 const char warnstr[] = "error sending command";
4614 if (arglist & CAM_ARG_VERBOSE) {
4615 cam_error_print(device, ccb, CAM_ESF_ALL,
4616 CAM_EPF_ALL, stderr);
4623 * If the device supports the long response bit, try again and see
4624 * if we can get all of the data.
4626 if ((response->long_response & SMP_RG_LONG_RESPONSE)
4627 && (long_response == 0)) {
4628 ccb->ccb_h.status = CAM_REQ_INPROG;
4629 bzero(&(&ccb->ccb_h)[1],
4630 sizeof(union ccb) - sizeof(struct ccb_hdr));
4636 * XXX KDM detect and decode SMP errors here.
4638 sb = sbuf_new_auto();
4640 warnx("%s: error allocating sbuf", __func__);
4644 smp_report_general_sbuf(response, sizeof(*response), sb);
4648 printf("%s", sbuf_data(sb));
4654 if (request != NULL)
4657 if (response != NULL)
4666 struct camcontrol_opts phy_ops[] = {
4667 {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
4668 {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
4669 {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
4670 {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
4671 {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
4672 {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
4673 {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
4674 {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
4675 {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
4680 smpphycontrol(struct cam_device *device, int argc, char **argv,
4681 char *combinedopt, int retry_count, int timeout)
4684 struct smp_phy_control_request *request = NULL;
4685 struct smp_phy_control_response *response = NULL;
4686 int long_response = 0;
4689 uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
4691 uint64_t attached_dev_name = 0;
4692 int dev_name_set = 0;
4693 uint32_t min_plr = 0, max_plr = 0;
4694 uint32_t pp_timeout_val = 0;
4695 int slumber_partial = 0;
4696 int set_pp_timeout_val = 0;
4700 * Note that at the moment we don't support sending SMP CCBs to
4701 * devices that aren't probed by CAM.
4703 ccb = cam_getccb(device);
4705 warnx("%s: error allocating CCB", __func__);
4709 bzero(&(&ccb->ccb_h)[1],
4710 sizeof(union ccb) - sizeof(struct ccb_hdr));
4712 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4720 if (strcasecmp(optarg, "enable") == 0)
4722 else if (strcasecmp(optarg, "disable") == 0)
4725 warnx("%s: Invalid argument %s", __func__,
4732 slumber_partial |= enable <<
4733 SMP_PC_SAS_SLUMBER_SHIFT;
4736 slumber_partial |= enable <<
4737 SMP_PC_SAS_PARTIAL_SHIFT;
4740 slumber_partial |= enable <<
4741 SMP_PC_SATA_SLUMBER_SHIFT;
4744 slumber_partial |= enable <<
4745 SMP_PC_SATA_PARTIAL_SHIFT;
4748 warnx("%s: programmer error", __func__);
4751 break; /*NOTREACHED*/
4756 attached_dev_name = (uintmax_t)strtoumax(optarg,
4765 * We don't do extensive checking here, so this
4766 * will continue to work when new speeds come out.
4768 min_plr = strtoul(optarg, NULL, 0);
4770 || (min_plr > 0xf)) {
4771 warnx("%s: invalid link rate %x",
4779 * We don't do extensive checking here, so this
4780 * will continue to work when new speeds come out.
4782 max_plr = strtoul(optarg, NULL, 0);
4784 || (max_plr > 0xf)) {
4785 warnx("%s: invalid link rate %x",
4792 camcontrol_optret optreturn;
4793 cam_argmask argnums;
4796 if (phy_op_set != 0) {
4797 warnx("%s: only one phy operation argument "
4798 "(-o) allowed", __func__);
4806 * Allow the user to specify the phy operation
4807 * numerically, as well as with a name. This will
4808 * future-proof it a bit, so options that are added
4809 * in future specs can be used.
4811 if (isdigit(optarg[0])) {
4812 phy_operation = strtoul(optarg, NULL, 0);
4813 if ((phy_operation == 0)
4814 || (phy_operation > 0xff)) {
4815 warnx("%s: invalid phy operation %#x",
4816 __func__, phy_operation);
4822 optreturn = getoption(phy_ops, optarg, &phy_operation,
4825 if (optreturn == CC_OR_AMBIGUOUS) {
4826 warnx("%s: ambiguous option %s", __func__,
4831 } else if (optreturn == CC_OR_NOT_FOUND) {
4832 warnx("%s: option %s not found", __func__,
4844 pp_timeout_val = strtoul(optarg, NULL, 0);
4845 if (pp_timeout_val > 15) {
4846 warnx("%s: invalid partial pathway timeout "
4847 "value %u, need a value less than 16",
4848 __func__, pp_timeout_val);
4852 set_pp_timeout_val = 1;
4860 warnx("%s: a PHY (-p phy) argument is required",__func__);
4865 if (((dev_name_set != 0)
4866 && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
4867 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
4868 && (dev_name_set == 0))) {
4869 warnx("%s: -d name and -o setdevname arguments both "
4870 "required to set device name", __func__);
4875 request = malloc(sizeof(*request));
4876 if (request == NULL) {
4877 warn("%s: unable to allocate %zd bytes", __func__,
4883 response = malloc(sizeof(*response));
4884 if (response == NULL) {
4885 warn("%s: unable to allocate %zd bytes", __func__,
4891 smp_phy_control(&ccb->smpio,
4896 (uint8_t *)response,
4899 /*expected_exp_change_count*/ 0,
4902 (set_pp_timeout_val != 0) ? 1 : 0,
4910 if (((retval = cam_send_ccb(device, ccb)) < 0)
4911 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4912 const char warnstr[] = "error sending command";
4919 if (arglist & CAM_ARG_VERBOSE) {
4921 * Use CAM_EPF_NORMAL so we only get one line of
4922 * SMP command decoding.
4924 cam_error_print(device, ccb, CAM_ESF_ALL,
4925 CAM_EPF_NORMAL, stderr);
4931 /* XXX KDM print out something here for success? */
4936 if (request != NULL)
4939 if (response != NULL)
4946 smpmaninfo(struct cam_device *device, int argc, char **argv,
4947 char *combinedopt, int retry_count, int timeout)
4950 struct smp_report_manuf_info_request request;
4951 struct smp_report_manuf_info_response response;
4952 struct sbuf *sb = NULL;
4953 int long_response = 0;
4958 * Note that at the moment we don't support sending SMP CCBs to
4959 * devices that aren't probed by CAM.
4961 ccb = cam_getccb(device);
4963 warnx("%s: error allocating CCB", __func__);
4967 bzero(&(&ccb->ccb_h)[1],
4968 sizeof(union ccb) - sizeof(struct ccb_hdr));
4970 while ((c = getopt(argc, argv, combinedopt)) != -1) {
4979 bzero(&request, sizeof(request));
4980 bzero(&response, sizeof(response));
4982 smp_report_manuf_info(&ccb->smpio,
4987 (uint8_t *)&response,
4992 if (((retval = cam_send_ccb(device, ccb)) < 0)
4993 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4994 const char warnstr[] = "error sending command";
5001 if (arglist & CAM_ARG_VERBOSE) {
5002 cam_error_print(device, ccb, CAM_ESF_ALL,
5003 CAM_EPF_ALL, stderr);
5009 sb = sbuf_new_auto();
5011 warnx("%s: error allocating sbuf", __func__);
5015 smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
5019 printf("%s", sbuf_data(sb));
5033 getdevid(struct cam_devitem *item)
5036 union ccb *ccb = NULL;
5038 struct cam_device *dev;
5040 dev = cam_open_btl(item->dev_match.path_id,
5041 item->dev_match.target_id,
5042 item->dev_match.target_lun, O_RDWR, NULL);
5045 warnx("%s", cam_errbuf);
5050 item->device_id_len = 0;
5052 ccb = cam_getccb(dev);
5054 warnx("%s: error allocating CCB", __func__);
5059 bzero(&(&ccb->ccb_h)[1],
5060 sizeof(union ccb) - sizeof(struct ccb_hdr));
5063 * On the first try, we just probe for the size of the data, and
5064 * then allocate that much memory and try again.
5067 ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
5068 ccb->ccb_h.flags = CAM_DIR_IN;
5069 ccb->cdai.flags = 0;
5070 ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
5071 ccb->cdai.bufsiz = item->device_id_len;
5072 if (item->device_id_len != 0)
5073 ccb->cdai.buf = (uint8_t *)item->device_id;
5075 if (cam_send_ccb(dev, ccb) < 0) {
5076 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
5081 if (ccb->ccb_h.status != CAM_REQ_CMP) {
5082 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
5087 if (item->device_id_len == 0) {
5089 * This is our first time through. Allocate the buffer,
5090 * and then go back to get the data.
5092 if (ccb->cdai.provsiz == 0) {
5093 warnx("%s: invalid .provsiz field returned with "
5094 "XPT_GDEV_ADVINFO CCB", __func__);
5098 item->device_id_len = ccb->cdai.provsiz;
5099 item->device_id = malloc(item->device_id_len);
5100 if (item->device_id == NULL) {
5101 warn("%s: unable to allocate %d bytes", __func__,
5102 item->device_id_len);
5106 ccb->ccb_h.status = CAM_REQ_INPROG;
5112 cam_close_device(dev);
5121 * XXX KDM merge this code with getdevtree()?
5124 buildbusdevlist(struct cam_devlist *devlist)
5127 int bufsize, fd = -1;
5128 struct dev_match_pattern *patterns;
5129 struct cam_devitem *item = NULL;
5130 int skip_device = 0;
5133 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
5134 warn("couldn't open %s", XPT_DEVICE);
5138 bzero(&ccb, sizeof(union ccb));
5140 ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
5141 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
5142 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
5144 ccb.ccb_h.func_code = XPT_DEV_MATCH;
5145 bufsize = sizeof(struct dev_match_result) * 100;
5146 ccb.cdm.match_buf_len = bufsize;
5147 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
5148 if (ccb.cdm.matches == NULL) {
5149 warnx("can't malloc memory for matches");
5153 ccb.cdm.num_matches = 0;
5154 ccb.cdm.num_patterns = 2;
5155 ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
5156 ccb.cdm.num_patterns;
5158 patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
5159 if (patterns == NULL) {
5160 warnx("can't malloc memory for patterns");
5165 ccb.cdm.patterns = patterns;
5166 bzero(patterns, ccb.cdm.pattern_buf_len);
5168 patterns[0].type = DEV_MATCH_DEVICE;
5169 patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
5170 patterns[0].pattern.device_pattern.path_id = devlist->path_id;
5171 patterns[1].type = DEV_MATCH_PERIPH;
5172 patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
5173 patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
5176 * We do the ioctl multiple times if necessary, in case there are
5177 * more than 100 nodes in the EDT.
5182 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
5183 warn("error sending CAMIOCOMMAND ioctl");
5188 if ((ccb.ccb_h.status != CAM_REQ_CMP)
5189 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
5190 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
5191 warnx("got CAM error %#x, CDM error %d\n",
5192 ccb.ccb_h.status, ccb.cdm.status);
5197 for (i = 0; i < ccb.cdm.num_matches; i++) {
5198 switch (ccb.cdm.matches[i].type) {
5199 case DEV_MATCH_DEVICE: {
5200 struct device_match_result *dev_result;
5203 &ccb.cdm.matches[i].result.device_result;
5205 if (dev_result->flags &
5206 DEV_RESULT_UNCONFIGURED) {
5212 item = malloc(sizeof(*item));
5214 warn("%s: unable to allocate %zd bytes",
5215 __func__, sizeof(*item));
5219 bzero(item, sizeof(*item));
5220 bcopy(dev_result, &item->dev_match,
5221 sizeof(*dev_result));
5222 STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
5225 if (getdevid(item) != 0) {
5231 case DEV_MATCH_PERIPH: {
5232 struct periph_match_result *periph_result;
5235 &ccb.cdm.matches[i].result.periph_result;
5237 if (skip_device != 0)
5239 item->num_periphs++;
5240 item->periph_matches = realloc(
5241 item->periph_matches,
5243 sizeof(struct periph_match_result));
5244 if (item->periph_matches == NULL) {
5245 warn("%s: error allocating periph "
5250 bcopy(periph_result, &item->periph_matches[
5251 item->num_periphs - 1],
5252 sizeof(*periph_result));
5256 fprintf(stderr, "%s: unexpected match "
5257 "type %d\n", __func__,
5258 ccb.cdm.matches[i].type);
5261 break; /*NOTREACHED*/
5264 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
5265 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
5273 free(ccb.cdm.matches);
5276 freebusdevlist(devlist);
5282 freebusdevlist(struct cam_devlist *devlist)
5284 struct cam_devitem *item, *item2;
5286 STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
5287 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
5289 free(item->device_id);
5290 free(item->periph_matches);
5295 static struct cam_devitem *
5296 findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
5298 struct cam_devitem *item;
5300 STAILQ_FOREACH(item, &devlist->dev_queue, links) {
5304 * XXX KDM look for LUN IDs as well?
5306 item_addr = scsi_get_devid(item->device_id,
5307 item->device_id_len,
5308 scsi_devid_is_sas_target);
5309 if (item_addr == NULL)
5312 if (scsi_8btou64(item_addr) == sasaddr)
5320 smpphylist(struct cam_device *device, int argc, char **argv,
5321 char *combinedopt, int retry_count, int timeout)
5323 struct smp_report_general_request *rgrequest = NULL;
5324 struct smp_report_general_response *rgresponse = NULL;
5325 struct smp_discover_request *disrequest = NULL;
5326 struct smp_discover_response *disresponse = NULL;
5327 struct cam_devlist devlist;
5329 int long_response = 0;
5336 * Note that at the moment we don't support sending SMP CCBs to
5337 * devices that aren't probed by CAM.
5339 ccb = cam_getccb(device);
5341 warnx("%s: error allocating CCB", __func__);
5345 bzero(&(&ccb->ccb_h)[1],
5346 sizeof(union ccb) - sizeof(struct ccb_hdr));
5348 rgrequest = malloc(sizeof(*rgrequest));
5349 if (rgrequest == NULL) {
5350 warn("%s: unable to allocate %zd bytes", __func__,
5351 sizeof(*rgrequest));
5356 rgresponse = malloc(sizeof(*rgresponse));
5357 if (rgresponse == NULL) {
5358 warn("%s: unable to allocate %zd bytes", __func__,
5359 sizeof(*rgresponse));
5364 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5377 smp_report_general(&ccb->smpio,
5381 /*request_len*/ sizeof(*rgrequest),
5382 (uint8_t *)rgresponse,
5383 /*response_len*/ sizeof(*rgresponse),
5384 /*long_response*/ long_response,
5387 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5389 if (((retval = cam_send_ccb(device, ccb)) < 0)
5390 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
5391 const char warnstr[] = "error sending command";
5398 if (arglist & CAM_ARG_VERBOSE) {
5399 cam_error_print(device, ccb, CAM_ESF_ALL,
5400 CAM_EPF_ALL, stderr);
5406 num_phys = rgresponse->num_phys;
5408 if (num_phys == 0) {
5410 fprintf(stdout, "%s: No Phys reported\n", __func__);
5415 STAILQ_INIT(&devlist.dev_queue);
5416 devlist.path_id = device->path_id;
5418 retval = buildbusdevlist(&devlist);
5423 fprintf(stdout, "%d PHYs:\n", num_phys);
5424 fprintf(stdout, "PHY Attached SAS Address\n");
5427 disrequest = malloc(sizeof(*disrequest));
5428 if (disrequest == NULL) {
5429 warn("%s: unable to allocate %zd bytes", __func__,
5430 sizeof(*disrequest));
5435 disresponse = malloc(sizeof(*disresponse));
5436 if (disresponse == NULL) {
5437 warn("%s: unable to allocate %zd bytes", __func__,
5438 sizeof(*disresponse));
5443 for (i = 0; i < num_phys; i++) {
5444 struct cam_devitem *item;
5445 struct device_match_result *dev_match;
5446 char vendor[16], product[48], revision[16];
5450 bzero(&(&ccb->ccb_h)[1],
5451 sizeof(union ccb) - sizeof(struct ccb_hdr));
5453 ccb->ccb_h.status = CAM_REQ_INPROG;
5454 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5456 smp_discover(&ccb->smpio,
5460 sizeof(*disrequest),
5461 (uint8_t *)disresponse,
5462 sizeof(*disresponse),
5464 /*ignore_zone_group*/ 0,
5468 if (((retval = cam_send_ccb(device, ccb)) < 0)
5469 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
5470 && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
5471 const char warnstr[] = "error sending command";
5478 if (arglist & CAM_ARG_VERBOSE) {
5479 cam_error_print(device, ccb, CAM_ESF_ALL,
5480 CAM_EPF_ALL, stderr);
5486 if (disresponse->function_result == SMP_FR_PHY_VACANT) {
5488 fprintf(stdout, "%3d <vacant>\n", i);
5492 item = findsasdevice(&devlist,
5493 scsi_8btou64(disresponse->attached_sas_address));
5496 || (item != NULL)) {
5497 fprintf(stdout, "%3d 0x%016jx", i,
5498 (uintmax_t)scsi_8btou64(
5499 disresponse->attached_sas_address));
5501 fprintf(stdout, "\n");
5504 } else if (quiet != 0)
5507 dev_match = &item->dev_match;
5509 if (dev_match->protocol == PROTO_SCSI) {
5510 cam_strvis(vendor, dev_match->inq_data.vendor,
5511 sizeof(dev_match->inq_data.vendor),
5513 cam_strvis(product, dev_match->inq_data.product,
5514 sizeof(dev_match->inq_data.product),
5516 cam_strvis(revision, dev_match->inq_data.revision,
5517 sizeof(dev_match->inq_data.revision),
5519 sprintf(tmpstr, "<%s %s %s>", vendor, product,
5521 } else if ((dev_match->protocol == PROTO_ATA)
5522 || (dev_match->protocol == PROTO_SATAPM)) {
5523 cam_strvis(product, dev_match->ident_data.model,
5524 sizeof(dev_match->ident_data.model),
5526 cam_strvis(revision, dev_match->ident_data.revision,
5527 sizeof(dev_match->ident_data.revision),
5529 sprintf(tmpstr, "<%s %s>", product, revision);
5531 sprintf(tmpstr, "<>");
5533 fprintf(stdout, " %-33s ", tmpstr);
5536 * If we have 0 periphs, that's a bug...
5538 if (item->num_periphs == 0) {
5539 fprintf(stdout, "\n");
5543 fprintf(stdout, "(");
5544 for (j = 0; j < item->num_periphs; j++) {
5546 fprintf(stdout, ",");
5548 fprintf(stdout, "%s%d",
5549 item->periph_matches[j].periph_name,
5550 item->periph_matches[j].unit_number);
5553 fprintf(stdout, ")\n");
5567 freebusdevlist(&devlist);
5573 atapm(struct cam_device *device, int argc, char **argv,
5574 char *combinedopt, int retry_count, int timeout)
5582 ccb = cam_getccb(device);
5585 warnx("%s: error allocating ccb", __func__);
5589 while ((c = getopt(argc, argv, combinedopt)) != -1) {
5598 if (strcmp(argv[1], "idle") == 0) {
5600 cmd = ATA_IDLE_IMMEDIATE;
5603 } else if (strcmp(argv[1], "standby") == 0) {
5605 cmd = ATA_STANDBY_IMMEDIATE;
5607 cmd = ATA_STANDBY_CMD;
5615 else if (t <= (240 * 5))
5617 else if (t <= (252 * 5))
5618 /* special encoding for 21 minutes */
5620 else if (t <= (11 * 30 * 60))
5621 sc = (t - 1) / (30 * 60) + 241;
5625 cam_fill_ataio(&ccb->ataio,
5628 /*flags*/CAM_DIR_NONE,
5632 timeout ? timeout : 30 * 1000);
5633 ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
5635 /* Disable freezing the device queue */
5636 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5638 if (arglist & CAM_ARG_ERR_RECOVER)
5639 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5641 if (cam_send_ccb(device, ccb) < 0) {
5642 warn("error sending command");
5644 if (arglist & CAM_ARG_VERBOSE)
5645 cam_error_print(device, ccb, CAM_ESF_ALL,
5646 CAM_EPF_ALL, stderr);
5652 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5653 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
5662 #endif /* MINIMALISTIC */
5667 fprintf(verbose ? stdout : stderr,
5668 "usage: camcontrol <command> [device id][generic args][command args]\n"
5669 " camcontrol devlist [-v]\n"
5670 #ifndef MINIMALISTIC
5671 " camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
5672 " camcontrol tur [dev_id][generic args]\n"
5673 " camcontrol inquiry [dev_id][generic args] [-D] [-S] [-R]\n"
5674 " camcontrol identify [dev_id][generic args] [-v]\n"
5675 " camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
5676 " camcontrol readcap [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
5678 " camcontrol start [dev_id][generic args]\n"
5679 " camcontrol stop [dev_id][generic args]\n"
5680 " camcontrol load [dev_id][generic args]\n"
5681 " camcontrol eject [dev_id][generic args]\n"
5682 #endif /* MINIMALISTIC */
5683 " camcontrol rescan <all | bus[:target:lun]>\n"
5684 " camcontrol reset <all | bus[:target:lun]>\n"
5685 #ifndef MINIMALISTIC
5686 " camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n"
5687 " camcontrol modepage [dev_id][generic args] <-m page | -l>\n"
5688 " [-P pagectl][-e | -b][-d]\n"
5689 " camcontrol cmd [dev_id][generic args]\n"
5690 " <-a cmd [args] | -c cmd [args]>\n"
5691 " [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
5692 " camcontrol smpcmd [dev_id][generic args]\n"
5693 " <-r len fmt [args]> <-R len fmt [args]>\n"
5694 " camcontrol smprg [dev_id][generic args][-l]\n"
5695 " camcontrol smppc [dev_id][generic args] <-p phy> [-l]\n"
5696 " [-o operation][-d name][-m rate][-M rate]\n"
5697 " [-T pp_timeout][-a enable|disable]\n"
5698 " [-A enable|disable][-s enable|disable]\n"
5699 " [-S enable|disable]\n"
5700 " camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
5701 " camcontrol smpmaninfo [dev_id][generic args][-l]\n"
5702 " camcontrol debug [-I][-P][-T][-S][-X][-c]\n"
5703 " <all|bus[:target[:lun]]|off>\n"
5704 " camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n"
5705 " camcontrol negotiate [dev_id][generic args] [-a][-c]\n"
5706 " [-D <enable|disable>][-M mode][-O offset]\n"
5707 " [-q][-R syncrate][-v][-T <enable|disable>]\n"
5708 " [-U][-W bus_width]\n"
5709 " camcontrol format [dev_id][generic args][-q][-r][-w][-y]\n"
5710 " camcontrol idle [dev_id][generic args][-t time]\n"
5711 " camcontrol standby [dev_id][generic args][-t time]\n"
5712 " camcontrol sleep [dev_id][generic args]\n"
5713 #endif /* MINIMALISTIC */
5714 " camcontrol help\n");
5717 #ifndef MINIMALISTIC
5719 "Specify one of the following options:\n"
5720 "devlist list all CAM devices\n"
5721 "periphlist list all CAM peripheral drivers attached to a device\n"
5722 "tur send a test unit ready to the named device\n"
5723 "inquiry send a SCSI inquiry command to the named device\n"
5724 "identify send a ATA identify command to the named device\n"
5725 "reportluns send a SCSI report luns command to the device\n"
5726 "readcap send a SCSI read capacity command to the device\n"
5727 "start send a Start Unit command to the device\n"
5728 "stop send a Stop Unit command to the device\n"
5729 "load send a Start Unit command to the device with the load bit set\n"
5730 "eject send a Stop Unit command to the device with the eject bit set\n"
5731 "rescan rescan all busses, the given bus, or bus:target:lun\n"
5732 "reset reset all busses, the given bus, or bus:target:lun\n"
5733 "defects read the defect list of the specified device\n"
5734 "modepage display or edit (-e) the given mode page\n"
5735 "cmd send the given SCSI command, may need -i or -o as well\n"
5736 "smpcmd send the given SMP command, requires -o and -i\n"
5737 "smprg send the SMP Report General command\n"
5738 "smppc send the SMP PHY Control command, requires -p\n"
5739 "smpphylist display phys attached to a SAS expander\n"
5740 "smpmaninfo send the SMP Report Manufacturer Info command\n"
5741 "debug turn debugging on/off for a bus, target, or lun, or all devices\n"
5742 "tags report or set the number of transaction slots for a device\n"
5743 "negotiate report or set device negotiation parameters\n"
5744 "format send the SCSI FORMAT UNIT command to the named device\n"
5745 "idle send the ATA IDLE command to the named device\n"
5746 "standby send the ATA STANDBY command to the named device\n"
5747 "sleep send the ATA SLEEP command to the named device\n"
5748 "help this message\n"
5749 "Device Identifiers:\n"
5750 "bus:target specify the bus and target, lun defaults to 0\n"
5751 "bus:target:lun specify the bus, target and lun\n"
5752 "deviceUNIT specify the device name, like \"da4\" or \"cd2\"\n"
5753 "Generic arguments:\n"
5754 "-v be verbose, print out sense information\n"
5755 "-t timeout command timeout in seconds, overrides default timeout\n"
5756 "-n dev_name specify device name, e.g. \"da\", \"cd\"\n"
5757 "-u unit specify unit number, e.g. \"0\", \"5\"\n"
5758 "-E have the kernel attempt to perform SCSI error recovery\n"
5759 "-C count specify the SCSI command retry count (needs -E to work)\n"
5760 "modepage arguments:\n"
5761 "-l list all available mode pages\n"
5762 "-m page specify the mode page to view or edit\n"
5763 "-e edit the specified mode page\n"
5764 "-b force view to binary mode\n"
5765 "-d disable block descriptors for mode sense\n"
5766 "-P pgctl page control field 0-3\n"
5767 "defects arguments:\n"
5768 "-f format specify defect list format (block, bfi or phys)\n"
5769 "-G get the grown defect list\n"
5770 "-P get the permanant defect list\n"
5771 "inquiry arguments:\n"
5772 "-D get the standard inquiry data\n"
5773 "-S get the serial number\n"
5774 "-R get the transfer rate, etc.\n"
5775 "reportluns arguments:\n"
5776 "-c only report a count of available LUNs\n"
5777 "-l only print out luns, and not a count\n"
5778 "-r <reporttype> specify \"default\", \"wellknown\" or \"all\"\n"
5779 "readcap arguments\n"
5780 "-b only report the blocksize\n"
5781 "-h human readable device size, base 2\n"
5782 "-H human readable device size, base 10\n"
5783 "-N print the number of blocks instead of last block\n"
5784 "-q quiet, print numbers only\n"
5785 "-s only report the last block/device size\n"
5787 "-c cdb [args] specify the SCSI CDB\n"
5788 "-i len fmt specify input data and input data format\n"
5789 "-o len fmt [args] specify output data and output data fmt\n"
5790 "smpcmd arguments:\n"
5791 "-r len fmt [args] specify the SMP command to be sent\n"
5792 "-R len fmt [args] specify SMP response format\n"
5793 "smprg arguments:\n"
5794 "-l specify the long response format\n"
5795 "smppc arguments:\n"
5796 "-p phy specify the PHY to operate on\n"
5797 "-l specify the long request/response format\n"
5798 "-o operation specify the phy control operation\n"
5799 "-d name set the attached device name\n"
5800 "-m rate set the minimum physical link rate\n"
5801 "-M rate set the maximum physical link rate\n"
5802 "-T pp_timeout set the partial pathway timeout value\n"
5803 "-a enable|disable enable or disable SATA slumber\n"
5804 "-A enable|disable enable or disable SATA partial phy power\n"
5805 "-s enable|disable enable or disable SAS slumber\n"
5806 "-S enable|disable enable or disable SAS partial phy power\n"
5807 "smpphylist arguments:\n"
5808 "-l specify the long response format\n"
5809 "-q only print phys with attached devices\n"
5810 "smpmaninfo arguments:\n"
5811 "-l specify the long response format\n"
5812 "debug arguments:\n"
5813 "-I CAM_DEBUG_INFO -- scsi commands, errors, data\n"
5814 "-T CAM_DEBUG_TRACE -- routine flow tracking\n"
5815 "-S CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
5816 "-c CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
5818 "-N tags specify the number of tags to use for this device\n"
5819 "-q be quiet, don't report the number of tags\n"
5820 "-v report a number of tag-related parameters\n"
5821 "negotiate arguments:\n"
5822 "-a send a test unit ready after negotiation\n"
5823 "-c report/set current negotiation settings\n"
5824 "-D <arg> \"enable\" or \"disable\" disconnection\n"
5825 "-M mode set ATA mode\n"
5826 "-O offset set command delay offset\n"
5827 "-q be quiet, don't report anything\n"
5828 "-R syncrate synchronization rate in MHz\n"
5829 "-T <arg> \"enable\" or \"disable\" tagged queueing\n"
5830 "-U report/set user negotiation settings\n"
5831 "-W bus_width set the bus width in bits (8, 16 or 32)\n"
5832 "-v also print a Path Inquiry CCB for the controller\n"
5833 "format arguments:\n"
5834 "-q be quiet, don't print status messages\n"
5835 "-r run in report only mode\n"
5836 "-w don't send immediate format command\n"
5837 "-y don't ask any questions\n"
5838 "idle/standby arguments:\n"
5839 "-t <arg> number of seconds before respective state.\n");
5840 #endif /* MINIMALISTIC */
5844 main(int argc, char **argv)
5847 char *device = NULL;
5849 struct cam_device *cam_dev = NULL;
5850 int timeout = 0, retry_count = 1;
5851 camcontrol_optret optreturn;
5853 const char *mainopt = "C:En:t:u:v";
5854 const char *subopt = NULL;
5855 char combinedopt[256];
5856 int error = 0, optstart = 2;
5858 #ifndef MINIMALISTIC
5859 int bus, target, lun;
5860 #endif /* MINIMALISTIC */
5862 cmdlist = CAM_CMD_NONE;
5863 arglist = CAM_ARG_NONE;
5871 * Get the base option.
5873 optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
5875 if (optreturn == CC_OR_AMBIGUOUS) {
5876 warnx("ambiguous option %s", argv[1]);
5879 } else if (optreturn == CC_OR_NOT_FOUND) {
5880 warnx("option %s not found", argv[1]);
5886 * Ahh, getopt(3) is a pain.
5888 * This is a gross hack. There really aren't many other good
5889 * options (excuse the pun) for parsing options in a situation like
5890 * this. getopt is kinda braindead, so you end up having to run
5891 * through the options twice, and give each invocation of getopt
5892 * the option string for the other invocation.
5894 * You would think that you could just have two groups of options.
5895 * The first group would get parsed by the first invocation of
5896 * getopt, and the second group would get parsed by the second
5897 * invocation of getopt. It doesn't quite work out that way. When
5898 * the first invocation of getopt finishes, it leaves optind pointing
5899 * to the argument _after_ the first argument in the second group.
5900 * So when the second invocation of getopt comes around, it doesn't
5901 * recognize the first argument it gets and then bails out.
5903 * A nice alternative would be to have a flag for getopt that says
5904 * "just keep parsing arguments even when you encounter an unknown
5905 * argument", but there isn't one. So there's no real clean way to
5906 * easily parse two sets of arguments without having one invocation
5907 * of getopt know about the other.
5909 * Without this hack, the first invocation of getopt would work as
5910 * long as the generic arguments are first, but the second invocation
5911 * (in the subfunction) would fail in one of two ways. In the case
5912 * where you don't set optreset, it would fail because optind may be
5913 * pointing to the argument after the one it should be pointing at.
5914 * In the case where you do set optreset, and reset optind, it would
5915 * fail because getopt would run into the first set of options, which
5916 * it doesn't understand.
5918 * All of this would "sort of" work if you could somehow figure out
5919 * whether optind had been incremented one option too far. The
5920 * mechanics of that, however, are more daunting than just giving
5921 * both invocations all of the expect options for either invocation.
5923 * Needless to say, I wouldn't mind if someone invented a better
5924 * (non-GPL!) command line parsing interface than getopt. I
5925 * wouldn't mind if someone added more knobs to getopt to make it
5926 * work better. Who knows, I may talk myself into doing it someday,
5927 * if the standards weenies let me. As it is, it just leads to
5928 * hackery like this and causes people to avoid it in some cases.
5930 * KDM, September 8th, 1998
5933 sprintf(combinedopt, "%s%s", mainopt, subopt);
5935 sprintf(combinedopt, "%s", mainopt);
5938 * For these options we do not parse optional device arguments and
5939 * we do not open a passthrough device.
5941 if ((cmdlist == CAM_CMD_RESCAN)
5942 || (cmdlist == CAM_CMD_RESET)
5943 || (cmdlist == CAM_CMD_DEVTREE)
5944 || (cmdlist == CAM_CMD_USAGE)
5945 || (cmdlist == CAM_CMD_DEBUG))
5948 #ifndef MINIMALISTIC
5950 && (argc > 2 && argv[2][0] != '-')) {
5954 if (isdigit(argv[2][0])) {
5955 /* device specified as bus:target[:lun] */
5956 rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
5958 errx(1, "numeric device specification must "
5959 "be either bus:target, or "
5961 /* default to 0 if lun was not specified */
5962 if ((arglist & CAM_ARG_LUN) == 0) {
5964 arglist |= CAM_ARG_LUN;
5968 if (cam_get_device(argv[2], name, sizeof name, &unit)
5970 errx(1, "%s", cam_errbuf);
5971 device = strdup(name);
5972 arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
5976 #endif /* MINIMALISTIC */
5978 * Start getopt processing at argv[2/3], since we've already
5979 * accepted argv[1..2] as the command name, and as a possible
5985 * Now we run through the argument list looking for generic
5986 * options, and ignoring options that possibly belong to
5989 while ((c = getopt(argc, argv, combinedopt))!= -1){
5992 retry_count = strtol(optarg, NULL, 0);
5993 if (retry_count < 0)
5994 errx(1, "retry count %d is < 0",
5996 arglist |= CAM_ARG_RETRIES;
5999 arglist |= CAM_ARG_ERR_RECOVER;
6002 arglist |= CAM_ARG_DEVICE;
6004 while (isspace(*tstr) && (*tstr != '\0'))
6006 device = (char *)strdup(tstr);
6009 timeout = strtol(optarg, NULL, 0);
6011 errx(1, "invalid timeout %d", timeout);
6012 /* Convert the timeout from seconds to ms */
6014 arglist |= CAM_ARG_TIMEOUT;
6017 arglist |= CAM_ARG_UNIT;
6018 unit = strtol(optarg, NULL, 0);
6021 arglist |= CAM_ARG_VERBOSE;
6028 #ifndef MINIMALISTIC
6030 * For most commands we'll want to open the passthrough device
6031 * associated with the specified device. In the case of the rescan
6032 * commands, we don't use a passthrough device at all, just the
6033 * transport layer device.
6036 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
6037 && (((arglist & CAM_ARG_DEVICE) == 0)
6038 || ((arglist & CAM_ARG_UNIT) == 0))) {
6039 errx(1, "subcommand \"%s\" requires a valid device "
6040 "identifier", argv[1]);
6043 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
6044 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
6045 cam_open_spec_device(device,unit,O_RDWR,NULL)))
6047 errx(1,"%s", cam_errbuf);
6049 #endif /* MINIMALISTIC */
6052 * Reset optind to 2, and reset getopt, so these routines can parse
6053 * the arguments again.
6059 #ifndef MINIMALISTIC
6060 case CAM_CMD_DEVLIST:
6061 error = getdevlist(cam_dev);
6063 #endif /* MINIMALISTIC */
6064 case CAM_CMD_DEVTREE:
6065 error = getdevtree();
6067 #ifndef MINIMALISTIC
6069 error = testunitready(cam_dev, retry_count, timeout, 0);
6071 case CAM_CMD_INQUIRY:
6072 error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
6073 retry_count, timeout);
6075 case CAM_CMD_IDENTIFY:
6076 error = ataidentify(cam_dev, retry_count, timeout);
6078 case CAM_CMD_STARTSTOP:
6079 error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
6080 arglist & CAM_ARG_EJECT, retry_count,
6083 #endif /* MINIMALISTIC */
6084 case CAM_CMD_RESCAN:
6085 error = dorescan_or_reset(argc, argv, 1);
6088 error = dorescan_or_reset(argc, argv, 0);
6090 #ifndef MINIMALISTIC
6091 case CAM_CMD_READ_DEFECTS:
6092 error = readdefects(cam_dev, argc, argv, combinedopt,
6093 retry_count, timeout);
6095 case CAM_CMD_MODE_PAGE:
6096 modepage(cam_dev, argc, argv, combinedopt,
6097 retry_count, timeout);
6099 case CAM_CMD_SCSI_CMD:
6100 error = scsicmd(cam_dev, argc, argv, combinedopt,
6101 retry_count, timeout);
6103 case CAM_CMD_SMP_CMD:
6104 error = smpcmd(cam_dev, argc, argv, combinedopt,
6105 retry_count, timeout);
6107 case CAM_CMD_SMP_RG:
6108 error = smpreportgeneral(cam_dev, argc, argv,
6109 combinedopt, retry_count,
6112 case CAM_CMD_SMP_PC:
6113 error = smpphycontrol(cam_dev, argc, argv, combinedopt,
6114 retry_count, timeout);
6116 case CAM_CMD_SMP_PHYLIST:
6117 error = smpphylist(cam_dev, argc, argv, combinedopt,
6118 retry_count, timeout);
6120 case CAM_CMD_SMP_MANINFO:
6121 error = smpmaninfo(cam_dev, argc, argv, combinedopt,
6122 retry_count, timeout);
6125 error = camdebug(argc, argv, combinedopt);
6128 error = tagcontrol(cam_dev, argc, argv, combinedopt);
6131 error = ratecontrol(cam_dev, retry_count, timeout,
6132 argc, argv, combinedopt);
6134 case CAM_CMD_FORMAT:
6135 error = scsiformat(cam_dev, argc, argv,
6136 combinedopt, retry_count, timeout);
6138 case CAM_CMD_REPORTLUNS:
6139 error = scsireportluns(cam_dev, argc, argv,
6140 combinedopt, retry_count,
6143 case CAM_CMD_READCAP:
6144 error = scsireadcapacity(cam_dev, argc, argv,
6145 combinedopt, retry_count,
6149 case CAM_CMD_STANDBY:
6151 error = atapm(cam_dev, argc, argv,
6152 combinedopt, retry_count,
6155 #endif /* MINIMALISTIC */
6165 if (cam_dev != NULL)
6166 cam_close_device(cam_dev);